Roll multi-rs across execute-all for all types

This commit is contained in:
Sean Corfield 2020-06-07 12:13:32 -07:00
parent 92f7923a2a
commit 067919a296
3 changed files with 57 additions and 56 deletions

View file

@ -582,17 +582,25 @@
(.getGeneratedKeys stmt) (.getGeneratedKeys stmt)
(catch Exception _))))) (catch Exception _)))))
(defn- stmt->result-set' (defn- stmt->result-set-update-count
"Given a `PreparedStatement` and options, execute it and return a `ResultSet` "Given a connectable, a `Statement`, a flag indicating there might
if possible." be a result set, and options, return a (datafiable) result set if possible
^ResultSet (either from the statement or from generated keys). If no result set is
[^PreparedStatement stmt go opts] available, return a 'fake' result set containing the update count.
(if go
(.getResultSet stmt) If no update count is available either, return nil."
(when (:return-keys opts) [connectable ^Statement stmt go opts]
(try (if-let [^ResultSet
(.getGeneratedKeys stmt) rs (if go
(catch Exception _))))) (.getResultSet stmt)
(when (:return-keys opts)
(try
(.getGeneratedKeys stmt)
(catch Exception _))))]
(datafiable-result-set rs connectable opts)
(let [n (.getUpdateCount stmt)]
(when-not (= -1 n)
[{:next.jdbc/update-count n}]))))
(defn- reduce-stmt (defn- reduce-stmt
"Execute the `PreparedStatement`, attempt to get either its `ResultSet` or "Execute the `PreparedStatement`, attempt to get either its `ResultSet` or
@ -616,15 +624,14 @@
(defn- stmt-sql->result-set (defn- stmt-sql->result-set
"Given a `Statement`, a SQL command, and options, execute it and return a "Given a `Statement`, a SQL command, and options, execute it and return a
`ResultSet` if possible." `ResultSet` if possible. We always attempt to return keys."
^ResultSet ^ResultSet
[^Statement stmt ^String sql opts] [^Statement stmt ^String sql opts]
(if (.execute stmt sql) (if (.execute stmt sql)
(.getResultSet stmt) (.getResultSet stmt)
(when (:return-keys opts) (try
(try (.getGeneratedKeys stmt)
(.getGeneratedKeys stmt) (catch Exception _))))
(catch Exception _)))))
(defn- reduce-stmt-sql (defn- reduce-stmt-sql
"Execute the SQL command on the given `Statement`, attempt to get either "Execute the SQL command on the given `Statement`, attempt to get either
@ -673,9 +680,14 @@
(first sql-params) (first sql-params)
(rest sql-params) (rest sql-params)
opts)] opts)]
(if-let [rs (stmt->result-set stmt opts)] (if (:multi-rs opts)
(datafiable-result-set rs this opts) (loop [go (.execute stmt) acc [] rsn 0]
[{:next.jdbc/update-count (.getUpdateCount stmt)}]))) (if-let [rs (stmt->result-set-update-count this stmt go opts)]
(recur (.getMoreResults stmt) (conj acc rs) (inc rsn))
acc))
(if-let [rs (stmt->result-set stmt opts)]
(datafiable-result-set rs this opts)
[{:next.jdbc/update-count (.getUpdateCount stmt)}]))))
javax.sql.DataSource javax.sql.DataSource
(-execute [this sql-params opts] (-execute [this sql-params opts]
@ -706,26 +718,11 @@
(first sql-params) (first sql-params)
(rest sql-params) (rest sql-params)
opts)] opts)]
(if-let [multi (:multi-rs opts)] (if (:multi-rs opts)
(loop [go (.execute stmt) acc (if (= :delimited multi) nil []) rsn 0] (loop [go (.execute stmt) acc [] rsn 0]
(let [rs (if-let [rs (stmt->result-set' stmt go opts)] (if-let [rs (stmt->result-set-update-count this stmt go opts)]
(datafiable-result-set rs this opts) (recur (.getMoreResults stmt) (conj acc rs) (inc rsn))
(let [n (.getUpdateCount stmt)] acc))
(if (= -1 n)
nil
[{:next.jdbc/update-count (.getUpdateCount stmt)}])))]
(if-not rs
acc
(recur (.getMoreResults stmt)
(cond (not= :delimited multi)
(conj acc rs)
acc
(-> acc
(conj {:next.jdbc/result-set rsn})
(into rs))
:else
rs)
(inc rsn)))))
(if-let [rs (stmt->result-set stmt opts)] (if-let [rs (stmt->result-set stmt opts)]
(datafiable-result-set rs this opts) (datafiable-result-set rs this opts)
[{:next.jdbc/update-count (.getUpdateCount stmt)}])))) [{:next.jdbc/update-count (.getUpdateCount stmt)}]))))
@ -748,25 +745,27 @@
(.getConnection this) opts))) (.getConnection this) opts)))
{:next.jdbc/update-count (.getUpdateCount this)})) {:next.jdbc/update-count (.getUpdateCount this)}))
(-execute-all [this _ opts] (-execute-all [this _ opts]
(if-let [rs (stmt->result-set this opts)] (if (:multi-rs opts)
(datafiable-result-set rs (.getConnection this) opts) (loop [go (.execute this) acc [] rsn 0]
[{:next.jdbc/update-count (.getUpdateCount this)}])) (if-let [rs (stmt->result-set-update-count (.getConnection this) this go opts)]
(recur (.getMoreResults this) (conj acc rs) (inc rsn))
acc))
(if-let [rs (stmt->result-set this opts)]
(datafiable-result-set rs (.getConnection this) opts)
[{:next.jdbc/update-count (.getUpdateCount this)}])))
java.sql.Statement java.sql.Statement
;; we can't tell if this Statement will return generated
;; keys so we pass a truthy value to at least attempt it if we
;; do not get a ResultSet back from the execute call
(-execute [this sql-params opts] (-execute [this sql-params opts]
(assert (= 1 (count sql-params)) (assert (= 1 (count sql-params))
"Parameters cannot be provided when executing a non-prepared Statement") "Parameters cannot be provided when executing a non-prepared Statement")
(reify clojure.lang.IReduceInit (reify clojure.lang.IReduceInit
(reduce [_ f init] (reduce [_ f init]
(reduce-stmt-sql this (first sql-params) f init (assoc opts :return-keys true))) (reduce-stmt-sql this (first sql-params) f init opts))
(toString [_] "`IReduceInit` from `plan` -- missing reduction?"))) (toString [_] "`IReduceInit` from `plan` -- missing reduction?")))
(-execute-one [this sql-params opts] (-execute-one [this sql-params opts]
(assert (= 1 (count sql-params)) (assert (= 1 (count sql-params))
"Parameters cannot be provided when executing a non-prepared Statement") "Parameters cannot be provided when executing a non-prepared Statement")
(if-let [rs (stmt-sql->result-set this (first sql-params) (assoc opts :return-keys true))] (if-let [rs (stmt-sql->result-set this (first sql-params) opts)]
(let [builder-fn (get opts :builder-fn as-maps) (let [builder-fn (get opts :builder-fn as-maps)
builder (builder-fn rs opts)] builder (builder-fn rs opts)]
(when (.next rs) (when (.next rs)
@ -776,9 +775,15 @@
(-execute-all [this sql-params opts] (-execute-all [this sql-params opts]
(assert (= 1 (count sql-params)) (assert (= 1 (count sql-params))
"Parameters cannot be provided when executing a non-prepared Statement") "Parameters cannot be provided when executing a non-prepared Statement")
(if-let [rs (stmt-sql->result-set this (first sql-params) opts)] (if (:multi-rs opts)
(datafiable-result-set rs (.getConnection this) opts) (loop [go (.execute this (first sql-params)) acc [] rsn 0]
[{:next.jdbc/update-count (.getUpdateCount this)}])) (if-let [rs (stmt->result-set-update-count
(.getConnection this) this go (assoc opts :return-keys true))]
(recur (.getMoreResults this) (conj acc rs) (inc rsn))
acc))
(if-let [rs (stmt-sql->result-set this (first sql-params) opts)]
(datafiable-result-set rs (.getConnection this) opts)
[{:next.jdbc/update-count (.getUpdateCount this)}])))
Object Object
(-execute [this sql-params opts] (-execute [this sql-params opts]

View file

@ -152,7 +152,7 @@ CREATE TABLE " fruit " (
(when (stored-proc?) (when (stored-proc?)
(let [[begin end] (if (postgres?) ["$$" "$$"] ["BEGIN" "END"])] (let [[begin end] (if (postgres?) ["$$" "$$"] ["BEGIN" "END"])]
(try (try
(jdbc/execute-one! con [(str " (do-commands con [(str "
CREATE PROCEDURE FRUITP" (cond (= "hsqldb" (:dbtype db)) "() READS SQL DATA DYNAMIC RESULT SETS 2 " CREATE PROCEDURE FRUITP" (cond (= "hsqldb" (:dbtype db)) "() READS SQL DATA DYNAMIC RESULT SETS 2 "
(mssql?) " AS " (mssql?) " AS "
(postgres?) "() LANGUAGE SQL AS " (postgres?) "() LANGUAGE SQL AS "

View file

@ -317,14 +317,10 @@ VALUES ('Pear', 'green', 49, 47)
(when (stored-proc?) (when (stored-proc?)
(testing "stored proc; multiple result sets" (testing "stored proc; multiple result sets"
(try (try
(println "====" (:dbtype (db)) "==== true") (println "====" (:dbtype (db)) "====")
(clojure.pprint/pprint (clojure.pprint/pprint
(jdbc/execute! (ds) [(if (mssql?) "EXEC FRUITP" "CALL FRUITP()")] (jdbc/execute! (ds) [(if (mssql?) "EXEC FRUITP" "CALL FRUITP()")]
{:multi-rs true})) {:multi-rs true}))
(println "====" (:dbtype (db)) "==== :delimited")
(clojure.pprint/pprint
(jdbc/execute! (ds) [(if (mssql?) "EXEC FRUITP" "CALL FRUITP()")]
{:multi-rs :delimited}))
(catch Throwable t (catch Throwable t
(println 'call-proc (:dbtype (db)) (ex-message t) (some-> t (ex-cause) (ex-message)))))))) (println 'call-proc (:dbtype (db)) (ex-message t) (some-> t (ex-cause) (ex-message))))))))