qpdb / mentat

A persistent, relational store inspired by Datomic and DataScript.
https://mentat.rs/
Apache License 2.0
52 stars 2 forks source link

[tx] Fail transactions where complex upserts resolve to multiple entids #232

Open gburd opened 4 years ago

gburd commented 4 years ago

While investigating #532, I discovered a serious logical error in the transactor's upsert mechanics. Suppose the store is:

[1 :unique/ref 1 ?tx]
[2 :unique/ref 2 ?tx]

Right now, we allow the following transaction:

[[:db/add "a" :unique/ref 1]
 [:db/add "b" :unique/ref 2]
 [:db/add "a" :unique/ref "b"]]

What happens is that the two simple upserts "a" and "b" both resolve to distinct entids (1 and 2, respectively), and then the complex upsert "a" :unique/ref "b" is resolved to 1 :unique/ref 2. That conflicts with the simple resolution 1 :unique/ref 2, and that's not right.

In this situation, I don't think anything catches the cardinality one constraint, so we get bad data on disk.