Split :entities into two options

`:table-fn` and `:column-fn`
This commit is contained in:
Sean Corfield 2019-04-18 08:12:56 -07:00
parent e5ea6af959
commit 7f2d3479e9
3 changed files with 36 additions and 39 deletions

View file

@ -18,15 +18,6 @@
via a schema definition). via a schema definition).
* with-transaction -- execute a series of SQL operations within a transaction. * with-transaction -- execute a series of SQL operations within a transaction.
The following options are supported generally:
* :entities -- specify a function used to convert strings to SQL entity names
(to turn table and column names into appropriate SQL names -- see the
next.jdbc.quoted namespace for the most common ones you might need),
* :identifiers -- specify a function used to convert SQL entity (column)
names to Clojure names (that are then turned into keywords),
* :row-fn -- when consuming a ResultSet, apply this function to each row of
data; defaults to a function that produces a datafiable hash map.
The following options are supported where a PreparedStatement is created: The following options are supported where a PreparedStatement is created:
* :concurrency -- :read-only, :updatable, * :concurrency -- :read-only, :updatable,
* :cursors -- :close, :hold * :cursors -- :close, :hold
@ -36,9 +27,9 @@
* :return-keys -- either true or a vector of key names to return, * :return-keys -- either true or a vector of key names to return,
* :timeout -- the query timeout." * :timeout -- the query timeout."
(:require [next.jdbc.connection] ; used to extend protocols (:require [next.jdbc.connection] ; used to extend protocols
[next.jdbc.prepare :as prepare] ; used to extend protocols [next.jdbc.prepare] ; used to extend protocols
[next.jdbc.protocols :as p] [next.jdbc.protocols :as p]
[next.jdbc.result-set :as rs] [next.jdbc.result-set] ; used to extend protocols
[next.jdbc.transaction])) ; used to extend protocols [next.jdbc.transaction])) ; used to extend protocols
(set! *warn-on-reflection* true) (set! *warn-on-reflection* true)

View file

