Store elements on the context.
This commit is contained in:
parent
64460f7eef
commit
437a80a978
1 changed files with 42 additions and 21 deletions
|
@ -29,7 +29,7 @@
|
||||||
;; `:bindings` is a map from var to qualified columns.
|
;; `:bindings` is a map from var to qualified columns.
|
||||||
;; `:wheres` is a list of fragments that can be joined by `:and`.
|
;; `:wheres` is a list of fragments that can be joined by `:and`.
|
||||||
;;
|
;;
|
||||||
(defrecord Context [from bindings wheres attribute-transform constant-transform])
|
(defrecord Context [from bindings wheres elements attribute-transform constant-transform])
|
||||||
|
|
||||||
(defn attribute-in-context [context attribute]
|
(defn attribute-in-context [context attribute]
|
||||||
((:attribute-transform context) attribute))
|
((:attribute-transform context) attribute))
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
(raise (str "Couldn't find variable " variable))))
|
(raise (str "Couldn't find variable " variable))))
|
||||||
|
|
||||||
(defn make-context []
|
(defn make-context []
|
||||||
(->Context [] {} []
|
(->Context [] {} [] []
|
||||||
transforms/attribute-transform-string
|
transforms/attribute-transform-string
|
||||||
transforms/constant-transform-default))
|
transforms/constant-transform-default))
|
||||||
|
|
||||||
|
@ -124,12 +124,15 @@
|
||||||
(assoc context :wheres (concat (bindings->where (:bindings context))
|
(assoc context :wheres (concat (bindings->where (:bindings context))
|
||||||
(:wheres context))))
|
(:wheres context))))
|
||||||
|
|
||||||
|
(defn apply-elements-to-context [context elements]
|
||||||
|
(assoc context :elements elements))
|
||||||
|
|
||||||
(defn patterns->context
|
(defn patterns->context
|
||||||
"Turn a sequence of patterns into a Context."
|
"Turn a sequence of patterns into a Context."
|
||||||
[patterns]
|
[patterns]
|
||||||
(reduce apply-pattern-to-context (make-context) patterns))
|
(reduce apply-pattern-to-context (make-context) patterns))
|
||||||
|
|
||||||
(defn elements->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
|
||||||
projection clause, suitable for passing as a `:select` clause to
|
projection clause, suitable for passing as a `:select` clause to
|
||||||
honeysql.
|
honeysql.
|
||||||
|
@ -146,19 +149,30 @@
|
||||||
|
|
||||||
[[:datoms12.e :foo] [:datoms13.e :bar]]
|
[[:datoms12.e :foo] [:datoms13.e :bar]]
|
||||||
|
|
||||||
@param context A Context.
|
@param context A Context, containing elements.
|
||||||
@param elements The input clause.
|
|
||||||
@return a sequence of pairs."
|
@return a sequence of pairs."
|
||||||
[context elements]
|
[context]
|
||||||
(when-not (every? #(instance? Variable %1) elements)
|
(let [elements (:elements context)]
|
||||||
(raise "Unable to :find non-variables."))
|
(when-not (every? #(instance? Variable %1) elements)
|
||||||
(map (fn [elem]
|
(raise "Unable to :find non-variables."))
|
||||||
(let [var (:symbol elem)]
|
(map (fn [elem]
|
||||||
[(lookup-variable context var) (var->sql-var var)]))
|
(let [var (:symbol elem)]
|
||||||
elements))
|
[(lookup-variable context var) (var->sql-var var)]))
|
||||||
|
elements)))
|
||||||
|
|
||||||
(defn context->sql-clause [context elements]
|
(defn row-transducer [context projection rf]
|
||||||
{:select (elements->sql-projection context elements)
|
;; For now, we only support straight var lists, so
|
||||||
|
;; our transducer is trivial.
|
||||||
|
(let [columns-in-order (map second projection)
|
||||||
|
row-mapper (fn [row] (map columns-in-order row))]
|
||||||
|
(fn
|
||||||
|
([] (rf))
|
||||||
|
([result] (rf result))
|
||||||
|
([result input]
|
||||||
|
(rf result (row-mapper input))))))
|
||||||
|
|
||||||
|
(defn context->sql-clause [context]
|
||||||
|
{:select (sql-projection context)
|
||||||
:from (:from context)
|
:from (:from context)
|
||||||
:where (if (empty? (:wheres context))
|
:where (if (empty? (:wheres context))
|
||||||
nil
|
nil
|
||||||
|
@ -173,6 +187,18 @@
|
||||||
(= "$" (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]
|
||||||
|
;; 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.
|
||||||
|
(let [{:keys [find in with where]} find] ; Destructure the Datalog query.
|
||||||
|
(validate-with with)
|
||||||
|
(validate-in in)
|
||||||
|
(apply-elements-to-context
|
||||||
|
(expand-where-from-bindings
|
||||||
|
(patterns->context where)) ; 'where' here is the Datalog :where clause.
|
||||||
|
(: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."
|
||||||
|
@ -180,13 +206,8 @@
|
||||||
;; 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.
|
||||||
(let [{:keys [find in with where]} find] ; Destructure the Datalog query.
|
(context->sql-clause
|
||||||
(validate-with with)
|
(find->prepared-context find)))
|
||||||
(validate-in in)
|
|
||||||
(context->sql-clause
|
|
||||||
(expand-where-from-bindings
|
|
||||||
(patterns->context where)) ; 'where' here is the Datalog :where clause.
|
|
||||||
(:elements find))))
|
|
||||||
|
|
||||||
(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."
|
||||||
|
|
Loading…
Reference in a new issue