Extension: allow non-constant attributes in fulltext expressions. Fixes #42.

This change breaks compatibility with Datomic, but is useful when we simply want
to find entities linked somehow to matching content.
This commit is contained in:
Richard Newman 2016-08-18 14:51:02 -07:00
parent 31e354ae61
commit 7d684216f0
2 changed files with 32 additions and 14 deletions

View file

@ -190,12 +190,15 @@
(concat (:wheres cc) (concat (:wheres cc)
(bindings->where (:bindings cc)))))) (bindings->where (:bindings cc))))))
(defn binding-for-symbol-or-throw [cc symbol] (defn binding-for-symbol [cc symbol]
(let [internal-bindings (symbol (:bindings cc)) (let [internal-bindings (symbol (:bindings cc))
external-bindings (symbol (:external-bindings cc))] external-bindings (symbol (:external-bindings cc))]
(or (first internal-bindings) (or (first internal-bindings)
(first external-bindings) (first external-bindings))))
(raise-str "No bindings yet for " symbol))))
(defn binding-for-symbol-or-throw [cc symbol]
(or (binding-for-symbol cc symbol)
(raise-str "No bindings yet for " symbol)))
(defn argument->value (defn argument->value
"Take a value from an argument list and resolve it against the CC. "Take a value from an argument list and resolve it against the CC.

View file

@ -71,10 +71,8 @@
(when-not (and (instance? SrcVar src) (when-not (and (instance? SrcVar src)
(= "$" (name (:symbol src)))) (= "$" (name (:symbol src))))
(raise "Non-default sources not supported." {:arg src})) (raise "Non-default sources not supported." {:arg src}))
(when-not (instance? Constant attr) (when (and (instance? Constant attr)
(raise "Non-constant fulltext attributes not supported." {:arg attr})) (not (fulltext-attribute? (:source cc) (:value attr))))
(when-not (fulltext-attribute? (:source cc) (:value attr))
(raise-str "Attribute " (:value attr) " is not a fulltext-indexed attribute.")) (raise-str "Attribute " (:value attr) " is not a fulltext-indexed attribute."))
(when-not (and (instance? BindColl bind-coll) (when-not (and (instance? BindColl bind-coll)
@ -94,6 +92,18 @@
;; We do not currently support scoring; the score value will always be 0. ;; We do not currently support scoring; the score value will always be 0.
(let [[src attr search] (:args function) (let [[src attr search] (:args function)
;; Note that DataScript's parser won't allow us to write a term like
;;
;; [(fulltext $ _ "foo") [[?x]]]
;;
;; so we instead have a placeholder attribute. Sigh.
attr-constant (or
(and (instance? Constant attr)
(not (= :any (:value attr)))
(source/attribute-in-source (:source cc) (:value attr)))
(and (instance? Variable attr)
(cc/binding-for-symbol-or-throw cc (:symbol attr))))
;; Pull out the symbols for the binding array. ;; Pull out the symbols for the binding array.
[entity value tx score] [entity value tx score]
(map (comp :symbol :variable) ; This will nil-out placeholders. (map (comp :symbol :variable) ; This will nil-out placeholders.
@ -112,22 +122,27 @@
from [[fulltext-table fulltext-alias] from [[fulltext-table fulltext-alias]
[datom-table datom-alias]] [datom-table datom-alias]]
wheres [[:match match-column match-value] ; The FTS match. extracted-types {} ; TODO
wheres (concat
[[:match match-column match-value] ; The FTS match.
;; The fulltext rowid-to-datom correspondence. ;; The fulltext rowid-to-datom correspondence.
[:= [:=
(sql/qualify datom-alias :v) (sql/qualify datom-alias :v)
(sql/qualify fulltext-alias :rowid)] (sql/qualify fulltext-alias :rowid)]]
;; The attribute itself must match. (when attr-constant
[:= ;; If known, the attribute itself must match.
(sql/qualify datom-alias :a) [[:=
(source/attribute-in-source (:source cc) (:value attr))]] (sql/qualify datom-alias :a)
attr-constant]]))
;; Now compose any bindings for entity, value, tx, and score. ;; Now compose any bindings for entity, value, tx, and score.
;; TODO: do we need to examine existing bindings to capture ;; TODO: do we need to examine existing bindings to capture
;; wheres for any of these? We shouldn't, because the CC will ;; wheres for any of these? We shouldn't, because the CC will
;; be internally cross-where'd when everything is done... ;; be internally cross-where'd when everything is done...
;; TODO: bind attribute?
bindings (into {} bindings (into {}
(filter (filter
(comp not nil? first) (comp not nil? first)
@ -139,7 +154,7 @@
;; if this is a variable rather than a placeholder. ;; if this is a variable rather than a placeholder.
[score [0]]]))] [score [0]]]))]
(cc/augment-cc cc from bindings wheres))) (cc/augment-cc cc from bindings extracted-types wheres)))
;; get-else is how Datalog handles optional attributes. ;; get-else is how Datalog handles optional attributes.
;; ;;