Pass a Context into query.

This commit is contained in:
Nick Alexander 2016-07-15 12:45:50 -07:00 committed by Richard Newman
parent f4b9b867a4
commit 9ae9a0572b
2 changed files with 41 additions and 32 deletions

View file

@ -9,29 +9,30 @@
[datomish.pair-chan :refer [go-pair <?]] [datomish.pair-chan :refer [go-pair <?]]
[cljs.core.async.macros :refer [go]])) [cljs.core.async.macros :refer [go]]))
(:require (:require
[datomish.sqlite :as s] [datomish.sqlite :as s]
[datomish.sqlite-schema :as ss] [datomish.sqlite-schema :as ss]
[datomish.query :as dq] [datomish.query :as dq]
#?@(:clj #?@(:clj
[[datomish.jdbc-sqlite] [[datomish.jdbc-sqlite]
[datomish.pair-chan :refer [go-pair <?]] [datomish.pair-chan :refer [go-pair <?]]
[datomish.util :refer [while-let]] [datomish.util :refer [while-let]]
[clojure.core.async :refer [clojure.core.async :refer
[go ; macro in cljs. [go ; macro in cljs.
<! >! chan close! take!]]]) <! >! chan close! take!]]])
#?@(:cljs #?@(:cljs
[[datomish.promise-sqlite] [[datomish.promise-sqlite]
[datomish.pair-chan] [datomish.pair-chan]
[datomish.util] [datomish.util]
[cljs.core.async :as a :refer [cljs.core.async :as a :refer
[<! >! chan close! take!]]]))) [<! >! chan close! take!]]])))
(defn <?run (defn <?run
"Execute the provided query on the provided DB. "Execute the provided query on the provided DB.
Returns a transduced channel of [result err] pairs. Returns a transduced channel of [result err] pairs.
Closes the channel when fully consumed." Closes the channel when fully consumed."
[db find] [db find]
(let [context (dq/find->prepared-context (dq/parse find)) (let [initial-context (dq/make-context)
context (dq/expand-find-into-context initial-context (dq/parse find))
row-pair-transducer (dq/row-pair-transducer context (dq/sql-projection context)) row-pair-transducer (dq/row-pair-transducer context (dq/sql-projection context))
chan (chan 50 row-pair-transducer)] chan (chan 50 row-pair-transducer)]

View file

@ -52,10 +52,16 @@
(or (-> context :bindings variable first) (or (-> context :bindings variable first)
(raise (str "Couldn't find variable " variable)))) (raise (str "Couldn't find variable " variable))))
(defn make-context [] (defn make-context
(->Context [] {} [] [] ([]
transforms/attribute-transform-string (make-context transforms/attribute-transform-string transforms/constant-transform-default))
transforms/constant-transform-default)) ([attribute-transform constant-transform]
(map->Context {:from []
:bindings {}
:wheres []
:elements []
:attribute-transform attribute-transform
:constant-transform constant-transform})))
(defn apply-pattern-to-context (defn apply-pattern-to-context
"Transform a DataScript Pattern instance into the parts needed "Transform a DataScript Pattern instance into the parts needed
@ -127,10 +133,10 @@
(defn apply-elements-to-context [context elements] (defn apply-elements-to-context [context elements]
(assoc context :elements elements)) (assoc context :elements elements))
(defn patterns->context (defn expand-patterns-into-context
"Turn a sequence of patterns into a Context." "Reduce a sequence of patterns into a Context."
[patterns] [context patterns]
(reduce apply-pattern-to-context (make-context) patterns)) (reduce apply-pattern-to-context context patterns))
(defn sql-projection (defn sql-projection
"Take a `find` clause's `:elements` list and turn it into a SQL "Take a `find` clause's `:elements` list and turn it into a SQL
@ -192,7 +198,7 @@
(= "$" (name (-> in first :variable :symbol)))) (= "$" (name (-> in first :variable :symbol))))
(raise (str "Complex `in` not supported: " (print-str in))))) (raise (str "Complex `in` not supported: " (print-str in)))))
(defn find->prepared-context [find] (defn expand-find-into-context [context find]
;; There's some confusing use of 'where' and friends here. That's because ;; There's some confusing use of 'where' and friends here. That's because
;; the parsed Datalog includes :where, and it's also input to honeysql's ;; the parsed Datalog includes :where, and it's also input to honeysql's
;; SQL formatter. ;; SQL formatter.
@ -201,24 +207,26 @@
(validate-in in) (validate-in in)
(apply-elements-to-context (apply-elements-to-context
(expand-where-from-bindings (expand-where-from-bindings
(patterns->context where)) ; 'where' here is the Datalog :where clause. (expand-patterns-into-context context where)) ; 'where' here is the Datalog :where clause.
(:elements find)))) (:elements find))))
(defn find->sql-clause (defn find->sql-clause
"Take a parsed `find` expression and turn it into a structured SQL "Take a parsed `find` expression and turn it into a structured SQL
expression that can be formatted by honeysql." expression that can be formatted by honeysql."
[find] [context find]
;; There's some confusing use of 'where' and friends here. That's because ;; There's some confusing use of 'where' and friends here. That's because
;; the parsed Datalog includes :where, and it's also input to honeysql's ;; the parsed Datalog includes :where, and it's also input to honeysql's
;; SQL formatter. ;; SQL formatter.
(-> find find->prepared-context context->sql-clause)) (->> find
(expand-find-into-context context)
context->sql-clause))
(defn find->sql-string (defn find->sql-string
"Take a parsed `find` expression and turn it into SQL." "Take a parsed `find` expression and turn it into SQL."
[find] [context find]
(-> (->>
find find
find->sql-clause (find->sql-clause context)
(sql/format :quoting sql-quoting-style))) (sql/format :quoting sql-quoting-style)))
(defn parse (defn parse