Permalink
Browse files

Implement insert and re-implement insert! in terms of that

  • Loading branch information...
1 parent 2c68f11 commit 16e5b85c3842740308aceba2902232de2423e078 @seancorfield committed Jul 12, 2012
Showing with 76 additions and 26 deletions.
  1. +48 −18 src/jsql/core.clj
  2. +21 −0 test/jsql/test/core.clj
  3. +7 −8 test/jsql/test/db_ops.clj
View
66 src/jsql/core.clj
@@ -52,8 +52,48 @@
(when where " WHERE ") where)]
params))
-(defn insert [tables & clauses]
- [""])
+(defn- insert-multi-row [table columns values entities]
+ (let [nc (count columns)
+ vcs (map count values)]
+ (if (not (apply = nc vcs))
+ (throw (IllegalArgumentException. "insert called with inconsistent number of columns / values"))
+ (into [(str "INSERT INTO " (table-str table entities) " ( "
+ (str-join ", " (map (fn [col] (col-str col entities)) columns))
+ " ) VALUES "
+ (str-join ", "
+ (repeat (count values)
+ (str "( "
+ (str-join ", " (repeat nc "?"))
+ " )"))))]
+ (apply concat values)))))
+
+(defn- insert-single-row [table row entities]
+ (let [ks (keys row)]
+ (into [(str "INSERT INTO " (table-str table entities) " ( "
+ (str-join ", " (map (fn [col] (col-str col entities)) ks))
+ " ) VALUES ( "
+ (str-join ", " (repeat (count ks) "?"))
+ " )")]
+ (vals row))))
+
+(defn insert [table & clauses]
+ (let [rows (take-while map? clauses)
+ n-rows (count rows)
+ cols-and-vals-etc (drop n-rows clauses)
+ cols-and-vals (take-while (comp not keyword?) cols-and-vals-etc)
+ n-cols-and-vals (count cols-and-vals)
+ no-cols-and-vals (zero? n-cols-and-vals)
+ options (drop (+ (count rows) (count cols-and-vals)) clauses)
+ {:keys [entities] :or {entities as-is}} (apply hash-map options)]
+ (if (zero? n-rows)
+ (if no-cols-and-vals
+ (throw (IllegalArgumentException. "insert called without data to insert"))
+ (if (< n-cols-and-vals 2)
+ (throw (IllegalArgumentException. "insert called with columns but no values"))
+ (insert-multi-row table (first cols-and-vals) (rest cols-and-vals) entities)))
+ (if no-cols-and-vals
+ (map (fn [row] (insert-single-row table row entities)) rows)
+ (throw (IllegalArgumentException. "insert may take records or columns and values, not both"))))))
(defn join [table on-map & {:keys [entities] :or {entities as-is}}]
(str "JOIN " (table-str table entities) " ON "
@@ -145,23 +185,13 @@
(execute! db (delete table where-map :entities entities)))
(defn insert! [db table & maps-or-cols-and-values-etc]
- (let [records (take-while map? maps-or-cols-and-values-etc)
- cols-and-values-etc (drop (count records) maps-or-cols-and-values-etc)
- cols-and-values (take-while (comp not keyword?) cols-and-values-etc)
- [cols & values] cols-and-values
- options (drop (count cols-and-values) cols-and-values-etc)
- {:keys [entities identifiers]
- :or {entities as-is identifiers lower-case}} options]
- (if cols
- (do
- (when (seq records) (throw (IllegalArgumentException. "insert! may take records or columns and values, not both")))
- (when (nil? values) (throw (IllegalArgumentException. "insert! called with columns but no values"))))
- (when (empty? records) (throw (IllegalArgumentException. "insert! called without data to insert"))))
+ (let [stmts (apply insert table maps-or-cols-and-values-etc)]
(jdbc/with-connection db
- (condp = (count records)
- 0 (apply jdbc/insert-values table cols values)
- 1 (jdbc/insert-record table (first records))
- (apply jdbc/insert-records table records)))))
+ (if (string? (first stmts))
+ (jdbc/do-prepared (first stmts) (rest stmts))
+ (doall (map (fn [row] (first (vals (jdbc/do-prepared-return-keys
+ (first row) (rest row)))))
+ stmts))))))
(defn update! [db table set-map where-map & {:keys [entities]
:or {entities as-is}}]
View
21 test/jsql/test/core.clj
@@ -112,3 +112,24 @@
(expect ["DELETE FROM `a` WHERE `b` = ?" 2]
(entities (quoted \`)
(delete :a (where {:b 2}))))
+
+(expect ["INSERT INTO a ( b ) VALUES ( ? )" 2]
+ (insert :a [:b] [2]))
+(expect [["INSERT INTO a ( b ) VALUES ( ? )" 2]]
+ (insert :a {:b 2}))
+(expect ["INSERT INTO a ( b ) VALUES ( ? ), ( ? )" 2 3]
+ (insert :a [:b] [2] [3]))
+(expect ["INSERT INTO a ( b, c, d ) VALUES ( ?, ?, ? ), ( ?, ?, ? )" 2 3 4 3 4 5]
+ (insert :a [:b :c :d] [2 3 4] [3 4 5]))
+(expect [["INSERT INTO a ( b ) VALUES ( ? )" 2]
+ ["INSERT INTO a ( c ) VALUES ( ? )" 3]]
+ (insert :a {:b 2} {:c 3}))
+(expect ["INSERT INTO `a` ( `b` ) VALUES ( ? )" 2]
+ (entities (quoted \`)
+ (insert :a [:b] [2])))
+
+(expect IllegalArgumentException (insert))
+(expect IllegalArgumentException (insert :a))
+(expect IllegalArgumentException (insert :a [:b]))
+(expect IllegalArgumentException (insert :a {:b 1} [:c] [2]))
+(expect IllegalArgumentException (insert :a [:b] [2 3]))
View
15 test/jsql/test/db_ops.clj
@@ -51,7 +51,7 @@
(create-test-table :fruit mysql-db))
(let [result (insert! mysql-db :fruit
{:name "Apple"})]
- (expect {:generated_key 1} result)))
+ (expect [1] result)))
(scenario ;; insert! and query returns inserted row
(jdbc/with-connection mysql-db
@@ -61,7 +61,7 @@
{:name "Apple"})
rows (query mysql-db
(select * :fruit))]
- (expect {:generated_key 1} new-key)
+ (expect [1] new-key)
(expect [{:id 1 :name "Apple" :appearance nil :grade nil :cost nil}] rows)))
(scenario ;; insert! and query returns inserted row
@@ -72,7 +72,7 @@
[:name] ["Apple"])
rows (query mysql-db
(select * :fruit))]
- (expect {:generated_key 1} new-key)
+ (expect [1] new-key)
(expect [{:id 1 :name "Apple" :appearance nil :grade nil :cost nil}] rows)))
(scenario ;; insert! two records and query returns inserted rows
@@ -85,8 +85,7 @@
rows (query mysql-db
(select * :fruit
(order-by :id)))]
- (expect [{:generated_key 1}
- {:generated_key 2}] new-key)
+ (expect [1 2] new-key)
(expect [{:id 1 :name "Apple" :appearance nil :grade nil :cost nil}
{:id 2 :name "Pear" :appearance nil :grade nil :cost nil}] rows)))
@@ -99,7 +98,7 @@
rows (query mysql-db
(select * :fruit
(order-by :id)))]
- (expect [1 1] update-counts)
+ (expect [2] update-counts)
(expect [{:id 1 :name "Apple" :appearance nil :grade nil :cost nil}
{:id 2 :name "Pear" :appearance nil :grade nil :cost nil}] rows)))
@@ -114,7 +113,7 @@
(where {:id 1}))
rows (query mysql-db
(select * :fruit))]
- (expect {:generated_key 1} new-key)
+ (expect [1] new-key)
(expect [1] update-result)
(expect [{:id 1 :name "Apple" :appearance "Green" :grade 1.2 :cost 12}] rows)))
@@ -128,7 +127,7 @@
(where {:id 1}))
rows (query mysql-db
(select * :fruit))]
- (expect {:generated_key 1} new-key)
+ (expect [1] new-key)
(expect [1] delete-result)
(expect [] rows)))

0 comments on commit 16e5b85

Please sign in to comment.