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 <?]]
[cljs.core.async.macros :refer [go]]))
(:require
[datomish.sqlite :as s]
[datomish.sqlite-schema :as ss]
[datomish.query :as dq]
#?@(:clj
[[datomish.jdbc-sqlite]
[datomish.pair-chan :refer [go-pair <?]]
[datomish.util :refer [while-let]]
[clojure.core.async :refer
[go ; macro in cljs.
<! >! chan close! take!]]])
#?@(:cljs
[[datomish.promise-sqlite]
[datomish.pair-chan]
[datomish.util]
[cljs.core.async :as a :refer
[<! >! chan close! take!]]])))
[datomish.sqlite :as s]
[datomish.sqlite-schema :as ss]
[datomish.query :as dq]
#?@(:clj
[[datomish.jdbc-sqlite]
[datomish.pair-chan :refer [go-pair <?]]
[datomish.util :refer [while-let]]
[clojure.core.async :refer
[go ; macro in cljs.
<! >! chan close! take!]]])
#?@(:cljs
[[datomish.promise-sqlite]
[datomish.pair-chan]
[datomish.util]
[cljs.core.async :as a :refer
[<! >! chan close! take!]]])))
(defn <?run
"Execute the provided query on the provided DB.
Returns a transduced channel of [result err] pairs.
Closes the channel when fully consumed."
[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))
chan (chan 50 row-pair-transducer)]

View file

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