From d5e3716ebae2654150401e5d809d51905b66fb56 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Thu, 4 Aug 2016 16:40:03 -0700 Subject: [PATCH] Turn Source into a protocol. Allow source->from to switch on attribute. --- src/datomish/query/clauses.cljc | 11 ++++- src/datomish/query/source.cljc | 75 ++++++++++++++++++++++----------- test/datomish/test/query.cljc | 3 +- 3 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/datomish/query/clauses.cljc b/src/datomish/query/clauses.cljc index 8b3d0dda..ce020148 100644 --- a/src/datomish/query/clauses.cljc +++ b/src/datomish/query/clauses.cljc @@ -143,11 +143,14 @@ Constant (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 places))) +(defn pattern->attribute [pattern] + (second (:pattern pattern))) + ;; Accumulates a pattern into the CC. Returns a new CC. (defn apply-pattern-clause "Transform a DataScript Pattern instance into the parts needed @@ -162,7 +165,11 @@ (when-not (instance? DefaultSrc (:source 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 ;; Record the new table mapping. diff --git a/src/datomish/query/source.cljc b/src/datomish/query/source.cljc index d5df8535..1e488279 100644 --- a/src/datomish/query/source.cljc +++ b/src/datomish/query/source.cljc @@ -4,7 +4,15 @@ (ns datomish.query.source (: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: @@ -24,9 +32,17 @@ ;;; * Transform constants and attributes into something usable ;;; 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 - Source - [table ; e.g., :datoms + DatomsSource + [table ; Typically :datoms. + fts-view ; Typically :fulltext_datoms. columns ; e.g., [:e :a :v :tx] ;; `attribute-transform` is a function from attribute to constant value. Used to @@ -41,29 +57,38 @@ ;; Not currently used. make-constraints ; ?fn [source alias] => [where-clauses] - ]) + ] + Source -(defn gensym-table-alias [table] - (gensym (name table))) + (source->from [source attribute] + (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] - (->Source :datoms - [:e :a :v :tx :added] - transforms/attribute-transform-string - transforms/constant-transform-default - gensym-table-alias - nil)) + (map->DatomsSource + {:table :datoms + :fts-view :fulltext_datoms + :columns [:e :a :v :tx :added] + :attribute-transform transforms/attribute-transform-string + :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)) diff --git a/test/datomish/test/query.cljc b/test/datomish/test/query.cljc index ffeef40d..2518a5a6 100644 --- a/test/datomish/test/query.cljc +++ b/test/datomish/test/query.cljc @@ -26,8 +26,9 @@ (fgensym s (dec (swap! counter inc))))))) (defn mock-source [db] - (source/map->Source + (source/map->DatomsSource {:table :datoms + :fts-view :fulltext_datoms :columns [:e :a :v :tx :added] :attribute-transform transforms/attribute-transform-string :constant-transform transforms/constant-transform-default