Turn Source into a protocol. Allow source->from to switch on attribute. r=nalexander

This commit is contained in:
Richard Newman 2016-08-04 16:40:03 -07:00
parent c948902c52
commit 4c2230929e
3 changed files with 61 additions and 28 deletions

View file

@ -143,11 +143,14 @@
Constant Constant
(constrain-column-to-constant cc col position (:value pattern-part)) (constrain-column-to-constant cc col position (:value pattern-part))
(raise-str "Unknown pattern part " pattern-part)))) (raise "Unknown pattern part." {:part pattern-part :clause pattern}))))
cc cc
places))) places)))
(defn pattern->attribute [pattern]
(second (:pattern pattern)))
;; Accumulates a pattern into the CC. Returns a new CC. ;; Accumulates a pattern into the CC. Returns a new CC.
(defn apply-pattern-clause (defn apply-pattern-clause
"Transform a DataScript Pattern instance into the parts needed "Transform a DataScript Pattern instance into the parts needed
@ -162,7 +165,11 @@
(when-not (instance? DefaultSrc (:source pattern)) (when-not (instance? DefaultSrc (:source pattern))
(raise-str "Non-default sources are not supported in patterns. Pattern: " pattern)) (raise-str "Non-default sources are not supported in patterns. Pattern: " pattern))
(let [[table alias] (source->from (:source cc))] ; e.g., [:datoms :datoms123] ;; TODO: look up the attribute in external bindings if it's a var. Perhaps we
;; already know what it is…
(let [[table alias] (source->from
(:source cc) ; e.g., [:datoms :datoms123]
(pattern->attribute pattern))]
(apply-pattern-clause-for-alias (apply-pattern-clause-for-alias
;; Record the new table mapping. ;; Record the new table mapping.

View file

@ -4,7 +4,15 @@
(ns datomish.query.source (ns datomish.query.source
(:require (:require
[datomish.query.transforms :as transforms])) [datomish.query.transforms :as transforms]
[datascript.parser
#?@(:cljs
[:refer [Variable Constant Placeholder]])])
#?(:clj
(:import [datascript.parser Variable Constant Placeholder])))
(defn- gensym-table-alias [table]
(gensym (name table)))
;;; ;;;
;;; A source is something that can match patterns. For example: ;;; A source is something that can match patterns. For example:
@ -24,9 +32,17 @@
;;; * Transform constants and attributes into something usable ;;; * Transform constants and attributes into something usable
;;; by the source. ;;; by the source.
(defprotocol Source
(source->from [source attribute]
"Returns a pair, `[table alias]` for a pattern with the provided attribute.")
(source->constraints [source alias])
(attribute-in-source [source attribute])
(constant-in-source [source constant]))
(defrecord (defrecord
Source DatomsSource
[table ; e.g., :datoms [table ; Typically :datoms.
fts-view ; Typically :fulltext_datoms.
columns ; e.g., [:e :a :v :tx] columns ; e.g., [:e :a :v :tx]
;; `attribute-transform` is a function from attribute to constant value. Used to ;; `attribute-transform` is a function from attribute to constant value. Used to
@ -41,29 +57,38 @@
;; Not currently used. ;; Not currently used.
make-constraints ; ?fn [source alias] => [where-clauses] make-constraints ; ?fn [source alias] => [where-clauses]
]) ]
Source
(defn gensym-table-alias [table] (source->from [source attribute]
(gensym (name table))) (let [table
(if (and (instance? Constant attribute)
;; TODO: look in the DB schema to see if `attribute` is known to not be
;; a fulltext attribute.
true)
(:table source)
;; It's variable. We must act as if it could be a fulltext datom.
(:fts-view source))]
[table ((:table-alias source) table)]))
(source->constraints [source alias]
(when-let [f (:make-constraints source)]
(f alias)))
(attribute-in-source [source attribute]
((:attribute-transform source) attribute))
(constant-in-source [source constant]
((:constant-transform source) constant)))
(defn datoms-source [db] (defn datoms-source [db]
(->Source :datoms (map->DatomsSource
[:e :a :v :tx :added] {:table :datoms
transforms/attribute-transform-string :fts-view :fulltext_datoms
transforms/constant-transform-default :columns [:e :a :v :tx :added]
gensym-table-alias :attribute-transform transforms/attribute-transform-string
nil)) :constant-transform transforms/constant-transform-default
:table-alias gensym-table-alias
:make-constraints nil}))
(defn source->from [source]
(let [table (:table source)]
[table ((:table-alias source) table)]))
(defn source->constraints [source alias]
(when-let [f (:make-constraints source)]
(f alias)))
(defn attribute-in-source [source attribute]
((:attribute-transform source) attribute))
(defn constant-in-source [source constant]
((:constant-transform source) constant))

View file

@ -26,8 +26,9 @@
(fgensym s (dec (swap! counter inc))))))) (fgensym s (dec (swap! counter inc)))))))
(defn mock-source [db] (defn mock-source [db]
(source/map->Source (source/map->DatomsSource
{:table :datoms {:table :datoms
:fts-view :fulltext_datoms
:columns [:e :a :v :tx :added] :columns [:e :a :v :tx :added]
:attribute-transform transforms/attribute-transform-string :attribute-transform transforms/attribute-transform-string
:constant-transform transforms/constant-transform-default :constant-transform transforms/constant-transform-default