   (:require [clojure.core.match :refer [match]]
             [clojure.tools.logging :as log]
             [clojure.string :as s]
-            [clojure.walk :as walk]
-            [korma.core :refer :all, :exclude [update]]
-            [korma.sql.utils :as utils]
+            (korma [core :as k]
+                   [db :as kdb])
+            (korma.sql [fns :as kfns]
+                       [utils :as utils])
             [metabase.config :as config]
             [metabase.driver :as driver]
             [metabase.driver.query-processor :as qp]

  (if (= filter-type :inside)
    ;; INSIDE filter subclause
    (let [{:keys [lat lon]} filter]
      (list 'and {(formatted (:field lat)) ['< (formatted (:max lat))]}
                 {(formatted (:field lat)) ['> (formatted (:min lat))]}
                 {(formatted (:field lon)) ['< (formatted (:max lon))]}
                 {(formatted (:field lon)) ['> (formatted (:min lon))]}))

    ;; all other filter subclauses
    (let [field (formatted (:field filter))

     (formatted this false))
    ([{value :value, {unit :unit} :field} _]
     ;; prevent Clojure from converting this to #inst literal, which is a util.date
     ((:date (:driver *query*)) unit value)))

  RelativeDateTimeValue
  (formatted
    ([this]
     (formatted this false))
    ([{:keys [amount unit], {field-unit :unit} :field} _]
     (let [{:keys [date date-interval]} (:driver *query*)]
       (date field-unit (if (zero? amount)
                          (k/sqlfn :NOW)
                          (date-interval unit amount)))))))


;;; ## Clause Handlers

(defn- apply-aggregation [korma-query {{:keys [aggregation-type field]} :aggregation}]
  (if-not field
    ;; aggregation clauses w/o a Field
    (case aggregation-type
      :rows  korma-query ; don't need to do anything special for `rows` - `select` selects all rows by default
      :count (k/aggregate korma-query (count :*) :count))
    ;; aggregation clauses with a Field
    (let [field (formatted field)]
      (case aggregation-type
        :avg      (k/aggregate korma-query (avg field) :avg)
        :count    (k/aggregate korma-query (count field) :count)
        :distinct (k/aggregate korma-query (count (k/sqlfn :DISTINCT field)) :count)
        :stddev   (k/fields    korma-query [(k/sqlfn :STDDEV field) :stddev])
        :sum      (k/aggregate korma-query (sum field) :sum)))))

(defn- apply-breakout [korma-query {fields :breakout}]
  (-> korma-query
      ;; Group by all the breakout fields
      ((partial apply k/group) (map formatted fields))
      ;; Add fields form only for fields that weren't specified in :fields clause -- we don't want to include it twice, or korma will barf
      ((partial apply k/fields) (->> fields
                                     (filter (partial (complement contains?) (set (:fields (:query *query*)))))
                                     (map (u/rpartial formatted :include-as))))))

(defn- apply-fields [korma-query {fields :fields}]
  (apply k/fields korma-query (for [field fields]
                                (formatted field :include-as))))

(defn- filter-subclause->predicate
  "Given a filter SUBCLAUSE, return a Korma filter predicate form for use in korma `where`."
