Project real values. Fixes #30.

This commit is contained in:
Richard Newman 2016-08-19 12:21:20 -07:00
parent 1c6244db5b
commit 479a7fd583
2 changed files with 50 additions and 9 deletions

View file

@ -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.
projectors
(make-projectors-for-columns elements known-types extracted-types)]
(map
(fn [[row err]]
(if err (if err
[row err] [row err]
[(map row columns-in-order) nil]))))) [(map (fn [projector] (projector row)) projectors) nil])))))

View file

@ -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]]