Merge pull request #545 from alexander-yakushev/perf-opt
Introduce more efficient implementations of str and join
This commit is contained in:
commit
8c93e287ff
3 changed files with 229 additions and 106 deletions
|
|
@ -27,10 +27,11 @@
|
||||||
and optionally set a global `:quoted` option.
|
and optionally set a global `:quoted` option.
|
||||||
* `sql-kw` -- turns a Clojure keyword (or symbol) into SQL code (makes
|
* `sql-kw` -- turns a Clojure keyword (or symbol) into SQL code (makes
|
||||||
it uppercase and replaces - with space). "
|
it uppercase and replaces - with space). "
|
||||||
(:refer-clojure :exclude [format])
|
(:refer-clojure :exclude [format str])
|
||||||
(:require [clojure.string :as str]
|
(:require [clojure.string :as str]
|
||||||
#?(:clj [clojure.template])
|
#?(:clj [clojure.template])
|
||||||
[honey.sql.protocols :as p]))
|
[honey.sql.protocols :as p]
|
||||||
|
[honey.sql.util :refer [str join]]))
|
||||||
|
|
||||||
;; default formatting for known clauses
|
;; default formatting for known clauses
|
||||||
|
|
||||||
|
|
@ -317,7 +318,7 @@
|
||||||
[%]
|
[%]
|
||||||
(str/split % #"\."))))
|
(str/split % #"\."))))
|
||||||
parts (parts-fn col-e)
|
parts (parts-fn col-e)
|
||||||
entity (str/join "." (map #(cond-> % (not= "*" %) (quote-fn)) parts))]
|
entity (join "." (map #(cond-> % (not= "*" %) (quote-fn))) parts)]
|
||||||
(suspicious-entity-check entity)
|
(suspicious-entity-check entity)
|
||||||
entity))
|
entity))
|
||||||
|
|
||||||
|
|
@ -376,7 +377,7 @@
|
||||||
#?(:cljs Symbol :default clojure.lang.Symbol)
|
#?(:cljs Symbol :default clojure.lang.Symbol)
|
||||||
(sqlize [x] (sql-kw x))
|
(sqlize [x] (sql-kw x))
|
||||||
#?(:cljs PersistentVector :default clojure.lang.IPersistentVector)
|
#?(:cljs PersistentVector :default clojure.lang.IPersistentVector)
|
||||||
(sqlize [x] (str "[" (str/join ", " (map p/sqlize x)) "]"))
|
(sqlize [x] (str "[" (join ", " (map p/sqlize) x) "]"))
|
||||||
#?@(:clj [java.util.UUID
|
#?@(:clj [java.util.UUID
|
||||||
;; issue 385: quoted UUIDs for PostgreSQL/ANSI
|
;; issue 385: quoted UUIDs for PostgreSQL/ANSI
|
||||||
(sqlize [x] (str \' x \'))])
|
(sqlize [x] (str \' x \'))])
|
||||||
|
|
@ -420,10 +421,10 @@
|
||||||
;; qualified column names can be used:
|
;; qualified column names can be used:
|
||||||
(let [c (cond-> (str x) (keyword? x) (subs 1))]
|
(let [c (cond-> (str x) (keyword? x) (subs 1))]
|
||||||
(cond (= \% (first c))
|
(cond (= \% (first c))
|
||||||
(let [[f & args] (str/split (subs c 1) #"\.")
|
(let [[f & args] (str/split (subs c 1) #"\.")]
|
||||||
quoted-args (map #(format-entity (keyword %) opts) args)]
|
[(str (format-fn-name f) "("
|
||||||
[(str (format-fn-name f)
|
(join ", " (map #(format-entity (keyword %) opts)) args)
|
||||||
"(" (str/join ", " quoted-args) ")")])
|
")")])
|
||||||
(= \? (first c))
|
(= \? (first c))
|
||||||
(let [k (keyword (subs c 1))]
|
(let [k (keyword (subs c 1))]
|
||||||
(cond *inline*
|
(cond *inline*
|
||||||
|
|
@ -483,7 +484,7 @@
|
||||||
(cond (and (ident? k) (= "except" (name k)) arg)
|
(cond (and (ident? k) (= "except" (name k)) arg)
|
||||||
(let [[sqls params]
|
(let [[sqls params]
|
||||||
(format-expr-list arg {:aliased true})]
|
(format-expr-list arg {:aliased true})]
|
||||||
[(str (sql-kw k) " (" (str/join ", " sqls) ")")
|
[(str (sql-kw k) " (" (join ", " sqls) ")")
|
||||||
params])
|
params])
|
||||||
(and (ident? k) (= "replace" (name k)) arg)
|
(and (ident? k) (= "replace" (name k)) arg)
|
||||||
(let [[sql & params] (format-selects-common nil true arg)]
|
(let [[sql & params] (format-selects-common nil true arg)]
|
||||||
|
|
@ -551,7 +552,7 @@
|
||||||
(into params params')
|
(into params params')
|
||||||
more
|
more
|
||||||
fmt))
|
fmt))
|
||||||
(into [(str/join " " sqls)] params)))))
|
(into [(join " " sqls)] params)))))
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
(format-temporal [:for :some-time :all])
|
(format-temporal [:for :some-time :all])
|
||||||
|
|
@ -587,7 +588,7 @@
|
||||||
:end-line :end-column]
|
:end-line :end-column]
|
||||||
*ignored-metadata*)))]
|
*ignored-metadata*)))]
|
||||||
(when (seq items)
|
(when (seq items)
|
||||||
(str/join (str sep " ") (mapv sql-kw items))))))
|
(join (str sep " ") (map sql-kw) items)))))
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
(format-meta ^{:foo true :bar :baz :original {:line 1} :top 10} [])
|
(format-meta ^{:foo true :bar :baz :original {:line 1} :top 10} [])
|
||||||
|
|
@ -615,7 +616,7 @@
|
||||||
[sql' & params'] (when alias
|
[sql' & params'] (when alias
|
||||||
(if (sequential? alias)
|
(if (sequential? alias)
|
||||||
(let [[sqls params] (format-expr-list alias {:aliased true})]
|
(let [[sqls params] (format-expr-list alias {:aliased true})]
|
||||||
(into [(str/join " " sqls)] params))
|
(into [(join " " sqls)] params))
|
||||||
(format-selectable-dsl alias {:aliased true})))
|
(format-selectable-dsl alias {:aliased true})))
|
||||||
[sql'' & params''] (when temporal
|
[sql'' & params''] (when temporal
|
||||||
(format-temporal temporal))]
|
(format-temporal temporal))]
|
||||||
|
|
@ -665,7 +666,7 @@
|
||||||
|
|
||||||
(defn- format-on-set-op [k xs]
|
(defn- format-on-set-op [k xs]
|
||||||
(let [[sqls params] (reduce-sql (map #(format-dsl %) xs))]
|
(let [[sqls params] (reduce-sql (map #(format-dsl %) xs))]
|
||||||
(into [(str/join (str " " (sql-kw k) " ") sqls)] params)))
|
(into [(join (str " " (sql-kw k) " ") sqls)] params)))
|
||||||
|
|
||||||
(defn- inline-kw?
|
(defn- inline-kw?
|
||||||
"Return true if the expression should be treated as an inline SQL keeyword."
|
"Return true if the expression should be treated as an inline SQL keeyword."
|
||||||
|
|
@ -741,7 +742,7 @@
|
||||||
(contains-clause? :replace-into)))
|
(contains-clause? :replace-into)))
|
||||||
[]
|
[]
|
||||||
(let [[sqls params] (format-expr-list xs {:drop-ns true})]
|
(let [[sqls params] (format-expr-list xs {:drop-ns true})]
|
||||||
(into [(str "(" (str/join ", " sqls) ")")] params))))
|
(into [(str "(" (join ", " sqls) ")")] params))))
|
||||||
|
|
||||||
(defn- format-selects-common [prefix as xs]
|
(defn- format-selects-common [prefix as xs]
|
||||||
(let [qualifier (format-meta xs)
|
(let [qualifier (format-meta xs)
|
||||||
|
|
@ -754,7 +755,7 @@
|
||||||
(when (empty? xs)
|
(when (empty? xs)
|
||||||
(throw (ex-info (str prefix " empty column list is illegal")
|
(throw (ex-info (str prefix " empty column list is illegal")
|
||||||
{:clause (into [prefix] xs)}))))
|
{:clause (into [prefix] xs)}))))
|
||||||
(into [(str (when prefix (str prefix " ")) (str/join ", " sqls))] params))
|
(into [(str (when prefix (str prefix " ")) (join ", " sqls))] params))
|
||||||
(let [[sql & params] (format-selectable-dsl xs {:as as})]
|
(let [[sql & params] (format-selectable-dsl xs {:as as})]
|
||||||
(into [(str (when prefix (str prefix " ")) sql)] params)))))
|
(into [(str (when prefix (str prefix " ")) sql)] params)))))
|
||||||
|
|
||||||
|
|
@ -800,7 +801,7 @@
|
||||||
(format-selects-common
|
(format-selects-common
|
||||||
(str (sql-kw k) "(" sql ")"
|
(str (sql-kw k) "(" sql ")"
|
||||||
(when (seq parts) " ")
|
(when (seq parts) " ")
|
||||||
(str/join " " (map sql-kw parts)))
|
(join " " (map sql-kw) parts))
|
||||||
true
|
true
|
||||||
cols)]
|
cols)]
|
||||||
(-> [sql'] (into params) (into params'))))
|
(-> [sql'] (into params) (into params'))))
|
||||||
|
|
@ -849,7 +850,7 @@
|
||||||
params (into params)
|
params (into params)
|
||||||
params' (into params')))))
|
params' (into params')))))
|
||||||
xs))]
|
xs))]
|
||||||
(into [(str (sql-kw k) " " (str/join ", " sqls))] params)))
|
(into [(str (sql-kw k) " " (join ", " sqls))] params)))
|
||||||
|
|
||||||
(defn- format-selector [k xs]
|
(defn- format-selector [k xs]
|
||||||
(format-selects k [xs]))
|
(format-selects k [xs]))
|
||||||
|
|
@ -881,7 +882,7 @@
|
||||||
" "
|
" "
|
||||||
(cond (seq cols)
|
(cond (seq cols)
|
||||||
(str "("
|
(str "("
|
||||||
(str/join ", " c-sqls)
|
(join ", " c-sqls)
|
||||||
") ")
|
") ")
|
||||||
(seq cols')
|
(seq cols')
|
||||||
(str cols-sql' " "))
|
(str cols-sql' " "))
|
||||||
|
|
@ -897,7 +898,7 @@
|
||||||
[c-sqls c-params] (reduce-sql (map #'format-entity-alias cols))]
|
[c-sqls c-params] (reduce-sql (map #'format-entity-alias cols))]
|
||||||
(-> [(str (sql-kw k) " " t-sql
|
(-> [(str (sql-kw k) " " t-sql
|
||||||
" ("
|
" ("
|
||||||
(str/join ", " c-sqls)
|
(join ", " c-sqls)
|
||||||
")"
|
")"
|
||||||
overriding)]
|
overriding)]
|
||||||
(into t-params)
|
(into t-params)
|
||||||
|
|
@ -937,7 +938,7 @@
|
||||||
[(conj sqls
|
[(conj sqls
|
||||||
"USING"
|
"USING"
|
||||||
(str "("
|
(str "("
|
||||||
(str/join ", " u-sqls)
|
(join ", " u-sqls)
|
||||||
")"))
|
")"))
|
||||||
(-> params (into params-j) (into u-params))])
|
(-> params (into params-j) (into u-params))])
|
||||||
(let [[sql & params'] (when e (format-expr e))]
|
(let [[sql & params'] (when e (format-expr e))]
|
||||||
|
|
@ -947,7 +948,7 @@
|
||||||
(into params'))]))))
|
(into params'))]))))
|
||||||
[[] []]
|
[[] []]
|
||||||
(partition-all 2 clauses))]
|
(partition-all 2 clauses))]
|
||||||
(into [(str/join " " sqls)] params)))
|
(into [(join " " sqls)] params)))
|
||||||
|
|
||||||
(def ^:private join-by-aliases
|
(def ^:private join-by-aliases
|
||||||
"Map of shorthand to longhand join names."
|
"Map of shorthand to longhand join names."
|
||||||
|
|
@ -989,7 +990,7 @@
|
||||||
[(conj sqls sql') (into params params')])))
|
[(conj sqls sql') (into params params')])))
|
||||||
[[] []]
|
[[] []]
|
||||||
(partition 2 joins))]
|
(partition 2 joins))]
|
||||||
(into [(str/join " " sqls)] params))))
|
(into [(join " " sqls)] params))))
|
||||||
|
|
||||||
(defn- format-on-expr [k e]
|
(defn- format-on-expr [k e]
|
||||||
(if (or (not (sequential? e)) (seq e))
|
(if (or (not (sequential? e)) (seq e))
|
||||||
|
|
@ -999,7 +1000,7 @@
|
||||||
|
|
||||||
(defn- format-group-by [k xs]
|
(defn- format-group-by [k xs]
|
||||||
(let [[sqls params] (format-expr-list (ensure-sequential xs))]
|
(let [[sqls params] (format-expr-list (ensure-sequential xs))]
|
||||||
(into [(str (sql-kw k) " " (str/join ", " sqls))] params)))
|
(into [(str (sql-kw k) " " (join ", " sqls))] params)))
|
||||||
|
|
||||||
(defn- format-order-by [k xs]
|
(defn- format-order-by [k xs]
|
||||||
(let [xs (ensure-sequential xs)
|
(let [xs (ensure-sequential xs)
|
||||||
|
|
@ -1007,10 +1008,10 @@
|
||||||
[sqls params]
|
[sqls params]
|
||||||
(format-expr-list (map #(if (sequential? %) (first %) %) xs))]
|
(format-expr-list (map #(if (sequential? %) (first %) %) xs))]
|
||||||
(into [(str (sql-kw k) " "
|
(into [(str (sql-kw k) " "
|
||||||
(str/join ", " (map (fn [sql dir]
|
(join ", " (map (fn [sql dir]
|
||||||
(str sql " " (sql-kw (or dir :asc))))
|
(str sql " " (sql-kw (or dir :asc))))
|
||||||
sqls
|
sqls
|
||||||
dirs)))] params)))
|
dirs)))] params)))
|
||||||
|
|
||||||
(defn- format-lock-strength [k xs]
|
(defn- format-lock-strength [k xs]
|
||||||
(let [[strength tables nowait] (ensure-sequential xs)]
|
(let [[strength tables nowait] (ensure-sequential xs)]
|
||||||
|
|
@ -1022,7 +1023,7 @@
|
||||||
(str " " (sql-kw tables))
|
(str " " (sql-kw tables))
|
||||||
(sequential? tables)
|
(sequential? tables)
|
||||||
(str " OF "
|
(str " OF "
|
||||||
(str/join ", " (map #'format-entity tables)))
|
(join ", " (map #'format-entity) tables))
|
||||||
:else
|
:else
|
||||||
(str " OF " (format-entity tables)))
|
(str " OF " (format-entity tables)))
|
||||||
(when nowait
|
(when nowait
|
||||||
|
|
@ -1040,8 +1041,7 @@
|
||||||
cols (if (= (set cols-1) cols-n) cols-1 cols-n)]
|
cols (if (= (set cols-1) cols-n) cols-1 cols-n)]
|
||||||
[cols (when-not skip-cols-sql
|
[cols (when-not skip-cols-sql
|
||||||
(str "("
|
(str "("
|
||||||
(str/join ", "
|
(join ", " (map #(format-entity % {:drop-ns true})) cols)
|
||||||
(map #(format-entity % {:drop-ns true}) cols))
|
|
||||||
")"))]))))
|
")"))]))))
|
||||||
|
|
||||||
(defn- format-values [k xs]
|
(defn- format-values [k xs]
|
||||||
|
|
@ -1066,7 +1066,7 @@
|
||||||
(reduce (fn [[sql params] [sqls' params']]
|
(reduce (fn [[sql params] [sqls' params']]
|
||||||
[(conj sql
|
[(conj sql
|
||||||
(if (sequential? sqls')
|
(if (sequential? sqls')
|
||||||
(str "(" (str/join ", " sqls') ")")
|
(str "(" (join ", " sqls') ")")
|
||||||
sqls'))
|
sqls'))
|
||||||
(into params params')])
|
(into params params')])
|
||||||
[[] []]
|
[[] []]
|
||||||
|
|
@ -1074,7 +1074,7 @@
|
||||||
(format-expr-list %)
|
(format-expr-list %)
|
||||||
[(sql-kw %)])
|
[(sql-kw %)])
|
||||||
xs'))]
|
xs'))]
|
||||||
(into [(str (sql-kw k) " " (str/join ", " sqls))] params))
|
(into [(str (sql-kw k) " " (join ", " sqls))] params))
|
||||||
|
|
||||||
(map? first-xs)
|
(map? first-xs)
|
||||||
;; [{:a 1 :b 2 :c 3}]
|
;; [{:a 1 :b 2 :c 3}]
|
||||||
|
|
@ -1086,7 +1086,7 @@
|
||||||
(reduce (fn [[sql params] [sqls' params']]
|
(reduce (fn [[sql params] [sqls' params']]
|
||||||
[(conj sql
|
[(conj sql
|
||||||
(if (sequential? sqls')
|
(if (sequential? sqls')
|
||||||
(str "(" (str/join ", " sqls') ")")
|
(str "(" (join ", " sqls') ")")
|
||||||
sqls'))
|
sqls'))
|
||||||
(if params' (into params params') params')])
|
(if params' (into params params') params')])
|
||||||
[[] []]
|
[[] []]
|
||||||
|
|
@ -1107,7 +1107,7 @@
|
||||||
(str cols-sql " "))
|
(str cols-sql " "))
|
||||||
(sql-kw k)
|
(sql-kw k)
|
||||||
" "
|
" "
|
||||||
(str/join ", " sqls))]
|
(join ", " sqls))]
|
||||||
params))
|
params))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
|
|
@ -1126,7 +1126,7 @@
|
||||||
(if params' (into params params') params)]))
|
(if params' (into params params') params)]))
|
||||||
[[] []]
|
[[] []]
|
||||||
xs)]
|
xs)]
|
||||||
(into [(str (sql-kw k) " " (str/join ", " sqls))] params)))
|
(into [(str (sql-kw k) " " (join ", " sqls))] params)))
|
||||||
|
|
||||||
(defn- format-on-conflict [k x]
|
(defn- format-on-conflict [k x]
|
||||||
(if (sequential? x)
|
(if (sequential? x)
|
||||||
|
|
@ -1144,7 +1144,7 @@
|
||||||
(format-dsl clause))]
|
(format-dsl clause))]
|
||||||
(-> [(str (sql-kw k)
|
(-> [(str (sql-kw k)
|
||||||
(when (pos? n)
|
(when (pos? n)
|
||||||
(str " (" (str/join ", " sqls) ")"))
|
(str " (" (join ", " sqls) ")"))
|
||||||
(when sql
|
(when sql
|
||||||
(str " " sql)))]
|
(str " " sql)))]
|
||||||
(into expr-params)
|
(into expr-params)
|
||||||
|
|
@ -1159,11 +1159,11 @@
|
||||||
(if (map? fields)
|
(if (map? fields)
|
||||||
(format-set-exprs k fields)
|
(format-set-exprs k fields)
|
||||||
[(str (sql-kw k) " "
|
[(str (sql-kw k) " "
|
||||||
(str/join ", "
|
(join ", "
|
||||||
(map (fn [e]
|
(map (fn [e]
|
||||||
(let [e (format-entity e {:drop-ns true})]
|
(let [e (format-entity e {:drop-ns true})]
|
||||||
(str e " = EXCLUDED." e)))
|
(str e " = EXCLUDED." e))))
|
||||||
fields)))])
|
fields))])
|
||||||
where (or (:where x) ('where x))
|
where (or (:where x) ('where x))
|
||||||
[sql & params] (when where (format-dsl {:where where}))]
|
[sql & params] (when where (format-dsl {:where where}))]
|
||||||
(-> [(str sets (when sql (str " " sql)))]
|
(-> [(str sets (when sql (str " " sql)))]
|
||||||
|
|
@ -1199,7 +1199,9 @@
|
||||||
(if (sequential? x)
|
(if (sequential? x)
|
||||||
[(str (sql-kw k) " " (format-entity (first x))
|
[(str (sql-kw k) " " (format-entity (first x))
|
||||||
(when-let [clauses (next x)]
|
(when-let [clauses (next x)]
|
||||||
(str " " (str/join ", " (map #(format-simple-clause % "column/index operations") clauses)))))]
|
(str " " (join ", "
|
||||||
|
(map #(format-simple-clause % "column/index operations"))
|
||||||
|
clauses))))]
|
||||||
[(str (sql-kw k) " " (format-entity x))]))
|
[(str (sql-kw k) " " (format-entity x))]))
|
||||||
|
|
||||||
(def ^:private special-ddl-keywords
|
(def ^:private special-ddl-keywords
|
||||||
|
|
@ -1223,12 +1225,12 @@
|
||||||
(cond (map? opt)
|
(cond (map? opt)
|
||||||
(format-simple-clause opt context)
|
(format-simple-clause opt context)
|
||||||
(sequential? opt)
|
(sequential? opt)
|
||||||
(str/join " "
|
(join " "
|
||||||
(map (fn [e]
|
(map (fn [e]
|
||||||
(if (ident? e)
|
(if (ident? e)
|
||||||
(sql-kw-ddl e)
|
(sql-kw-ddl e)
|
||||||
(format-simple-expr e context)))
|
(format-simple-expr e context))))
|
||||||
opt))
|
opt)
|
||||||
(ident? opt)
|
(ident? opt)
|
||||||
(sql-kw-ddl opt)
|
(sql-kw-ddl opt)
|
||||||
:else
|
:else
|
||||||
|
|
@ -1252,7 +1254,7 @@
|
||||||
[(cons ine (butlast (butlast coll))) (last (butlast coll)) nil]
|
[(cons ine (butlast (butlast coll))) (last (butlast coll)) nil]
|
||||||
:else
|
:else
|
||||||
[(butlast coll) (last coll) nil]))]
|
[(butlast coll) (last coll) nil]))]
|
||||||
(into [(str/join " " (map sql-kw prequel))
|
(into [(join " " (map sql-kw) prequel)
|
||||||
(when table
|
(when table
|
||||||
(let [[v & more] (format-var table)]
|
(let [[v & more] (format-var table)]
|
||||||
(when (seq more)
|
(when (seq more)
|
||||||
|
|
@ -1270,9 +1272,9 @@
|
||||||
[pre table ine options] (destructure-ddl-item [table options] "truncate")]
|
[pre table ine options] (destructure-ddl-item [table options] "truncate")]
|
||||||
(when (seq pre) (throw (ex-info "TRUNCATE syntax error" {:unexpected pre})))
|
(when (seq pre) (throw (ex-info "TRUNCATE syntax error" {:unexpected pre})))
|
||||||
(when (seq ine) (throw (ex-info "TRUNCATE syntax error" {:unexpected ine})))
|
(when (seq ine) (throw (ex-info "TRUNCATE syntax error" {:unexpected ine})))
|
||||||
[(str/join " " (cond-> ["TRUNCATE TABLE" table]
|
[(join " " (cond-> ["TRUNCATE TABLE" table]
|
||||||
(seq options)
|
(seq options)
|
||||||
(conj options)))]))
|
(conj options)))]))
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
(destructure-ddl-item [:foo [:abc [:continue :wibble] :identity]] "test")
|
(destructure-ddl-item [:foo [:abc [:continue :wibble] :identity]] "test")
|
||||||
|
|
@ -1285,15 +1287,15 @@
|
||||||
(defn- format-create [q k item as]
|
(defn- format-create [q k item as]
|
||||||
(let [[pre entity ine & more]
|
(let [[pre entity ine & more]
|
||||||
(destructure-ddl-item item (str (sql-kw q) " options"))]
|
(destructure-ddl-item item (str (sql-kw q) " options"))]
|
||||||
[(str/join " " (remove nil?
|
[(join " " (remove nil?)
|
||||||
(-> [(sql-kw q)
|
(-> [(sql-kw q)
|
||||||
(when (and (= :create q) (seq pre)) pre)
|
(when (and (= :create q) (seq pre)) pre)
|
||||||
(sql-kw k)
|
(sql-kw k)
|
||||||
ine
|
ine
|
||||||
(when (and (= :refresh q) (seq pre)) pre)
|
(when (and (= :refresh q) (seq pre)) pre)
|
||||||
entity]
|
entity]
|
||||||
(into more)
|
(into more)
|
||||||
(conj (when as (sql-kw as))))))]))
|
(conj (when as (sql-kw as)))))]))
|
||||||
|
|
||||||
(defn- format-create-index [k clauses]
|
(defn- format-create-index [k clauses]
|
||||||
(let [[index-spec [table & exprs]] clauses
|
(let [[index-spec [table & exprs]] clauses
|
||||||
|
|
@ -1302,20 +1304,19 @@
|
||||||
exprs
|
exprs
|
||||||
(cons nil exprs))
|
(cons nil exprs))
|
||||||
[sqls params] (format-expr-list exprs)]
|
[sqls params] (format-expr-list exprs)]
|
||||||
(into [(str/join " " (remove empty?
|
(into [(join " " (remove empty?)
|
||||||
(-> ["CREATE" pre "INDEX" ine entity
|
(-> ["CREATE" pre "INDEX" ine entity
|
||||||
"ON" (format-entity table)
|
"ON" (format-entity table)
|
||||||
(when using (sql-kw using))
|
(when using (sql-kw using))
|
||||||
(str "(" (str/join ", " sqls) ")")]
|
(str "(" (join ", " sqls) ")")]
|
||||||
(into more))))]
|
(into more)))]
|
||||||
params)))
|
params)))
|
||||||
|
|
||||||
(defn- format-with-data [_ data]
|
(defn- format-with-data [_ data]
|
||||||
(let [data (if (sequential? data) (first data) data)]
|
(let [data (if (sequential? data) (first data) data)]
|
||||||
[(str/join " " (remove nil?
|
[(join " " (remove nil?) [(sql-kw :with)
|
||||||
[(sql-kw :with)
|
(when-not data (sql-kw :no))
|
||||||
(when-not data (sql-kw :no))
|
(sql-kw :data)])]))
|
||||||
(sql-kw :data)]))]))
|
|
||||||
|
|
||||||
(defn- destructure-drop-items [tables context]
|
(defn- destructure-drop-items [tables context]
|
||||||
(let [params
|
(let [params
|
||||||
|
|
@ -1329,13 +1330,13 @@
|
||||||
coll
|
coll
|
||||||
(cons nil coll))]
|
(cons nil coll))]
|
||||||
(into [(when if-exists (sql-kw :if-exists))
|
(into [(when if-exists (sql-kw :if-exists))
|
||||||
(str/join ", " (map #'format-entity tables))]
|
(join ", " (map #'format-entity) tables)]
|
||||||
(format-ddl-options opts context))))
|
(format-ddl-options opts context))))
|
||||||
|
|
||||||
(defn- format-drop-items
|
(defn- format-drop-items
|
||||||
[k params]
|
[k params]
|
||||||
(let [[if-exists tables & more] (destructure-drop-items params "DROP options")]
|
(let [[if-exists tables & more] (destructure-drop-items params "DROP options")]
|
||||||
[(str/join " " (remove nil? (into [(sql-kw k) if-exists tables] more)))]))
|
[(join " " (remove nil?) (into [(sql-kw k) if-exists tables] more))]))
|
||||||
|
|
||||||
(defn- format-single-column [xs]
|
(defn- format-single-column [xs]
|
||||||
(let [[col & options] (if (ident? (first xs)) xs (cons nil xs))
|
(let [[col & options] (if (ident? (first xs)) xs (cons nil xs))
|
||||||
|
|
@ -1343,7 +1344,7 @@
|
||||||
(destructure-ddl-item [col options] "column operation")]
|
(destructure-ddl-item [col options] "column operation")]
|
||||||
(when (seq pre) (throw (ex-info "column syntax error" {:unexpected pre})))
|
(when (seq pre) (throw (ex-info "column syntax error" {:unexpected pre})))
|
||||||
(when (seq ine) (throw (ex-info "column syntax error" {:unexpected ine})))
|
(when (seq ine) (throw (ex-info "column syntax error" {:unexpected ine})))
|
||||||
(str/join " " (filter seq (cons col options)))))
|
(join " " (remove empty?) (cons col options))))
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
(destructure-ddl-item [:foo [:abc [:continue :wibble] :identity]] "test")
|
(destructure-ddl-item [:foo [:abc [:continue :wibble] :identity]] "test")
|
||||||
|
|
@ -1362,7 +1363,7 @@
|
||||||
|
|
||||||
(defn- format-table-columns [_ xs]
|
(defn- format-table-columns [_ xs]
|
||||||
[(str "("
|
[(str "("
|
||||||
(str/join ", " (map #'format-single-column xs))
|
(join ", " (map #'format-single-column) xs)
|
||||||
")")])
|
")")])
|
||||||
|
|
||||||
(defn- format-add-single-item [k spec]
|
(defn- format-add-single-item [k spec]
|
||||||
|
|
@ -1372,7 +1373,7 @@
|
||||||
|
|
||||||
(defn- format-add-item [k spec]
|
(defn- format-add-item [k spec]
|
||||||
(let [items (if (and (sequential? spec) (sequential? (first spec))) spec [spec])]
|
(let [items (if (and (sequential? spec) (sequential? (first spec))) spec [spec])]
|
||||||
[(str/join ", " (for [item items] (format-add-single-item k item)))]))
|
[(join ", " (map #(format-add-single-item k %)) items)]))
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
(format-add-item :add-column [:address :text])
|
(format-add-item :add-column [:address :text])
|
||||||
|
|
@ -1394,7 +1395,7 @@
|
||||||
[(conj sqls s) params]))
|
[(conj sqls s) params]))
|
||||||
[[] []]
|
[[] []]
|
||||||
s)]
|
s)]
|
||||||
(into [(str/join sqls)] params))
|
(into [(join "" sqls)] params))
|
||||||
[s]))
|
[s]))
|
||||||
|
|
||||||
(defn- destructure-drop-columns [tables]
|
(defn- destructure-drop-columns [tables]
|
||||||
|
|
@ -1421,7 +1422,7 @@
|
||||||
(defn- format-drop-columns
|
(defn- format-drop-columns
|
||||||
[k params]
|
[k params]
|
||||||
(let [tables (destructure-drop-columns params)]
|
(let [tables (destructure-drop-columns params)]
|
||||||
[(str/join ", " (mapv #(str (sql-kw k) " " %) tables))]))
|
[(join ", " (map #(str (sql-kw k) " " %)) tables)]))
|
||||||
|
|
||||||
(defn- format-interval
|
(defn- format-interval
|
||||||
[k args]
|
[k args]
|
||||||
|
|
@ -1430,7 +1431,7 @@
|
||||||
(if (seq units)
|
(if (seq units)
|
||||||
(let [[sql & params] (format-expr n)]
|
(let [[sql & params] (format-expr n)]
|
||||||
(into [(str (sql-kw k) " " sql " "
|
(into [(str (sql-kw k) " " sql " "
|
||||||
(str/join " " (map sql-kw units)))]
|
(join " " (map sql-kw) units))]
|
||||||
params))
|
params))
|
||||||
(binding [*inline* true]
|
(binding [*inline* true]
|
||||||
(let [[sql & params] (format-expr n)]
|
(let [[sql & params] (format-expr n)]
|
||||||
|
|
@ -1604,12 +1605,12 @@
|
||||||
*clause-order*)]
|
*clause-order*)]
|
||||||
(if (seq leftover)
|
(if (seq leftover)
|
||||||
(throw (ex-info (str "These SQL clauses are unknown or have nil values: "
|
(throw (ex-info (str "These SQL clauses are unknown or have nil values: "
|
||||||
(str/join ", " (keys leftover))
|
(join ", " (keys leftover))
|
||||||
"(perhaps you need [:lift {"
|
"(perhaps you need [:lift {"
|
||||||
(first (keys leftover))
|
(first (keys leftover))
|
||||||
" ...}] here?)")
|
" ...}] here?)")
|
||||||
leftover))
|
leftover))
|
||||||
(into [(cond-> (str/join (if pretty "\n" " ") (filter seq sqls))
|
(into [(cond-> (join (if pretty "\n" " ") (remove empty?) sqls)
|
||||||
pretty
|
pretty
|
||||||
(as-> s (str "\n" s "\n"))
|
(as-> s (str "\n" s "\n"))
|
||||||
(and nested (not aliased))
|
(and nested (not aliased))
|
||||||
|
|
@ -1670,7 +1671,7 @@
|
||||||
(= "?" sql-y)
|
(= "?" sql-y)
|
||||||
(= 1 (count params-y))
|
(= 1 (count params-y))
|
||||||
(coll? v1))
|
(coll? v1))
|
||||||
(let [sql (str "(" (str/join ", " (repeat (count v1) "?")) ")")]
|
(let [sql (str "(" (join ", " (repeat (count v1) "?")) ")")]
|
||||||
(-> [(str sql-x " " (sql-kw in) " " sql)]
|
(-> [(str sql-x " " (sql-kw in) " " sql)]
|
||||||
(into params-x)
|
(into params-x)
|
||||||
(into v1)))
|
(into v1)))
|
||||||
|
|
@ -1679,7 +1680,7 @@
|
||||||
(= 1 (count params-y))
|
(= 1 (count params-y))
|
||||||
(coll? v1))
|
(coll? v1))
|
||||||
(let [vs (for [v v1] (->numbered v))
|
(let [vs (for [v v1] (->numbered v))
|
||||||
sql (str "(" (str/join ", " (map first vs)) ")")]
|
sql (str "(" (join ", " (map first) vs) ")")]
|
||||||
(-> [(str sql-x " " (sql-kw in) " " sql)]
|
(-> [(str sql-x " " (sql-kw in) " " sql)]
|
||||||
(into params-x)
|
(into params-x)
|
||||||
(conj nil)
|
(conj nil)
|
||||||
|
|
@ -1693,9 +1694,9 @@
|
||||||
[(str (sql-kw k)
|
[(str (sql-kw k)
|
||||||
(when (seq xs)
|
(when (seq xs)
|
||||||
(str "("
|
(str "("
|
||||||
(str/join ", "
|
(join ", "
|
||||||
(map #(format-simple-expr % "column/index operation")
|
(map #(format-simple-expr % "column/index operation"))
|
||||||
xs))
|
xs)
|
||||||
")")))])
|
")")))])
|
||||||
|
|
||||||
(defn- function-1 [k xs]
|
(defn- function-1 [k xs]
|
||||||
|
|
@ -1705,9 +1706,9 @@
|
||||||
"column/index operation")
|
"column/index operation")
|
||||||
(when-let [args (next xs)]
|
(when-let [args (next xs)]
|
||||||
(str "("
|
(str "("
|
||||||
(str/join ", "
|
(join ", "
|
||||||
(map #(format-simple-expr % "column/index operation")
|
(map #(format-simple-expr % "column/index operation"))
|
||||||
args))
|
args)
|
||||||
")")))))])
|
")")))))])
|
||||||
|
|
||||||
(defn- function-1-opt [k xs]
|
(defn- function-1-opt [k xs]
|
||||||
|
|
@ -1717,9 +1718,9 @@
|
||||||
(str " " (format-simple-expr e "column/index operation")))
|
(str " " (format-simple-expr e "column/index operation")))
|
||||||
(when-let [args (next xs)]
|
(when-let [args (next xs)]
|
||||||
(str "("
|
(str "("
|
||||||
(str/join ", "
|
(join ", "
|
||||||
(map #(format-simple-expr % "column/index operation")
|
(map #(format-simple-expr % "column/index operation"))
|
||||||
args))
|
args)
|
||||||
")")))))])
|
")")))))])
|
||||||
|
|
||||||
(defn- expr-clause-pairs
|
(defn- expr-clause-pairs
|
||||||
|
|
@ -1734,7 +1735,7 @@
|
||||||
(-> params (into params-e) (into params-c))]))
|
(-> params (into params-e) (into params-c))]))
|
||||||
[[] []]
|
[[] []]
|
||||||
(partition 2 pairs))]
|
(partition 2 pairs))]
|
||||||
(into [(str/join ", " sqls)] params)))
|
(into [(join ", " sqls)] params)))
|
||||||
|
|
||||||
(defn- case-clauses
|
(defn- case-clauses
|
||||||
"For both :case and :case-expr."
|
"For both :case and :case-expr."
|
||||||
|
|
@ -1756,7 +1757,7 @@
|
||||||
(-> [(str (sql-kw :case) " "
|
(-> [(str (sql-kw :case) " "
|
||||||
(when case-expr?
|
(when case-expr?
|
||||||
(str sqlx " "))
|
(str sqlx " "))
|
||||||
(str/join " " sqls)
|
(join " " sqls)
|
||||||
" " (sql-kw :end))]
|
" " (sql-kw :end))]
|
||||||
(into paramsx)
|
(into paramsx)
|
||||||
(into params))))
|
(into params))))
|
||||||
|
|
@ -1799,11 +1800,11 @@
|
||||||
;; bigquery column types:
|
;; bigquery column types:
|
||||||
:bigquery/array (fn [_ spec]
|
:bigquery/array (fn [_ spec]
|
||||||
[(str "ARRAY<"
|
[(str "ARRAY<"
|
||||||
(str/join " " (map #(sql-kw %) spec))
|
(join " " (map sql-kw) spec)
|
||||||
">")])
|
">")])
|
||||||
:bigquery/struct (fn [_ spec]
|
:bigquery/struct (fn [_ spec]
|
||||||
[(str "STRUCT<"
|
[(str "STRUCT<"
|
||||||
(str/join ", " (map format-single-column spec))
|
(join ", " (map format-single-column) spec)
|
||||||
">")])
|
">")])
|
||||||
:array
|
:array
|
||||||
(fn [_ [arr type]]
|
(fn [_ [arr type]]
|
||||||
|
|
@ -1814,7 +1815,7 @@
|
||||||
;; allow for (unwrap arr) here?
|
;; allow for (unwrap arr) here?
|
||||||
(let [[sqls params] (format-expr-list arr)
|
(let [[sqls params] (format-expr-list arr)
|
||||||
type-str (when type (str "::" (sql-kw type) "[]"))]
|
type-str (when type (str "::" (sql-kw type) "[]"))]
|
||||||
(into [(str "ARRAY[" (str/join ", " sqls) "]" type-str)] params))))
|
(into [(str "ARRAY[" (join ", " sqls) "]" type-str)] params))))
|
||||||
:at-time-zone
|
:at-time-zone
|
||||||
(fn [_ [expr tz]]
|
(fn [_ [expr tz]]
|
||||||
(let [[sql & params] (format-expr expr {:nested true})
|
(let [[sql & params] (format-expr expr {:nested true})
|
||||||
|
|
@ -1845,7 +1846,7 @@
|
||||||
:composite
|
:composite
|
||||||
(fn [_ [& args]]
|
(fn [_ [& args]]
|
||||||
(let [[sqls params] (format-expr-list args)]
|
(let [[sqls params] (format-expr-list args)]
|
||||||
(into [(str "(" (str/join ", " sqls) ")")] params)))
|
(into [(str "(" (join ", " sqls) ")")] params)))
|
||||||
:distinct
|
:distinct
|
||||||
(fn [_ [x]]
|
(fn [_ [x]]
|
||||||
(let [[sql & params] (format-expr x {:nested true})]
|
(let [[sql & params] (format-expr x {:nested true})]
|
||||||
|
|
@ -1862,14 +1863,13 @@
|
||||||
:inline
|
:inline
|
||||||
(fn [_ xs]
|
(fn [_ xs]
|
||||||
(binding [*inline* true]
|
(binding [*inline* true]
|
||||||
(let [sqls (mapcat format-expr xs)]
|
[(join " " (mapcat format-expr) xs)]))
|
||||||
[(str/join " " sqls)])))
|
|
||||||
:interval format-interval
|
:interval format-interval
|
||||||
:join
|
:join
|
||||||
(fn [_ [e & js]]
|
(fn [_ [e & js]]
|
||||||
(let [[sqls params] (reduce-sql (cons (format-selectable-dsl e {:as true})
|
(let [[sqls params] (reduce-sql (cons (format-selectable-dsl e {:as true})
|
||||||
(map format-dsl js)))]
|
(map format-dsl js)))]
|
||||||
(into [(str "(" (str/join " " sqls) ")")] params)))
|
(into [(str "(" (join " " sqls) ")")] params)))
|
||||||
:lateral
|
:lateral
|
||||||
(fn [_ [clause-or-expr]]
|
(fn [_ [clause-or-expr]]
|
||||||
(if (map? clause-or-expr)
|
(if (map? clause-or-expr)
|
||||||
|
|
@ -1917,7 +1917,7 @@
|
||||||
(-> params (into params-e) (into params-p))]))
|
(-> params (into params-e) (into params-p))]))
|
||||||
[[] []]
|
[[] []]
|
||||||
args)]
|
args)]
|
||||||
(into [(str/join ", " sqls)] params)))
|
(into [(join ", " sqls)] params)))
|
||||||
:param
|
:param
|
||||||
(fn [_ [k]]
|
(fn [_ [k]]
|
||||||
(let [k (sym->kw k)]
|
(let [k (sym->kw k)]
|
||||||
|
|
@ -1975,7 +1975,7 @@
|
||||||
(when-not (pos? (count sqls))
|
(when-not (pos? (count sqls))
|
||||||
(throw (ex-info (str "no operands found for " op')
|
(throw (ex-info (str "no operands found for " op')
|
||||||
{:expr expr})))
|
{:expr expr})))
|
||||||
(into [(cond-> (str/join (str " " (sql-kw op) " ") sqls)
|
(into [(cond-> (join (str " " (sql-kw op) " ") sqls)
|
||||||
(and (contains? @op-can-be-unary op)
|
(and (contains? @op-can-be-unary op)
|
||||||
(= 1 (count sqls)))
|
(= 1 (count sqls)))
|
||||||
(as-> s (str (sql-kw op) " " s))
|
(as-> s (str (sql-kw op) " " s))
|
||||||
|
|
@ -1991,7 +1991,7 @@
|
||||||
(map? (first args))
|
(map? (first args))
|
||||||
(= 1 (count sqls)))
|
(= 1 (count sqls)))
|
||||||
(str " " (first sqls))
|
(str " " (first sqls))
|
||||||
(str "(" (str/join ", " sqls) ")")))]
|
(str "(" (join ", " sqls) ")")))]
|
||||||
params)))
|
params)))
|
||||||
|
|
||||||
(defn format-expr
|
(defn format-expr
|
||||||
|
|
@ -2025,7 +2025,7 @@
|
||||||
:else
|
:else
|
||||||
(format-fn-call-expr op expr))
|
(format-fn-call-expr op expr))
|
||||||
(let [[sqls params] (format-expr-list expr)]
|
(let [[sqls params] (format-expr-list expr)]
|
||||||
(into [(str "(" (str/join ", " sqls) ")")] params))))
|
(into [(str "(" (join ", " sqls) ")")] params))))
|
||||||
|
|
||||||
(boolean? expr)
|
(boolean? expr)
|
||||||
[(upper-case (str expr))]
|
[(upper-case (str expr))]
|
||||||
|
|
@ -2178,7 +2178,7 @@
|
||||||
[opts]
|
[opts]
|
||||||
(let [unknowns (dissoc opts :checking :inline :numbered :quoted :quoted-snake)]
|
(let [unknowns (dissoc opts :checking :inline :numbered :quoted :quoted-snake)]
|
||||||
(when (seq unknowns)
|
(when (seq unknowns)
|
||||||
(throw (ex-info (str (str/join ", " (keys unknowns))
|
(throw (ex-info (str (join ", " (keys unknowns))
|
||||||
" are not options that can be set globally.")
|
" are not options that can be set globally.")
|
||||||
unknowns)))
|
unknowns)))
|
||||||
(when (contains? opts :checking)
|
(when (contains? opts :checking)
|
||||||
|
|
|
||||||
78
src/honey/sql/util.cljc
Normal file
78
src/honey/sql/util.cljc
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
(ns honey.sql.util
|
||||||
|
"Utility functions for the main honey.sql namespace."
|
||||||
|
(:refer-clojure :exclude [str])
|
||||||
|
(:require clojure.string))
|
||||||
|
|
||||||
|
(defn str
|
||||||
|
"More efficient implementation of `clojure.core/str` because it has more
|
||||||
|
non-variadic arities. Optimization is Clojure-only, on other platforms it
|
||||||
|
reverts back to `clojure.core/str`."
|
||||||
|
{:tag String}
|
||||||
|
(^String [] "")
|
||||||
|
(^String [^Object a]
|
||||||
|
#?(:clj (if (nil? a) "" (.toString a))
|
||||||
|
:default (clojure.core/str a)))
|
||||||
|
(^String [^Object a, ^Object b]
|
||||||
|
#?(:clj (if (nil? a)
|
||||||
|
(str b)
|
||||||
|
(if (nil? b)
|
||||||
|
(.toString a)
|
||||||
|
(.concat (.toString a) (.toString b))))
|
||||||
|
:default (clojure.core/str a b)))
|
||||||
|
(^String [a b c]
|
||||||
|
#?(:clj (let [sb (StringBuilder.)]
|
||||||
|
(.append sb (str a))
|
||||||
|
(.append sb (str b))
|
||||||
|
(.append sb (str c))
|
||||||
|
(.toString sb))
|
||||||
|
:default (clojure.core/str a b c)))
|
||||||
|
(^String [a b c d]
|
||||||
|
#?(:clj (let [sb (StringBuilder.)]
|
||||||
|
(.append sb (str a))
|
||||||
|
(.append sb (str b))
|
||||||
|
(.append sb (str c))
|
||||||
|
(.append sb (str d))
|
||||||
|
(.toString sb))
|
||||||
|
:default (clojure.core/str a b c d)))
|
||||||
|
(^String [a b c d e]
|
||||||
|
#?(:clj (let [sb (StringBuilder.)]
|
||||||
|
(.append sb (str a))
|
||||||
|
(.append sb (str b))
|
||||||
|
(.append sb (str c))
|
||||||
|
(.append sb (str d))
|
||||||
|
(.append sb (str e))
|
||||||
|
(.toString sb))
|
||||||
|
:default (clojure.core/str a b c d e)))
|
||||||
|
(^String [a b c d e & more]
|
||||||
|
#?(:clj (let [sb (StringBuilder.)]
|
||||||
|
(.append sb (str a))
|
||||||
|
(.append sb (str b))
|
||||||
|
(.append sb (str c))
|
||||||
|
(.append sb (str d))
|
||||||
|
(.append sb (str e))
|
||||||
|
(run! #(.append sb (str %)) more)
|
||||||
|
(.toString sb))
|
||||||
|
:default (apply clojure.core/str a b c d e more))))
|
||||||
|
|
||||||
|
(defn join
|
||||||
|
"More efficient implementation of `clojure.string/join`. May accept a transducer
|
||||||
|
`xform` to perform operations on each element before combining them together
|
||||||
|
into a string. Clojure-only, delegates to `clojure.string/join` on other
|
||||||
|
platforms."
|
||||||
|
([separator coll] (join separator identity coll))
|
||||||
|
([separator xform coll]
|
||||||
|
#?(:clj
|
||||||
|
(let [sb (StringBuilder.)
|
||||||
|
sep (str separator)]
|
||||||
|
(transduce xform
|
||||||
|
(fn
|
||||||
|
([] false)
|
||||||
|
([_] (.toString sb))
|
||||||
|
([add-sep? x]
|
||||||
|
(when add-sep? (.append sb sep))
|
||||||
|
(.append sb (str x))
|
||||||
|
true))
|
||||||
|
false coll))
|
||||||
|
|
||||||
|
:default
|
||||||
|
(clojure.string/join separator (transduce xform conj [] coll)))))
|
||||||
45
test/honey/util_test.cljc
Normal file
45
test/honey/util_test.cljc
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
(ns honey.util-test
|
||||||
|
(:refer-clojure :exclude [str])
|
||||||
|
(:require [clojure.test :refer [deftest is are]]
|
||||||
|
[honey.sql.util :as sut]))
|
||||||
|
|
||||||
|
(deftest str-test
|
||||||
|
(are [arg1 result] (= result (sut/str arg1))
|
||||||
|
nil ""
|
||||||
|
1 "1"
|
||||||
|
"foo" "foo"
|
||||||
|
:foo ":foo")
|
||||||
|
(are [arg1 arg2 result] (= result (sut/str arg1 arg2))
|
||||||
|
nil nil ""
|
||||||
|
nil 1 "1"
|
||||||
|
1 nil "1"
|
||||||
|
1 2 "12"
|
||||||
|
:foo "bar" ":foobar")
|
||||||
|
(are [arg1 arg2 arg3 result] (= result (sut/str arg1 arg2 arg3))
|
||||||
|
nil nil nil ""
|
||||||
|
nil 1 nil "1"
|
||||||
|
1 nil nil "1"
|
||||||
|
1 nil 2 "12"
|
||||||
|
:foo "bar" 'baz ":foobarbaz")
|
||||||
|
(are [args result] (= result (apply sut/str args))
|
||||||
|
(range 10) "0123456789"
|
||||||
|
[] ""))
|
||||||
|
|
||||||
|
(deftest join-test
|
||||||
|
(is (= "0123456789" (sut/join "" (range 10))))
|
||||||
|
(is (= "1" (sut/join "" [1])))
|
||||||
|
(is (= "" (sut/join "" [])))
|
||||||
|
(is (= "0, 1, 2, 3, 4, 5, 6, 7, 8, 9" (sut/join ", " (range 10))))
|
||||||
|
(is (= "1" (sut/join ", " [1])))
|
||||||
|
(is (= "" (sut/join ", " [])))
|
||||||
|
|
||||||
|
(is (= "0_0, 1_1, 2_2, 3_3, 4_4, 5_5, 6_6, 7_7, 8_8, 9_9"
|
||||||
|
(sut/join ", " (map #(sut/str % "_" %)) (range 10))))
|
||||||
|
(is (= "1_1"
|
||||||
|
(sut/join ", " (map #(sut/str % "_" %)) [1])))
|
||||||
|
(is (= ""
|
||||||
|
(sut/join ", " (map #(sut/str % "_" %)) [])))
|
||||||
|
|
||||||
|
(is (= "1, 2, 3, 4"
|
||||||
|
(sut/join ", " (remove nil?) [1 nil 2 nil 3 nil nil nil 4])))
|
||||||
|
(is (= "" (sut/join ", " (remove nil?) [nil nil nil nil]))))
|
||||||
Loading…
Reference in a new issue