Project real values. Fixes #30.
This commit is contained in:
parent
1c6244db5b
commit
479a7fd583
2 changed files with 50 additions and 9 deletions
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
(ns datomish.query.projection
|
(ns datomish.query.projection
|
||||||
(:require
|
(:require
|
||||||
|
[datomish.query.source :as source]
|
||||||
|
[datomish.sqlite-schema :as ss]
|
||||||
[datomish.util :as util #?(:cljs :refer-macros :clj :refer) [raise-str cond-let]]
|
[datomish.util :as util #?(:cljs :refer-macros :clj :refer) [raise-str cond-let]]
|
||||||
[datascript.parser :as dp
|
[datascript.parser :as dp
|
||||||
#?@(:cljs [:refer [Pattern DefaultSrc Variable Constant Placeholder]])]
|
#?@(:cljs [:refer [Pattern DefaultSrc Variable Constant Placeholder]])]
|
||||||
|
@ -57,11 +59,48 @@
|
||||||
(util/var->sql-type-var var)]])))
|
(util/var->sql-type-var var)]])))
|
||||||
elements)))
|
elements)))
|
||||||
|
|
||||||
|
(defn make-projectors-for-columns [elements known-types extracted-types]
|
||||||
|
{:pre [(map? extracted-types)
|
||||||
|
(map? known-types)]}
|
||||||
|
(map (fn [elem]
|
||||||
|
(let [var (:symbol elem)
|
||||||
|
projected-var (util/var->sql-var var)
|
||||||
|
tag-decoder (memoize
|
||||||
|
(fn [tag]
|
||||||
|
(partial ss/<-tagged-SQLite tag)))]
|
||||||
|
|
||||||
|
(if-let [type (get known-types var)]
|
||||||
|
;; We know the type! We already know how to decode it.
|
||||||
|
;; TODO: most of these tags don't actually require calling through to <-tagged-SQLite.
|
||||||
|
;; TODO: optimize this without making it horrible.
|
||||||
|
(let [decoder (tag-decoder (ss/->tag type))]
|
||||||
|
(fn [row]
|
||||||
|
(decoder (get row projected-var))))
|
||||||
|
|
||||||
|
;; We don't know the type. Find the type projection column
|
||||||
|
;; and use it to decode the value.
|
||||||
|
(if (contains? extracted-types var)
|
||||||
|
(let [type-column (util/var->sql-type-var var)]
|
||||||
|
(fn [row]
|
||||||
|
(ss/<-tagged-SQLite
|
||||||
|
(get row type-column)
|
||||||
|
(get row projected-var))))
|
||||||
|
|
||||||
|
;; We didn't extract a type and we don't know it in advance.
|
||||||
|
;; Just pass through; the :col will look itself up in the row.
|
||||||
|
projected-var))))
|
||||||
|
elements))
|
||||||
|
|
||||||
(defn row-pair-transducer [context]
|
(defn row-pair-transducer [context]
|
||||||
;; For now, we only support straight var lists, so
|
(let [{:keys [elements cc]} context
|
||||||
;; our transducer is trivial.
|
{:keys [source known-types extracted-types]} cc
|
||||||
(let [columns-in-order (map second (sql-projection context))]
|
|
||||||
(map (fn [[row err]]
|
;; We know the projection will fail above if these aren't simple variables.
|
||||||
(if err
|
projectors
|
||||||
[row err]
|
(make-projectors-for-columns elements known-types extracted-types)]
|
||||||
[(map row columns-in-order) nil])))))
|
|
||||||
|
(map
|
||||||
|
(fn [[row err]]
|
||||||
|
(if err
|
||||||
|
[row err]
|
||||||
|
[(map (fn [projector] (projector row)) projectors) nil])))))
|
||||||
|
|
|
@ -10,12 +10,14 @@
|
||||||
[cljs.core.async.macros :as a :refer [go]]))
|
[cljs.core.async.macros :as a :refer [go]]))
|
||||||
(:require
|
(:require
|
||||||
[datomish.api :as d]
|
[datomish.api :as d]
|
||||||
#?@(:clj [[datomish.pair-chan :refer [go-pair <?]]
|
#?@(:clj [[datomish.jdbc-sqlite]
|
||||||
|
[datomish.pair-chan :refer [go-pair <?]]
|
||||||
[tempfile.core :refer [tempfile with-tempfile]]
|
[tempfile.core :refer [tempfile with-tempfile]]
|
||||||
[datomish.test-macros :refer [deftest-async]]
|
[datomish.test-macros :refer [deftest-async]]
|
||||||
[clojure.test :as t :refer [is are deftest testing]]
|
[clojure.test :as t :refer [is are deftest testing]]
|
||||||
[clojure.core.async :refer [go <! >!]]])
|
[clojure.core.async :refer [go <! >!]]])
|
||||||
#?@(:cljs [[datomish.pair-chan]
|
#?@(:cljs [[datomish.promise-sqlite]
|
||||||
|
[datomish.pair-chan]
|
||||||
[datomish.test-macros :refer-macros [deftest-async]]
|
[datomish.test-macros :refer-macros [deftest-async]]
|
||||||
[datomish.node-tempfile :refer [tempfile]]
|
[datomish.node-tempfile :refer [tempfile]]
|
||||||
[cljs.test :as t :refer-macros [is are deftest testing async]]
|
[cljs.test :as t :refer-macros [is are deftest testing async]]
|
||||||
|
|
Loading…
Reference in a new issue