From c075434f840a28ebe01d6b5c26c690b005b49728 Mon Sep 17 00:00:00 2001 From: Grisha Kruglov Date: Mon, 4 Jun 2018 16:53:31 -0400 Subject: [PATCH] Convert query_projector/ to failure. --- query-projector/Cargo.toml | 3 +- query-projector/src/aggregates.rs | 12 ++-- query-projector/src/errors.rs | 96 ++++++++++++----------------- query-projector/src/lib.rs | 34 +++++----- query-projector/src/project.rs | 22 +++---- query-projector/src/pull.rs | 4 +- query-projector/tests/aggregates.rs | 7 +-- 7 files changed, 83 insertions(+), 95 deletions(-) diff --git a/query-projector/Cargo.toml b/query-projector/Cargo.toml index 1bdcc4c1..be414ef0 100644 --- a/query-projector/Cargo.toml +++ b/query-projector/Cargo.toml @@ -4,7 +4,8 @@ version = "0.0.1" workspace = ".." [dependencies] -error-chain = { git = "https://github.com/rnewman/error-chain", branch = "rnewman/sync" } +failure = "0.1.1" +failure_derive = "0.1.1" indexmap = "1" [dependencies.rusqlite] diff --git a/query-projector/src/aggregates.rs b/query-projector/src/aggregates.rs index 99808fa7..8fde9b2a 100644 --- a/query-projector/src/aggregates.rs +++ b/query-projector/src/aggregates.rs @@ -33,7 +33,7 @@ use mentat_query_sql::{ }; use errors::{ - ErrorKind, + ProjectorError, Result, }; @@ -79,7 +79,7 @@ impl SimpleAggregationOp { pub(crate) fn is_applicable_to_types(&self, possibilities: ValueTypeSet) -> Result { use self::SimpleAggregationOp::*; if possibilities.is_empty() { - bail!(ErrorKind::CannotProjectImpossibleBinding(*self)) + bail!(ProjectorError::CannotProjectImpossibleBinding(*self)) } match self { @@ -92,7 +92,7 @@ impl SimpleAggregationOp { // The mean of a set of numeric values will always, for our purposes, be a double. Ok(ValueType::Double) } else { - bail!(ErrorKind::CannotApplyAggregateOperationToTypes(*self, possibilities)) + bail!(ProjectorError::CannotApplyAggregateOperationToTypes(*self, possibilities)) } }, &Sum => { @@ -104,7 +104,7 @@ impl SimpleAggregationOp { Ok(ValueType::Long) } } else { - bail!(ErrorKind::CannotApplyAggregateOperationToTypes(*self, possibilities)) + bail!(ProjectorError::CannotApplyAggregateOperationToTypes(*self, possibilities)) } }, @@ -124,7 +124,7 @@ impl SimpleAggregationOp { // These types are unordered. Keyword | Ref | Uuid => { - bail!(ErrorKind::CannotApplyAggregateOperationToTypes(*self, possibilities)) + bail!(ProjectorError::CannotApplyAggregateOperationToTypes(*self, possibilities)) }, } } else { @@ -139,7 +139,7 @@ impl SimpleAggregationOp { Ok(ValueType::Long) } } else { - bail!(ErrorKind::CannotApplyAggregateOperationToTypes(*self, possibilities)) + bail!(ProjectorError::CannotApplyAggregateOperationToTypes(*self, possibilities)) } } }, diff --git a/query-projector/src/errors.rs b/query-projector/src/errors.rs index 8db51d21..d25366eb 100644 --- a/query-projector/src/errors.rs +++ b/query-projector/src/errors.rs @@ -8,72 +8,58 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. -use rusqlite; +use std; // To refer to std::result::Result. + +use failure::{ + Error, +}; use mentat_core::{ ValueTypeSet, }; -use mentat_db; - use mentat_query::{ PlainSymbol, }; -use mentat_query_pull; - use aggregates::{ SimpleAggregationOp, }; -error_chain! { - types { - Error, ErrorKind, ResultExt, Result; - } - - errors { - /// We're just not done yet. Message that the feature is recognized but not yet - /// implemented. - NotYetImplemented(t: String) { - description("not yet implemented") - display("not yet implemented: {}", t) - } - CannotProjectImpossibleBinding(op: SimpleAggregationOp) { - description("no possible types for variable in projection list") - display("no possible types for value provided to {:?}", op) - } - CannotApplyAggregateOperationToTypes(op: SimpleAggregationOp, types: ValueTypeSet) { - description("cannot apply projection operation to types") - display("cannot apply projection operation {:?} to types {:?}", op, types) - } - InvalidProjection(t: String) { - description("invalid projection") - display("invalid projection: {}", t) - } - UnboundVariable(var: PlainSymbol) { - description("cannot project unbound variable") - display("cannot project unbound variable {:?}", var) - } - NoTypeAvailableForVariable(var: PlainSymbol) { - description("cannot find type for variable") - display("cannot find type for variable {:?}", var) - } - UnexpectedResultsType(actual: &'static str, expected: &'static str) { - description("unexpected query results type") - display("expected {}, got {}", expected, actual) - } - AmbiguousAggregates(min_max_count: usize, corresponding_count: usize) { - description("ambiguous aggregates") - display("min/max expressions: {} (max 1), corresponding: {}", min_max_count, corresponding_count) - } - } - - foreign_links { - Rusqlite(rusqlite::Error); - } - - links { - DbError(mentat_db::Error, mentat_db::ErrorKind); - PullError(mentat_query_pull::errors::Error, mentat_query_pull::errors::ErrorKind); - } +#[macro_export] +macro_rules! bail { + ($e:expr) => ( + return Err($e.into()); + ) +} + +pub type Result = std::result::Result; + +#[derive(Debug, Fail)] +pub enum ProjectorError { + /// We're just not done yet. Message that the feature is recognized but not yet + /// implemented. + #[fail(display = "not yet implemented: {}", _0)] + NotYetImplemented(String), + + #[fail(display = "no possible types for value provided to {:?}", _0)] + CannotProjectImpossibleBinding(SimpleAggregationOp), + + #[fail(display = "cannot apply projection operation {:?} to types {:?}", _0, _1)] + CannotApplyAggregateOperationToTypes(SimpleAggregationOp, ValueTypeSet), + + #[fail(display = "invalid projection: {}", _0)] + InvalidProjection(String), + + #[fail(display = "cannot project unbound variable {:?}", _0)] + UnboundVariable(PlainSymbol), + + #[fail(display = "cannot find type for variable {:?}", _0)] + NoTypeAvailableForVariable(PlainSymbol), + + #[fail(display = "expected {}, got {}", _0, _1)] + UnexpectedResultsType(&'static str, &'static str), + + #[fail(display = "min/max expressions: {} (max 1), corresponding: {}", _0, _1)] + AmbiguousAggregates(usize, usize), } diff --git a/query-projector/src/lib.rs b/query-projector/src/lib.rs index 94bc9d5b..c74fcc31 100644 --- a/query-projector/src/lib.rs +++ b/query-projector/src/lib.rs @@ -8,8 +8,10 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. +extern crate failure; + #[macro_use] -extern crate error_chain; +extern crate failure_derive; extern crate indexmap; extern crate rusqlite; @@ -67,12 +69,14 @@ use mentat_query_sql::{ Projection, }; +#[macro_use] +pub mod errors; + mod aggregates; mod project; mod projectors; mod pull; mod relresult; -pub mod errors; pub use aggregates::{ SimpleAggregationOp, @@ -109,7 +113,7 @@ pub use relresult::{ }; use errors::{ - ErrorKind, + ProjectorError, Result, }; @@ -296,35 +300,35 @@ impl QueryResults { pub fn into_scalar(self) -> Result> { match self { QueryResults::Scalar(o) => Ok(o), - QueryResults::Coll(_) => bail!(ErrorKind::UnexpectedResultsType("coll", "scalar")), - QueryResults::Tuple(_) => bail!(ErrorKind::UnexpectedResultsType("tuple", "scalar")), - QueryResults::Rel(_) => bail!(ErrorKind::UnexpectedResultsType("rel", "scalar")), + QueryResults::Coll(_) => bail!(ProjectorError::UnexpectedResultsType("coll", "scalar")), + QueryResults::Tuple(_) => bail!(ProjectorError::UnexpectedResultsType("tuple", "scalar")), + QueryResults::Rel(_) => bail!(ProjectorError::UnexpectedResultsType("rel", "scalar")), } } pub fn into_coll(self) -> Result> { match self { - QueryResults::Scalar(_) => bail!(ErrorKind::UnexpectedResultsType("scalar", "coll")), + QueryResults::Scalar(_) => bail!(ProjectorError::UnexpectedResultsType("scalar", "coll")), QueryResults::Coll(c) => Ok(c), - QueryResults::Tuple(_) => bail!(ErrorKind::UnexpectedResultsType("tuple", "coll")), - QueryResults::Rel(_) => bail!(ErrorKind::UnexpectedResultsType("rel", "coll")), + QueryResults::Tuple(_) => bail!(ProjectorError::UnexpectedResultsType("tuple", "coll")), + QueryResults::Rel(_) => bail!(ProjectorError::UnexpectedResultsType("rel", "coll")), } } pub fn into_tuple(self) -> Result>> { match self { - QueryResults::Scalar(_) => bail!(ErrorKind::UnexpectedResultsType("scalar", "tuple")), - QueryResults::Coll(_) => bail!(ErrorKind::UnexpectedResultsType("coll", "tuple")), + QueryResults::Scalar(_) => bail!(ProjectorError::UnexpectedResultsType("scalar", "tuple")), + QueryResults::Coll(_) => bail!(ProjectorError::UnexpectedResultsType("coll", "tuple")), QueryResults::Tuple(t) => Ok(t), - QueryResults::Rel(_) => bail!(ErrorKind::UnexpectedResultsType("rel", "tuple")), + QueryResults::Rel(_) => bail!(ProjectorError::UnexpectedResultsType("rel", "tuple")), } } pub fn into_rel(self) -> Result> { match self { - QueryResults::Scalar(_) => bail!(ErrorKind::UnexpectedResultsType("scalar", "rel")), - QueryResults::Coll(_) => bail!(ErrorKind::UnexpectedResultsType("coll", "rel")), - QueryResults::Tuple(_) => bail!(ErrorKind::UnexpectedResultsType("tuple", "rel")), + QueryResults::Scalar(_) => bail!(ProjectorError::UnexpectedResultsType("scalar", "rel")), + QueryResults::Coll(_) => bail!(ProjectorError::UnexpectedResultsType("coll", "rel")), + QueryResults::Tuple(_) => bail!(ProjectorError::UnexpectedResultsType("tuple", "rel")), QueryResults::Rel(r) => Ok(r), } } diff --git a/query-projector/src/project.rs b/query-projector/src/project.rs index 57ec1619..92d43433 100644 --- a/query-projector/src/project.rs +++ b/query-projector/src/project.rs @@ -55,7 +55,7 @@ use aggregates::{ }; use errors::{ - ErrorKind, + ProjectorError, Result, }; @@ -127,14 +127,14 @@ fn candidate_type_column(cc: &ConjoiningClauses, var: &Variable) -> Result<(Colu let type_name = VariableColumn::VariableTypeTag(var.clone()).column_name(); (ColumnOrExpression::Column(alias), type_name) }) - .ok_or_else(|| ErrorKind::UnboundVariable(var.name()).into()) + .ok_or_else(|| ProjectorError::UnboundVariable(var.name()).into()) } fn cc_column(cc: &ConjoiningClauses, var: &Variable) -> Result { cc.column_bindings .get(var) .and_then(|cols| cols.get(0).cloned()) - .ok_or_else(|| ErrorKind::UnboundVariable(var.name()).into()) + .ok_or_else(|| ProjectorError::UnboundVariable(var.name()).into()) } fn candidate_column(cc: &ConjoiningClauses, var: &Variable) -> Result<(ColumnOrExpression, Name)> { @@ -211,18 +211,18 @@ pub(crate) fn project_elements<'a, I: IntoIterator>( match e { &Element::Variable(ref var) => { if outer_variables.contains(var) { - bail!(ErrorKind::InvalidProjection(format!("Duplicate variable {} in query.", var))); + bail!(ProjectorError::InvalidProjection(format!("Duplicate variable {} in query.", var))); } if corresponded_variables.contains(var) { - bail!(ErrorKind::InvalidProjection(format!("Can't project both {} and `(the {})` from a query.", var, var))); + bail!(ProjectorError::InvalidProjection(format!("Can't project both {} and `(the {})` from a query.", var, var))); } }, &Element::Corresponding(ref var) => { if outer_variables.contains(var) { - bail!(ErrorKind::InvalidProjection(format!("Can't project both {} and `(the {})` from a query.", var, var))); + bail!(ProjectorError::InvalidProjection(format!("Can't project both {} and `(the {})` from a query.", var, var))); } if corresponded_variables.contains(var) { - bail!(ErrorKind::InvalidProjection(format!("`(the {})` appears twice in query.", var))); + bail!(ProjectorError::InvalidProjection(format!("`(the {})` appears twice in query.", var))); } }, &Element::Aggregate(_) => { @@ -346,7 +346,7 @@ pub(crate) fn project_elements<'a, I: IntoIterator>( i += 1; } else { // TODO: complex aggregates. - bail!(ErrorKind::NotYetImplemented("complex aggregates".into())); + bail!(ProjectorError::NotYetImplemented("complex aggregates".into())); } }, } @@ -355,13 +355,13 @@ pub(crate) fn project_elements<'a, I: IntoIterator>( match (min_max_count, corresponded_variables.len()) { (0, 0) | (_, 0) => {}, (0, _) => { - bail!(ErrorKind::InvalidProjection("Warning: used `the` without `min` or `max`.".to_string())); + bail!(ProjectorError::InvalidProjection("Warning: used `the` without `min` or `max`.".to_string())); }, (1, _) => { // This is the success case! }, (n, c) => { - bail!(ErrorKind::AmbiguousAggregates(n, c)); + bail!(ProjectorError::AmbiguousAggregates(n, c)); }, } @@ -465,7 +465,7 @@ pub(crate) fn project_elements<'a, I: IntoIterator>( .extracted_types .get(&var) .cloned() - .ok_or_else(|| ErrorKind::NoTypeAvailableForVariable(var.name().clone()))?; + .ok_or_else(|| ProjectorError::NoTypeAvailableForVariable(var.name().clone()))?; inner_projection.push(ProjectedColumn(ColumnOrExpression::Column(type_col), type_name.clone())); } if group { diff --git a/query-projector/src/pull.rs b/query-projector/src/pull.rs index bca0c217..b0ee05e1 100644 --- a/query-projector/src/pull.rs +++ b/query-projector/src/pull.rs @@ -30,9 +30,7 @@ use mentat_query_pull::{ Puller, }; -use errors::{ - Result, -}; +use errors::Result; use super::{ Index, diff --git a/query-projector/tests/aggregates.rs b/query-projector/tests/aggregates.rs index 6b148ed3..584f6431 100644 --- a/query-projector/tests/aggregates.rs +++ b/query-projector/tests/aggregates.rs @@ -99,11 +99,10 @@ fn test_the_without_max_or_min() { let projection = query_projection(&schema, &algebrized); assert!(projection.is_err()); use ::mentat_query_projector::errors::{ - ErrorKind, - Error, + ProjectorError, }; - match projection { - Result::Err(Error(ErrorKind::InvalidProjection(s) , _)) => { + match projection.err().expect("expected failure").downcast().expect("expected specific error") { + ProjectorError::InvalidProjection(s) => { assert_eq!(s.as_str(), "Warning: used `the` without `min` or `max`."); }, _ => panic!(),