@ -1,9 +1,9 @@
;; copyright (c) 2019 Sean Corfield, all rights reserved ;; copyright (c) 2019 Sean Corfield, all rights reserved
(ns next.jdbc.quoted (ns next.jdbc.quoted
"Provides functions for use with the :entities option that define "Provides functions for use with the :table-fn and :column-fn options
how SQL entities should be quoted in strings constructed from that define how SQL entities should be quoted in strings constructed
Clojure data.") from Clojure data.")
(defn ansi "ANSI \"quoting\"" [s] (str \" s \")) (defn ansi "ANSI \"quoting\"" [s] (str \" s \"))

View file

@ -8,7 +8,13 @@
(insert!, update!, delete!, etc). For anything more complex, use a library (insert!, update!, delete!, etc). For anything more complex, use a library
like HoneySQL https://github.com/jkk/honeysql to generate SQL + parameters. like HoneySQL https://github.com/jkk/honeysql to generate SQL + parameters.
This is primarily intended to be an implementation detail." The following options are supported:
* :table-fn -- specify a function used to convert table names (strings)
to SQL entity names -- see the next.jdbc.quoted namespace for the
most common quoting strategy functions,
* :column-fn -- specify a function used to convert column names (strings)
to SQL entity names -- see the next.jdbc.quoted namespace for the
most common quoting strategy functions."
(:require [clojure.string :as str] (:require [clojure.string :as str]
[next.jdbc :refer [execute! execute-one!]])) [next.jdbc :refer [execute! execute-one!]]))
@ -16,9 +22,9 @@
"Given a hash map of column names and values and a clause type (:set, :where), "Given a hash map of column names and values and a clause type (:set, :where),
return a vector of a SQL clause and its parameters. return a vector of a SQL clause and its parameters.
Applies any :entities function supplied in the options." Applies any :column-fn supplied in the options."
[key-map clause opts] [key-map clause opts]
(let [entity-fn (:entities opts identity) (let [entity-fn (:column-fn opts identity)
[where params] (reduce-kv (fn [[conds params] k v] [where params] (reduce-kv (fn [[conds params] k v]
(let [e (entity-fn (name k))] (let [e (entity-fn (name k))]
(if (and (= :where clause) (nil? v)) (if (and (= :where clause) (nil? v))
@ -34,9 +40,9 @@
"Given a hash map of column names and values, return a string of all the "Given a hash map of column names and values, return a string of all the
column names. column names.
Applies any :entities function supplied in the options." Applies any :column-fn supplied in the options."
[key-map opts] [key-map opts]
(str/join ", " (map (comp (:entities opts identity) name) (keys key-map)))) (str/join ", " (map (comp (:column-fn opts identity) name) (keys key-map))))
(defn- as-? (defn- as-?
"Given a hash map of column names and values, or a vector of column names, "Given a hash map of column names and values, or a vector of column names,
@ -49,9 +55,9 @@
vector of SQL (where clause) and its parameters, return a vector of the vector of SQL (where clause) and its parameters, return a vector of the
full SELECT SQL string and its parameters. full SELECT SQL string and its parameters.
Applies any :entities function supplied in the options." Applies any :table-fn / :column-fn supplied in the options."
[table where-params opts] [table where-params opts]
(let [entity-fn (:entities opts identity) (let [entity-fn (:table-fn opts identity)
where-params (if (map? where-params) where-params (if (map? where-params)
(by-keys where-params :where opts) (by-keys where-params :where opts)
(into [(str "WHERE " (first where-params))] (into [(str "WHERE " (first where-params))]
@ -65,9 +71,9 @@
vector of SQL (where clause) and its parameters, return a vector of the vector of SQL (where clause) and its parameters, return a vector of the
full DELETE SQL string and its parameters. full DELETE SQL string and its parameters.
Applies any :entities function supplied in the options." Applies any :table-fn / :column-fn supplied in the options."
[table where-params opts] [table where-params opts]
(let [entity-fn (:entities opts identity) (let [entity-fn (:table-fn opts identity)
where-params (if (map? where-params) where-params (if (map? where-params)
(by-keys where-params :where opts) (by-keys where-params :where opts)
(into [(str "WHERE " (first where-params))] (into [(str "WHERE " (first where-params))]
@ -82,9 +88,9 @@
and its parameters, return a vector of the full UPDATE SQL string and its and its parameters, return a vector of the full UPDATE SQL string and its
parameters. parameters.
Applies any :entities function supplied in the options." Applies any :table-fn / :column-fn supplied in the options."
[table key-map where-params opts] [table key-map where-params opts]
(let [entity-fn (:entities opts identity) (let [entity-fn (:table-fn opts identity)
set-params (by-keys key-map :set opts) set-params (by-keys key-map :set opts)
where-params (if (map? where-params) where-params (if (map? where-params)
(by-keys where-params :where opts) (by-keys where-params :where opts)
@ -100,9 +106,9 @@
"Given a table name and a hash map of column names and their values, "Given a table name and a hash map of column names and their values,
return a vector of the full INSERT SQL string and its parameters. return a vector of the full INSERT SQL string and its parameters.
Applies any :entities function supplied in the options." Applies any :table-fn / :column-fn supplied in the options."
[table key-map opts] [table key-map opts]
(let [entity-fn (:entities opts identity) (let [entity-fn (:table-fn opts identity)
params (as-keys key-map opts) params (as-keys key-map opts)
places (as-? key-map opts)] places (as-? key-map opts)]
(into [(str "INSERT INTO " (entity-fn (name table)) (into [(str "INSERT INTO " (entity-fn (name table))
@ -115,10 +121,10 @@
(each row is a vector of its values), return a vector of the full INSERT (each row is a vector of its values), return a vector of the full INSERT
SQL string and its parameters. SQL string and its parameters.
Applies any :entities function supplied in the options." Applies any :table-fn / :column-fn supplied in the options."
[table cols rows opts] [table cols rows opts]
(assert (apply = (count cols) (map count rows))) (assert (apply = (count cols) (map count rows)))
(let [entity-fn (:entities opts identity) (let [entity-fn (:table-fn opts identity)
params (str/join ", " (map (comp entity-fn name) cols)) params (str/join ", " (map (comp entity-fn name) cols))
places (as-? (first rows) opts)] places (as-? (first rows) opts)]
(into [(str "INSERT INTO " (entity-fn (name table)) (into [(str "INSERT INTO " (entity-fn (name table))
@ -222,27 +228,27 @@
;=> a, b, c ;=> a, b, c
(as-? {:a nil :b 42 :c "s"} {}) (as-? {:a nil :b 42 :c "s"} {})
;=> ?, ?, ? ;=> ?, ?, ?
(for-query :user {:id 9} {:entities mysql}) (for-query :user {:id 9} {:table-fn mysql :column-fn mysql})
;=> ["SELECT * FROM `user` WHERE `id` = ?" 9] ;=> ["SELECT * FROM `user` WHERE `id` = ?" 9]
(for-query :user {:id nil} {:entities mysql}) (for-query :user {:id nil} {:table-fn mysql :column-fn mysql})
;=> ["SELECT * FROM `user` WHERE `id` IS NULL"] ;=> ["SELECT * FROM `user` WHERE `id` IS NULL"]
(for-query :user ["id = ? and opt is null" 9] {:entities mysql}) (for-query :user ["id = ? and opt is null" 9] {:table-fn mysql :column-fn mysql})
;=> ["SELECT * FROM `user` WHERE id = ? and opt is null" 9] ;=> ["SELECT * FROM `user` WHERE id = ? and opt is null" 9]
(for-delete :user {:opt nil :id 9} {:entities mysql}) (for-delete :user {:opt nil :id 9} {:table-fn mysql :column-fn mysql})
;=> ["DELETE FROM `user` WHERE `opt` IS NULL AND `id` = ?" 9] ;=> ["DELETE FROM `user` WHERE `opt` IS NULL AND `id` = ?" 9]
(for-delete :user ["id = ? and opt is null" 9] {:entities mysql}) (for-delete :user ["id = ? and opt is null" 9] {:table-fn mysql :column-fn mysql})
;=> ["DELETE FROM `user` WHERE id = ? and opt is null" 9] ;=> ["DELETE FROM `user` WHERE id = ? and opt is null" 9]
(for-update :user {:status 42} {} {:entities mysql}) (for-update :user {:status 42} {} {:table-fn mysql :column-fn mysql})
;=> ["UPDATE `user` SET `status` = ? WHERE " 42] ;=> ["UPDATE `user` SET `status` = ? WHERE " 42]
(for-update :user {:status 42} {:id 9} {:entities mysql}) (for-update :user {:status 42} {:id 9} {:table-fn mysql :column-fn mysql})
;=> ["UPDATE `user` SET `status` = ? WHERE `id` = ?" 42 9] ;=> ["UPDATE `user` SET `status` = ? WHERE `id` = ?" 42 9]
(for-update :user {:status 42, :opt nil} ["id = ?" 9] {:entities mysql}) (for-update :user {:status 42, :opt nil} ["id = ?" 9] {:table-fn mysql :column-fn mysql})
;=> ["UPDATE `user` SET `status` = ?, `opt` = ? WHERE id = ?" 42 nil 9] ;=> ["UPDATE `user` SET `status` = ?, `opt` = ? WHERE id = ?" 42 nil 9]
(for-insert :user {:id 9 :status 42 :opt nil} {:entities mysql}) (for-insert :user {:id 9 :status 42 :opt nil} {:table-fn mysql :column-fn mysql})
;=> ["INSERT INTO `user` (`id`, `status`, `opt`) VALUES (?, ?, ?)" 9 42 nil] ;=> ["INSERT INTO `user` (`id`, `status`, `opt`) VALUES (?, ?, ?)" 9 42 nil]
(for-insert-multi :user [:id :status] (for-insert-multi :user [:id :status]
[[42 "hello"] [[42 "hello"]
[35 "world"] [35 "world"]
[64 "dollars"]] [64 "dollars"]]
{:entities mysql})) {:table-fn mysql :column-fn mysql}))
;=> ["INSERT INTO `user` (`id`, `status`) VALUES (?, ?), (?, ?), (?, ?)" 42 "hello" 35 "world" 64 "dollars"]) ;=> ["INSERT INTO `user` (`id`, `status`) VALUES (?, ?), (?, ?), (?, ?)" 42 "hello" 35 "world" 64 "dollars"])