Allow execute! on a PreparedStatement

Refactors reduce of prepared statement so it can be reused.
Remove options from `mapify-result-set` until option handling is figured out.
This commit is contained in:
Sean Corfield 2019-01-10 11:35:17 -08:00
parent a99b4542ca
commit 4ae5b44a52

View file

@ -344,7 +344,7 @@
Later we may realize a new hash map when assoc (and other, future, operations Later we may realize a new hash map when assoc (and other, future, operations
are performed on the result set row)." are performed on the result set row)."
[^ResultSet rs opts] [^ResultSet rs]
(let [cols (delay (get-column-names rs))] (let [cols (delay (get-column-names rs))]
(reify (reify
@ -380,29 +380,37 @@
(.getObject rs i))) (.getObject rs i)))
(range 1 (inc (count @cols))))))))) (range 1 (inc (count @cols)))))))))
(defn- reduce-stmt
""
[^PreparedStatement stmt f init]
(if (.execute stmt)
(let [rs (.getResultSet stmt)
rs-map (mapify-result-set rs)]
(loop [init' init]
(if (.next rs)
(let [result (f init' rs-map)]
(if (reduced? result)
@result
(recur result)))
init')))
(.getUpdateCount stmt)))
(defn execute! (defn execute!
"General SQL execution function. Returns a reducible that, when reduced, "General SQL execution function.
runs the SQL and yields the result."
[db-spec sql-params & [opts]] Returns a reducible that, when reduced, runs the SQL and yields the result."
(let [opts (merge (when (map? db-spec) db-spec) opts)] ([stmt]
(reify clojure.lang.IReduceInit (reify clojure.lang.IReduceInit
(reduce [this f init] (reduce [this f init] (reduce-stmt stmt f init))))
(with-open [con (get-connection db-spec)] ([connectable sql-params & [opts]]
(with-open [stmt (prepare con sql-params opts)] (let [opts (merge (when (map? connectable) connectable) opts)]
(if (.execute stmt) (reify clojure.lang.IReduceInit
(let [rs (.getResultSet stmt) (reduce [this f init]
rs-map (mapify-result-set rs opts)] (with-open [con (get-connection connectable)]
(loop [init' init] (with-open [stmt (prepare con sql-params opts)]
(if (.next rs) (reduce-stmt stmt f init))))))))
(let [result (f init' rs-map)]
(if (reduced? result)
@result
(recur result)))
init')))
(.getUpdateCount stmt))))))))
(comment (comment
(def db-spec {:dbtype "mysql" :dbname "worldsingles" :user "root" :password "visual" :useSSL false})
(def db-spec {:dbtype "h2:mem" :dbname "perf"}) (def db-spec {:dbtype "h2:mem" :dbname "perf"})
(def con db-spec) (def con db-spec)
(def con (get-connection db-spec)) (def con (get-connection db-spec))
@ -416,6 +424,19 @@
(require '[criterium.core :refer [bench quick-bench]]) (require '[criterium.core :refer [bench quick-bench]])
;; calibrate ;; calibrate
(quick-bench (reduce + (take 10e6 (range)))) (quick-bench (reduce + (take 10e6 (range))))
(with-open [ps (prepare con ["select * from fruit where appearance = ?"] {})]
(quick-bench
(reduce (fn [_ row] (reduced (:name row)))
nil
(execute! (set-parameters ps ["red"])))))
(with-open [ps (prepare con ["select * from fruit where appearance = ?"] {})]
(quick-bench
[(reduce (fn [_ row] (reduced (:name row)))
nil
(execute! (set-parameters ps ["red"])))
(reduce (fn [_ row] (reduced (:name row)))
nil
(execute! (set-parameters ps ["fuzzy"])))]))
(quick-bench (quick-bench
(reduce (fn [_ row] (reduced (:name row))) (reduce (fn [_ row] (reduced (:name row)))
nil nil