Flesh out duplicate txInstant support.

This commit is contained in:
Richard Newman 2018-01-29 16:38:02 -08:00
parent a8dcad65da
commit 7c5143d4e9
4 changed files with 34 additions and 19 deletions

View file

@ -1344,18 +1344,17 @@ mod tests {
assert_transact!(conn, "[[:db/add :db/tx :db/txInstant #inst \"2017-06-16T00:59:11.257Z\"] assert_transact!(conn, "[[:db/add :db/tx :db/txInstant #inst \"2017-06-16T00:59:11.257Z\"]
[:db/add :db/tx :db/txInstant #inst \"2017-06-16T00:59:11.752Z\"] [:db/add :db/tx :db/txInstant #inst \"2017-06-16T00:59:11.752Z\"]
[:db/add 102 :db/ident :name/Vlad]]", [:db/add 102 :db/ident :name/Vlad]]",
Err("Could not insert non-fts one statements into temporary search table!")); Err("conflicting datoms in tx"));
// Test multiple txInstants with the same value. // Test multiple txInstants with the same value.
// Test disabled: depends on #535. assert_transact!(conn, "[[:db/add :db/tx :db/txInstant #inst \"2017-06-16T00:59:11.257Z\"]
// assert_transact!(conn, "[[:db/add :db/tx :db/txInstant #inst \"2017-06-16T00:59:11.257Z\"] [:db/add :db/tx :db/txInstant #inst \"2017-06-16T00:59:11.257Z\"]
// [:db/add :db/tx :db/txInstant #inst \"2017-06-16T00:59:11.257Z\"] [:db/add 103 :db/ident :name/Dimitri]
// [:db/add 103 :db/ident :name/Dimitri] [:db/add 104 :db/ident :name/Anton]]");
// [:db/add 104 :db/ident :name/Anton]]"); assert_matches!(conn.last_transaction(),
// assert_matches!(conn.last_transaction(), "[[103 :db/ident :name/Dimitri ?tx true]
// "[[103 :db/ident :name/Dimitri ?tx true] [104 :db/ident :name/Anton ?tx true]
// [104 :db/ident :name/Anton ?tx true] [?tx :db/txInstant #inst \"2017-06-16T00:59:11.257Z\" ?tx true]]");
// [?tx :db/txInstant #inst \"2017-06-16T00:59:11.257Z\" ?tx true]]");
// Test txInstant retraction // Test txInstant retraction
// Test disabled: retracting a datom that doesn't exist should fail. // Test disabled: retracting a datom that doesn't exist should fail.

View file

@ -82,5 +82,10 @@ error_chain! {
description("unrecognized or no ident found for entid") description("unrecognized or no ident found for entid")
display("unrecognized or no ident found for entid: {}", entid) display("unrecognized or no ident found for entid: {}", entid)
} }
ConflictingDatoms {
description("conflicting datoms in tx")
display("conflicting datoms in tx")
}
} }
} }

View file

@ -8,6 +8,9 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
// Oh, error_chain.
#![recursion_limit="128"]
#[macro_use] #[macro_use]
extern crate error_chain; extern crate error_chain;
extern crate itertools; extern crate itertools;

View file

@ -633,11 +633,21 @@ impl<'conn, 'a> Tx<'conn, 'a> {
let added = op == OpType::Add; let added = op == OpType::Add;
// We take the last encountered :db/txInstant value. // We take the last encountered :db/txInstant value.
// If more than one is provided, the transactor will fail.
if added && if added &&
e == self.tx_id && e == self.tx_id &&
a == entids::DB_TX_INSTANT { a == entids::DB_TX_INSTANT {
if let TypedValue::Instant(instant) = v { if let TypedValue::Instant(instant) = v {
if let Some(ts) = self.tx_instant {
if ts == instant {
// Dupes are fine.
} else {
bail!(ErrorKind::ConflictingDatoms);
}
} else {
self.tx_instant = Some(instant); self.tx_instant = Some(instant);
}
continue;
} else { } else {
// The type error has been caught earlier. // The type error has been caught earlier.
unreachable!() unreachable!()
@ -657,14 +667,12 @@ impl<'conn, 'a> Tx<'conn, 'a> {
tx_instant = self.tx_instant.unwrap_or_else(now); tx_instant = self.tx_instant.unwrap_or_else(now);
// Transact [:db/add :db/txInstant NOW :db/tx] if it doesn't exist. // Transact [:db/add :db/txInstant tx_instant :db/tx].
if self.tx_instant == None {
non_fts_one.push((self.tx_id, non_fts_one.push((self.tx_id,
entids::DB_TX_INSTANT, entids::DB_TX_INSTANT,
self.schema.require_attribute_for_entid(entids::DB_TX_INSTANT).unwrap(), self.schema.require_attribute_for_entid(entids::DB_TX_INSTANT).unwrap(),
TypedValue::Instant(tx_instant), tx_instant.into(),
true)); true));
}
if !non_fts_one.is_empty() { if !non_fts_one.is_empty() {
self.store.insert_non_fts_searches(&non_fts_one[..], db::SearchType::Inexact)?; self.store.insert_non_fts_searches(&non_fts_one[..], db::SearchType::Inexact)?;