Convert query_projector/ to failure.

This commit is contained in:
Grisha Kruglov 2018-06-04 16:53:31 -04:00 committed by Nick Alexander
parent 061967f268
commit c075434f84
7 changed files with 83 additions and 95 deletions

View file

@ -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]

View file

@ -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<ValueType> {
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))
}
}
},

View file

@ -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<T> = std::result::Result<T, Error>;
#[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),
}

View file

@ -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<Option<Binding>> {
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<Vec<Binding>> {
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<Option<Vec<Binding>>> {
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<RelResult<Binding>> {
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),
}
}

View file

@ -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<QualifiedAlias> {
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<Item = &'a Element>>(
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<Item = &'a Element>>(
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<Item = &'a Element>>(
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<Item = &'a Element>>(
.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 {

View file

@ -30,9 +30,7 @@ use mentat_query_pull::{
Puller,
};
use errors::{
Result,
};
use errors::Result;
use super::{
Index,

View file

@ -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!(),