Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Order-dependence in not-join #481

Closed
greglook opened this issue Jan 2, 2025 · 2 comments
Closed

Order-dependence in not-join #481

greglook opened this issue Jan 2, 2025 · 2 comments

Comments

@greglook
Copy link

greglook commented Jan 2, 2025

We got a strange issue in one of our test suites after upgrading from Datascript 1.0.0 to the latest 1.7.3 release (yeah, I know...). The failure came from a query that was using a not-join clause to test whether an attribute value on an A entity matched an identifier on some other B entity in the database - effectively a referential integrity check. However, the test case that started failing did not include any entities of type B, and the query started returning an empty set after the upgrade.

A minimal example showing what this looks like:

(def db1
  (d/db-with
    (d/empty-db)
    [{:node/type :foo, :foo/bar 123}]))

(d/q '[:find ?foo ?id
       :where
       [?foo :foo/bar ?id]
       (not-join [?id]
                 [?bar :node/type :bar]
                 [?bar :bar/id ?id])])]
     db1)
=> #{}

Based on my reading of the Datomic query reference, this should return the node, since the not-join subquery returns no results as there are no "bar" entities. If there is at least one bar entity, the query works as expected:

(def db2
  (d/db-with
    (d/empty-db)
    [{:node/type :foo, :foo/bar 123}
     {:node/type :bar, :bar/id 456}]))

(d/q '[:find ?foo ?id
       :where
       [?foo :foo/bar ?id]
       (not-join [?id]
                 [?bar :node/type :bar]
                 [?bar :bar/id ?id])])]
     db2)
=> #{[1 123]}

However, reordering the clauses in the join fixes this on the original example:

(d/q '[:find ?foo ?id
       :where
       [?foo :foo/bar ?id]
       (not-join [?id]
                 [?bar :bar/id ?id]
                 [?bar :node/type :bar])])]
     db1)
=> #{[1 123]}

This seems like a bug? At least, I don't see anything about order dependence in any docs. The fact that it works correctly on a database that has unrelated entities that satisfy the leading predicate makes me suspect this is related to some empty-relation short circuiting somewhere that's not accounting for this being in a negation clause.

@tonsky tonsky closed this as completed in 53533a2 Jan 5, 2025
@tonsky
Copy link
Owner

tonsky commented Jan 5, 2025

Fixed in 1.7.4. Indeed, it was a bug. Thanks for reporting!

@greglook
Copy link
Author

greglook commented Jan 6, 2025

Thank you for the quick fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants