nil
is meant to be allowed in heterogenous tuples, right?
for example, let's say i have a tuple like this:
[:db.type/ref :db.type/ref]
and nil in the second value
{:person/parents [123456 nil]}
i get an exception when i untuple
and bind on the nil value
(d/q '{:find [?person ?parent-a-name]
:in [$]
:where [
[?person :person/parents ?parents-tuple]
[(untuple ?parents-tuple) [?parent-a ?parent-b]]
[?parent-a :person/name ?parent-a-name]
[?parent-b :person/name] ;<-- throws exception
]}
db)
Execution error (NullPointerException) at datomic.core.db/asserting-datum (db.clj:-1).
null
clojure.lang.ExceptionInfo: processing clause: [?parent-b :parent/name], message: #:cognitect.anomalies{:category :cognitect.anomalies/incorrect, :message "processing clause: [?parent-b :parent/name], message: "}
i don't think this is a composite tuple though. this is a heterogenous tuple.
Heterogeneous tuples cannot contain refs
hmm, i don't doubt what you're saying.. maybe i'm just confused here. i thought this is a heterogeneous tuple (from the schema in the forum post above):
{:db/ident :person/parents
:db/valueType :db.type/tuple
:db/tupleTypes [:db.type/ref :db.type/ref]
:db/cardinality :db.cardinality/one}
which allows refs, and works with transactions and pulls. are you saying that hetero tuples shouldn't contain refs, rather than cannot contain refs?they shouldn’t, and I thought they could not
if you read the docs, they make no mention of this
also conceptually, it’s bad: ref values are supposed to be managed by datomic--this is no different than putting a long into a tuple
with composite tuples, it knows what assertion it’s denormalized from; here, there is no support. and you can’t use lookup refs or keywords or tempids to reference these
I’m wrong though, :db.type/ref is lised as a scalar type
I am pretty sure it wasn’t the last time I read this--maybe a change? Anyway, it still seems like a bad idea
but if you really need to do it, queries needs to be defensive against nils
[(!= ?x nil)]
immediately might work, [(some? ?x)]
should definitely work.
hey favila, both of your solutions worked. thanks. in my case i'm storing some rankings in tuples...
{:race/finishers [[0 sally-ref coach-1-ref]
[1 bob-ref nil]
[2 jane-ref coach-2-ref]]}
of course the alternative (and more verbose) solution is to have separate ranking entities that store all of the context (the race, the people involved, and a rank), but as an experiment i thought tuples might be an interesting solution. in my example i don't see why storing references in tuples seems like a bad idea.@joshkh I'm afraid you can't have nil there
If I'm not mistaken the value just would not be there
{:parents [123456]}
that makes sense to me. do you know if that is the official stance? i am allowed to both transact and pull nil values. as for binding i would have expected the query to not unify instead of throw an exception
I believe you get that exception because theres actually a value (nil), which makes the whole hting unify but it wont comply to your clause :person/name
That would be my guess
fair enough 🙂
just a funny observation: when retracting an entity referenced in a tuple, the tuple retrains the entity db/id even after the target has been retracted. that feels equally strange to me but for other reasons.
Not sure why, but I think if you look at it like independent datoms, kinda makes sense. Its not like a component, where you retract the mother entity and the child follows along. But you have a fair point
also from Jaret on the forums (at least regarding homogenous tuples) > Additionally you may be interested in knowing that, `nil` is a legal value for any slot in a tuple. This facilitates using tuples in range searches, where `nil` sorts lowest. https://forum.datomic.com/t/tuple-with-single-item-fails-transaction/1690
maybe i'll make an ol' posteroo on the forums
I hope Jaret get a raise soon enough, he's always the one to respond my tickets xD
Jaret and Marshall both do a great job of putting up with my bs 😎
couldn't say it better
(in case someone from Cognitect reads the thread, i've posted the question here: https://forum.datomic.com/t/nil-value-in-heterogeneous-tuple-throws-a-nullpointerexception/1693)
I think this is just a mismatch between datalog unification and how tuples are handled. Since this is a composite attribute, consider reading the source attribute value instead of the composite
(I’ve often wished for composite attributes to have a “not nillable” option, so that they are not asserted unless all values are present)