Dear all,
From the Learn XTDB Datalog Today session on Rules we learn that, when multiple rules are defined, “[s]ubsequent rule definitions will only be used if the ones preceding it aren’t satisfied”.
Now, here’s a query example adapted from a concrete situation:
(q '{:find [name]
:where [[student :enrollment-per-period/student-id _]
(preferred-name student name)]
:rules [[(preferred-name ?person ?preferred-name) ;; (1)
[?person :enrollment-per-period/social-name ?preferred-name]
(not [(clojure.string/blank? ?preferred-name)])]
[(preferred-name ?person ?preferred-name) ;; (2)
[?person :enrollment-per-period/social-name ?social-name] ;; (3)
[(clojure.string/blank? ?social-name)] ;; (4)
[?person :enrollment-per-period/given-name ?preferred-name]]]
:order-by [[name :asc]]})
The idea is that the first rule defined at (1)
would pick the case when a student has a social name. The second rule at (2)
would serve the other cases, when the student has no social name (a blank field). Everyone in the database has given names.
I believed that the statements at (3)
and (4)
would be logically redundant and unnecessary. To my surprise, though, in cases where the student has a social name, if I don’t add these lines to the second rule, I’ll end up picking the same student twice, both with her given name and her social name.
Could someone please help me understand?
EDIT: The 1.x Language Reference, quoted below, states that multiple rule bodies are similar to or-join
legs. I suppose, then, that the description in Learn XTDB Today is incorrect.
Multiple rule bodies may be defined for a single rule name (i.e. using matching rule heads) which works in a similar fashion to an
or-join
. Rules andor-join
both execute internally as non-lazy subqueries whose results are unified (and potentially cross-joined) with the tuples in the outer query.
(I also note in passing the subsection on Bound arguments, according to which the rules would preferably be stated as (preferred-name [?person] ?preferred-name)
.)