diff --git a/backend/src/app/db.clj b/backend/src/app/db.clj index 4a583256ef..e17bc21b25 100644 --- a/backend/src/app/db.clj +++ b/backend/src/app/db.clj @@ -10,19 +10,20 @@ [app.common.data :as d] [app.common.exceptions :as ex] [app.common.geom.point :as gpt] + [app.common.json :as json] [app.common.logging :as l] [app.common.schema :as sm] [app.common.transit :as t] [app.common.uuid :as uuid] [app.db.sql :as sql] [app.metrics :as mtx] - [app.util.json :as json] [app.util.time :as dt] [clojure.java.io :as io] [clojure.set :as set] [integrant.core :as ig] [next.jdbc :as jdbc] [next.jdbc.date-time :as jdbc-dt] + [next.jdbc.prepare :as jdbc.prepare] [next.jdbc.transaction]) (:import com.zaxxer.hikari.HikariConfig @@ -33,6 +34,7 @@ java.io.InputStream java.io.OutputStream java.sql.Connection + java.sql.PreparedStatement java.sql.Savepoint org.postgresql.PGConnection org.postgresql.geometric.PGpoint @@ -404,6 +406,24 @@ :hint "database object not found")) row)) + +(defn get-with-sql + [ds sql & {:as opts}] + (let [rows (cond->> (exec! ds sql opts) + (::remove-deleted opts true) + (remove is-row-deleted?) + + :always + (not-empty))] + + (when (and (not rows) (::throw-if-not-exists opts true)) + (ex/raise :type :not-found + :code :object-not-found + :hint "database object not found")) + + (first rows))) + + (def ^:private default-plan-opts (-> default-opts (assoc :fetch-size 1000) @@ -599,7 +619,7 @@ val (.getValue o)] (if (or (= typ "json") (= typ "jsonb")) - (json/decode val) + (json/decode val :key-fn keyword) val)))) (defn decode-transit-pgobject @@ -640,7 +660,7 @@ (when data (doto (org.postgresql.util.PGobject.) (.setType "jsonb") - (.setValue (json/encode-str data))))) + (.setValue (json/encode data))))) ;; --- Locks @@ -686,3 +706,8 @@ [cause] (and (sql-exception? cause) (= "40001" (.getSQLState ^java.sql.SQLException cause)))) + +(extend-protocol jdbc.prepare/SettableParameter + clojure.lang.Keyword + (set-parameter [^clojure.lang.Keyword v ^PreparedStatement s ^long i] + (.setObject s i ^String (d/name v))))