2020-01-14 15:46:21 +00:00
|
|
|
// Copyright 2018 Mozilla
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
|
|
// this file except in compliance with the License. You may obtain a copy of the
|
|
|
|
// License at http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
// Unless required by applicable law or agreed to in writing, software distributed
|
|
|
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
|
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
|
|
// specific language governing permissions and limitations under the License.
|
|
|
|
|
|
|
|
#[macro_use]
|
|
|
|
extern crate mentat;
|
|
|
|
|
|
|
|
use mentat::conn::Conn;
|
|
|
|
|
|
|
|
use core_traits::{Entid, KnownEntid, TypedValue};
|
|
|
|
|
|
|
|
use mentat_core::{HasSchema, TxReport};
|
|
|
|
|
|
|
|
use mentat_transaction::{Queryable, TermBuilder};
|
|
|
|
|
|
|
|
use public_traits::errors::MentatError;
|
|
|
|
|
|
|
|
use mentat::entity_builder::BuildTerms;
|
|
|
|
|
|
|
|
// In reality we expect the store to hand these out safely.
|
|
|
|
fn fake_known_entid(e: Entid) -> KnownEntid {
|
|
|
|
KnownEntid(e)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_entity_builder_bogus_entids() {
|
|
|
|
let mut builder = TermBuilder::new();
|
|
|
|
let e = builder.named_tempid("x");
|
|
|
|
let a1 = fake_known_entid(37); // :db/doc
|
|
|
|
let a2 = fake_known_entid(999);
|
|
|
|
let v = TypedValue::typed_string("Some attribute");
|
|
|
|
let ve = fake_known_entid(12345);
|
|
|
|
|
|
|
|
builder.add(e.clone(), a1, v).expect("add succeeded");
|
|
|
|
builder
|
|
|
|
.add(e.clone(), a2, e.clone())
|
|
|
|
.expect("add succeeded, even though it's meaningless");
|
|
|
|
builder
|
2020-08-06 03:03:58 +00:00
|
|
|
.add(e, a2, ve)
|
2020-01-14 15:46:21 +00:00
|
|
|
.expect("add succeeded, even though it's meaningless");
|
|
|
|
let (terms, tempids) = builder.build().expect("build succeeded");
|
|
|
|
|
|
|
|
assert_eq!(tempids.len(), 1);
|
|
|
|
assert_eq!(terms.len(), 3); // TODO: check the contents?
|
|
|
|
|
|
|
|
// Now try to add them to a real store.
|
|
|
|
let mut sqlite = mentat_db::db::new_connection("").unwrap();
|
|
|
|
let mut conn = Conn::connect(&mut sqlite).unwrap();
|
|
|
|
let mut in_progress = conn
|
|
|
|
.begin_transaction(&mut sqlite)
|
|
|
|
.expect("begun successfully");
|
|
|
|
|
|
|
|
// This should fail: unrecognized entid.
|
|
|
|
match in_progress
|
|
|
|
.transact_entities(terms)
|
|
|
|
.expect_err("expected transact to fail")
|
|
|
|
{
|
|
|
|
MentatError::DbError(e) => {
|
|
|
|
assert_eq!(
|
|
|
|
e.kind(),
|
|
|
|
db_traits::errors::DbErrorKind::UnrecognizedEntid(999)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
_ => panic!("Should have rejected the entid."),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_in_progress_builder() {
|
|
|
|
let mut sqlite = mentat_db::db::new_connection("").unwrap();
|
|
|
|
let mut conn = Conn::connect(&mut sqlite).unwrap();
|
|
|
|
|
|
|
|
// Give ourselves a schema to work with!
|
|
|
|
conn.transact(
|
|
|
|
&mut sqlite,
|
|
|
|
r#"[
|
|
|
|
[:db/add "o" :db/ident :foo/one]
|
|
|
|
[:db/add "o" :db/valueType :db.type/long]
|
|
|
|
[:db/add "o" :db/cardinality :db.cardinality/one]
|
|
|
|
[:db/add "m" :db/ident :foo/many]
|
|
|
|
[:db/add "m" :db/valueType :db.type/string]
|
|
|
|
[:db/add "m" :db/cardinality :db.cardinality/many]
|
|
|
|
[:db/add "r" :db/ident :foo/ref]
|
|
|
|
[:db/add "r" :db/valueType :db.type/ref]
|
|
|
|
[:db/add "r" :db/cardinality :db.cardinality/one]
|
|
|
|
]"#,
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let in_progress = conn
|
|
|
|
.begin_transaction(&mut sqlite)
|
|
|
|
.expect("begun successfully");
|
|
|
|
|
|
|
|
// We can use this or not!
|
|
|
|
let a_many = in_progress.get_entid(&kw!(:foo/many)).expect(":foo/many");
|
|
|
|
|
|
|
|
let mut builder = in_progress.builder();
|
|
|
|
let e_x = builder.named_tempid("x");
|
|
|
|
let v_many_1 = TypedValue::typed_string("Some text");
|
|
|
|
let v_many_2 = TypedValue::typed_string("Other text");
|
|
|
|
builder
|
|
|
|
.add(e_x.clone(), kw!(:foo/many), v_many_1)
|
|
|
|
.expect("add succeeded");
|
2020-08-06 03:03:58 +00:00
|
|
|
builder.add(e_x, a_many, v_many_2).expect("add succeeded");
|
2020-01-14 15:46:21 +00:00
|
|
|
builder.commit().expect("commit succeeded");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_entity_builder() {
|
|
|
|
let mut sqlite = mentat_db::db::new_connection("").unwrap();
|
|
|
|
let mut conn = Conn::connect(&mut sqlite).unwrap();
|
|
|
|
|
|
|
|
let foo_one = kw!(:foo/one);
|
|
|
|
let foo_many = kw!(:foo/many);
|
|
|
|
let foo_ref = kw!(:foo/ref);
|
|
|
|
let report: TxReport;
|
|
|
|
|
|
|
|
// Give ourselves a schema to work with!
|
|
|
|
// Scoped borrow of conn.
|
|
|
|
{
|
|
|
|
conn.transact(
|
|
|
|
&mut sqlite,
|
|
|
|
r#"[
|
|
|
|
[:db/add "o" :db/ident :foo/one]
|
|
|
|
[:db/add "o" :db/valueType :db.type/long]
|
|
|
|
[:db/add "o" :db/cardinality :db.cardinality/one]
|
|
|
|
[:db/add "m" :db/ident :foo/many]
|
|
|
|
[:db/add "m" :db/valueType :db.type/string]
|
|
|
|
[:db/add "m" :db/cardinality :db.cardinality/many]
|
|
|
|
[:db/add "r" :db/ident :foo/ref]
|
|
|
|
[:db/add "r" :db/valueType :db.type/ref]
|
|
|
|
[:db/add "r" :db/cardinality :db.cardinality/one]
|
|
|
|
]"#,
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let mut in_progress = conn
|
|
|
|
.begin_transaction(&mut sqlite)
|
|
|
|
.expect("begun successfully");
|
|
|
|
|
|
|
|
// Scoped borrow of in_progress.
|
|
|
|
{
|
|
|
|
let mut builder = TermBuilder::new();
|
|
|
|
let e_x = builder.named_tempid("x");
|
|
|
|
let e_y = builder.named_tempid("y");
|
|
|
|
let a_ref = in_progress.get_entid(&foo_ref).expect(":foo/ref");
|
|
|
|
let a_one = in_progress.get_entid(&foo_one).expect(":foo/one");
|
|
|
|
let a_many = in_progress.get_entid(&foo_many).expect(":foo/many");
|
|
|
|
let v_many_1 = TypedValue::typed_string("Some text");
|
|
|
|
let v_many_2 = TypedValue::typed_string("Other text");
|
|
|
|
let v_long: TypedValue = 123.into();
|
|
|
|
|
|
|
|
builder
|
|
|
|
.add(e_x.clone(), a_many, v_many_1)
|
|
|
|
.expect("add succeeded");
|
|
|
|
builder
|
|
|
|
.add(e_x.clone(), a_many, v_many_2)
|
|
|
|
.expect("add succeeded");
|
2020-08-06 03:03:58 +00:00
|
|
|
builder.add(e_y, a_ref, e_x.clone()).expect("add succeeded");
|
|
|
|
builder.add(e_x, a_one, v_long).expect("add succeeded");
|
2020-01-14 15:46:21 +00:00
|
|
|
|
|
|
|
let (terms, tempids) = builder.build().expect("build succeeded");
|
|
|
|
|
|
|
|
assert_eq!(tempids.len(), 2);
|
|
|
|
assert_eq!(terms.len(), 4);
|
|
|
|
|
|
|
|
report = in_progress.transact_entities(terms).expect("add succeeded");
|
|
|
|
let x = report.tempids.get("x").expect("our tempid has an ID");
|
|
|
|
let y = report.tempids.get("y").expect("our tempid has an ID");
|
|
|
|
assert_eq!(
|
|
|
|
in_progress
|
|
|
|
.lookup_value_for_attribute(*y, &foo_ref)
|
|
|
|
.expect("lookup succeeded"),
|
|
|
|
Some(TypedValue::Ref(*x))
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
in_progress
|
|
|
|
.lookup_value_for_attribute(*x, &foo_one)
|
|
|
|
.expect("lookup succeeded"),
|
|
|
|
Some(TypedValue::Long(123))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
in_progress.commit().expect("commit succeeded");
|
|
|
|
}
|
|
|
|
|
|
|
|
// It's all still there after the commit.
|
|
|
|
let x = report.tempids.get("x").expect("our tempid has an ID");
|
|
|
|
let y = report.tempids.get("y").expect("our tempid has an ID");
|
|
|
|
assert_eq!(
|
2020-08-06 03:03:58 +00:00
|
|
|
conn.lookup_value_for_attribute(&sqlite, *y, &foo_ref)
|
2020-01-14 15:46:21 +00:00
|
|
|
.expect("lookup succeeded"),
|
|
|
|
Some(TypedValue::Ref(*x))
|
|
|
|
);
|
|
|
|
}
|