Part 1: flatten V2 schema into V1. Add UUID and URI.

Bump expected ident and bootstrap datom count in tests.
This commit is contained in:
Richard Newman 2017-04-28 09:35:33 -07:00
parent 407dd7a07a
commit 044635e8bc
4 changed files with 34 additions and 58 deletions

View file

@ -61,6 +61,8 @@ lazy_static! {
(ns_keyword!("db.type", "long"), entids::DB_TYPE_LONG),
(ns_keyword!("db.type", "double"), entids::DB_TYPE_DOUBLE),
(ns_keyword!("db.type", "string"), entids::DB_TYPE_STRING),
(ns_keyword!("db.type", "uuid"), entids::DB_TYPE_UUID),
(ns_keyword!("db.type", "uri"), entids::DB_TYPE_URI),
(ns_keyword!("db.type", "boolean"), entids::DB_TYPE_BOOLEAN),
(ns_keyword!("db.type", "instant"), entids::DB_TYPE_INSTANT),
(ns_keyword!("db.type", "bytes"), entids::DB_TYPE_BYTES),
@ -69,16 +71,11 @@ lazy_static! {
(ns_keyword!("db.unique", "value"), entids::DB_UNIQUE_VALUE),
(ns_keyword!("db.unique", "identity"), entids::DB_UNIQUE_IDENTITY),
(ns_keyword!("db", "doc"), entids::DB_DOC),
(ns_keyword!("db.schema", "version"), entids::DB_SCHEMA_VERSION),
(ns_keyword!("db.schema", "attribute"), entids::DB_SCHEMA_ATTRIBUTE),
]
};
static ref V2_IDENTS: Vec<(symbols::NamespacedKeyword, i64)> = {
[(*V1_IDENTS).clone(),
vec![(ns_keyword!("db.schema", "version"), entids::DB_SCHEMA_VERSION),
(ns_keyword!("db.schema", "attribute"), entids::DB_SCHEMA_ATTRIBUTE),
]].concat()
};
static ref V1_PARTS: Vec<(symbols::NamespacedKeyword, i64, i64)> = {
vec![(ns_keyword!("db.part", "db"), 0, (1 + V1_IDENTS.len()) as i64),
(ns_keyword!("db.part", "user"), 0x10000, 0x10000),
@ -86,13 +83,6 @@ lazy_static! {
]
};
static ref V2_PARTS: Vec<(symbols::NamespacedKeyword, i64, i64)> = {
vec![(ns_keyword!("db.part", "db"), 0, (1 + V2_IDENTS.len()) as i64),
(ns_keyword!("db.part", "user"), 0x10000, 0x10000),
(ns_keyword!("db.part", "tx"), TX0, TX0),
]
};
static ref V1_SYMBOLIC_SCHEMA: Value = {
let s = r#"
{:db/ident {:db/valueType :db.type/keyword
@ -126,16 +116,8 @@ lazy_static! {
:db/fulltext {:db/valueType :db.type/boolean
:db/cardinality :db.cardinality/one}
:db/noHistory {:db/valueType :db.type/boolean
:db/cardinality :db.cardinality/one}}"#;
edn::parse::value(s)
.map(|v| v.without_spans())
.map_err(|_| ErrorKind::BadBootstrapDefinition("Unable to parse V1_SYMBOLIC_SCHEMA".into()))
.unwrap()
};
static ref V2_SYMBOLIC_SCHEMA: Value = {
let s = r#"
{:db.alter/attribute {:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one}
:db.alter/attribute {:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many}
:db.schema/version {:db/valueType :db.type/long
:db/cardinality :db.cardinality/one}
@ -146,13 +128,9 @@ lazy_static! {
:db/index true
:db/unique :db.unique/value
:db/cardinality :db.cardinality/many}}"#;
let right = edn::parse::value(s)
edn::parse::value(s)
.map(|v| v.without_spans())
.map_err(|_| ErrorKind::BadBootstrapDefinition("Unable to parse V2_SYMBOLIC_SCHEMA".into()))
.unwrap();
edn::utils::merge(&V1_SYMBOLIC_SCHEMA, &right)
.ok_or(ErrorKind::BadBootstrapDefinition("Unable to parse V2_SYMBOLIC_SCHEMA".into()))
.map_err(|_| ErrorKind::BadBootstrapDefinition("Unable to parse V1_SYMBOLIC_SCHEMA".into()))
.unwrap()
};
}
@ -248,27 +226,27 @@ fn symbolic_schema_to_assertions(symbolic_schema: &Value) -> Result<Vec<Value>>
}
pub fn bootstrap_partition_map() -> PartitionMap {
V2_PARTS[..].iter()
V1_PARTS[..].iter()
.map(|&(ref part, start, index)| (part.to_string(), Partition::new(start, index)))
.collect()
}
pub fn bootstrap_ident_map() -> IdentMap {
V2_IDENTS[..].iter()
V1_IDENTS[..].iter()
.map(|&(ref ident, entid)| (ident.clone(), entid))
.collect()
}
pub fn bootstrap_schema() -> Schema {
let ident_map = bootstrap_ident_map();
let bootstrap_triples = symbolic_schema_to_triples(&ident_map, &V2_SYMBOLIC_SCHEMA).unwrap();
let bootstrap_triples = symbolic_schema_to_triples(&ident_map, &V1_SYMBOLIC_SCHEMA).unwrap();
Schema::from_ident_map_and_triples(ident_map, bootstrap_triples).unwrap()
}
pub fn bootstrap_entities() -> Vec<Entity> {
let bootstrap_assertions: Value = Value::Vector([
symbolic_schema_to_assertions(&V2_SYMBOLIC_SCHEMA).unwrap(),
idents_to_assertions(&V2_IDENTS[..]),
symbolic_schema_to_assertions(&V1_SYMBOLIC_SCHEMA).unwrap(),
idents_to_assertions(&V1_IDENTS[..]),
].concat());
// Failure here is a coding error (since the inputs are fixed), not a runtime error.

View file

@ -72,10 +72,8 @@ pub fn new_connection<T>(uri: T) -> rusqlite::Result<rusqlite::Connection> where
/// Version history:
///
/// 1: initial schema.
/// 2: added :db.schema/version and /attribute in bootstrap; assigned idents 36 and 37, so we bump
/// the part range here; tie bootstrapping to the SQLite user_version.
pub const CURRENT_VERSION: i32 = 2;
/// 1: initial Mentat schema.
pub const CURRENT_VERSION: i32 = 1;
/// MIN_SQLITE_VERSION should be changed when there's a new minimum version of sqlite required
/// for the project to work.
@ -93,9 +91,9 @@ fn to_bool_ref(x: bool) -> &'static bool {
}
lazy_static! {
/// SQL statements to be executed, in order, to create the Mentat SQL schema (version 2).
/// SQL statements to be executed, in order, to create the Mentat SQL schema (version 1).
#[cfg_attr(rustfmt, rustfmt_skip)]
static ref V2_STATEMENTS: Vec<&'static str> = { vec![
static ref V1_STATEMENTS: Vec<&'static str> = { vec![
r#"CREATE TABLE datoms (e INTEGER NOT NULL, a SMALLINT NOT NULL, v BLOB NOT NULL, tx INTEGER NOT NULL,
value_type_tag SMALLINT NOT NULL,
index_avet TINYINT NOT NULL DEFAULT 0, index_vaet TINYINT NOT NULL DEFAULT 0,
@ -203,7 +201,7 @@ fn get_user_version(conn: &rusqlite::Connection) -> Result<i32> {
pub fn create_current_version(conn: &mut rusqlite::Connection) -> Result<DB> {
let tx = conn.transaction()?;
for statement in (&V2_STATEMENTS).iter() {
for statement in (&V1_STATEMENTS).iter() {
tx.execute(statement, &[])?;
}
@ -1173,12 +1171,12 @@ mod tests {
// Does not include :db/txInstant.
let datoms = debug::datoms_after(&conn, &db.schema, 0).unwrap();
assert_eq!(datoms.0.len(), 74);
assert_eq!(datoms.0.len(), 76);
// Includes :db/txInstant.
let transactions = debug::transactions_after(&conn, &db.schema, 0).unwrap();
assert_eq!(transactions.0.len(), 1);
assert_eq!(transactions.0[0].0.len(), 75);
assert_eq!(transactions.0[0].0.len(), 77);
let test_conn = TestConn {
sqlite: conn,

View file

@ -44,18 +44,18 @@ pub const DB_TYPE_KEYWORD: Entid = 24;
pub const DB_TYPE_LONG: Entid = 25;
pub const DB_TYPE_DOUBLE: Entid = 26;
pub const DB_TYPE_STRING: Entid = 27;
pub const DB_TYPE_BOOLEAN: Entid = 28;
pub const DB_TYPE_INSTANT: Entid = 29;
pub const DB_TYPE_BYTES: Entid = 30;
pub const DB_CARDINALITY_ONE: Entid = 31;
pub const DB_CARDINALITY_MANY: Entid = 32;
pub const DB_UNIQUE_VALUE: Entid = 33;
pub const DB_UNIQUE_IDENTITY: Entid = 34;
pub const DB_DOC: Entid = 35;
// Added in SQL schema v2.
pub const DB_SCHEMA_VERSION: Entid = 36;
pub const DB_SCHEMA_ATTRIBUTE: Entid = 37;
pub const DB_TYPE_UUID: Entid = 28;
pub const DB_TYPE_URI: Entid = 29;
pub const DB_TYPE_BOOLEAN: Entid = 30;
pub const DB_TYPE_INSTANT: Entid = 31;
pub const DB_TYPE_BYTES: Entid = 32;
pub const DB_CARDINALITY_ONE: Entid = 33;
pub const DB_CARDINALITY_MANY: Entid = 34;
pub const DB_UNIQUE_VALUE: Entid = 35;
pub const DB_UNIQUE_IDENTITY: Entid = 36;
pub const DB_DOC: Entid = 37;
pub const DB_SCHEMA_VERSION: Entid = 38;
pub const DB_SCHEMA_ATTRIBUTE: Entid = 39;
/// Return `false` if the given attribute will not change the metadata: recognized idents, schema,
/// partitions in the partition map.

View file

@ -46,7 +46,7 @@ fn test_rel() {
let end = time::PreciseTime::now();
// This will need to change each time we add a default ident.
assert_eq!(37, results.len());
assert_eq!(39, results.len());
// Every row is a pair of a Ref and a Keyword.
if let QueryResults::Rel(ref rel) = results {
@ -154,7 +154,7 @@ fn test_coll() {
.expect("Query failed");
let end = time::PreciseTime::now();
assert_eq!(37, results.len());
assert_eq!(39, results.len());
if let QueryResults::Coll(ref coll) = results {
assert!(coll.iter().all(|item| item.matches_type(ValueType::Ref)));