2021-01-30 00:11:52 +00:00
|
|
|
;; copyright (c) 2020-2021 sean corfield, all rights reserved
|
2020-09-28 20:47:55 +00:00
|
|
|
|
|
|
|
|
(ns honey.sql.helpers
|
|
|
|
|
"Helper functions for the built-in clauses in honey.sql."
|
2021-02-11 00:25:31 +00:00
|
|
|
(:refer-clojure :exclude [update set group-by for partition-by])
|
2021-02-14 19:37:27 +00:00
|
|
|
(:require [honey.sql]))
|
|
|
|
|
|
|
|
|
|
;; implementation helpers:
|
2020-09-28 20:47:55 +00:00
|
|
|
|
|
|
|
|
(defn- default-merge [current args]
|
|
|
|
|
(into (vec current) args))
|
|
|
|
|
|
2020-10-10 06:05:05 +00:00
|
|
|
(defn- and-merge
|
|
|
|
|
[current args]
|
2020-10-13 01:37:28 +00:00
|
|
|
(let [args (remove nil? args)]
|
|
|
|
|
(cond (= :and (first current))
|
|
|
|
|
(default-merge current args)
|
|
|
|
|
(seq current)
|
|
|
|
|
(if (seq args)
|
|
|
|
|
(default-merge [:and current] args)
|
|
|
|
|
current)
|
|
|
|
|
(= 1 (count args))
|
|
|
|
|
(vec (first args))
|
|
|
|
|
(seq args)
|
|
|
|
|
(default-merge [:and] args)
|
|
|
|
|
:else
|
|
|
|
|
(vec current))))
|
2020-10-10 06:05:05 +00:00
|
|
|
|
2020-09-28 20:47:55 +00:00
|
|
|
(def ^:private special-merges
|
2020-10-10 06:05:05 +00:00
|
|
|
{:where #'and-merge
|
|
|
|
|
:having #'and-merge})
|
2020-09-28 20:47:55 +00:00
|
|
|
|
|
|
|
|
(defn- helper-merge [data k args]
|
|
|
|
|
(let [merge-fn (special-merges k default-merge)]
|
|
|
|
|
(clojure.core/update data k merge-fn args)))
|
|
|
|
|
|
|
|
|
|
(defn- generic [k args]
|
|
|
|
|
(if (map? (first args))
|
|
|
|
|
(let [[data & args] args]
|
|
|
|
|
(helper-merge data k args))
|
|
|
|
|
(helper-merge {} k args)))
|
|
|
|
|
|
2020-10-10 06:05:05 +00:00
|
|
|
(defn- generic-1 [k [data arg]]
|
2020-10-10 06:59:30 +00:00
|
|
|
(if arg
|
2020-10-10 06:05:05 +00:00
|
|
|
(assoc data k arg)
|
|
|
|
|
(assoc {} k data)))
|
|
|
|
|
|
2021-02-14 19:37:27 +00:00
|
|
|
;; for every clause, there is a public helper
|
|
|
|
|
|
|
|
|
|
(defn alter-table
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :alter-table args))
|
|
|
|
|
|
|
|
|
|
(defn add-column
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :add-column args))
|
|
|
|
|
|
|
|
|
|
(defn drop-column
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :drop-column args))
|
|
|
|
|
|
|
|
|
|
(defn modify-column
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :modify-column args))
|
|
|
|
|
|
|
|
|
|
(defn rename-column
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :rename-column args))
|
|
|
|
|
|
|
|
|
|
(defn add-index
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :add-index args))
|
|
|
|
|
|
|
|
|
|
(defn drop-index
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :drop-index args))
|
|
|
|
|
|
|
|
|
|
(defn rename-table
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :rename-table args))
|
|
|
|
|
|
|
|
|
|
(defn create-table
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :create-table args))
|
|
|
|
|
|
|
|
|
|
(defn create-extension
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :create-extension args))
|
|
|
|
|
|
|
|
|
|
(defn with-columns
|
|
|
|
|
[& args]
|
2021-02-13 18:50:36 +00:00
|
|
|
;; special case so (with-columns [[:col-1 :definition] [:col-2 :definition]])
|
|
|
|
|
;; also works in addition to (with-columns [:col-1 :definition] [:col-2 :definition])
|
|
|
|
|
(cond (and (= 1 (count args)) (sequential? (first args)) (sequential? (ffirst args)))
|
|
|
|
|
(generic-1 :with-columns args)
|
|
|
|
|
(and (= 2 (count args)) (sequential? (second args)) (sequential? (fnext args)))
|
|
|
|
|
(generic-1 :with-columns args)
|
|
|
|
|
:else
|
|
|
|
|
(generic :with-columns args)))
|
2021-02-14 19:37:27 +00:00
|
|
|
|
|
|
|
|
(defn create-view
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :create-view args))
|
|
|
|
|
|
|
|
|
|
(defn drop-table
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :drop-table args))
|
|
|
|
|
|
|
|
|
|
(defn drop-extension
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :drop-extension args))
|
|
|
|
|
|
|
|
|
|
(defn nest
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :nest args))
|
|
|
|
|
|
|
|
|
|
(defn with
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :with args))
|
|
|
|
|
|
|
|
|
|
(defn with-recursive
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :with-recursive args))
|
|
|
|
|
|
2021-02-01 22:49:17 +00:00
|
|
|
;; these five need to supply an empty hash map since they wrap
|
|
|
|
|
;; all of their arguments:
|
2021-02-14 19:37:27 +00:00
|
|
|
(defn intersect
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :intersect (cons {} args)))
|
|
|
|
|
|
|
|
|
|
(defn union
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :union (cons {} args)))
|
|
|
|
|
|
|
|
|
|
(defn union-all
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :union-all (cons {} args)))
|
|
|
|
|
|
|
|
|
|
(defn except
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :except (cons {} args)))
|
|
|
|
|
|
|
|
|
|
(defn except-all
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :except-all (cons {} args)))
|
|
|
|
|
|
|
|
|
|
(defn select
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :select args))
|
|
|
|
|
|
|
|
|
|
(defn select-distinct
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :select-distinct args))
|
|
|
|
|
|
|
|
|
|
(defn select-distinct-on
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :select-distinct-on args))
|
|
|
|
|
|
|
|
|
|
(defn insert-into
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :insert-into args))
|
|
|
|
|
|
|
|
|
|
(defn update
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :update args))
|
|
|
|
|
|
|
|
|
|
(defn delete
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :delete args))
|
|
|
|
|
|
|
|
|
|
(defn delete-from
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :delete-from args))
|
|
|
|
|
|
|
|
|
|
(defn truncate
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :truncate args))
|
|
|
|
|
|
|
|
|
|
(defn columns
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :columns args))
|
|
|
|
|
|
|
|
|
|
(defn set
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :set args))
|
|
|
|
|
|
|
|
|
|
(defn from
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :from args))
|
|
|
|
|
|
|
|
|
|
(defn using
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :using args))
|
|
|
|
|
|
|
|
|
|
(defn join
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :join args))
|
|
|
|
|
|
|
|
|
|
(defn left-join
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :left-join args))
|
|
|
|
|
|
|
|
|
|
(defn right-join
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :right-join args))
|
|
|
|
|
|
|
|
|
|
(defn inner-join
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :inner-join args))
|
|
|
|
|
|
|
|
|
|
(defn outer-join
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :outer-join args))
|
|
|
|
|
|
|
|
|
|
(defn full-join
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :full-join args))
|
|
|
|
|
|
|
|
|
|
(defn cross-join
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :cross-join args))
|
|
|
|
|
|
|
|
|
|
(defn where
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :where args))
|
|
|
|
|
|
|
|
|
|
(defn group-by
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :group-by args))
|
|
|
|
|
|
|
|
|
|
(defn having
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :having args))
|
|
|
|
|
|
|
|
|
|
(defn window
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :window args))
|
|
|
|
|
|
|
|
|
|
(defn partition-by
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :partition-by args))
|
|
|
|
|
|
|
|
|
|
(defn order-by
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :order-by args))
|
|
|
|
|
|
|
|
|
|
(defn limit
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :limit args))
|
|
|
|
|
|
|
|
|
|
(defn offset
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :offset args))
|
|
|
|
|
|
|
|
|
|
(defn for
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :for args))
|
|
|
|
|
|
|
|
|
|
(defn values
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :values args))
|
|
|
|
|
|
|
|
|
|
(defn on-conflict
|
|
|
|
|
[& args]
|
|
|
|
|
(generic-1 :on-conflict args))
|
|
|
|
|
|
|
|
|
|
(defn on-constraint
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :on-constraint args))
|
|
|
|
|
|
|
|
|
|
(defn do-nothing
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :do-nothing args))
|
|
|
|
|
|
|
|
|
|
(defn do-update-set
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :do-update-set args))
|
|
|
|
|
|
|
|
|
|
(defn returning
|
|
|
|
|
[& args]
|
|
|
|
|
(generic :returning args))
|
2020-09-28 20:47:55 +00:00
|
|
|
|
2020-10-12 18:42:47 +00:00
|
|
|
;; helpers that produce non-clause expressions -- must be listed below:
|
2021-02-14 19:37:27 +00:00
|
|
|
(defn composite
|
|
|
|
|
[& args]
|
|
|
|
|
(into [:composite] args))
|
|
|
|
|
|
2021-02-11 00:25:31 +00:00
|
|
|
;; to make this easy to use in a select, wrap it so it becomes a function:
|
2021-02-14 19:37:27 +00:00
|
|
|
(defn over
|
|
|
|
|
[& args]
|
|
|
|
|
[(into [:over] args)])
|
2020-10-12 18:42:47 +00:00
|
|
|
|
2021-02-14 03:08:40 +00:00
|
|
|
;; this helper is intended to ease the migration from nilenso:
|
|
|
|
|
(defn upsert
|
|
|
|
|
([clause] (upsert {} clause))
|
|
|
|
|
([data clause]
|
|
|
|
|
(let [{:keys [on-conflict do-nothing do-update-set where]} clause]
|
|
|
|
|
(cond-> data
|
|
|
|
|
on-conflict
|
|
|
|
|
(assoc :on-conflict on-conflict)
|
|
|
|
|
do-nothing
|
|
|
|
|
(assoc :do-nothing do-nothing)
|
|
|
|
|
do-update-set
|
|
|
|
|
(assoc :do-update-set (if where
|
|
|
|
|
{:fields do-update-set
|
|
|
|
|
:where where}
|
|
|
|
|
do-update-set))))))
|
2021-02-13 18:50:36 +00:00
|
|
|
|
2020-09-28 20:47:55 +00:00
|
|
|
#?(:clj
|
2021-02-14 19:37:27 +00:00
|
|
|
(assert (= (clojure.core/set (conj @@#'honey.sql/base-clause-order
|
2021-02-13 18:50:36 +00:00
|
|
|
:composite :over :upsert))
|
2020-09-28 20:47:55 +00:00
|
|
|
(clojure.core/set (map keyword (keys (ns-publics *ns*)))))))
|