Generate known type for the entity in a fulltext expression, and add a test. Fixes #85.
This commit is contained in:
parent
445364f192
commit
feebfd09da
4 changed files with 93 additions and 5 deletions
|
@ -132,10 +132,18 @@
|
||||||
[:= (sql/qualify table-alias (name :v))
|
[:= (sql/qualify table-alias (name :v))
|
||||||
(constant-in-source (:source cc) value)]])))
|
(constant-in-source (:source cc) value)]])))
|
||||||
|
|
||||||
(defn augment-cc [cc from bindings extracted-types wheres]
|
(defn combine-known-types [left right]
|
||||||
|
(merge-with (fn [lt rt]
|
||||||
|
(if (= lt rt)
|
||||||
|
lt
|
||||||
|
(raise "Incompatible types: " lt " != " rt {:types [lt rt]})))
|
||||||
|
left right))
|
||||||
|
|
||||||
|
(defn augment-cc [cc from bindings known-types extracted-types wheres]
|
||||||
(assoc cc
|
(assoc cc
|
||||||
:from (concat (:from cc) from)
|
:from (concat (:from cc) from)
|
||||||
:bindings (merge-with concat (:bindings cc) bindings)
|
:bindings (merge-with concat (:bindings cc) bindings)
|
||||||
|
:known-types (combine-known-types (:known-types cc) known-types)
|
||||||
:extracted-types (merge (:extracted-types cc) extracted-types)
|
:extracted-types (merge (:extracted-types cc) extracted-types)
|
||||||
:wheres (concat (:wheres cc) wheres)))
|
:wheres (concat (:wheres cc) wheres)))
|
||||||
|
|
||||||
|
@ -143,6 +151,7 @@
|
||||||
(augment-cc left
|
(augment-cc left
|
||||||
(:from right)
|
(:from right)
|
||||||
(:bindings right)
|
(:bindings right)
|
||||||
|
(:known-types right)
|
||||||
(:extracted-types right)
|
(:extracted-types right)
|
||||||
(:wheres right)))
|
(:wheres right)))
|
||||||
|
|
||||||
|
|
|
@ -469,12 +469,15 @@
|
||||||
bindings (into {} (map (fn [var]
|
bindings (into {} (map (fn [var]
|
||||||
(let [sym (:symbol var)]
|
(let [sym (:symbol var)]
|
||||||
[sym [(sql/qualify alias (util/var->sql-var sym))]]))
|
[sym [(sql/qualify alias (util/var->sql-var sym))]]))
|
||||||
free-vars))]
|
free-vars))
|
||||||
|
|
||||||
|
known-types
|
||||||
|
(reduce cc/combine-known-types {} (map :known-types ccs))]
|
||||||
|
|
||||||
(cc/map->ConjoiningClauses
|
(cc/map->ConjoiningClauses
|
||||||
{:source source
|
{:source source
|
||||||
:from [[subqueries alias]]
|
:from [[subqueries alias]]
|
||||||
:known-types (apply merge (map :known-types ccs))
|
:known-types known-types
|
||||||
:extracted-types (apply merge (map :extracted-types ccs))
|
:extracted-types (apply merge (map :extracted-types ccs))
|
||||||
:external-bindings {} ; No need: caller will merge.
|
:external-bindings {} ; No need: caller will merge.
|
||||||
:bindings bindings
|
:bindings bindings
|
||||||
|
|
|
@ -147,6 +147,7 @@
|
||||||
[datom-table datom-alias]]
|
[datom-table datom-alias]]
|
||||||
|
|
||||||
extracted-types {} ; TODO
|
extracted-types {} ; TODO
|
||||||
|
known-types {entity :db.type/ref} ; All entities are refs.
|
||||||
|
|
||||||
wheres (concat
|
wheres (concat
|
||||||
[[:match match-column match-value] ; The FTS match.
|
[[:match match-column match-value] ; The FTS match.
|
||||||
|
@ -181,7 +182,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 extracted-types wheres)))
|
(cc/augment-cc cc from bindings known-types extracted-types wheres)))
|
||||||
|
|
||||||
;; get-else is how Datalog handles optional attributes.
|
;; get-else is how Datalog handles optional attributes.
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -824,3 +824,78 @@
|
||||||
'[?save :save/excerpt ?excerpt]]))]
|
'[?save :save/excerpt ?excerpt]]))]
|
||||||
(is (or (= ["Some page title" "Some page excerpt"] result)
|
(is (or (= ["Some page title" "Some page excerpt"] result)
|
||||||
(= ["A different page" "A different excerpt"] result))))))
|
(= ["A different page" "A different excerpt"] result))))))
|
||||||
|
|
||||||
|
(deftest-db test-or-join-real-world conn
|
||||||
|
;; This tests the simplest cause of https://github.com/mozilla/datomish/issues/84.
|
||||||
|
(testing "or-join with fulltext expressions doesn't leak type_tag columns."
|
||||||
|
(let [attrs (<? (<initialize-with-schema
|
||||||
|
conn
|
||||||
|
(concat save-schema schema-with-page)))]
|
||||||
|
(is
|
||||||
|
(=
|
||||||
|
{:select (list
|
||||||
|
[:datoms6.v :url]
|
||||||
|
[{:select [(sql/call :coalesce
|
||||||
|
{:select [:v]
|
||||||
|
:from [:datoms]
|
||||||
|
:where [:and
|
||||||
|
[:= 'a 65546]
|
||||||
|
[:= 'e :orjoin0.page]]
|
||||||
|
:limit 1}
|
||||||
|
"")]
|
||||||
|
:limit 1}
|
||||||
|
:title])
|
||||||
|
:modifiers []
|
||||||
|
:from (list
|
||||||
|
[{:union (list
|
||||||
|
{:select '([:datoms2.e :page])
|
||||||
|
:from '([:fulltext_values fulltext_values1] [:datoms datoms2])
|
||||||
|
:where (list :and
|
||||||
|
[:match :fulltext_values1.fulltext_values (sql/param :str)]
|
||||||
|
[:= :datoms2.v :fulltext_values1.rowid]
|
||||||
|
(list :or [:= :datoms2.a (:page/url attrs)] [:= :datoms2.a (:page/title attrs)]))}
|
||||||
|
{:select '([:datoms5.e :page])
|
||||||
|
:from '([:fulltext_values fulltext_values3] [:datoms datoms4] [:datoms datoms5])
|
||||||
|
:where (list :and
|
||||||
|
[:match :fulltext_values3.fulltext_values (sql/param :str)]
|
||||||
|
[:= :datoms4.v :fulltext_values3.rowid]
|
||||||
|
(list :or
|
||||||
|
[:= :datoms4.a (:save/title attrs)]
|
||||||
|
[:= :datoms4.a (:save/content attrs)]
|
||||||
|
[:= :datoms4.a (:save/excerpt attrs)]
|
||||||
|
)
|
||||||
|
[:= :datoms5.a (:page/save attrs)]
|
||||||
|
[:= :datoms4.e :datoms5.v])})}
|
||||||
|
'orjoin0]
|
||||||
|
'[:datoms datoms6])
|
||||||
|
:where (list :and
|
||||||
|
[:= :datoms6.a (:page/url attrs)]
|
||||||
|
[:= :orjoin0.page :datoms6.e])
|
||||||
|
:limit 1}
|
||||||
|
|
||||||
|
(expand
|
||||||
|
'[:find [?url ?title]
|
||||||
|
:in $ ?str
|
||||||
|
:where
|
||||||
|
(or-join [?page]
|
||||||
|
[(fulltext $ #{:page/url :page/title} ?str) [[?page]]]
|
||||||
|
(and
|
||||||
|
[(fulltext $ #{:save/title :save/excerpt :save/content} ?str) [[?save]]]
|
||||||
|
[?page :page/save ?save]))
|
||||||
|
[?page :page/url ?url]
|
||||||
|
[(get-else $ ?page :page/title "") ?title]]
|
||||||
|
conn))))))
|
||||||
|
|
||||||
|
;; honeysql up to 0.8.2 includes parentheses around the arms of a
|
||||||
|
;; UNION. This isn't acceptable to SQLite.
|
||||||
|
;; See https://github.com/jkk/honeysql/pull/142.
|
||||||
|
(deftest test-honeysql-union
|
||||||
|
(testing "UNION doesn't include surplus parentheses."
|
||||||
|
(is (= ["SELECT x FROM (SELECT x FROM abc UNION SELECT x FROM def) foo"]
|
||||||
|
(sql/format {:select ['x]
|
||||||
|
:from (list [{:union (list
|
||||||
|
{:select ['x]
|
||||||
|
:from [:abc]}
|
||||||
|
{:select ['x]
|
||||||
|
:from [:def]})}
|
||||||
|
:foo])})))))
|
||||||
|
|
Loading…
Reference in a new issue