Convert query_projector/ to failure.
This commit is contained in:
parent
061967f268
commit
c075434f84
7 changed files with 83 additions and 95 deletions
|
@ -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]
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -30,9 +30,7 @@ use mentat_query_pull::{
|
|||
Puller,
|
||||
};
|
||||
|
||||
use errors::{
|
||||
Result,
|
||||
};
|
||||
use errors::Result;
|
||||
|
||||
use super::{
|
||||
Index,
|
||||
|
|
|
@ -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!(),
|
||||
|
|
Loading…
Reference in a new issue