Skip to content
This repository was archived by the owner on Sep 12, 2018. It is now read-only.

Cardinality constraints with a trie#685

Merged
ncalexan merged 2 commits into
mozilla:masterfrom
ncalexan:cardinality-constraints-trie
May 14, 2018
Merged

Cardinality constraints with a trie#685
ncalexan merged 2 commits into
mozilla:masterfrom
ncalexan:cardinality-constraints-trie

Conversation

@ncalexan

@ncalexan ncalexan commented May 9, 2018

Copy link
Copy Markdown
Member

This obsoletes #673. @rnewman, I've left that one in place for you to compare -- sorry for leaving some comments behind.

I think you'll find it easier to review without the history, tbh. I didn't change things in the SQLite schema for simplicity; we can address a more useful index on transactions later, and we can make the indices on the temporary tables only apply to the debug configuration later too.

Give it a whirl!

@ncalexan ncalexan requested a review from rnewman May 9, 2018 23:31
@ncalexan ncalexan force-pushed the cardinality-constraints-trie branch from e9cac01 to db19c82 Compare May 14, 2018 22:21
…#663, mozilla#532, mozilla#679)

This should address mozilla#663, by re-inserting type checking in the
transactor stack after the entry point used by the term builder.

Before this commit, we were using an SQLite UNIQUE index to assert
that no `[e a]` pair, with `a` a cardinality one attribute, was
asserted more than once.  However, that's not in line with Datomic,
which treats transaction inputs as a set and allows a single datom
like `[e a v]` to appear multiple times.  It's both awkward and not
particularly efficient to look for _distinct_ repetitions in SQL, so
we accept some runtime cost in order to check for repetitions in the
transactor.  This will allow us to address mozilla#532, which is really about
whether we treat inputs as sets.  A side benefit is that we can
provide more helpful error messages when the transactor does detect
that the input truly violates the cardinality constraints of the
schema.

This commit builds a trie while error checking and collecting final
terms, which should be fairly efficient.  It also allows a simpler
expression of input-provided :db/txInstant datoms, which in turn
uncovered a small issue with the transaction watcher, where-by the
watcher would not see non-input-provided :db/txInstant datoms.

This transition to Datomic-like input-as-set semantics allows us to
address mozilla#532.  Previously, two tempids that upserted to the same entid
would produce duplicate datoms, and that would have been rejected by
the transactor -- correctly, since we did not allow duplicate datoms
under the input-as-list semantics.  With input-as-set semantics,
duplicate datoms are allowed; and that means that we must allow
tempids to be equivalent, i.e., to resolve to the same tempid.

To achieve this, we:
- index the set of tempids
- identify tempid indices that share an upsert
- map tempids to a dense set of contiguous integer labels

We use the well-known union-find algorithm, as implemented by
petgraph, to efficiently manage the set of equivalent tempids.

Along the way, I've fixed and added tests for two small errors in the
transactor.  First, don't drop datoms resolved by upsert (mozilla#679).
Second, ensure that complex upserts are allocated.

I don't know quite what happened here.  The Clojure implementation
correctly kept complex upserts that hadn't resolved as complex
upserts (see
https://github.com/mozilla/mentat/blob/9a9dfb502acf5e4cdb1059d4aac831d7603063c8/src/common/datomish/transact.cljc#L436)
and then allocated complex upserts if they didn't resolve (see
https://github.com/mozilla/mentat/blob/9a9dfb502acf5e4cdb1059d4aac831d7603063c8/src/common/datomish/transact.cljc#L509).

Based on the code comments, I think the Rust implementation must have
incorrectly tried to optimize by handling all complex upserts in at
most a single generation of evolution, and that's just not correct.
We're effectively implementing a topological sort, using very specific
domain knowledge, and its not true that a node in a topological sort
can be considered only once!
@ncalexan ncalexan force-pushed the cardinality-constraints-trie branch from db19c82 to 9693820 Compare May 14, 2018 22:21
@ncalexan

Copy link
Copy Markdown
Member Author

This still isn't perfect but I want to get it landed and out of my queue.

@ncalexan ncalexan merged commit 46c2a08 into mozilla:master May 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant