Skip to content

Instantly share code, notes, and snippets.

@zeitstein
Last active November 10, 2022 07:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zeitstein/6182a270def0baa1c202c70930762d3d to your computer and use it in GitHub Desktop.
Save zeitstein/6182a270def0baa1c202c70930762d3d to your computer and use it in GitHub Desktop.
A repro of XTDB rule issue https://github.com/xtdb/xtdb/issues/1569
(ns xtdb-rules-bug
(:require [xtdb.api :as xt]))
;; rules bug https://github.com/xtdb/xtdb/issues/1569
(def n (xt/start-node {:xtdb.lucene/lucene-store {}}))
(def data
[;; loop
{:xt/id 1 :text "t1" :child 2}
{:xt/id 2 :text "t2" :child 3}
{:xt/id 3 :text "t3" :child 2}
;; non-loop
{:xt/id 4 :text "t4" :child 5}
{:xt/id 5 :text "t5" :child 6}
{:xt/id 6 :text "t6"}])
(xt/submit-tx n (mapv #(vector ::xt/put %) data))
(xt/sync n)
(def rules
'[[(follow-unbounded p c)
[p :child c]]
[(follow-unbounded p c)
[p :child i]
(follow-unbounded i c)]
[(follow-bounded1 [p] c)
[p :child c]]
[(follow-bounded1 [p] c)
[p :child i]
(follow-bounded1 i c)]
[(follow-bounded2 [p c])
[p :child c]]
[(follow-bounded2 [p c])
[p :child i]
(follow-bounded2 i c)]])
(defn q [where]
(xt/q (xt/db n)
{:find '[e]
:rules rules
:where where}))
;; ✔ non loop, returns expected 5,6
(q '[[e :text] (follow-unbounded 4 e)])
(q '[[e :text] (follow-bounded1 4 e)])
(q '[[e :text] (follow-bounded2 4 e)])
;; ❌ #{[1] [2] [3] [4] [5] [6]}, expected: 2, 3
(q '[[e :text] (follow-unbounded 1 e)])
;; ✔ 2, 3
(q '[[e :text] (follow-bounded1 1 e)])
;; ❌ #{[1] [2] [3] [4] [5] [6]}, expected: 2, 3
(q '[[e :text] (follow-bounded2 1 e)])
;; ✔ indirection fixes it
(q '[[e :text] [(== e e*)] (follow-unbounded 1 e*)])
;; ❌ indirection does not fix it
(q '[[e :text] [e* :text] [(== e e*)] (follow-bounded2 1 e*)])
;; * adding lucene
;; ✔ works ok for non-loop
(q '[[(text-search :text "t*") [[e]]] (follow-unbounded 4 e)])
(q '[[(text-search :text "t*") [[e]]] (follow-bounded1 4 e)])
(q '[[(text-search :text "t*") [[e]]] (follow-bounded2 4 e)])
;; ✔
(q '[[(text-search :text "t*") [[e]]] (follow-bounded1 1 e)])
;; ❌ returns all, but expecting 2,3
(q '[[(text-search :text "t*") [[e]]] (follow-unbounded 1 e)])
(q '[[(text-search :text "t*") [[e]]] (follow-bounded2 1 e)])
;; ✔ same trick fixes unbounded
(q '[[(text-search :text "t*") [[e]]] [(== e e*)] (follow-unbounded 1 e*)])
;; ❌ but not bounded
(q '[[(text-search :text "t*") [[e]]] [e* :text] [(== e e*)] (follow-bounded2 1 e*)])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment