Last active
January 4, 2022 15:54
-
-
Save source-c/d39499ebb928570c9f04972cfed66719 to your computer and use it in GitHub Desktop.
H2 database upsert implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns com.myproject.model | |
(:require [honey.sql :as sql] | |
[clojure.string :as s])) | |
;; honeysql clause extension | |
;; Updates existing rows, and insert rows that don't exist. | |
;; If no key column is specified, the primary key columns are used to find the row. | |
;; If more than one row per new row is affected, an exception is thrown. | |
(sql/register-clause! :vals | |
(fn [c [pk xs]] | |
(let [cols-1 (keys (first xs)) | |
cols-n (into #{} (mapcat keys) xs) | |
cols (if (= (set cols-1) cols-n) cols-1 cols-n) | |
[sqls params] | |
(reduce (fn [[sql params] [sqls' params']] | |
[(conj sql (str "(" (s/join ", " sqls') ")")) | |
(if params' (into params params') params')]) | |
[[] []] | |
(map (fn [m] | |
(sql/format-expr-list | |
(map #(get m %) cols))) | |
xs))] | |
(into [(str "(" | |
(s/join ", " | |
(map #(sql/format-entity % {:drop-ns true}) cols)) | |
") " | |
(when pk (str (sql/sql-kw :key) "(" | |
(if (sequential? pk) | |
(s/join "," (map #(sql/format-entity % {:drop-ns true}) pk)) | |
(sql/format-entity pk {:drop-ns true})) | |
") ")) | |
(sql/sql-kw :values) | |
" " | |
(s/join ", " sqls))] | |
params))) | |
nil) | |
(sql/register-clause! :merge-into | |
(fn [clause x] | |
(let [[sql & params] | |
(if (ident? x) | |
(sql/format-expr x) | |
(sql/format-dsl x))] | |
(into [(str (sql/sql-kw clause) " " sql)] params))) | |
:vals) ; <!> MERGE INTO ... ... KEY(_pk) VALUES ... | |
;; impl example | |
(defn- upsert [data table & [pk]] | |
(-> {:merge-into table | |
:vals [pk data]} | |
sql/format)) | |
;; usage examples | |
(upsert [{:aa 11 :bb 22}] :table) | |
;; ["MERGE INTO table (aa, bb) VALUES (?, ?)" 11 22] | |
(upsert [{:aa 11 :bb 22}] :table :aa) | |
;; ["MERGE INTO table (aa, bb) KEY(aa) VALUES (?, ?)" 11 22] | |
(upsert [{:aa 11 :bb 22}] :table [:p :s]) | |
;; ["MERGE INTO table (aa, bb) KEY(p,s) VALUES (?, ?)" 11 22] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment