Convert src/ to failure.

This commit is contained in:
Grisha Kruglov 2018-06-04 18:07:09 -04:00 committed by Nick Alexander
parent 836fdb3a35
commit 4e01929334
11 changed files with 131 additions and 197 deletions

View file

@ -28,7 +28,8 @@ rustc_version = "0.2"
[dependencies] [dependencies]
chrono = "0.4" chrono = "0.4"
error-chain = { git = "https://github.com/rnewman/error-chain", branch = "rnewman/sync" } failure = "0.1.1"
failure_derive = "0.1.1"
lazy_static = "0.2" lazy_static = "0.2"
time = "0.1" time = "0.1"
uuid = { version = "0.5", features = ["v4", "serde"] } uuid = { version = "0.5", features = ["v4", "serde"] }

View file

@ -93,7 +93,10 @@ use entity_builder::{
TermBuilder, TermBuilder,
}; };
use errors::*; use errors::{
Result,
MentatError,
};
use query::{ use query::{
Known, Known,
@ -474,7 +477,7 @@ impl<'a, 'c> InProgress<'a, 'c> {
// Retrying is tracked by https://github.com/mozilla/mentat/issues/357. // Retrying is tracked by https://github.com/mozilla/mentat/issues/357.
// This should not occur -- an attempt to take a competing IMMEDIATE transaction // This should not occur -- an attempt to take a competing IMMEDIATE transaction
// will fail with `SQLITE_BUSY`, causing this function to abort. // will fail with `SQLITE_BUSY`, causing this function to abort.
bail!("Lost the transact() race!"); bail!(MentatError::UnexpectedLostTransactRace);
} }
// Commit the SQLite transaction while we hold the mutex. // Commit the SQLite transaction while we hold the mutex.
@ -506,7 +509,7 @@ impl<'a, 'c> InProgress<'a, 'c> {
cache_action: CacheAction) -> Result<()> { cache_action: CacheAction) -> Result<()> {
let attribute_entid: Entid = self.schema let attribute_entid: Entid = self.schema
.attribute_for_ident(&attribute) .attribute_for_ident(&attribute)
.ok_or_else(|| ErrorKind::UnknownAttribute(attribute.to_string()))?.1.into(); .ok_or_else(|| MentatError::UnknownAttribute(attribute.to_string()))?.1.into();
match cache_action { match cache_action {
CacheAction::Register => { CacheAction::Register => {
@ -579,17 +582,16 @@ impl Conn {
/// Prepare the provided SQLite handle for use as a Mentat store. Creates tables but /// Prepare the provided SQLite handle for use as a Mentat store. Creates tables but
/// _does not_ write the bootstrap schema. This constructor should only be used by /// _does not_ write the bootstrap schema. This constructor should only be used by
/// consumers that expect to populate raw transaction data themselves. /// consumers that expect to populate raw transaction data themselves.
pub(crate) fn empty(sqlite: &mut rusqlite::Connection) -> Result<Conn> { pub(crate) fn empty(sqlite: &mut rusqlite::Connection) -> Result<Conn> {
let (tx, db) = db::create_empty_current_version(sqlite) let (tx, db) = db::create_empty_current_version(sqlite)?;
.chain_err(|| "Unable to initialize Mentat store")?;
tx.commit()?; tx.commit()?;
Ok(Conn::new(db.partition_map, db.schema)) Ok(Conn::new(db.partition_map, db.schema))
} }
pub fn connect(sqlite: &mut rusqlite::Connection) -> Result<Conn> { pub fn connect(sqlite: &mut rusqlite::Connection) -> Result<Conn> {
let db = db::ensure_current_version(sqlite) let db = db::ensure_current_version(sqlite)?;
.chain_err(|| "Unable to initialize Mentat store")?;
Ok(Conn::new(db.partition_map, db.schema)) Ok(Conn::new(db.partition_map, db.schema))
} }
@ -801,7 +803,7 @@ impl Conn {
{ {
attribute_entid = metadata.schema attribute_entid = metadata.schema
.attribute_for_ident(&attribute) .attribute_for_ident(&attribute)
.ok_or_else(|| ErrorKind::UnknownAttribute(attribute.to_string()))?.1.into(); .ok_or_else(|| MentatError::UnknownAttribute(attribute.to_string()))?.1.into();
} }
let cache = &mut metadata.attribute_cache; let cache = &mut metadata.attribute_cache;
@ -869,11 +871,11 @@ mod tests {
.partition_map[":db.part/user"].index; .partition_map[":db.part/user"].index;
let t = format!("[[:db/add {} :db.schema/attribute \"tempid\"]]", next + 1); let t = format!("[[:db/add {} :db.schema/attribute \"tempid\"]]", next + 1);
match conn.transact(&mut sqlite, t.as_str()).unwrap_err() { match conn.transact(&mut sqlite, t.as_str()).expect_err("expected transact error").downcast() {
Error(ErrorKind::DbError(::mentat_db::errors::ErrorKind::UnrecognizedEntid(e)), _) => { Ok(::mentat_db::DbError::UnrecognizedEntid(e)) => {
assert_eq!(e, next + 1); assert_eq!(e, next + 1);
}, },
x => panic!("expected transact error, got {:?}", x), x => panic!("expected db error, got {:?}", x),
} }
// Transact two more tempids. // Transact two more tempids.
@ -896,12 +898,12 @@ mod tests {
// we should reject this, because the first ID was provided by the user! // we should reject this, because the first ID was provided by the user!
let t = format!("[[:db/add {} :db.schema/attribute \"tempid\"]]", next); let t = format!("[[:db/add {} :db.schema/attribute \"tempid\"]]", next);
match conn.transact(&mut sqlite, t.as_str()).unwrap_err() { match conn.transact(&mut sqlite, t.as_str()).expect_err("expected transact error").downcast() {
Error(ErrorKind::DbError(::mentat_db::errors::ErrorKind::UnrecognizedEntid(e)), _) => { Ok(::mentat_db::DbError::UnrecognizedEntid(e)) => {
// All this, despite this being the ID we were about to allocate! // All this, despite this being the ID we were about to allocate!
assert_eq!(e, next); assert_eq!(e, next);
}, },
x => panic!("expected transact error, got {:?}", x), x => panic!("expected db error, got {:?}", x),
} }
// And if we subsequently transact in a way that allocates one ID, we _will_ use that one. // And if we subsequently transact in a way that allocates one ID, we _will_ use that one.
@ -1057,9 +1059,9 @@ mod tests {
// Bad EDN: missing closing ']'. // Bad EDN: missing closing ']'.
let report = conn.transact(&mut sqlite, "[[:db/add \"t\" :db/ident :a/keyword]"); let report = conn.transact(&mut sqlite, "[[:db/add \"t\" :db/ident :a/keyword]");
match report.unwrap_err() { match report.expect_err("expected transact to fail for bad edn").downcast() {
Error(ErrorKind::EdnParseError(_), _) => { }, Ok(edn::ParseError { .. }) => { },
x => panic!("expected EDN parse error, got {:?}", x), Err(x) => panic!("expected EDN parse error, got {:?}", x),
} }
// Good EDN. // Good EDN.
@ -1068,9 +1070,9 @@ mod tests {
// Bad transaction data: missing leading :db/add. // Bad transaction data: missing leading :db/add.
let report = conn.transact(&mut sqlite, "[[\"t\" :db/ident :b/keyword]]"); let report = conn.transact(&mut sqlite, "[[\"t\" :db/ident :b/keyword]]");
match report.unwrap_err() { match report.expect_err("expected transact error").downcast() {
Error(ErrorKind::EdnParseError(_), _) => { }, Ok(edn::ParseError { .. }) => { },
x => panic!("expected EDN parse error, got {:?}", x), Err(x) => panic!("expected EDN parse error, got {:?}", x),
} }
// Good transaction data. // Good transaction data.
@ -1080,8 +1082,8 @@ mod tests {
// Bad transaction based on state of store: conflicting upsert. // Bad transaction based on state of store: conflicting upsert.
let report = conn.transact(&mut sqlite, "[[:db/add \"u\" :db/ident :a/keyword] let report = conn.transact(&mut sqlite, "[[:db/add \"u\" :db/ident :a/keyword]
[:db/add \"u\" :db/ident :b/keyword]]"); [:db/add \"u\" :db/ident :b/keyword]]");
match report.unwrap_err() { match report.expect_err("expected transact error").downcast() {
Error(ErrorKind::DbError(::mentat_db::errors::ErrorKind::SchemaConstraintViolation(_)), _) => { }, Ok(::mentat_db::DbError::SchemaConstraintViolation(_)) => { },
x => panic!("expected schema constraint violation, got {:?}", x), x => panic!("expected schema constraint violation, got {:?}", x),
} }
} }
@ -1099,8 +1101,8 @@ mod tests {
let kw = kw!(:foo/bat); let kw = kw!(:foo/bat);
let schema = conn.current_schema(); let schema = conn.current_schema();
let res = conn.cache(&mut sqlite, &schema, &kw, CacheDirection::Forward, CacheAction::Register); let res = conn.cache(&mut sqlite, &schema, &kw, CacheDirection::Forward, CacheAction::Register);
match res.unwrap_err() { match res.expect_err("expected cache to fail").downcast() {
Error(ErrorKind::UnknownAttribute(msg), _) => assert_eq!(msg, ":foo/bat"), Ok(MentatError::UnknownAttribute(msg)) => assert_eq!(msg, ":foo/bat"),
x => panic!("expected UnknownAttribute error, got {:?}", x), x => panic!("expected UnknownAttribute error, got {:?}", x),
} }
} }

View file

@ -85,7 +85,7 @@ use conn::{
}; };
use errors::{ use errors::{
ErrorKind, MentatError,
Result, Result,
}; };
@ -277,12 +277,12 @@ impl<'a, 'c> InProgressBuilder<'a, 'c> {
let provided = tv.value_type(); let provided = tv.value_type();
let expected = attr.value_type; let expected = attr.value_type;
if provided != expected { if provided != expected {
bail!(ErrorKind::ValueTypeMismatch(provided, expected)); bail!(MentatError::ValueTypeMismatch(provided, expected));
} }
} }
attribute = aa; attribute = aa;
} else { } else {
bail!(ErrorKind::UnknownAttribute(a.to_string())); bail!(MentatError::UnknownAttribute(a.to_string()));
} }
Ok((attribute, v)) Ok((attribute, v))
} }
@ -380,11 +380,6 @@ impl FromThing<KnownEntid> for TypedValueOr<TempIdHandle> {
mod testing { mod testing {
extern crate mentat_db; extern crate mentat_db;
use errors::{
Error,
ErrorKind,
};
// For matching inside a test. // For matching inside a test.
use mentat_db::ErrorKind::{ use mentat_db::ErrorKind::{
UnrecognizedEntid, UnrecognizedEntid,
@ -429,7 +424,7 @@ mod testing {
let mut in_progress = conn.begin_transaction(&mut sqlite).expect("begun successfully"); let mut in_progress = conn.begin_transaction(&mut sqlite).expect("begun successfully");
// This should fail: unrecognized entid. // This should fail: unrecognized entid.
if let Err(Error(ErrorKind::DbError(UnrecognizedEntid(e)), _)) = in_progress.transact_terms(terms, tempids) { if let Err(Error(MentatError::DbError(UnrecognizedEntid(e)), _)) = in_progress.transact_terms(terms, tempids) {
assert_eq!(e, 999); assert_eq!(e, 999);
} else { } else {
panic!("Should have rejected the entid."); panic!("Should have rejected the entid.");

View file

@ -10,102 +10,63 @@
#![allow(dead_code)] #![allow(dead_code)]
use rusqlite; use std; // To refer to std::result::Result.
use uuid;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use edn; use failure::Error;
use mentat_core::{ use mentat_core::{
Attribute, Attribute,
ValueType, ValueType,
}; };
use mentat_db;
use mentat_query; use mentat_query;
use mentat_query_algebrizer;
use mentat_query_projector;
use mentat_query_pull;
use mentat_query_translator;
use mentat_sql;
use mentat_tolstoy;
error_chain! { pub type Result<T> = std::result::Result<T, Error>;
types {
Error, ErrorKind, ResultExt, Result;
}
foreign_links { #[macro_export]
EdnParseError(edn::ParseError); macro_rules! bail {
Rusqlite(rusqlite::Error); ($e:expr) => (
UuidParseError(uuid::ParseError); return Err($e.into());
IoError(::std::io::Error); )
} }
links { #[derive(Debug, Fail)]
DbError(mentat_db::Error, mentat_db::ErrorKind); pub enum MentatError {
QueryError(mentat_query_algebrizer::Error, mentat_query_algebrizer::ErrorKind); // Let's not leak the term 'algebrizer'. #[fail(display = "path {} already exists", _0)]
ProjectorError(mentat_query_projector::errors::Error, mentat_query_projector::errors::ErrorKind); PathAlreadyExists(String),
PullError(mentat_query_pull::errors::Error, mentat_query_pull::errors::ErrorKind);
TranslatorError(mentat_query_translator::Error, mentat_query_translator::ErrorKind); #[fail(display = "variables {:?} unbound at query execution time", _0)]
SqlError(mentat_sql::Error, mentat_sql::ErrorKind); UnboundVariables(BTreeSet<String>),
SyncError(mentat_tolstoy::Error, mentat_tolstoy::ErrorKind);
} #[fail(display = "invalid argument name: '{}'", _0)]
InvalidArgumentName(String),
errors {
PathAlreadyExists(path: String) { #[fail(display = "unknown attribute: '{}'", _0)]
description("path already exists") UnknownAttribute(String),
display("path {} already exists", path)
} #[fail(display = "invalid vocabulary version")]
InvalidVocabularyVersion,
UnboundVariables(names: BTreeSet<String>) {
description("unbound variables at query execution time") #[fail(display = "vocabulary {}/{} already has attribute {}, and the requested definition differs", _0, _1, _2)]
display("variables {:?} unbound at query execution time", names) ConflictingAttributeDefinitions(String, ::vocabulary::Version, String, Attribute, Attribute),
}
#[fail(display = "existing vocabulary {} too new: wanted {}, got {}", _0, _1, _2)]
InvalidArgumentName(name: String) { ExistingVocabularyTooNew(String, ::vocabulary::Version, ::vocabulary::Version),
description("invalid argument name")
display("invalid argument name: '{}'", name) #[fail(display = "core schema: wanted {}, got {:?}", _0, _1)]
} UnexpectedCoreSchema(::vocabulary::Version, Option<::vocabulary::Version>),
UnknownAttribute(name: String) { #[fail(display = "Lost the transact() race!")]
description("unknown attribute") UnexpectedLostTransactRace,
display("unknown attribute: '{}'", name)
} #[fail(display = "missing core attribute {}", _0)]
MissingCoreVocabulary(mentat_query::Keyword),
InvalidVocabularyVersion {
description("invalid vocabulary version") #[fail(display = "schema changed since query was prepared")]
display("invalid vocabulary version") PreparedQuerySchemaMismatch,
}
#[fail(display = "provided value of type {} doesn't match attribute value type {}", _0, _1)]
ConflictingAttributeDefinitions(vocabulary: String, version: ::vocabulary::Version, attribute: String, current: Attribute, requested: Attribute) { ValueTypeMismatch(ValueType, ValueType),
description("conflicting attribute definitions")
display("vocabulary {}/{} already has attribute {}, and the requested definition differs", vocabulary, version, attribute)
}
ExistingVocabularyTooNew(name: String, existing: ::vocabulary::Version, ours: ::vocabulary::Version) {
description("existing vocabulary too new")
display("existing vocabulary too new: wanted {}, got {}", ours, existing)
}
UnexpectedCoreSchema(version: Option<::vocabulary::Version>) {
description("unexpected core schema version")
display("core schema: wanted {}, got {:?}", mentat_db::CORE_SCHEMA_VERSION, version)
}
MissingCoreVocabulary(kw: mentat_query::Keyword) {
description("missing core vocabulary")
display("missing core attribute {}", kw)
}
PreparedQuerySchemaMismatch {
description("schema changed since query was prepared")
display("schema changed since query was prepared")
}
ValueTypeMismatch(provided: ValueType, expected: ValueType) {
description("provided value doesn't match value type")
display("provided value of type {} doesn't match attribute value type {}", provided, expected)
}
}
} }

View file

@ -11,7 +11,8 @@
#![recursion_limit="128"] #![recursion_limit="128"]
#[macro_use] #[macro_use]
extern crate error_chain; extern crate failure_derive;
extern crate failure;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
@ -101,9 +102,10 @@ macro_rules! kw {
}; };
} }
#[macro_use]
pub mod errors;
pub mod conn; pub mod conn;
pub mod entity_builder; pub mod entity_builder;
pub mod errors;
pub mod ident; pub mod ident;
pub mod query; pub mod query;
pub mod query_builder; pub mod query_builder;

View file

@ -74,7 +74,7 @@ pub use mentat_query_projector::{
}; };
use errors::{ use errors::{
ErrorKind, MentatError,
Result, Result,
}; };
@ -178,7 +178,7 @@ fn algebrize_query<T>
// If they aren't, the user has made an error -- perhaps writing the wrong variable in `:in`, or // If they aren't, the user has made an error -- perhaps writing the wrong variable in `:in`, or
// not binding in the `QueryInput`. // not binding in the `QueryInput`.
if !unbound.is_empty() { if !unbound.is_empty() {
bail!(ErrorKind::UnboundVariables(unbound.into_iter().map(|v| v.to_string()).collect())); bail!(MentatError::UnboundVariables(unbound.into_iter().map(|v| v.to_string()).collect()));
} }
Ok(algebrized) Ok(algebrized)
} }
@ -211,7 +211,7 @@ fn fetch_values<'sqlite>
fn lookup_attribute(schema: &Schema, attribute: &Keyword) -> Result<KnownEntid> { fn lookup_attribute(schema: &Schema, attribute: &Keyword) -> Result<KnownEntid> {
schema.get_entid(attribute) schema.get_entid(attribute)
.ok_or_else(|| ErrorKind::UnknownAttribute(attribute.name().into()).into()) .ok_or_else(|| MentatError::UnknownAttribute(attribute.name().into()).into())
} }
/// Return a single value for the provided entity and attribute. /// Return a single value for the provided entity and attribute.
@ -398,7 +398,7 @@ pub fn q_prepare<'sqlite, 'schema, 'cache, 'query, T>
if !unbound.is_empty() { if !unbound.is_empty() {
// TODO: Allow binding variables at execution time, not just // TODO: Allow binding variables at execution time, not just
// preparation time. // preparation time.
bail!(ErrorKind::UnboundVariables(unbound.into_iter().map(|v| v.to_string()).collect())); bail!(MentatError::UnboundVariables(unbound.into_iter().map(|v| v.to_string()).collect()));
} }
if algebrized.is_known_empty() { if algebrized.is_known_empty() {

View file

@ -34,7 +34,7 @@ use ::{
}; };
use errors::{ use errors::{
ErrorKind, MentatError,
Result, Result,
}; };
@ -56,7 +56,7 @@ impl<'a> QueryBuilder<'a> {
} }
pub fn bind_ref_from_kw(&mut self, var: &str, value: Keyword) -> Result<&mut Self> { pub fn bind_ref_from_kw(&mut self, var: &str, value: Keyword) -> Result<&mut Self> {
let entid = self.store.conn().current_schema().get_entid(&value).ok_or(ErrorKind::UnknownAttribute(value.to_string()))?; let entid = self.store.conn().current_schema().get_entid(&value).ok_or(MentatError::UnknownAttribute(value.to_string()))?;
self.values.insert(Variable::from_valid_name(var), TypedValue::Ref(entid.into())); self.values.insert(Variable::from_valid_name(var), TypedValue::Ref(entid.into()));
Ok(self) Ok(self)
} }

View file

@ -84,7 +84,7 @@ impl Store {
pub fn open_empty(path: &str) -> Result<Store> { pub fn open_empty(path: &str) -> Result<Store> {
if !path.is_empty() { if !path.is_empty() {
if Path::new(path).exists() { if Path::new(path).exists() {
bail!(ErrorKind::PathAlreadyExists(path.to_string())); bail!(MentatError::PathAlreadyExists(path.to_string()));
} }
} }
@ -124,7 +124,7 @@ impl Store {
pub fn open_empty_with_key(path: &str, encryption_key: &str) -> Result<Store> { pub fn open_empty_with_key(path: &str, encryption_key: &str) -> Result<Store> {
if !path.is_empty() { if !path.is_empty() {
if Path::new(path).exists() { if Path::new(path).exists() {
bail!(ErrorKind::PathAlreadyExists(path.to_string())); bail!(MentatError::PathAlreadyExists(path.to_string()));
} }
} }

View file

@ -121,7 +121,7 @@ use ::conn::{
}; };
use ::errors::{ use ::errors::{
ErrorKind, MentatError,
Result, Result,
}; };
@ -375,17 +375,17 @@ trait HasCoreSchema {
impl<T> HasCoreSchema for T where T: HasSchema { impl<T> HasCoreSchema for T where T: HasSchema {
fn core_type(&self, t: ValueType) -> Result<KnownEntid> { fn core_type(&self, t: ValueType) -> Result<KnownEntid> {
self.entid_for_type(t) self.entid_for_type(t)
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into()) .ok_or_else(|| MentatError::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
} }
fn core_entid(&self, ident: &Keyword) -> Result<KnownEntid> { fn core_entid(&self, ident: &Keyword) -> Result<KnownEntid> {
self.get_entid(ident) self.get_entid(ident)
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into()) .ok_or_else(|| MentatError::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
} }
fn core_attribute(&self, ident: &Keyword) -> Result<KnownEntid> { fn core_attribute(&self, ident: &Keyword) -> Result<KnownEntid> {
self.attribute_for_ident(ident) self.attribute_for_ident(ident)
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into()) .ok_or_else(|| MentatError::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
.map(|(_, e)| e) .map(|(_, e)| e)
} }
} }
@ -568,7 +568,7 @@ pub trait VersionedStore: HasVocabularies + HasSchema {
// We have two vocabularies with the same name, same version, and // We have two vocabularies with the same name, same version, and
// different definitions for an attribute. That's a coding error. // different definitions for an attribute. That's a coding error.
// We can't accept this vocabulary. // We can't accept this vocabulary.
bail!(ErrorKind::ConflictingAttributeDefinitions( bail!(MentatError::ConflictingAttributeDefinitions(
definition.name.to_string(), definition.name.to_string(),
definition.version, definition.version,
pair.0.to_string(), pair.0.to_string(),
@ -615,13 +615,13 @@ pub trait VersionedStore: HasVocabularies + HasSchema {
fn verify_core_schema(&self) -> Result<()> { fn verify_core_schema(&self) -> Result<()> {
if let Some(core) = self.read_vocabulary_named(&DB_SCHEMA_CORE)? { if let Some(core) = self.read_vocabulary_named(&DB_SCHEMA_CORE)? {
if core.version != CORE_SCHEMA_VERSION { if core.version != CORE_SCHEMA_VERSION {
bail!(ErrorKind::UnexpectedCoreSchema(Some(core.version))); bail!(MentatError::UnexpectedCoreSchema(CORE_SCHEMA_VERSION, Some(core.version)));
} }
// TODO: check things other than the version. // TODO: check things other than the version.
} else { } else {
// This would be seriously messed up. // This would be seriously messed up.
bail!(ErrorKind::UnexpectedCoreSchema(None)); bail!(MentatError::UnexpectedCoreSchema(CORE_SCHEMA_VERSION, None));
} }
Ok(()) Ok(())
} }
@ -682,7 +682,7 @@ impl<'a, 'c> VersionedStore for InProgress<'a, 'c> {
VocabularyCheck::NotPresent => self.install_vocabulary(definition), VocabularyCheck::NotPresent => self.install_vocabulary(definition),
VocabularyCheck::PresentButNeedsUpdate { older_version } => self.upgrade_vocabulary(definition, older_version), VocabularyCheck::PresentButNeedsUpdate { older_version } => self.upgrade_vocabulary(definition, older_version),
VocabularyCheck::PresentButMissingAttributes { attributes } => self.install_attributes_for(definition, attributes), VocabularyCheck::PresentButMissingAttributes { attributes } => self.install_attributes_for(definition, attributes),
VocabularyCheck::PresentButTooNew { newer_version } => Err(ErrorKind::ExistingVocabularyTooNew(definition.name.to_string(), newer_version.version, definition.version).into()), VocabularyCheck::PresentButTooNew { newer_version } => Err(MentatError::ExistingVocabularyTooNew(definition.name.to_string(), newer_version.version, definition.version).into()),
} }
} }
@ -701,7 +701,7 @@ impl<'a, 'c> VersionedStore for InProgress<'a, 'c> {
out.insert(definition.name.clone(), VocabularyOutcome::Existed); out.insert(definition.name.clone(), VocabularyOutcome::Existed);
}, },
VocabularyCheck::PresentButTooNew { newer_version } => { VocabularyCheck::PresentButTooNew { newer_version } => {
bail!(ErrorKind::ExistingVocabularyTooNew(definition.name.to_string(), newer_version.version, definition.version)); bail!(MentatError::ExistingVocabularyTooNew(definition.name.to_string(), newer_version.version, definition.version));
}, },
c @ VocabularyCheck::NotPresent | c @ VocabularyCheck::NotPresent |
@ -868,7 +868,7 @@ impl<T> HasVocabularies for T where T: HasSchema + Queryable {
attributes: attributes, attributes: attributes,
})) }))
}, },
Some(_) => bail!(ErrorKind::InvalidVocabularyVersion), Some(_) => bail!(MentatError::InvalidVocabularyVersion),
} }
} else { } else {
Ok(None) Ok(None)

View file

@ -61,8 +61,7 @@ use mentat::query::q_uncached;
use mentat::conn::Conn; use mentat::conn::Conn;
use mentat::errors::{ use mentat::errors::{
Error, MentatError,
ErrorKind,
}; };
#[test] #[test]
@ -234,11 +233,11 @@ fn test_unbound_inputs() {
let results = q_uncached(&c, &db.schema, let results = q_uncached(&c, &db.schema,
"[:find ?i . :in ?e :where [?e :db/ident ?i]]", inputs); "[:find ?i . :in ?e :where [?e :db/ident ?i]]", inputs);
match results { match results.expect_err("expected unbound variables").downcast().expect("expected specific error") {
Result::Err(Error(ErrorKind::UnboundVariables(vars), _)) => { MentatError::UnboundVariables(vars) => {
assert_eq!(vars, vec!["?e".to_string()].into_iter().collect()); assert_eq!(vars, vec!["?e".to_string()].into_iter().collect());
}, },
_ => panic!("Expected unbound variables."), _ => panic!("Expected UnboundVariables variant."),
} }
} }
@ -412,8 +411,8 @@ fn test_fulltext() {
[?a :foo/term ?term] [?a :foo/term ?term]
]"#; ]"#;
let r = conn.q_once(&mut c, query, None); let r = conn.q_once(&mut c, query, None);
match r { match r.expect_err("expected query to fail").downcast() {
Err(Error(ErrorKind::QueryError(mentat_query_algebrizer::ErrorKind::InvalidArgument(PlainSymbol(s), ty, i)), _)) => { Ok(mentat_query_algebrizer::AlgebrizerError::InvalidArgument(PlainSymbol(s), ty, i)) => {
assert_eq!(s, "fulltext"); assert_eq!(s, "fulltext");
assert_eq!(ty, "string"); assert_eq!(ty, "string");
assert_eq!(i, 2); assert_eq!(i, 2);
@ -427,8 +426,8 @@ fn test_fulltext() {
[?a :foo/term ?term] [?a :foo/term ?term]
[(fulltext $ :foo/fts ?a) [[?x ?val]]]]"#; [(fulltext $ :foo/fts ?a) [[?x ?val]]]]"#;
let r = conn.q_once(&mut c, query, None); let r = conn.q_once(&mut c, query, None);
match r { match r.expect_err("expected query to fail").downcast() {
Err(Error(ErrorKind::QueryError(mentat_query_algebrizer::ErrorKind::InvalidArgument(PlainSymbol(s), ty, i)), _)) => { Ok(mentat_query_algebrizer::AlgebrizerError::InvalidArgument(PlainSymbol(s), ty, i)) => {
assert_eq!(s, "fulltext"); assert_eq!(s, "fulltext");
assert_eq!(ty, "string"); assert_eq!(ty, "string");
assert_eq!(i, 2); assert_eq!(i, 2);
@ -583,42 +582,25 @@ fn test_aggregates_type_handling() {
// No type limits => can't do it. // No type limits => can't do it.
let r = store.q_once(r#"[:find (sum ?v) . :where [_ _ ?v]]"#, None); let r = store.q_once(r#"[:find (sum ?v) . :where [_ _ ?v]]"#, None);
let all_types = ValueTypeSet::any(); let all_types = ValueTypeSet::any();
match r { match r.expect_err("expected query to fail").downcast() {
Result::Err( Ok(::mentat_query_projector::errors::ProjectorError::CannotApplyAggregateOperationToTypes(
Error( SimpleAggregationOp::Sum, types)) => {
ErrorKind::TranslatorError( assert_eq!(types, all_types);
::mentat_query_translator::ErrorKind::ProjectorError( },
::mentat_query_projector::errors::ErrorKind::CannotApplyAggregateOperationToTypes( e => panic!("Unexpected error type {:?}", e),
SimpleAggregationOp::Sum,
types
),
)
),
_)) => {
assert_eq!(types, all_types);
},
r => panic!("Unexpected: {:?}", r),
} }
// You can't sum instants. // You can't sum instants.
let r = store.q_once(r#"[:find (sum ?v) . let r = store.q_once(r#"[:find (sum ?v) .
:where [_ _ ?v] [(type ?v :db.type/instant)]]"#, :where [_ _ ?v] [(type ?v :db.type/instant)]]"#,
None); None);
match r { match r.expect_err("expected query to fail").downcast() {
Result::Err( Ok(::mentat_query_projector::errors::ProjectorError::CannotApplyAggregateOperationToTypes(
Error( SimpleAggregationOp::Sum,
ErrorKind::TranslatorError( types)) => {
::mentat_query_translator::ErrorKind::ProjectorError( assert_eq!(types, ValueTypeSet::of_one(ValueType::Instant));
::mentat_query_projector::errors::ErrorKind::CannotApplyAggregateOperationToTypes( },
SimpleAggregationOp::Sum, e => panic!("Unexpected error type {:?}", e),
types
),
)
),
_)) => {
assert_eq!(types, ValueTypeSet::of_one(ValueType::Instant));
},
r => panic!("Unexpected: {:?}", r),
} }
// But you can count them. // But you can count them.
@ -1354,19 +1336,13 @@ fn test_aggregation_implicit_grouping() {
[?person :foo/play ?game] [?person :foo/play ?game]
[?person :foo/is-vegetarian true] [?person :foo/is-vegetarian true]
[?person :foo/name ?name]]"#, None); [?person :foo/name ?name]]"#, None);
match res { match res.expect_err("expected query to fail").downcast() {
Result::Err( Ok(::mentat_query_projector::errors::ProjectorError::AmbiguousAggregates(mmc, cc)) => {
Error(
ErrorKind::TranslatorError(
::mentat_query_translator::ErrorKind::ProjectorError(
::mentat_query_projector::errors::ErrorKind::AmbiguousAggregates(mmc, cc)
)
), _)) => {
assert_eq!(mmc, 2); assert_eq!(mmc, 2);
assert_eq!(cc, 1); assert_eq!(cc, 1);
}, },
r => { e => {
panic!("Unexpected result {:?}.", r); panic!("Unexpected error type {:?}.", e);
}, },
} }

View file

@ -59,10 +59,7 @@ use mentat::entity_builder::{
TermBuilder, TermBuilder,
}; };
use mentat::errors::{ use mentat::errors::MentatError;
Error,
ErrorKind,
};
lazy_static! { lazy_static! {
static ref FOO_NAME: Keyword = { static ref FOO_NAME: Keyword = {
@ -289,8 +286,8 @@ fn test_add_vocab() {
// Scoped borrow of `conn`. // Scoped borrow of `conn`.
{ {
let mut in_progress = conn.begin_transaction(&mut sqlite).expect("begun successfully"); let mut in_progress = conn.begin_transaction(&mut sqlite).expect("begun successfully");
match in_progress.ensure_vocabulary(&foo_v1_malformed) { match in_progress.ensure_vocabulary(&foo_v1_malformed).expect_err("expected vocabulary to fail").downcast() {
Result::Err(Error(ErrorKind::ConflictingAttributeDefinitions(vocab, version, attr, theirs, ours), _)) => { Ok(MentatError::ConflictingAttributeDefinitions(vocab, version, attr, theirs, ours)) => {
assert_eq!(vocab.as_str(), ":org.mozilla/foo"); assert_eq!(vocab.as_str(), ":org.mozilla/foo");
assert_eq!(attr.as_str(), ":foo/baz"); assert_eq!(attr.as_str(), ":foo/baz");
assert_eq!(version, 1); assert_eq!(version, 1);