|
29 | 29 | (:import [java.sql PreparedStatement SQLException]) |
30 | 30 | (:gen-class)) |
31 | 31 |
|
32 | | -(def DB_EXEC_MODE_QUERY "query") |
33 | | -(def DB_EXEC_MODE_EXEC "execute") |
| 32 | +(def DB_EXEC_MODE_QUERY "query") |
| 33 | +(def DB_EXEC_MODE_QUERY_CURSOR "query_cursor") |
| 34 | +(def DB_EXEC_MODE_EXEC "execute") |
34 | 35 |
|
35 | 36 | ;; Error handling ---------------------------------------------------------------------------- |
36 | 37 |
|
|
669 | 670 | detail-map)) |
670 | 671 |
|
671 | 672 |
|
| 673 | +(defn sql-cursor->result-set-fn-results [ |
| 674 | + conn |
| 675 | + [sql & params :as sql-params] |
| 676 | + result-set-fn & |
| 677 | + [{:keys [transaction? as-arrays? fetch-size] :as opt-map}]] |
| 678 | + |
| 679 | + """ |
| 680 | + Runs the provided SQL and passes the result set cursor to the provided |
| 681 | + result set function. Using a cursor allows rows to be fetched in batches |
| 682 | + (of size (:fetch-size opt-map)), but requires the a function to process |
| 683 | + results due to the need to manage the transaction and cursor requirements |
| 684 | + properly (i.e. ensure auto commit is off, that the cursor is closed, etc.) |
| 685 | +
|
| 686 | + The interface works with parameters as expected by other clojure.java.jdbc |
| 687 | + function. |
| 688 | +
|
| 689 | + TODO: Add handling of :multi? opt key |
| 690 | + """ |
| 691 | + |
| 692 | + ; Factored out body of function: |
| 693 | + (let [ |
| 694 | + body-fn |
| 695 | + (fn fn-body-sql->cursor [ |
| 696 | + conn |
| 697 | + [sql & params :as sql-params] & |
| 698 | + [{:keys [transaction? as-arrays? fetch-size] :as opt-map}]] |
| 699 | + |
| 700 | + (let [fetch-size (or fetch-size 1000)] |
| 701 | + |
| 702 | + (with-open [ |
| 703 | + cursor |
| 704 | + (let [stmt (.prepareStatement (:connection conn) sql)] |
| 705 | + (doseq [[index value] (map vector (iterate inc 1) params)] |
| 706 | + (.setObject stmt index value)) |
| 707 | + (.setFetchSize stmt fetch-size) |
| 708 | + (.executeQuery stmt))] |
| 709 | + |
| 710 | + (result-set-fn |
| 711 | + (if (true? as-arrays?) |
| 712 | + (do (map #(into [] (vals %)) (resultset-seq cursor))) |
| 713 | + (do (resultset-seq cursor)))))))] |
| 714 | + |
| 715 | + ; Run the body optionally wrapped in a transaction |
| 716 | + (let [auto-commit-val (.getAutoCommit (:connection conn))] |
| 717 | + (if (or transaction? auto-commit-val) |
| 718 | + (do |
| 719 | + (.setAutoCommit (:connection conn) false) |
| 720 | + (clojure.java.jdbc/with-db-transaction [conn (dbconfig {} "connection")] |
| 721 | + (body-fn conn sql-params opt-map)) |
| 722 | + (when (true? auto-commit-val) |
| 723 | + (.commit (:connection conn)) |
| 724 | + (.setAutoCommit (:connection conn) auto-commit-val))) |
| 725 | + (do (body-fn conn sql-params opt-map)))))) |
| 726 | + |
| 727 | + |
672 | 728 | (defn run-statement |
673 | 729 | [conn {:keys [stmt-text exec-mode op-comment binds opt-map commit?] :as stmt-detail-map}] |
674 | 730 |
|
|
686 | 742 | (let [updated-map |
687 | 743 | (assoc-in stmt-detail-map [:result] |
688 | 744 | (cond |
689 | | - (= exec-mode DB_EXEC_MODE_QUERY) |
| 745 | + (and (:result-set-fn opt-map) (= exec-mode DB_EXEC_MODE_QUERY_CURSOR)) |
| 746 | + ; Execute query using cursor to fetch results in batches (requires a |
| 747 | + ; result set function that processes rows) |
| 748 | + (do |
| 749 | + (log/debug |
| 750 | + "Issuing statement as query with cursor and batch " |
| 751 | + "fetching (results expected) ...") |
| 752 | + (sql-cursor->result-set-fn-results conn sql-params (:result-set-fn opt-map) opt-map)) |
| 753 | + (or |
| 754 | + (= exec-mode DB_EXEC_MODE_QUERY) |
| 755 | + (and (= exec-mode DB_EXEC_MODE_QUERY_CURSOR) (not (:result-set-fn opt-map)))) |
| 756 | + ; Execute a query using clojure query function; all results |
| 757 | + ; are materialized during the fetch |
690 | 758 | (do |
691 | 759 | (log/debug "Issuing statement as query (results expected) ...") |
692 | 760 | (clojure.java.jdbc/query conn sql-params opt-map)) |
|
729 | 797 | (for [stmt-detail-map stmt-detail-vec] |
730 | 798 | (run-statement conn stmt-detail-map)))))) |
731 | 799 |
|
| 800 | + |
0 commit comments