PageRenderTime 35ms CodeModel.GetById 9ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lobos/internal.clj

http://github.com/budu/lobos
Clojure | 132 lines | 101 code | 18 blank | 13 comment | 2 complexity | 6c011d9a991b27b503e0a6fe7c7a97ae MD5 | raw file
  1; Copyright (c) Nicolas Buduroi. All rights reserved.
  2; The use and distribution terms for this software are covered by the
  3; Eclipse Public License 1.0 which can be found in the file
  4; epl-v10.html at the root of this distribution. By using this software
  5; in any fashion, you are agreeing to be bound by the terms of this
  6; license.
  7; You must not remove this notice, or any other, from this software.
  8
  9(ns lobos.internal
 10  (:refer-clojure :exclude [defonce])
 11  (:require (lobos [compiler :as compiler]
 12                   [connectivity :as conn]
 13                   [metadata :as metadata]
 14                   [schema :as schema]))
 15  (:use (clojure.tools [macro :only [name-with-attributes]])
 16        lobos.utils))
 17
 18(defonce debug-level
 19  (atom nil)
 20  "This atom keeps the currently set debug level, see
 21  `set-debug-level`. *For internal use*.")
 22
 23;; -----------------------------------------------------------------------------
 24
 25;; ## Statement Execution Helpers
 26
 27(defn autorequire-backend
 28  "Automatically require the backend for the given connection-info."
 29  [connection-info]
 30  (if (:subprotocol connection-info)
 31    (->> connection-info
 32         :subprotocol
 33         (str "lobos.backends.")
 34         symbol
 35         require)
 36    (throw (Exception. "The :subprotocol key is missing from db-spec."))))
 37
 38(defn- execute*
 39  "Execute the given SQL string or sequence of strings. Prints them if
 40  the `debug-level` is set to `:sql`."
 41  [sql]
 42  (doseq [sql-string (if (seq? sql) sql [sql])]
 43    (when (= :sql @debug-level) (println sql-string))
 44    (with-open [stmt (.createStatement (conn/connection))]
 45      (.execute stmt sql-string))))
 46
 47(defn execute
 48  "Executes the given statement(s) using the specified connection
 49  information, the bound one or the default connection. It will executes
 50  an extra *mode* statement if defined by the backend compiler. *For
 51  internal purpose*."
 52  [statements & [connection-info]]
 53  (let [statements (if (seq? statements)
 54                     statements
 55                     [statements])
 56        db-spec (conn/get-db-spec connection-info)
 57        mode (compiler/compile (compiler/mode db-spec))]
 58    (conn/with-connection connection-info
 59      (autorequire-backend connection-info)
 60      (when mode (execute* mode))
 61      (doseq [statement statements]
 62        (let [sql (if (string? statement)
 63                           statement
 64                           (compiler/compile statement))]
 65          (when sql (execute* sql)))))) nil)
 66
 67;; -----------------------------------------------------------------------------
 68
 69;; ## Optional Arguments Helpers
 70
 71(defn optional-cnx-or-schema [args]
 72  (let [[cnx-or-schema args]
 73        (optional #(or (schema/schema? %)
 74                       (and (-> % schema/definition? not)
 75                            (conn/connection? %))) args)
 76        args* args
 77        schema (when (schema/schema? cnx-or-schema) cnx-or-schema)
 78        cnx (or (conn/find-connection)
 79                (-> schema :options :db-spec)
 80                (when-not schema cnx-or-schema)
 81                :default-connection)
 82        db-spec (merge (conn/get-db-spec cnx)
 83                       (when schema
 84                         {:schema (-> schema :sname name)}))]
 85    [db-spec schema args]))
 86
 87(defn optional-cnx-and-sname [args]
 88  (let [[db-spec schema args] (optional-cnx-or-schema args)
 89        [sname args] (conn/with-connection db-spec
 90                       (optional #(or (nil? %)
 91                                      ((set (metadata/schemas)) %)) args))
 92        sname (or sname (:name schema))]
 93    [db-spec sname args]))
 94
 95;; -----------------------------------------------------------------------------
 96
 97;; ## DML Helpers
 98
 99(defn raw-query [sql-string]
100  (with-open [stmt (.createStatement (conn/connection))]
101    (let [resultset (.executeQuery stmt sql-string)]
102      (when resultset
103        (doall (resultset-seq resultset))))))
104
105(defn raw-update [sql-string]
106  (with-open [stmt (.createStatement (conn/connection))]
107    (.executeUpdate stmt sql-string)))
108
109(defn sql-from-where [db-spec stmt sname tname where-expr]
110  (do
111    (require (symbol (str "lobos.backends."
112                          (:subprotocol db-spec))))
113      (str stmt
114           " from "
115           (compiler/as-identifier db-spec tname sname)
116           (when where-expr
117             (str
118              " where "
119              (compiler/compile
120               (schema/build-definition where-expr db-spec)))))))
121
122(defmacro query [db-spec sname tname & [conditions]]
123  `(raw-query
124    (sql-from-where ~db-spec "select *" ~sname ~tname
125                    (when-not ~(nil? conditions)
126                      (schema/expression ~conditions)))))
127
128(defmacro delete [db-spec sname tname & [conditions]]
129  `(raw-update
130    (sql-from-where ~db-spec "delete" ~sname ~tname
131                    (when-not ~(nil? conditions)
132                      (schema/expression ~conditions)))))