This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-06-01
Channels
- # announcements (20)
- # babashka (3)
- # beginners (30)
- # calva (28)
- # cider (3)
- # circleci (4)
- # clerk (27)
- # clj-kondo (72)
- # cljdoc (15)
- # cljs-dev (1)
- # clojure (85)
- # clojure-europe (37)
- # clojure-nl (1)
- # clojure-norway (13)
- # clojure-spec (7)
- # clojurescript (19)
- # clr (1)
- # conjure (11)
- # datahike (2)
- # datomic (11)
- # emacs (26)
- # events (4)
- # hoplon (35)
- # hyperfiddle (41)
- # jobs (7)
- # lsp (10)
- # nrepl (3)
- # off-topic (57)
- # portal (47)
- # practicalli (1)
- # rdf (3)
- # reitit (21)
- # releases (1)
- # testing (6)
- # tools-build (16)
- # wasm (1)
- # xtdb (16)
Hi everyone, I wonder if anybody can point me in the right direction with some behaviour I ran into with Datomic rules? Basically, I want to pass an entity ident to a rule but this doesn't seem to work how I expected. I've got a test case to show what I'm trying to do which I'll post in the thread of this message so I don't clog this view up...
Here's my test case:
;; Set up the DB...
(def my-conn
(let [db-name "test"
client-config {:server-type :dev-local
:system db-name
:storage-dir :mem}
client (d/client client-config)]
(d/create-database client {:db-name db-name})
(d/connect client {:db-name db-name})))
(d/transact my-conn {:tx-data [{:db/ident :parent/id
:db/unique :db.unique/identity
:db/valueType :db.type/uuid
:db/cardinality :db.cardinality/one}
{:db/ident :parent/child
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one}
{:db/ident :child/id
:db/unique :db.unique/identity
:db/valueType :db.type/uuid
:db/cardinality :db.cardinality/one}]})
(def parent-id (random-uuid))
(def child-id (random-uuid))
(d/transact my-conn {:tx-data [{:parent/id parent-id
:parent/child {:child/id child-id}}]})
(def rules
'[[(demo-rule ?entity ?attr ?val)
[?entity ?attr ?val]]])
;; Here's the issue...
(d/q '[:find ?parent
:in $ ?child-ident
:where
[?parent :parent/child ?child-ident]]
(d/db my-conn)
[:child/id child-id])
;; Works as I expected: => [[79164837199948]]
(d/q '[:find ?parent
:in $ % ?child-ident
:where
(demo-rule ?parent :parent/child ?child-ident)]
(d/db my-conn)
rules
[:child/id child-id])
;; Not what I expected: => []
I've tried various things to try and work out what is going on here including printing the inputs to the rule (which all look as I expected). Unexpectedly, I've found that if I hard code the attr in the rule then it works as I expected, e.g.:
(def rules
'[[(demo-rule ?entity ?attr ?val)
[?entity :parent/child ?val]]])
(d/q '[:find ?parent
:in $ % ?child-ident
:where
(demo-rule ?parent :parent/child ?child-ident)]
(d/db my-conn)
rules
[:child/id child-id])
;; Works: => [[79164837199948]]
Although I'm not sure what this tells me!? If anyone has any ideas what might be up here (am I doing this incorrectly?) I'd be very grateful!
thanks! 🙂
This isn’t caused by the rule. The problem is that when the attribute is not a static value, the query does not infer that the ident is a reference.
the ident keyword is not actually in the datom value being matched (just like attribute keywords are not actually in the datoms either). It is translated to a number before matching if the attribute slot is known to be a ref type statically
that is not knowable with this pattern [?entity ?attr ?value]
, so it only performs exact-matches on ?value
Ahh, I see. Thanks for the explanation, that explains it. Thank you, I think I'll be able to work this out now, then. Cheers! 🙂