Flesh out duplicate txInstant support.
This commit is contained in:
parent
a8dcad65da
commit
7c5143d4e9
4 changed files with 34 additions and 19 deletions
19
db/src/db.rs
19
db/src/db.rs
|
@ -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.
|
||||||
|
|
|
@ -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")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
16
db/src/tx.rs
16
db/src/tx.rs
|
@ -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)?;
|
||||||
|
|
Loading…
Reference in a new issue