Down to just 8 failures now!
Mising: array, inline, parameterizer.
This commit is contained in:
parent
1a699f18ab
commit
f7d5e3a4cf
2 changed files with 203 additions and 95 deletions
|
|
@ -9,12 +9,13 @@
|
||||||
|
|
||||||
(declare format-dsl)
|
(declare format-dsl)
|
||||||
(declare format-expr)
|
(declare format-expr)
|
||||||
|
(declare format-expr-list)
|
||||||
|
|
||||||
;; dynamic dialect handling for formatting
|
;; dynamic dialect handling for formatting
|
||||||
|
|
||||||
(def ^:private default-clause-order
|
(def ^:private default-clause-order
|
||||||
"The (default) order for known clauses. Can have items added and removed."
|
"The (default) order for known clauses. Can have items added and removed."
|
||||||
[:intersect :union :union-all :except
|
[:with :with-recursive :intersect :union :union-all :except
|
||||||
:select :insert-into :update :delete :delete-from :truncate
|
:select :insert-into :update :delete :delete-from :truncate
|
||||||
:columns :set :from
|
:columns :set :from
|
||||||
:join :left-join :right-join :inner-join :outer-join :full-join
|
:join :left-join :right-join :inner-join :outer-join :full-join
|
||||||
|
|
@ -50,7 +51,9 @@
|
||||||
(def ^:private default-dialect (atom (:ansi dialects)))
|
(def ^:private default-dialect (atom (:ansi dialects)))
|
||||||
|
|
||||||
(def ^:private ^:dynamic *dialect* nil)
|
(def ^:private ^:dynamic *dialect* nil)
|
||||||
(def ^:private ^:dynamic *clause-order* nil)
|
;; nil would be a better default but that makes testing individual
|
||||||
|
;; functions harder than necessary:
|
||||||
|
(def ^:private ^:dynamic *clause-order* default-clause-order)
|
||||||
(def ^:private ^:dynamic *quoted* nil)
|
(def ^:private ^:dynamic *quoted* nil)
|
||||||
|
|
||||||
;; clause helpers
|
;; clause helpers
|
||||||
|
|
@ -72,41 +75,66 @@
|
||||||
(defn- sql-kw [k]
|
(defn- sql-kw [k]
|
||||||
(-> k (name) (upper-case) (str/replace "-" " ")))
|
(-> k (name) (upper-case) (str/replace "-" " ")))
|
||||||
|
|
||||||
(defn- format-entity [x]
|
(defn- format-entity [x & [{:keys [aliased? drop-ns?]}]]
|
||||||
(let [q (if *quoted* (:quote *dialect*) identity)
|
(let [q (if *quoted* (:quote *dialect*) identity)
|
||||||
[t c] (if-let [n (namespace x)]
|
call (fn [f x] (str f "(" x ")"))
|
||||||
[n (name x)]
|
[f t c] (if-let [n (when-not (or drop-ns? (string? x))
|
||||||
(let [[t c] (str/split (name x) #"\.")]
|
(namespace x))]
|
||||||
(if c [t c] [nil t])))]
|
[nil n (name x)]
|
||||||
|
(let [[t c] (if aliased?
|
||||||
|
[(name x)]
|
||||||
|
(str/split (name x) #"\."))]
|
||||||
|
;; I really dislike like %func.arg shorthand syntax!
|
||||||
|
(cond (= \% (first t))
|
||||||
|
[(subs t 1) nil c]
|
||||||
|
c
|
||||||
|
[nil t c]
|
||||||
|
:else
|
||||||
|
[nil nil t])))]
|
||||||
(cond->> c
|
(cond->> c
|
||||||
(not= "*" c)
|
(not= "*" c)
|
||||||
(q)
|
(q)
|
||||||
t
|
t
|
||||||
(str (q t) "."))))
|
(str (q t) ".")
|
||||||
|
f
|
||||||
|
(call f))))
|
||||||
|
|
||||||
(defn- format-selectable [x]
|
(defn- format-entity-alias [x]
|
||||||
(cond (sequential? x)
|
(cond (sequential? x)
|
||||||
(str (let [s (first x)]
|
(str (let [s (first x)]
|
||||||
(if (map? s)
|
(if (map? s)
|
||||||
(format-dsl s true)
|
(throw (ex-info "selectable cannot be statement!"
|
||||||
|
{:selectable s}))
|
||||||
(format-entity s)))
|
(format-entity s)))
|
||||||
#_" AS " " "
|
#_" AS " " "
|
||||||
(format-entity (second x)))
|
(format-entity (second x) {:aliased? true}))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(format-entity x)))
|
(format-entity x)))
|
||||||
|
|
||||||
(defn- format-selectable-dsl [x]
|
(defn- format-selectable-dsl [x & [{:keys [as? aliased?] :as opts}]]
|
||||||
(cond (map? x)
|
(cond (map? x)
|
||||||
(format-dsl x true)
|
(format-dsl x {:nested? true})
|
||||||
|
|
||||||
(sequential? x)
|
(sequential? x)
|
||||||
(let [s (first x)
|
(let [s (first x)
|
||||||
[sql & params] (if (map? s) (format-dsl s true) [(format-entity s)])]
|
a (second x)
|
||||||
(into [(str sql #_" AS " " " (format-entity (second x)))] params))
|
[sql & params] (if (map? s)
|
||||||
|
(format-dsl s {:nested? true})
|
||||||
|
(format-expr s))
|
||||||
|
[sql' & params'] (if (sequential? a)
|
||||||
|
(let [[sql params] (format-expr-list a {:aliased? true})]
|
||||||
|
(into [(str/join " " sql)] params))
|
||||||
|
(format-selectable-dsl a {:aliased? true}))]
|
||||||
|
(-> [(str sql (if as? " AS " " ") sql')]
|
||||||
|
(into params)
|
||||||
|
(into params')))
|
||||||
|
|
||||||
(keyword? x)
|
(or (keyword? x) (symbol? x))
|
||||||
[(format-entity x)]
|
[(format-entity x opts)]
|
||||||
|
|
||||||
|
(and aliased? (string? x))
|
||||||
|
[(format-entity x opts)]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(format-expr x)))
|
(format-expr x)))
|
||||||
|
|
@ -121,17 +149,55 @@
|
||||||
(map #'format-dsl xs))]
|
(map #'format-dsl xs))]
|
||||||
(into [(str/join (str " " (sql-kw k) " ") sqls)] params)))
|
(into [(str/join (str " " (sql-kw k) " ") sqls)] params)))
|
||||||
|
|
||||||
(defn- format-selector [k xs]
|
(defn- format-expr-list [xs & [opts]]
|
||||||
|
(reduce (fn [[sql params] [sql' & params']]
|
||||||
|
[(conj sql sql') (if params' (into params params') params)])
|
||||||
|
[[] []]
|
||||||
|
(map #(format-expr % opts) xs)))
|
||||||
|
|
||||||
|
(defn- format-columns [_ xs]
|
||||||
|
(let [[sqls params] (format-expr-list xs {:drop-ns? true})]
|
||||||
|
(into [(str "(" (str/join ", " sqls) ")")] params)))
|
||||||
|
|
||||||
|
(defn- format-selects [k xs]
|
||||||
(if (sequential? xs)
|
(if (sequential? xs)
|
||||||
(let [[sqls params]
|
(let [[sqls params]
|
||||||
(reduce (fn [[sql params] [sql' & params']]
|
(reduce (fn [[sql params] [sql' & params']]
|
||||||
[(conj sql sql') (if params' (into params params') params)])
|
[(conj sql sql') (if params' (into params params') params)])
|
||||||
[[] []]
|
[[] []]
|
||||||
(map #'format-selectable-dsl xs))]
|
(map #(format-selectable-dsl % {:as? (= k :select)}) xs))]
|
||||||
(into [(str (sql-kw k) " " (str/join ", " sqls))] params))
|
(into [(str (sql-kw k) " " (str/join ", " sqls))] params))
|
||||||
(let [[sql & params] (format-selectable-dsl xs)]
|
(let [[sql & params] (format-selectable-dsl xs {:as? (= k :select)})]
|
||||||
(into [(str (sql-kw k) " " sql)] params))))
|
(into [(str (sql-kw k) " " sql)] params))))
|
||||||
|
|
||||||
|
(defn- format-with-part [x]
|
||||||
|
(if (sequential? x)
|
||||||
|
(let [[sql & params] (format-dsl (second x))]
|
||||||
|
(into [(str (format-entity (first x)) " " sql)] params))
|
||||||
|
[(format-entity x)]))
|
||||||
|
|
||||||
|
(defn- format-with [k xs]
|
||||||
|
;; TODO: a sequence of pairs -- X AS expr -- where X is either [entity expr]
|
||||||
|
;; or just entity, as far as I can tell...
|
||||||
|
(let [[sqls params]
|
||||||
|
(reduce (fn [[sql params] [sql' & params']]
|
||||||
|
[(conj sql sql') (if params' (into params params') params)])
|
||||||
|
[[] []]
|
||||||
|
(map (fn [[x expr]]
|
||||||
|
(let [[sql & params] (format-with-part x)
|
||||||
|
[sql' & params'] (format-dsl expr)]
|
||||||
|
(cond-> [(str sql " AS "
|
||||||
|
(if (seq params')
|
||||||
|
(str "(" sql' ")")
|
||||||
|
sql'))]
|
||||||
|
params (into params)
|
||||||
|
params' (into params'))))
|
||||||
|
xs))]
|
||||||
|
(into [(str (sql-kw k) " " (str/join ", " sqls))] params)))
|
||||||
|
|
||||||
|
(defn- format-selector [k xs]
|
||||||
|
(format-selects k [xs]))
|
||||||
|
|
||||||
(defn- format-insert [k table]
|
(defn- format-insert [k table]
|
||||||
;; table can be just a table, a pair of table and statement, or a
|
;; table can be just a table, a pair of table and statement, or a
|
||||||
;; pair of a pair of table and columns and a statement (yikes!)
|
;; pair of a pair of table and columns and a statement (yikes!)
|
||||||
|
|
@ -139,24 +205,24 @@
|
||||||
(if (sequential? (first table))
|
(if (sequential? (first table))
|
||||||
(let [[[table cols] statement] table
|
(let [[[table cols] statement] table
|
||||||
[sql & params] (format-dsl statement)]
|
[sql & params] (format-dsl statement)]
|
||||||
(into [(str (sql-kw k) " " (format-selectable table)
|
(into [(str (sql-kw k) " " (format-entity-alias table)
|
||||||
" ("
|
" ("
|
||||||
(str/join ", " (map #'format-selectable cols))
|
(str/join ", " (map #'format-entity-alias cols))
|
||||||
") "
|
") "
|
||||||
sql)]
|
sql)]
|
||||||
params))
|
params))
|
||||||
(let [[table statement] table
|
(let [[table statement] table
|
||||||
[sql & params] (format-dsl statement)]
|
[sql & params] (format-dsl statement)]
|
||||||
(into [(str (sql-kw k) " " (format-selectable table)
|
(into [(str (sql-kw k) " " (format-entity-alias table)
|
||||||
" " sql)]
|
" " sql)]
|
||||||
params)))
|
params)))
|
||||||
[(str (sql-kw k) " " (format-selectable table))]))
|
[(str (sql-kw k) " " (format-entity-alias table))]))
|
||||||
|
|
||||||
(defn- format-join [k [j e]]
|
(defn- format-join [k [j e]]
|
||||||
(let [[sql & params] (format-expr e)]
|
(let [[sql & params] (format-expr e)]
|
||||||
;; for backward compatibility, treat plain JOIN as INNER JOIN:
|
;; for backward compatibility, treat plain JOIN as INNER JOIN:
|
||||||
(into [(str (sql-kw (if (= :join k) :inner-join k)) " "
|
(into [(str (sql-kw (if (= :join k) :inner-join k)) " "
|
||||||
(format-selectable j) " ON "
|
(format-entity-alias j) " ON "
|
||||||
sql)]
|
sql)]
|
||||||
params)))
|
params)))
|
||||||
|
|
||||||
|
|
@ -164,12 +230,6 @@
|
||||||
(let [[sql & params] (format-expr e)]
|
(let [[sql & params] (format-expr e)]
|
||||||
(into [(str (sql-kw k) " " sql)] params)))
|
(into [(str (sql-kw k) " " sql)] params)))
|
||||||
|
|
||||||
(defn- format-expr-list [xs]
|
|
||||||
(reduce (fn [[sql params] [sql' & params']]
|
|
||||||
[(conj sql sql') (if params' (into params params') params)])
|
|
||||||
[[] []]
|
|
||||||
(map #'format-expr xs)))
|
|
||||||
|
|
||||||
(defn- format-group-by [k xs]
|
(defn- format-group-by [k xs]
|
||||||
(let [[sqls params] (format-expr-list xs)]
|
(let [[sqls params] (format-expr-list xs)]
|
||||||
(into [(str (sql-kw k) " " (str/join ", " sqls))] params)))
|
(into [(str (sql-kw k) " " (str/join ", " sqls))] params)))
|
||||||
|
|
@ -184,7 +244,7 @@
|
||||||
dirs)))] params)))
|
dirs)))] params)))
|
||||||
|
|
||||||
(defn- format-values [k xs]
|
(defn- format-values [k xs]
|
||||||
(if (sequential? (first xs))
|
(cond (sequential? (first xs))
|
||||||
;; [[1 2 3] [4 5 6]]
|
;; [[1 2 3] [4 5 6]]
|
||||||
(let [[sqls params]
|
(let [[sqls params]
|
||||||
(reduce (fn [[sql params] [sqls' params']]
|
(reduce (fn [[sql params] [sqls' params']]
|
||||||
|
|
@ -193,13 +253,38 @@
|
||||||
[[] []]
|
[[] []]
|
||||||
(map #'format-expr-list xs))]
|
(map #'format-expr-list xs))]
|
||||||
(into [(str (sql-kw k) " " (str/join ", " sqls))] params))
|
(into [(str (sql-kw k) " " (str/join ", " sqls))] params))
|
||||||
;; [1 2 3]
|
|
||||||
(let [[sqls params] (format-expr-list xs)]
|
(map? (first xs))
|
||||||
(into [(str (sql-kw k) " (" (str/join ", " sqls) ")")] params))))
|
;; [{:a 1 :b 2 :c 3}]
|
||||||
|
(let [cols (keys (first xs))
|
||||||
|
[sqls params]
|
||||||
|
(reduce (fn [[sql params] [sqls' params']]
|
||||||
|
[(conj sql (str/join ", " sqls'))
|
||||||
|
(if params' (into params params') params')])
|
||||||
|
[[] []]
|
||||||
|
(map (fn [m]
|
||||||
|
(format-expr-list (map #(get m %) cols)))
|
||||||
|
xs))]
|
||||||
|
(into [(str "("
|
||||||
|
(str/join ", "
|
||||||
|
(map #(format-entity % {:drop-ns? true}) cols))
|
||||||
|
") "
|
||||||
|
(sql-kw k) " (" (str/join ", " sqls) ")")]
|
||||||
|
params))
|
||||||
|
|
||||||
|
:else
|
||||||
|
(throw (ex-info ":values expects sequences or maps"
|
||||||
|
{:first (first xs)}))))
|
||||||
|
|
||||||
(defn- format-set-exprs [k xs]
|
(defn- format-set-exprs [k xs]
|
||||||
;; TODO: !!!
|
(let [[sqls params]
|
||||||
["SET a = ?, b = ?" 42 13])
|
(reduce-kv (fn [[sql params] v e]
|
||||||
|
(let [[sql' & params'] (format-expr e)]
|
||||||
|
[(conj sql (str (format-entity v) " = " sql'))
|
||||||
|
(if params' (into params params') params)]))
|
||||||
|
[[] []]
|
||||||
|
xs)]
|
||||||
|
(into [(str (sql-kw k) " " (str/join ", " sqls))] params)))
|
||||||
|
|
||||||
(def ^:private current-clause-order
|
(def ^:private current-clause-order
|
||||||
"The (current) order for known clauses. Can have items added and removed."
|
"The (current) order for known clauses. Can have items added and removed."
|
||||||
|
|
@ -208,26 +293,28 @@
|
||||||
(def ^:private clause-format
|
(def ^:private clause-format
|
||||||
"The (default) behavior for each known clause. Can also have items added
|
"The (default) behavior for each known clause. Can also have items added
|
||||||
and removed."
|
and removed."
|
||||||
(atom {:intersect #'format-on-set-op
|
(atom {:with #'format-with
|
||||||
|
:with-recursive #'format-with
|
||||||
|
:intersect #'format-on-set-op
|
||||||
:union #'format-on-set-op
|
:union #'format-on-set-op
|
||||||
:union-all #'format-on-set-op
|
:union-all #'format-on-set-op
|
||||||
:except #'format-on-set-op
|
:except #'format-on-set-op
|
||||||
:select #'format-selector
|
:select #'format-selects
|
||||||
:insert-into #'format-insert
|
:insert-into #'format-insert
|
||||||
:update #'format-selector
|
:update #'format-selector
|
||||||
:delete #'format-selector
|
:delete #'format-selects
|
||||||
:delete-from #'format-selector
|
:delete-from #'format-selector
|
||||||
:truncate #'format-selector
|
:truncate #'format-selector
|
||||||
:columns #'format-selector
|
:columns #'format-columns
|
||||||
:set #'format-set-exprs
|
:set #'format-set-exprs
|
||||||
:from #'format-selector
|
:from #'format-selects
|
||||||
:join #'format-join
|
:join #'format-join
|
||||||
:left-join #'format-join
|
:left-join #'format-join
|
||||||
:right-join #'format-join
|
:right-join #'format-join
|
||||||
:inner-join #'format-join
|
:inner-join #'format-join
|
||||||
:outer-join #'format-join
|
:outer-join #'format-join
|
||||||
:full-join #'format-join
|
:full-join #'format-join
|
||||||
:cross-join #'format-selector
|
:cross-join #'format-selects
|
||||||
:where #'format-on-expr
|
:where #'format-on-expr
|
||||||
:group-by #'format-group-by
|
:group-by #'format-group-by
|
||||||
:having #'format-on-expr
|
:having #'format-on-expr
|
||||||
|
|
@ -239,8 +326,8 @@
|
||||||
(assert (= (set @current-clause-order) (set (keys @clause-format))))
|
(assert (= (set @current-clause-order) (set (keys @clause-format))))
|
||||||
|
|
||||||
(comment :target
|
(comment :target
|
||||||
{:with 20
|
{;:with 20
|
||||||
:with-recursive 30
|
;:with-recursive 30
|
||||||
;:intersect 35
|
;:intersect 35
|
||||||
;:union 40
|
;:union 40
|
||||||
;:union-all 45
|
;:union-all 45
|
||||||
|
|
@ -253,15 +340,15 @@
|
||||||
;:truncate 85
|
;:truncate 85
|
||||||
;:columns 90
|
;:columns 90
|
||||||
:composite 95
|
:composite 95
|
||||||
:set0 100 ; low-priority set clause
|
;; no longer needed/supported :set0 100 ; low-priority set clause
|
||||||
;:from 110
|
;:from 110
|
||||||
;:join 120
|
;:join 120
|
||||||
;:left-join 130
|
;:left-join 130
|
||||||
;:right-join 140
|
;:right-join 140
|
||||||
;:full-join 150
|
;:full-join 150
|
||||||
;:cross-join 152 ; doesn't have on clauses
|
;:cross-join 152 ; doesn't have on clauses
|
||||||
:set 155
|
;:set 155
|
||||||
:set1 156 ; high-priority set clause (synonym for :set)
|
;; no longer needed/supported :set1 156 ; high-priority set clause (synonym for :set)
|
||||||
;:where 160
|
;:where 160
|
||||||
;:group-by 170
|
;:group-by 170
|
||||||
;:having 180
|
;:having 180
|
||||||
|
|
@ -269,10 +356,10 @@
|
||||||
;:limit 200
|
;:limit 200
|
||||||
;:offset 210
|
;:offset 210
|
||||||
:lock 215
|
:lock 215
|
||||||
:values 220
|
;:values 220
|
||||||
:query-values 230})
|
:query-values 230})
|
||||||
|
|
||||||
(defn- format-dsl [x & [nested?]]
|
(defn- format-dsl [x & [{:keys [aliased? nested?]}]]
|
||||||
(let [[sqls params leftover]
|
(let [[sqls params leftover]
|
||||||
(reduce (fn [[sql params leftover] k]
|
(reduce (fn [[sql params leftover] k]
|
||||||
(if-let [xs (k x)]
|
(if-let [xs (k x)]
|
||||||
|
|
@ -294,7 +381,8 @@
|
||||||
leftover))
|
leftover))
|
||||||
[(str "<unknown" (str/join (keys leftover)) ">")])
|
[(str "<unknown" (str/join (keys leftover)) ">")])
|
||||||
(into [(cond-> (str/join " " sqls)
|
(into [(cond-> (str/join " " sqls)
|
||||||
nested? (as-> s (str "(" s ")")))] params))))
|
(and nested? (not aliased?))
|
||||||
|
(as-> s (str "(" s ")")))] params))))
|
||||||
|
|
||||||
(def ^:private infix-aliases
|
(def ^:private infix-aliases
|
||||||
"Provided for backward compatibility with earlier HoneySQL versions."
|
"Provided for backward compatibility with earlier HoneySQL versions."
|
||||||
|
|
@ -316,9 +404,9 @@
|
||||||
(def ^:private special-syntax
|
(def ^:private special-syntax
|
||||||
{:between
|
{:between
|
||||||
(fn [[x a b]]
|
(fn [[x a b]]
|
||||||
(let [[sql-x & params-x] (format-expr x true)
|
(let [[sql-x & params-x] (format-expr x {:nested? true})
|
||||||
[sql-a & params-a] (format-expr a true)
|
[sql-a & params-a] (format-expr a {:nested? true})
|
||||||
[sql-b & params-b] (format-expr b true)]
|
[sql-b & params-b] (format-expr b {:nested? true})]
|
||||||
(-> [(str sql-x " BETWEEN " sql-a " AND " sql-b)]
|
(-> [(str sql-x " BETWEEN " sql-a " AND " sql-b)]
|
||||||
(into params-x)
|
(into params-x)
|
||||||
(into params-a)
|
(into params-a)
|
||||||
|
|
@ -332,20 +420,20 @@
|
||||||
(let [[sql & params] (format-expr n)]
|
(let [[sql & params] (format-expr n)]
|
||||||
(into [(str "INTERVAL " sql " " (sql-kw units))] params)))})
|
(into [(str "INTERVAL " sql " " (sql-kw units))] params)))})
|
||||||
|
|
||||||
(defn format-expr [x & [nested?]]
|
(defn format-expr [x & [{:keys [nested?] :as opts}]]
|
||||||
(cond (keyword? x)
|
(cond (or (keyword? x) (symbol? x))
|
||||||
[(format-entity x)]
|
[(format-entity x opts)]
|
||||||
|
|
||||||
(map? x)
|
(map? x)
|
||||||
(format-dsl x true)
|
(format-dsl x (assoc opts :nested? true))
|
||||||
|
|
||||||
(sequential? x)
|
(sequential? x)
|
||||||
(let [op (first x)]
|
(let [op (first x)]
|
||||||
(if (keyword? op)
|
(if (keyword? op)
|
||||||
(cond (infix-ops op)
|
(cond (infix-ops op)
|
||||||
(let [[_ a b] x
|
(let [[_ a b] x
|
||||||
[s1 & p1] (format-expr a true)
|
[s1 & p1] (format-expr a {:nested? true})
|
||||||
[s2 & p2] (format-expr b true)]
|
[s2 & p2] (format-expr b {:nested? true})]
|
||||||
(-> (str s1 " "
|
(-> (str s1 " "
|
||||||
(sql-kw (get infix-aliases op op))
|
(sql-kw (get infix-aliases op op))
|
||||||
" " s2)
|
" " s2)
|
||||||
|
|
@ -358,14 +446,22 @@
|
||||||
(let [formatter (special-syntax op)]
|
(let [formatter (special-syntax op)]
|
||||||
(formatter (rest x)))
|
(formatter (rest x)))
|
||||||
:else
|
:else
|
||||||
(let [[sqls params] (format-expr-list (rest x))]
|
(let [args (rest x)
|
||||||
|
[sqls params] (format-expr-list args)]
|
||||||
(into [(str (sql-kw op)
|
(into [(str (sql-kw op)
|
||||||
"(" (str/join ", " sqls) ")")]
|
(if (and (= 1 (count args))
|
||||||
|
(map? (first args))
|
||||||
|
(= 1 (count sqls)))
|
||||||
|
(str " " (first sqls))
|
||||||
|
(str "(" (str/join ", " sqls) ")")))]
|
||||||
params)))
|
params)))
|
||||||
(into [(str "(" (str/join ", "
|
(into [(str "(" (str/join ", "
|
||||||
(repeat (count x) "?")) ")")]
|
(repeat (count x) "?")) ")")]
|
||||||
x)))
|
x)))
|
||||||
|
|
||||||
|
(boolean? x)
|
||||||
|
[(upper-case (str x))]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
["?" x]))
|
["?" x]))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
(deftest mysql-tests
|
(deftest mysql-tests
|
||||||
(is (= ["SELECT * FROM `table` WHERE `id` = ?" 1]
|
(is (= ["SELECT * FROM `table` WHERE `id` = ?" 1]
|
||||||
(#'sut/format {:select [:*] :from [:table] :where [:= :id 1]}
|
(sut/format {:select [:*] :from [:table] :where [:= :id 1]}
|
||||||
{:dialect :mysql}))))
|
{:dialect :mysql}))))
|
||||||
|
|
||||||
(deftest expr-tests
|
(deftest expr-tests
|
||||||
|
|
@ -33,24 +33,24 @@
|
||||||
|
|
||||||
(deftest general-tests
|
(deftest general-tests
|
||||||
(is (= ["SELECT * FROM \"table\" WHERE \"id\" = ?" 1]
|
(is (= ["SELECT * FROM \"table\" WHERE \"id\" = ?" 1]
|
||||||
(#'sut/format {:select [:*] :from [:table] :where [:= :id 1]} {:quoted true})))
|
(sut/format {:select [:*] :from [:table] :where [:= :id 1]} {:quoted true})))
|
||||||
;; temporarily remove AS from alias here
|
;; temporarily remove AS from alias here
|
||||||
(is (= ["SELECT \"t\".* FROM \"table\" \"t\" WHERE \"id\" = ?" 1]
|
(is (= ["SELECT \"t\".* FROM \"table\" \"t\" WHERE \"id\" = ?" 1]
|
||||||
(#'sut/format {:select [:t.*] :from [[:table :t]] :where [:= :id 1]} {:quoted true})))
|
(sut/format {:select [:t.*] :from [[:table :t]] :where [:= :id 1]} {:quoted true})))
|
||||||
(is (= ["SELECT * FROM \"table\" GROUP BY \"foo\", \"bar\""]
|
(is (= ["SELECT * FROM \"table\" GROUP BY \"foo\", \"bar\""]
|
||||||
(#'sut/format {:select [:*] :from [:table] :group-by [:foo :bar]} {:quoted true})))
|
(sut/format {:select [:*] :from [:table] :group-by [:foo :bar]} {:quoted true})))
|
||||||
(is (= ["SELECT * FROM \"table\" GROUP BY DATE(\"bar\")"]
|
(is (= ["SELECT * FROM \"table\" GROUP BY DATE(\"bar\")"]
|
||||||
(#'sut/format {:select [:*] :from [:table] :group-by [[:date :bar]]} {:quoted true})))
|
(sut/format {:select [:*] :from [:table] :group-by [[:date :bar]]} {:quoted true})))
|
||||||
(is (= ["SELECT * FROM \"table\" ORDER BY \"foo\" DESC, \"bar\" ASC"]
|
(is (= ["SELECT * FROM \"table\" ORDER BY \"foo\" DESC, \"bar\" ASC"]
|
||||||
(#'sut/format {:select [:*] :from [:table] :order-by [[:foo :desc] :bar]} {:quoted true})))
|
(sut/format {:select [:*] :from [:table] :order-by [[:foo :desc] :bar]} {:quoted true})))
|
||||||
(is (= ["SELECT * FROM \"table\" ORDER BY DATE(\"expiry\") DESC, \"bar\" ASC"]
|
(is (= ["SELECT * FROM \"table\" ORDER BY DATE(\"expiry\") DESC, \"bar\" ASC"]
|
||||||
(#'sut/format {:select [:*] :from [:table] :order-by [[[:date :expiry] :desc] :bar]} {:quoted true})))
|
(sut/format {:select [:*] :from [:table] :order-by [[[:date :expiry] :desc] :bar]} {:quoted true})))
|
||||||
(is (= ["SELECT * FROM \"table\" WHERE DATE_ADD(\"expiry\", INTERVAL ? DAYS) < NOW()" 30]
|
(is (= ["SELECT * FROM \"table\" WHERE DATE_ADD(\"expiry\", INTERVAL ? DAYS) < NOW()" 30]
|
||||||
(#'sut/format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval 30 :days]] [:now]]} {:quoted true})))
|
(sut/format {:select [:*] :from [:table] :where [:< [:date_add :expiry [:interval 30 :days]] [:now]]} {:quoted true})))
|
||||||
(is (= ["SELECT * FROM `table` WHERE `id` = ?" 1]
|
(is (= ["SELECT * FROM `table` WHERE `id` = ?" 1]
|
||||||
(#'sut/format {:select [:*] :from [:table] :where [:= :id 1]} {:dialect :mysql})))
|
(sut/format {:select [:*] :from [:table] :where [:= :id 1]} {:dialect :mysql})))
|
||||||
(is (= ["SELECT * FROM \"table\" WHERE \"id\" IN (?, ?, ?, ?)" 1 2 3 4]
|
(is (= ["SELECT * FROM \"table\" WHERE \"id\" IN (?, ?, ?, ?)" 1 2 3 4]
|
||||||
(#'sut/format {:select [:*] :from [:table] :where [:in :id [1 2 3 4]]} {:quoted true}))))
|
(sut/format {:select [:*] :from [:table] :where [:in :id [1 2 3 4]]} {:quoted true}))))
|
||||||
|
|
||||||
;; tests lifted from HoneySQL v1 to check for compatibility
|
;; tests lifted from HoneySQL v1 to check for compatibility
|
||||||
|
|
||||||
|
|
@ -105,8 +105,12 @@
|
||||||
["INSERT INTO foo (id) VALUES (?)" 2])))
|
["INSERT INTO foo (id) VALUES (?)" 2])))
|
||||||
|
|
||||||
(deftest exists-test
|
(deftest exists-test
|
||||||
(is (= (format {:exists {:select [:a] :from [:foo]}})
|
;; EXISTS should never have been implemented as SQL syntax: it's an operator!
|
||||||
|
#_(is (= (format {:exists {:select [:a] :from [:foo]}})
|
||||||
["EXISTS (SELECT a FROM foo)"]))
|
["EXISTS (SELECT a FROM foo)"]))
|
||||||
|
;; ugly because it's hard to select just a function call without an alias:
|
||||||
|
(is (= (format {:select [[[:exists {:select [:a] :from [:foo]}] :x]]})
|
||||||
|
["SELECT EXISTS (SELECT a FROM foo) AS x"]))
|
||||||
(is (= (format {:select [:id]
|
(is (= (format {:select [:id]
|
||||||
:from [:foo]
|
:from [:foo]
|
||||||
:where [:exists {:select [1]
|
:where [:exists {:select [1]
|
||||||
|
|
@ -115,12 +119,12 @@
|
||||||
["SELECT id FROM foo WHERE EXISTS (SELECT ? FROM bar WHERE deleted)" 1])))
|
["SELECT id FROM foo WHERE EXISTS (SELECT ? FROM bar WHERE deleted)" 1])))
|
||||||
|
|
||||||
(deftest array-test
|
(deftest array-test
|
||||||
(println 'sql-array :unimplemented)
|
(is nil "sql-array unimplemented")
|
||||||
#_(is (= (format {:insert-into :foo
|
#_(is (= (format {:insert-into :foo
|
||||||
:columns [:baz]
|
:columns [:baz]
|
||||||
:values [[(sql/array [1 2 3 4])]]})
|
:values [[(sql/array [1 2 3 4])]]})
|
||||||
["INSERT INTO foo (baz) VALUES (ARRAY[?, ?, ?, ?])" 1 2 3 4]))
|
["INSERT INTO foo (baz) VALUES (ARRAY[?, ?, ?, ?])" 1 2 3 4]))
|
||||||
(println 'sql-array :unimplemented)
|
(is nil "sql-array unimplemented")
|
||||||
#_(is (= (format {:insert-into :foo
|
#_(is (= (format {:insert-into :foo
|
||||||
:columns [:baz]
|
:columns [:baz]
|
||||||
:values [[(sql/array ["one" "two" "three"])]]})
|
:values [[(sql/array ["one" "two" "three"])]]})
|
||||||
|
|
@ -135,7 +139,15 @@
|
||||||
;; ORDER BY foo ASC
|
;; ORDER BY foo ASC
|
||||||
(is (= (format {:union [{:select [:foo] :from [:bar1]}
|
(is (= (format {:union [{:select [:foo] :from [:bar1]}
|
||||||
{:select [:foo] :from [:bar2]}]})
|
{:select [:foo] :from [:bar2]}]})
|
||||||
["SELECT foo FROM bar1 UNION SELECT foo FROM bar2"])))
|
["SELECT foo FROM bar1 UNION SELECT foo FROM bar2"]))
|
||||||
|
|
||||||
|
(testing "union complex values"
|
||||||
|
(is (= (format {:union [{:select [:foo] :from [:bar1]}
|
||||||
|
{:select [:foo] :from [:bar2]}]
|
||||||
|
:with [[[:bar {:columns [:spam :eggs]}]
|
||||||
|
{:values [[1 2] [3 4] [5 6]]}]]})
|
||||||
|
["WITH bar (spam, eggs) AS (VALUES (?, ?), (?, ?), (?, ?)) SELECT foo FROM bar1 UNION SELECT foo FROM bar2"
|
||||||
|
1 2 3 4 5 6]))))
|
||||||
|
|
||||||
(deftest union-all-test
|
(deftest union-all-test
|
||||||
(is (= (format {:union-all [{:select [:foo] :from [:bar1]}
|
(is (= (format {:union-all [{:select [:foo] :from [:bar1]}
|
||||||
|
|
@ -168,7 +180,7 @@
|
||||||
|
|
||||||
(deftest compare-expressions-test
|
(deftest compare-expressions-test
|
||||||
(testing "Sequences should be fns when in value/comparison spots"
|
(testing "Sequences should be fns when in value/comparison spots"
|
||||||
(is (= ["SELECT foo FROM bar WHERE (col1 mod ?) = (col2 + ?)" 4 4]
|
(is (= ["SELECT foo FROM bar WHERE (col1 MOD ?) = (col2 + ?)" 4 4]
|
||||||
(format {:select [:foo]
|
(format {:select [:foo]
|
||||||
:from [:bar]
|
:from [:bar]
|
||||||
:where [:= [:mod :col1 4] [:+ :col2 4]]}))))
|
:where [:= [:mod :col1 4] [:+ :col2 4]]}))))
|
||||||
|
|
@ -177,11 +189,11 @@
|
||||||
(let [sub {:select [:%sum.amount]
|
(let [sub {:select [:%sum.amount]
|
||||||
:from [:bar]
|
:from [:bar]
|
||||||
:where [:in :id ["id-1" "id-2"]]}]
|
:where [:in :id ["id-1" "id-2"]]}]
|
||||||
(is (= ["SELECT total FROM foo WHERE (SELECT sum(amount) FROM bar WHERE (id in (?, ?))) = total" "id-1" "id-2"]
|
(is (= ["SELECT total FROM foo WHERE (SELECT sum(amount) FROM bar WHERE id IN (?, ?)) = total" "id-1" "id-2"]
|
||||||
(format {:select [:total]
|
(format {:select [:total]
|
||||||
:from [:foo]
|
:from [:foo]
|
||||||
:where [:= sub :total]})))
|
:where [:= sub :total]})))
|
||||||
(is (= ["WITH t AS (SELECT sum(amount) FROM bar WHERE (id in (?, ?))) SELECT total FROM foo WHERE total = t" "id-1" "id-2"]
|
(is (= ["WITH t AS (SELECT sum(amount) FROM bar WHERE id IN (?, ?)) SELECT total FROM foo WHERE total = t" "id-1" "id-2"]
|
||||||
(format {:with [[:t sub]]
|
(format {:with [[:t sub]]
|
||||||
:select [:total]
|
:select [:total]
|
||||||
:from [:foo]
|
:from [:foo]
|
||||||
|
|
@ -204,7 +216,7 @@
|
||||||
|
|
||||||
(deftest parameterizer-none
|
(deftest parameterizer-none
|
||||||
(testing "array parameter"
|
(testing "array parameter"
|
||||||
(println 'sql-array :unimplemented)
|
(is nil "sql-array unimplemented")
|
||||||
#_(is (= (format {:insert-into :foo
|
#_(is (= (format {:insert-into :foo
|
||||||
:columns [:baz]
|
:columns [:baz]
|
||||||
:values [[(sql/array [1 2 3 4])]]}
|
:values [[(sql/array [1 2 3 4])]]}
|
||||||
|
|
@ -250,7 +262,7 @@
|
||||||
:from [[:bar :b]]
|
:from [[:bar :b]]
|
||||||
:where [:= :b.id 1]} :c]]
|
:where [:= :b.id 1]} :c]]
|
||||||
:where [:= :f.kind "drama"]}
|
:where [:= :f.kind "drama"]}
|
||||||
(format)))))
|
(format {:quoted true})))))
|
||||||
|
|
||||||
(deftest set-after-join
|
(deftest set-after-join
|
||||||
(is (=
|
(is (=
|
||||||
|
|
@ -282,7 +294,7 @@
|
||||||
(format {:dialect :mysql})))))
|
(format {:dialect :mysql})))))
|
||||||
|
|
||||||
(deftest inlined-values-are-stringified-correctly
|
(deftest inlined-values-are-stringified-correctly
|
||||||
(println 'inline :unimplemented)
|
(is nil "inline unimplemented")
|
||||||
#_(is (= ["SELECT foo, bar, NULL"]
|
#_(is (= ["SELECT foo, bar, NULL"]
|
||||||
(format {:select [(honeysql.core/inline "foo")
|
(format {:select [(honeysql.core/inline "foo")
|
||||||
(honeysql.core/inline :bar)
|
(honeysql.core/inline :bar)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue