summaryrefslogtreecommitdiff
path: root/src/clojure_sql/core.clj
blob: 01e128dd0b30ea3636055a6cf83439519e5819b4 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
(ns clojure-sql.core
  (:refer-clojure :exclude [sort take drop])
  (:require [clojure.set :as set]
            [clojure-sql.compiler :as c]
            [clojure-sql.dsl :as d]
            [clojure-sql.query :as q]
            [clojure-sql.util :as u]
            [clojure.walk]))

(defmacro ^:private pull [ns & vlist]
  `(do ~@(for [i vlist
               :let [sym (symbol (name ns) (name i))]] 
           `(def ~(with-meta i
                    (u/map-vals (fn [x] `(quote ~x)) (meta (resolve sym))))
              ~sym))
       nil))

(pull clojure-sql.dsl
      table join
      project rename
      prefix-names-matching prefix-names as-subobject
      select
      group having
      sort take drop
      union intersection)


(def ^:private ^:dynamic *database-type* nil)
(defn set-database-type! [new-type]
  (alter-var-root #'*database-type* (constantly new-type))
  nil)

(def ^:private ^:dynamic *query-executor* (comp second vector))
(defn set-query-executor! [exec-fn]
  (alter-var-root #'*query-executor* (constantly exec-fn))
  nil)



(defmethod print-method clojure_sql.query.Query [query writer]
  (binding [*out* writer]
    (pr (c/compile-select *database-type* query))))


(defn run-query
  "Run a select query. Return value is determined by query executor."
  [query]
  (assert *query-executor* "Cannot execute a query without a query executor")
  (*query-executor* :select (c/compile-select *database-type* query)))

(defn insert!
  "Insert a number of records into a table, setting each column to the
  corresponding value from the record. Return value is determined by
  query executor."
  [query & records]
  (assert *query-executor* "Cannot execute a query without a query executor")
  (let [compiled (apply c/compile-insert *database-type* query records)]
    (*query-executor* :insert compiled)))

(defn update!
  "Update everything which would have been selected by the query,
  setting each field in the query to the corresponding column in the
  table. Return value is determined by query executor.

  NOTE: if the map does not have a given key then this will result in
  a NULL being included in the query. To avoid this restrict the query
  with `project` before calling `update!`."

  [query partial-record]
  (assert *query-executor* "Cannot execute a query without a query executor")
  (let [compiled (c/compile-update *database-type* query partial-record)]
    (*query-executor* :update compiled)))

(defn delete!
  "Delete everything which would have been selected by the
  query. Return value is determined by query executor."
  [query]
  (assert *query-executor* "Cannot execute a query without a query executor")
  (let [compiled (c/compile-delete *database-type* query)]
    (*query-executor* :delete compiled)))

(q/set-query-deref-behaviour! run-query)

(let [users (-> (table :users)
                (project [:id :email]))
      people (-> (table :people)
                 (project [:id :name]))]
  (join (rename users (as-subobject :user))
        (rename people (as-subobject :person))
        :on `(= :user.id :person.id)))