Rules with multiple data sources?


#1

I’d like to define a rule that can operate on multiple data sources, for example:

(let [rules '[[(new-foo? [$before $after ?e])
               (not [$before ?e :foo])
               [$after ?e :foo]]]
      query '[:find ?e .
              :in $before $after % ?e
              :where (new-foo? $before $after ?e)]
      uri "datomic:mem://foo"
      _ (d/delete-database uri)
      _ (d/create-database uri)
      conn (d/connect uri)
      _ @(d/transact conn [{:db/ident :foo
                            :db/valueType :db.type/string
                            :db/cardinality :db.cardinality/one}])
      db-before (d/db conn)
      result (d/with db-before [{:foo "bar"}])
      eid (-> result :tempids vals first)]
  (println (d/q query db-before (:db-after result) rules eid)))

However this code doesn’t work because rules can’t have source variables as parameters. (You can specify a source variable with ($src rule-name ?a ?b ?c), but that only works for a single source).

I’m thinking of working around this by implementing a “rule-expand” function that will take a query and a set of rules and expand any rules that take multiple data sources. So e.g. the output for the example would be this query:

'[:find ?e .
  :in $before $after ?e
  :where (not [$before ?e :foo])
         [$after ?e :foo]]

Is there a possibility that future releases will allow rules with multiple data sources?


#2

Actually, it seems that even my rule-expand idea is unworkable. Even within the main body of the query, you can’t use multiple data sources inside the body of e.g. an or-join (which is necessary for handling multiple rule definitions, not to mention for allowing the rule definitions themselves to use or-join and other clauses).

This seems rather limiting. I guess multiple data sources are only intended to be used from the top-level clauses for relatively simple things (like the examples here: https://docs.datomic.com/on-prem/filters.html)? Or am I missing something?


#3

Would a peer function work?


#4

It would be easier on us if we could do it from just datalog, but since that seems to not be an option, it looks like we’ll have to do something along those lines.