From 5019995feb4f16bf2690f3307b39815587d42b44 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 17 Apr 2019 23:56:44 -0700 Subject: [PATCH] Move SQL sugar functions to next.jdbc.sql Make SQL string builder functions private. --- src/next/jdbc.clj | 90 ----------------------------- src/next/jdbc/result_set.clj | 5 +- src/next/jdbc/sql.clj | 109 +++++++++++++++++++++++++++++++---- test/next/jdbc_test.clj | 3 +- 4 files changed, 102 insertions(+), 105 deletions(-) diff --git a/src/next/jdbc.clj b/src/next/jdbc.clj index 51e9e6b..4b95400 100644 --- a/src/next/jdbc.clj +++ b/src/next/jdbc.clj @@ -18,9 +18,6 @@ via a schema definition). * with-transaction -- execute a series of SQL operations within a transaction. - In addition, there are some utility functions that make common operations - easier by providing some syntactic sugar over 'execute!'. - 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 @@ -42,7 +39,6 @@ [next.jdbc.prepare :as prepare] ; used to extend protocols [next.jdbc.protocols :as p] [next.jdbc.result-set :as rs] - [next.jdbc.sql :as sql] [next.jdbc.transaction])) ; used to extend protocols (set! *warn-on-reflection* true) @@ -186,89 +182,3 @@ * :rollback-only -- true / false." [[sym connectable opts] & body] `(transact ~connectable ~opts (fn [~sym] ~@body))) - -(defn insert! - "Syntactic sugar over execute-one! to make inserting hash maps easier. - - Given a connectable object, a table name, and a data hash map, inserts the - data as a single row in the database and attempts to return a map of generated - keys." - ([connectable table key-map] - (insert! connectable table key-map {})) - ([connectable table key-map opts] - (execute-one! connectable - (sql/for-insert table key-map opts) - (merge {:return-keys true} opts)))) - -(defn insert-multi! - "Syntactic sugar over execute! to make inserting columns/rows easier. - - Given a connectable object, a table name, a sequence of column names, and - a vector of rows of data (vectors of column values), inserts the data as - multiple rows in the database and attempts to return a vector of maps of - generated keys." - ([connectable table cols rows] - (insert-multi! connectable table cols rows {})) - ([connectable table cols rows opts] - (execute! connectable - (sql/for-insert-multi table cols rows opts) - (merge {:return-keys true} opts)))) - -(defn query - "Syntactic sugar over execute! to provide a query alias. - - Given a connectable object, and a vector of SQL and its parameters, - returns a vector of hash maps of rows that match." - ([connectable sql-params] - (query connectable sql-params {})) - ([connectable sql-params opts] - (execute! connectable sql-params opts))) - -(defn find-by-keys - "Syntactic sugar over execute! to make certain common queries easier. - - Given a connectable object, a table name, and a hash map of columns and - their values, returns a vector of hash maps of rows that match." - ([connectable table key-map] - (find-by-keys connectable table key-map {})) - ([connectable table key-map opts] - (execute! connectable (sql/for-query table key-map opts) opts))) - -(defn get-by-id - "Syntactic sugar over execute-one! to make certain common queries easier. - - Given a connectable object, a table name, and a primary key value, returns - a hash map of the first row that matches. - - By default, the primary key is assumed to be 'id' but that can be overridden - in the five-argument call." - ([connectable table pk] - (get-by-id connectable table pk :id {})) - ([connectable table pk opts] - (get-by-id connectable table pk :id opts)) - ([connectable table pk pk-name opts] - (execute-one! connectable (sql/for-query table {pk-name pk} opts) opts))) - -(defn update! - "Syntactic sugar over execute-one! to make certain common updates easier. - - Given a connectable object, a table name, a hash map of columns and values - to set, and either a hash map of columns and values to search on or a vector - of a SQL where clause and parameters, perform an update on the table." - ([connectable table key-map where-params] - (update! connectable table key-map where-params {})) - ([connectable table key-map where-params opts] - (execute-one! connectable - (sql/for-update table key-map where-params opts) - opts))) - -(defn delete! - "Syntactic sugar over execute-one! to make certain common deletes easier. - - Given a connectable object, a table name, and either a hash map of columns - and values to search on or a vector of a SQL where clause and parameters, - perform a delete on the table." - ([connectable table where-params] - (delete! connectable table where-params {})) - ([connectable table where-params opts] - (execute-one! connectable (sql/for-delete table where-params opts) opts))) diff --git a/src/next/jdbc/result_set.clj b/src/next/jdbc/result_set.clj index 2aa5419..165a7ab 100644 --- a/src/next/jdbc/result_set.clj +++ b/src/next/jdbc/result_set.clj @@ -390,8 +390,8 @@ (try (let [entity-fn (:entities opts identity) exec-fn! (if (= :many cardinality) - execute! - execute-one!)] + p/-execute-all + p/-execute-one)] (exec-fn! connectable [(str "SELECT * FROM " (entity-fn (name table)) @@ -399,7 +399,6 @@ (entity-fn (name fk)) " = ?") v] - #(datafiable-row % connectable opts) opts)) (catch Exception _ ;; assume an exception means we just cannot diff --git a/src/next/jdbc/sql.clj b/src/next/jdbc/sql.clj index 9a7761e..92af0b7 100644 --- a/src/next/jdbc/sql.clj +++ b/src/next/jdbc/sql.clj @@ -1,17 +1,18 @@ ;; copyright (c) 2019 Sean Corfield, all rights reserved (ns next.jdbc.sql - "Utilities to construct SQL strings (and lists of parameters) for - various types of SQL statements. + "Some utility functions that make common operations easier by + providing some syntactic sugar over 'execute!'/'execute-one!'. This is intended to provide a minimal level of parity with clojure.java.jdbc (insert!, update!, delete!, etc). For anything more complex, use a library like HoneySQL https://github.com/jkk/honeysql to generate SQL + parameters. This is primarily intended to be an implementation detail." - (:require [clojure.string :as str])) + (:require [clojure.string :as str] + [next.jdbc :refer [execute! execute-one!]])) -(defn by-keys +(defn- by-keys "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. @@ -29,7 +30,7 @@ (str/join (if (= :where clause) " AND " ", ") where))] params))) -(defn as-keys +(defn- as-keys "Given a hash map of column names and values, return a string of all the column names. @@ -37,13 +38,13 @@ [key-map opts] (str/join ", " (map (comp (:entities 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, return a string of ? placeholders for them." [key-map opts] (str/join ", " (repeat (count key-map) "?"))) -(defn for-query +(defn- for-query "Given a table name and either a hash map of column names and values or a vector of SQL (where clause) and its parameters, return a vector of the full SELECT SQL string and its parameters. @@ -59,7 +60,7 @@ " " (first where-params))] (rest where-params)))) -(defn for-delete +(defn- for-delete "Given a table name and either a hash map of column names and values or a vector of SQL (where clause) and its parameters, return a vector of the full DELETE SQL string and its parameters. @@ -75,7 +76,7 @@ " " (first where-params))] (rest where-params)))) -(defn for-update +(defn- for-update "Given a table name, a vector of column names to set and their values, and either a hash map of column names and values or a vector of SQL (where clause) and its parameters, return a vector of the full UPDATE SQL string and its @@ -95,7 +96,7 @@ (into (rest set-params)) (into (rest where-params))))) -(defn for-insert +(defn- for-insert "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. @@ -109,7 +110,7 @@ " VALUES (" places ")")] (vals key-map)))) -(defn for-insert-multi +(defn- for-insert-multi "Given a table name, a vector of column names, and a vector of row values (each row is a vector of its values), return a vector of the full INSERT SQL string and its parameters. @@ -127,6 +128,92 @@ cat rows))) +(defn insert! + "Syntactic sugar over execute-one! to make inserting hash maps easier. + + Given a connectable object, a table name, and a data hash map, inserts the + data as a single row in the database and attempts to return a map of generated + keys." + ([connectable table key-map] + (insert! connectable table key-map {})) + ([connectable table key-map opts] + (execute-one! connectable + (for-insert table key-map opts) + (merge {:return-keys true} opts)))) + +(defn insert-multi! + "Syntactic sugar over execute! to make inserting columns/rows easier. + + Given a connectable object, a table name, a sequence of column names, and + a vector of rows of data (vectors of column values), inserts the data as + multiple rows in the database and attempts to return a vector of maps of + generated keys." + ([connectable table cols rows] + (insert-multi! connectable table cols rows {})) + ([connectable table cols rows opts] + (execute! connectable + (for-insert-multi table cols rows opts) + (merge {:return-keys true} opts)))) + +(defn query + "Syntactic sugar over execute! to provide a query alias. + + Given a connectable object, and a vector of SQL and its parameters, + returns a vector of hash maps of rows that match." + ([connectable sql-params] + (query connectable sql-params {})) + ([connectable sql-params opts] + (execute! connectable sql-params opts))) + +(defn find-by-keys + "Syntactic sugar over execute! to make certain common queries easier. + + Given a connectable object, a table name, and a hash map of columns and + their values, returns a vector of hash maps of rows that match." + ([connectable table key-map] + (find-by-keys connectable table key-map {})) + ([connectable table key-map opts] + (execute! connectable (for-query table key-map opts) opts))) + +(defn get-by-id + "Syntactic sugar over execute-one! to make certain common queries easier. + + Given a connectable object, a table name, and a primary key value, returns + a hash map of the first row that matches. + + By default, the primary key is assumed to be 'id' but that can be overridden + in the five-argument call." + ([connectable table pk] + (get-by-id connectable table pk :id {})) + ([connectable table pk opts] + (get-by-id connectable table pk :id opts)) + ([connectable table pk pk-name opts] + (execute-one! connectable (for-query table {pk-name pk} opts) opts))) + +(defn update! + "Syntactic sugar over execute-one! to make certain common updates easier. + + Given a connectable object, a table name, a hash map of columns and values + to set, and either a hash map of columns and values to search on or a vector + of a SQL where clause and parameters, perform an update on the table." + ([connectable table key-map where-params] + (update! connectable table key-map where-params {})) + ([connectable table key-map where-params opts] + (execute-one! connectable + (for-update table key-map where-params opts) + opts))) + +(defn delete! + "Syntactic sugar over execute-one! to make certain common deletes easier. + + Given a connectable object, a table name, and either a hash map of columns + and values to search on or a vector of a SQL where clause and parameters, + perform a delete on the table." + ([connectable table where-params] + (delete! connectable table where-params {})) + ([connectable table where-params opts] + (execute-one! connectable (for-delete table where-params opts) opts))) + (comment (require '[next.jdbc.quoted :refer [mysql]]) (by-keys {:a nil :b 42 :c "s"} :where {}) diff --git a/test/next/jdbc_test.clj b/test/next/jdbc_test.clj index 3275b34..7c6b4c5 100644 --- a/test/next/jdbc_test.clj +++ b/test/next/jdbc_test.clj @@ -2,7 +2,8 @@ "Not exactly a test suite -- more a series of examples." (:require [clojure.test :refer [deftest is testing]] [next.jdbc :refer :all] - [next.jdbc.result-set :as rs])) + [next.jdbc.result-set :as rs] + [next.jdbc.sql :refer :all])) (deftest a-test (testing "FIXME, I fail."