lint
This commit is contained in:
parent
58e06742fd
commit
dfb5866174
9 changed files with 146 additions and 163 deletions
|
@ -28,14 +28,14 @@ pub enum SimpleAggregationOp {
|
|||
}
|
||||
|
||||
impl SimpleAggregationOp {
|
||||
pub fn to_sql(&self) -> &'static str {
|
||||
pub fn to_sql(self) -> &'static str {
|
||||
use self::SimpleAggregationOp::*;
|
||||
match self {
|
||||
&Avg => "avg",
|
||||
&Count => "count",
|
||||
&Max => "max",
|
||||
&Min => "min",
|
||||
&Sum => "sum",
|
||||
Avg => "avg",
|
||||
Count => "count",
|
||||
Max => "max",
|
||||
Min => "min",
|
||||
Sum => "sum",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,29 +57,29 @@ impl SimpleAggregationOp {
|
|||
/// but invalid to take `Max` of `{Uuid, String}`.
|
||||
///
|
||||
/// The returned type is the type of the result of the aggregation.
|
||||
pub fn is_applicable_to_types(&self, possibilities: ValueTypeSet) -> Result<ValueType> {
|
||||
pub fn is_applicable_to_types(self, possibilities: ValueTypeSet) -> Result<ValueType> {
|
||||
use self::SimpleAggregationOp::*;
|
||||
if possibilities.is_empty() {
|
||||
bail!(ProjectorError::CannotProjectImpossibleBinding(*self))
|
||||
bail!(ProjectorError::CannotProjectImpossibleBinding(self))
|
||||
}
|
||||
|
||||
match self {
|
||||
// One can always count results.
|
||||
&Count => Ok(ValueType::Long),
|
||||
Count => Ok(ValueType::Long),
|
||||
|
||||
// Only numeric types can be averaged or summed.
|
||||
&Avg => {
|
||||
Avg => {
|
||||
if possibilities.is_only_numeric() {
|
||||
// The mean of a set of numeric values will always, for our purposes, be a double.
|
||||
Ok(ValueType::Double)
|
||||
} else {
|
||||
bail!(ProjectorError::CannotApplyAggregateOperationToTypes(
|
||||
*self,
|
||||
self,
|
||||
possibilities
|
||||
))
|
||||
}
|
||||
}
|
||||
&Sum => {
|
||||
Sum => {
|
||||
if possibilities.is_only_numeric() {
|
||||
if possibilities.contains(ValueType::Double) {
|
||||
Ok(ValueType::Double)
|
||||
|
@ -89,18 +89,18 @@ impl SimpleAggregationOp {
|
|||
}
|
||||
} else {
|
||||
bail!(ProjectorError::CannotApplyAggregateOperationToTypes(
|
||||
*self,
|
||||
self,
|
||||
possibilities
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
&Max | &Min => {
|
||||
Max | Min => {
|
||||
if possibilities.is_unit() {
|
||||
use self::ValueType::*;
|
||||
let the_type = possibilities.exemplar().expect("a type");
|
||||
match the_type {
|
||||
// These types are numerically ordered.
|
||||
// Numerically ordered types.
|
||||
Double | Long | Instant => Ok(the_type),
|
||||
|
||||
// Boolean: false < true.
|
||||
|
@ -109,10 +109,10 @@ impl SimpleAggregationOp {
|
|||
// String: lexicographic order.
|
||||
String => Ok(the_type),
|
||||
|
||||
// These types are unordered.
|
||||
// Unordered types.
|
||||
Keyword | Ref | Uuid => {
|
||||
bail!(ProjectorError::CannotApplyAggregateOperationToTypes(
|
||||
*self,
|
||||
self,
|
||||
possibilities
|
||||
))
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ impl SimpleAggregationOp {
|
|||
}
|
||||
} else {
|
||||
bail!(ProjectorError::CannotApplyAggregateOperationToTypes(
|
||||
*self,
|
||||
self,
|
||||
possibilities
|
||||
))
|
||||
}
|
||||
|
|
|
@ -94,11 +94,11 @@ impl From<QueryOutput> for QueryResults {
|
|||
impl QueryOutput {
|
||||
pub fn empty_factory(spec: &FindSpec) -> Box<dyn Fn() -> QueryResults> {
|
||||
use self::FindSpec::*;
|
||||
match spec {
|
||||
&FindScalar(_) => Box::new(|| QueryResults::Scalar(None)),
|
||||
&FindTuple(_) => Box::new(|| QueryResults::Tuple(None)),
|
||||
&FindColl(_) => Box::new(|| QueryResults::Coll(vec![])),
|
||||
&FindRel(ref es) => {
|
||||
match *spec {
|
||||
FindScalar(_) => Box::new(|| QueryResults::Scalar(None)),
|
||||
FindTuple(_) => Box::new(|| QueryResults::Tuple(None)),
|
||||
FindColl(_) => Box::new(|| QueryResults::Coll(vec![])),
|
||||
FindRel(ref es) => {
|
||||
let width = es.len();
|
||||
Box::new(move || QueryResults::Rel(RelResult::empty(width)))
|
||||
}
|
||||
|
@ -115,48 +115,48 @@ impl QueryOutput {
|
|||
|
||||
pub fn empty(spec: &Rc<FindSpec>) -> QueryOutput {
|
||||
use self::FindSpec::*;
|
||||
let results = match &**spec {
|
||||
&FindScalar(_) => QueryResults::Scalar(None),
|
||||
&FindTuple(_) => QueryResults::Tuple(None),
|
||||
&FindColl(_) => QueryResults::Coll(vec![]),
|
||||
&FindRel(ref es) => QueryResults::Rel(RelResult::empty(es.len())),
|
||||
let results = match **spec {
|
||||
FindScalar(_) => QueryResults::Scalar(None),
|
||||
FindTuple(_) => QueryResults::Tuple(None),
|
||||
FindColl(_) => QueryResults::Coll(vec![]),
|
||||
FindRel(ref es) => QueryResults::Rel(RelResult::empty(es.len())),
|
||||
};
|
||||
QueryOutput {
|
||||
spec: spec.clone(),
|
||||
results: results,
|
||||
results,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_constants(spec: &Rc<FindSpec>, bindings: VariableBindings) -> QueryResults {
|
||||
use self::FindSpec::*;
|
||||
match &**spec {
|
||||
&FindScalar(Element::Variable(ref var))
|
||||
| &FindScalar(Element::Corresponding(ref var)) => {
|
||||
match **spec {
|
||||
FindScalar(Element::Variable(ref var))
|
||||
| FindScalar(Element::Corresponding(ref var)) => {
|
||||
let val = bindings.get(var).cloned().map(|v| v.into());
|
||||
QueryResults::Scalar(val)
|
||||
}
|
||||
&FindScalar(Element::Aggregate(ref _agg)) => {
|
||||
FindScalar(Element::Aggregate(ref _agg)) => {
|
||||
// TODO: static aggregates.
|
||||
unimplemented!();
|
||||
}
|
||||
&FindScalar(Element::Pull(ref _pull)) => {
|
||||
FindScalar(Element::Pull(ref _pull)) => {
|
||||
// TODO: static pull.
|
||||
unimplemented!();
|
||||
}
|
||||
&FindTuple(ref elements) => {
|
||||
FindTuple(ref elements) => {
|
||||
let values = elements
|
||||
.iter()
|
||||
.map(|e| match e {
|
||||
&Element::Variable(ref var) | &Element::Corresponding(ref var) => bindings
|
||||
.map(|e| match *e {
|
||||
Element::Variable(ref var) | Element::Corresponding(ref var) => bindings
|
||||
.get(var)
|
||||
.cloned()
|
||||
.expect("every var to have a binding")
|
||||
.into(),
|
||||
&Element::Pull(ref _pull) => {
|
||||
Element::Pull(ref _pull) => {
|
||||
// TODO: static pull.
|
||||
unreachable!();
|
||||
}
|
||||
&Element::Aggregate(ref _agg) => {
|
||||
Element::Aggregate(ref _agg) => {
|
||||
// TODO: static computation of aggregates, then
|
||||
// implement the condition in `is_fully_bound`.
|
||||
unreachable!();
|
||||
|
@ -165,7 +165,7 @@ impl QueryOutput {
|
|||
.collect();
|
||||
QueryResults::Tuple(Some(values))
|
||||
}
|
||||
&FindColl(Element::Variable(ref var)) | &FindColl(Element::Corresponding(ref var)) => {
|
||||
FindColl(Element::Variable(ref var)) | FindColl(Element::Corresponding(ref var)) => {
|
||||
let val = bindings
|
||||
.get(var)
|
||||
.cloned()
|
||||
|
@ -173,32 +173,32 @@ impl QueryOutput {
|
|||
.into();
|
||||
QueryResults::Coll(vec![val])
|
||||
}
|
||||
&FindColl(Element::Pull(ref _pull)) => {
|
||||
FindColl(Element::Pull(ref _pull)) => {
|
||||
// TODO: static pull.
|
||||
unimplemented!();
|
||||
}
|
||||
&FindColl(Element::Aggregate(ref _agg)) => {
|
||||
FindColl(Element::Aggregate(ref _agg)) => {
|
||||
// Does it even make sense to write
|
||||
// [:find [(max ?x) ...] :where [_ :foo/bar ?x]]
|
||||
// ?
|
||||
// TODO
|
||||
unimplemented!();
|
||||
}
|
||||
&FindRel(ref elements) => {
|
||||
FindRel(ref elements) => {
|
||||
let width = elements.len();
|
||||
let values = elements
|
||||
.iter()
|
||||
.map(|e| match e {
|
||||
&Element::Variable(ref var) | &Element::Corresponding(ref var) => bindings
|
||||
.map(|e| match *e {
|
||||
Element::Variable(ref var) | Element::Corresponding(ref var) => bindings
|
||||
.get(var)
|
||||
.cloned()
|
||||
.expect("every var to have a binding")
|
||||
.into(),
|
||||
&Element::Pull(ref _pull) => {
|
||||
Element::Pull(ref _pull) => {
|
||||
// TODO: static pull.
|
||||
unreachable!();
|
||||
}
|
||||
&Element::Aggregate(ref _agg) => {
|
||||
Element::Aggregate(ref _agg) => {
|
||||
// TODO: static computation of aggregates, then
|
||||
// implement the condition in `is_fully_bound`.
|
||||
unreachable!();
|
||||
|
@ -242,33 +242,33 @@ impl QueryOutput {
|
|||
impl QueryResults {
|
||||
pub fn len(&self) -> usize {
|
||||
use QueryResults::*;
|
||||
match self {
|
||||
&Scalar(ref o) => {
|
||||
match *self {
|
||||
Scalar(ref o) => {
|
||||
if o.is_some() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
&Tuple(ref o) => {
|
||||
Tuple(ref o) => {
|
||||
if o.is_some() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
&Coll(ref v) => v.len(),
|
||||
&Rel(ref r) => r.row_count(),
|
||||
Coll(ref v) => v.len(),
|
||||
Rel(ref r) => r.row_count(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
use QueryResults::*;
|
||||
match self {
|
||||
&Scalar(ref o) => o.is_none(),
|
||||
&Tuple(ref o) => o.is_none(),
|
||||
&Coll(ref v) => v.is_empty(),
|
||||
&Rel(ref r) => r.is_empty(),
|
||||
match *self {
|
||||
Scalar(ref o) => o.is_none(),
|
||||
Tuple(ref o) => o.is_none(),
|
||||
Coll(ref v) => v.is_empty(),
|
||||
Rel(ref r) => r.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,14 +341,14 @@ impl TypedIndex {
|
|||
fn lookup<'a>(&self, row: &Row<'a>) -> Result<Binding> {
|
||||
use TypedIndex::*;
|
||||
|
||||
match self {
|
||||
&Known(value_index, value_type) => {
|
||||
match *self {
|
||||
Known(value_index, value_type) => {
|
||||
let v: rusqlite::types::Value = row.get(value_index).unwrap();
|
||||
TypedValue::from_sql_value_pair(v, value_type)
|
||||
.map(|v| v.into())
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
&Unknown(value_index, type_index) => {
|
||||
Unknown(value_index, type_index) => {
|
||||
let v: rusqlite::types::Value = row.get(value_index).unwrap();
|
||||
let value_type_tag: i32 = row.get(type_index).unwrap();
|
||||
TypedValue::from_sql_value_pair(v, value_type_tag)
|
||||
|
@ -403,8 +403,8 @@ trait IsPull {
|
|||
|
||||
impl IsPull for Element {
|
||||
fn is_pull(&self) -> bool {
|
||||
match self {
|
||||
&Element::Pull(_) => true,
|
||||
match *self {
|
||||
Element::Pull(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -430,16 +430,16 @@ pub fn query_projection(
|
|||
|
||||
let variables: BTreeSet<Variable> = spec
|
||||
.columns()
|
||||
.map(|e| match e {
|
||||
&Element::Variable(ref var) | &Element::Corresponding(ref var) => var.clone(),
|
||||
.map(|e| match *e {
|
||||
Element::Variable(ref var) | Element::Corresponding(ref var) => var.clone(),
|
||||
|
||||
// Pull expressions can never be fully bound.
|
||||
// TODO: but the interior can be, in which case we
|
||||
// can handle this and simply project.
|
||||
&Element::Pull(_) => {
|
||||
Element::Pull(_) => {
|
||||
unreachable!();
|
||||
}
|
||||
&Element::Aggregate(ref _agg) => {
|
||||
Element::Aggregate(ref _agg) => {
|
||||
// TODO: static computation of aggregates, then
|
||||
// implement the condition in `is_fully_bound`.
|
||||
unreachable!();
|
||||
|
|
|
@ -67,7 +67,7 @@ impl ProjectedElements {
|
|||
sql_projection: self.sql_projection,
|
||||
pre_aggregate_projection: self.pre_aggregate_projection,
|
||||
datalog_projector: projector,
|
||||
distinct: distinct,
|
||||
distinct,
|
||||
group_by_cols: self.group_by,
|
||||
})
|
||||
}
|
||||
|
@ -98,14 +98,14 @@ fn candidate_type_column(
|
|||
let type_name = VariableColumn::VariableTypeTag(var.clone()).column_name();
|
||||
(ColumnOrExpression::Column(alias), type_name)
|
||||
})
|
||||
.ok_or_else(|| ProjectorError::UnboundVariable(var.name()).into())
|
||||
.ok_or_else(|| ProjectorError::UnboundVariable(var.name()))
|
||||
}
|
||||
|
||||
fn cc_column(cc: &ConjoiningClauses, var: &Variable) -> Result<QualifiedAlias> {
|
||||
cc.column_bindings
|
||||
.get(var)
|
||||
.and_then(|cols| cols.get(0).cloned())
|
||||
.ok_or_else(|| ProjectorError::UnboundVariable(var.name()).into())
|
||||
.ok_or_else(|| ProjectorError::UnboundVariable(var.name()))
|
||||
}
|
||||
|
||||
fn candidate_column(cc: &ConjoiningClauses, var: &Variable) -> Result<(ColumnOrExpression, Name)> {
|
||||
|
@ -130,7 +130,7 @@ pub fn projected_column_for_var(
|
|||
let tag = value.value_type();
|
||||
let name = VariableColumn::Variable(var.clone()).column_name();
|
||||
Ok((
|
||||
ProjectedColumn(ColumnOrExpression::Value(value.clone()), name),
|
||||
ProjectedColumn(ColumnOrExpression::Value(value), name),
|
||||
ValueTypeSet::of_one(tag),
|
||||
))
|
||||
} else {
|
||||
|
@ -184,8 +184,8 @@ pub(crate) fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
|
|||
|
||||
for e in elements {
|
||||
// Check for and reject duplicates.
|
||||
match e {
|
||||
&Element::Variable(ref var) => {
|
||||
match *e {
|
||||
Element::Variable(ref var) => {
|
||||
if outer_variables.contains(var) {
|
||||
bail!(ProjectorError::InvalidProjection(format!(
|
||||
"Duplicate variable {} in query.",
|
||||
|
@ -199,7 +199,7 @@ pub(crate) fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
|
|||
)));
|
||||
}
|
||||
}
|
||||
&Element::Corresponding(ref var) => {
|
||||
Element::Corresponding(ref var) => {
|
||||
if outer_variables.contains(var) {
|
||||
bail!(ProjectorError::InvalidProjection(format!(
|
||||
"Can't project both {} and `(the {})` from a query.",
|
||||
|
@ -213,38 +213,35 @@ pub(crate) fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
|
|||
)));
|
||||
}
|
||||
}
|
||||
&Element::Aggregate(_) => {}
|
||||
&Element::Pull(_) => {}
|
||||
Element::Aggregate(_) => {}
|
||||
Element::Pull(_) => {}
|
||||
};
|
||||
|
||||
// Record variables -- `(the ?x)` and `?x` are different in this regard, because we don't want
|
||||
// to group on variables that are corresponding-projected.
|
||||
match e {
|
||||
&Element::Variable(ref var) => {
|
||||
match *e {
|
||||
Element::Variable(ref var) => {
|
||||
outer_variables.insert(var.clone());
|
||||
}
|
||||
&Element::Corresponding(ref var) => {
|
||||
Element::Corresponding(ref var) => {
|
||||
// We will project these later; don't put them in `outer_variables`
|
||||
// so we know not to group them.
|
||||
corresponded_variables.insert(var.clone());
|
||||
}
|
||||
&Element::Pull(Pull {
|
||||
ref var,
|
||||
patterns: _,
|
||||
}) => {
|
||||
Element::Pull(Pull { ref var, .. }) => {
|
||||
// We treat `pull` as an ordinary variable extraction,
|
||||
// and we expand it later.
|
||||
outer_variables.insert(var.clone());
|
||||
}
|
||||
&Element::Aggregate(_) => {}
|
||||
Element::Aggregate(_) => {}
|
||||
};
|
||||
|
||||
// Now do the main processing of each element.
|
||||
match e {
|
||||
match *e {
|
||||
// Each time we come across a variable, we push a SQL column
|
||||
// into the SQL projection, aliased to the name of the variable,
|
||||
// and we push an annotated index into the projector.
|
||||
&Element::Variable(ref var) | &Element::Corresponding(ref var) => {
|
||||
Element::Variable(ref var) | Element::Corresponding(ref var) => {
|
||||
inner_variables.insert(var.clone());
|
||||
|
||||
let (projected_column, type_set) = projected_column_for_var(&var, &query.cc)?;
|
||||
|
@ -264,7 +261,7 @@ pub(crate) fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
|
|||
outer_projection.push(Either::Left(type_name));
|
||||
}
|
||||
}
|
||||
&Element::Pull(Pull {
|
||||
Element::Pull(Pull {
|
||||
ref var,
|
||||
ref patterns,
|
||||
}) => {
|
||||
|
@ -296,7 +293,7 @@ pub(crate) fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
|
|||
unreachable!();
|
||||
}
|
||||
}
|
||||
&Element::Aggregate(ref a) => {
|
||||
Element::Aggregate(ref a) => {
|
||||
if let Some(simple) = a.to_simple() {
|
||||
aggregates = true;
|
||||
|
||||
|
@ -343,7 +340,7 @@ pub(crate) fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
|
|||
templates.push(TypedIndex::Known(i, return_type.value_type_tag()));
|
||||
i += 1;
|
||||
} else {
|
||||
// TODO: complex aggregates.
|
||||
// TODO(gburd): complex aggregates.
|
||||
bail!(ProjectorError::NotYetImplemented(
|
||||
"complex aggregates".into()
|
||||
));
|
||||
|
@ -465,9 +462,12 @@ pub(crate) fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
|
|||
if needs_type_projection {
|
||||
let type_name = VariableColumn::VariableTypeTag(var.clone()).column_name();
|
||||
if !already_inner {
|
||||
let type_col = query.cc.extracted_types.get(&var).cloned().ok_or_else(|| {
|
||||
ProjectorError::NoTypeAvailableForVariable(var.name().clone())
|
||||
})?;
|
||||
let type_col = query
|
||||
.cc
|
||||
.extracted_types
|
||||
.get(&var)
|
||||
.cloned()
|
||||
.ok_or_else(|| ProjectorError::NoTypeAvailableForVariable(var.name()))?;
|
||||
inner_projection.push(ProjectedColumn(
|
||||
ColumnOrExpression::Column(type_col),
|
||||
type_name.clone(),
|
||||
|
|
|
@ -29,18 +29,15 @@ impl ConstantProjector {
|
|||
results_factory: Box<dyn Fn() -> QueryResults>,
|
||||
) -> ConstantProjector {
|
||||
ConstantProjector {
|
||||
spec: spec,
|
||||
results_factory: results_factory,
|
||||
spec,
|
||||
results_factory,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn project_without_rows<'stmt>(&self) -> Result<QueryOutput> {
|
||||
pub fn project_without_rows(&self) -> Result<QueryOutput> {
|
||||
let results = (self.results_factory)();
|
||||
let spec = self.spec.clone();
|
||||
Ok(QueryOutput {
|
||||
spec: spec,
|
||||
results: results,
|
||||
})
|
||||
Ok(QueryOutput { spec, results })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ impl ScalarTwoStagePullProjector {
|
|||
pull: PullOperation,
|
||||
) -> Result<ScalarTwoStagePullProjector> {
|
||||
Ok(ScalarTwoStagePullProjector {
|
||||
spec: spec,
|
||||
puller: Puller::prepare(schema, pull.0.clone())?,
|
||||
spec,
|
||||
puller: Puller::prepare(schema, pull.0)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ impl Projector for ScalarTwoStagePullProjector {
|
|||
|
||||
Ok(QueryOutput {
|
||||
spec: self.spec.clone(),
|
||||
results: results,
|
||||
results,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -111,10 +111,10 @@ impl TupleTwoStagePullProjector {
|
|||
pulls: Vec<PullTemplate>,
|
||||
) -> TupleTwoStagePullProjector {
|
||||
TupleTwoStagePullProjector {
|
||||
spec: spec,
|
||||
len: len,
|
||||
templates: templates,
|
||||
pulls: pulls,
|
||||
spec,
|
||||
len,
|
||||
templates,
|
||||
pulls,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ impl Projector for TupleTwoStagePullProjector {
|
|||
};
|
||||
Ok(QueryOutput {
|
||||
spec: self.spec.clone(),
|
||||
results: results,
|
||||
results,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -215,10 +215,10 @@ impl RelTwoStagePullProjector {
|
|||
pulls: Vec<PullTemplate>,
|
||||
) -> RelTwoStagePullProjector {
|
||||
RelTwoStagePullProjector {
|
||||
spec: spec,
|
||||
len: len,
|
||||
templates: templates,
|
||||
pulls: pulls,
|
||||
spec,
|
||||
len,
|
||||
templates,
|
||||
pulls,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,10 +320,7 @@ pub(crate) struct CollTwoStagePullProjector {
|
|||
|
||||
impl CollTwoStagePullProjector {
|
||||
fn with_pull(spec: Rc<FindSpec>, pull: PullOperation) -> CollTwoStagePullProjector {
|
||||
CollTwoStagePullProjector {
|
||||
spec: spec,
|
||||
pull: pull,
|
||||
}
|
||||
CollTwoStagePullProjector { spec, pull }
|
||||
}
|
||||
|
||||
pub(crate) fn combine(
|
||||
|
|
|
@ -26,10 +26,7 @@ pub(crate) struct ScalarProjector {
|
|||
|
||||
impl ScalarProjector {
|
||||
fn with_template(spec: Rc<FindSpec>, template: TypedIndex) -> ScalarProjector {
|
||||
ScalarProjector {
|
||||
spec: spec,
|
||||
template: template,
|
||||
}
|
||||
ScalarProjector { spec, template }
|
||||
}
|
||||
|
||||
pub(crate) fn combine(
|
||||
|
@ -62,7 +59,7 @@ impl Projector for ScalarProjector {
|
|||
};
|
||||
Ok(QueryOutput {
|
||||
spec: self.spec.clone(),
|
||||
results: results,
|
||||
results,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -85,9 +82,9 @@ impl TupleProjector {
|
|||
templates: Vec<TypedIndex>,
|
||||
) -> TupleProjector {
|
||||
TupleProjector {
|
||||
spec: spec,
|
||||
len: len,
|
||||
templates: templates,
|
||||
spec,
|
||||
len,
|
||||
templates,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +131,7 @@ impl Projector for TupleProjector {
|
|||
};
|
||||
Ok(QueryOutput {
|
||||
spec: self.spec.clone(),
|
||||
results: results,
|
||||
results,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -156,9 +153,9 @@ pub(crate) struct RelProjector {
|
|||
impl RelProjector {
|
||||
fn with_templates(spec: Rc<FindSpec>, len: usize, templates: Vec<TypedIndex>) -> RelProjector {
|
||||
RelProjector {
|
||||
spec: spec,
|
||||
len: len,
|
||||
templates: templates,
|
||||
spec,
|
||||
len,
|
||||
templates,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,10 +232,7 @@ pub(crate) struct CollProjector {
|
|||
|
||||
impl CollProjector {
|
||||
fn with_template(spec: Rc<FindSpec>, template: TypedIndex) -> CollProjector {
|
||||
CollProjector {
|
||||
spec: spec,
|
||||
template: template,
|
||||
}
|
||||
CollProjector { spec, template }
|
||||
}
|
||||
|
||||
pub(crate) fn combine(
|
||||
|
|
|
@ -61,9 +61,9 @@ impl<'schema> PullConsumer<'schema> {
|
|||
indices: PullIndices,
|
||||
) -> PullConsumer<'schema> {
|
||||
PullConsumer {
|
||||
indices: indices,
|
||||
schema: schema,
|
||||
puller: puller,
|
||||
indices,
|
||||
schema,
|
||||
puller,
|
||||
entities: Default::default(),
|
||||
results: Default::default(),
|
||||
}
|
||||
|
@ -114,10 +114,6 @@ impl<'schema> PullConsumer<'schema> {
|
|||
|
||||
// TODO: do we need to include empty maps for entities that didn't match any pull?
|
||||
pub(crate) fn into_coll_results(self) -> Vec<Binding> {
|
||||
self.results
|
||||
.values()
|
||||
.cloned()
|
||||
.map(|vrc| Binding::Map(vrc))
|
||||
.collect()
|
||||
self.results.values().cloned().map(Binding::Map).collect()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ pub type StructuredRelResult = RelResult<Binding>;
|
|||
impl<T> RelResult<T> {
|
||||
pub fn empty(width: usize) -> RelResult<T> {
|
||||
RelResult {
|
||||
width: width,
|
||||
width,
|
||||
values: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ impl<T> RelResult<T> {
|
|||
}
|
||||
|
||||
pub fn rows(&self) -> ::std::slice::Chunks<T> {
|
||||
// TODO: Nightly-only API `exact_chunks`. #47115.
|
||||
// TODO(gburd): Nightly-only API `exact_chunks`. #47115.
|
||||
self.values.chunks(self.width)
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ impl From<Vec<Vec<TypedValue>>> for RelResult<Binding> {
|
|||
} else {
|
||||
let width = src.get(0).map(|r| r.len()).unwrap_or(0);
|
||||
RelResult {
|
||||
width: width,
|
||||
width,
|
||||
values: src
|
||||
.into_iter()
|
||||
.flat_map(|r| r.into_iter().map(|v| v.into()))
|
||||
|
|
|
@ -224,7 +224,7 @@ impl ToConstraint for ColumnConstraint {
|
|||
|
||||
NotExists(computed_table) => {
|
||||
let subquery = table_for_computed(computed_table, TableAlias::new());
|
||||
Constraint::NotExists { subquery: subquery }
|
||||
Constraint::NotExists { subquery }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ struct ConsumableVec<T> {
|
|||
impl<T> From<Vec<T>> for ConsumableVec<T> {
|
||||
fn from(vec: Vec<T>) -> ConsumableVec<T> {
|
||||
ConsumableVec {
|
||||
inner: vec.into_iter().map(|x| Some(x)).collect(),
|
||||
inner: vec.into_iter().map(Some).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -369,20 +369,20 @@ fn cc_to_select_query(
|
|||
FromClause::TableList(TableList(tables.collect()))
|
||||
};
|
||||
|
||||
let order = order.map_or(vec![], |vec| vec.into_iter().map(|o| o.into()).collect());
|
||||
let order = order.map_or(vec![], |vec| vec.into_iter().map(|o| o).collect());
|
||||
let limit = if cc.empty_because.is_some() {
|
||||
Limit::Fixed(0)
|
||||
} else {
|
||||
limit
|
||||
};
|
||||
SelectQuery {
|
||||
distinct: distinct,
|
||||
projection: projection,
|
||||
from: from,
|
||||
group_by: group_by,
|
||||
distinct,
|
||||
projection,
|
||||
from,
|
||||
group_by,
|
||||
constraints: cc.wheres.into_iter().map(|c| c.to_constraint()).collect(),
|
||||
order: order,
|
||||
limit: limit,
|
||||
order,
|
||||
limit,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,11 +412,11 @@ fn re_project(mut inner: SelectQuery, projection: Projection) -> SelectQuery {
|
|||
|
||||
use self::Projection::*;
|
||||
|
||||
let nullable = match &projection {
|
||||
&Columns(ref columns) => columns
|
||||
let nullable = match projection {
|
||||
Columns(ref columns) => columns
|
||||
.iter()
|
||||
.filter_map(|pc| match pc {
|
||||
&ProjectedColumn(ColumnOrExpression::NullableAggregate(_, _), ref name) => {
|
||||
.filter_map(|pc| match *pc {
|
||||
ProjectedColumn(ColumnOrExpression::NullableAggregate(_, _), ref name) => {
|
||||
Some(Constraint::IsNotNull {
|
||||
value: ColumnOrExpression::ExistingColumn(name.clone()),
|
||||
})
|
||||
|
@ -424,21 +424,21 @@ fn re_project(mut inner: SelectQuery, projection: Projection) -> SelectQuery {
|
|||
_ => None,
|
||||
})
|
||||
.collect(),
|
||||
&Star => vec![],
|
||||
&One => vec![],
|
||||
Star => vec![],
|
||||
One => vec![],
|
||||
};
|
||||
|
||||
if nullable.is_empty() {
|
||||
return SelectQuery {
|
||||
distinct: outer_distinct,
|
||||
projection: projection,
|
||||
projection,
|
||||
from: FromClause::TableList(TableList(vec![TableOrSubquery::Subquery(Box::new(
|
||||
inner,
|
||||
))])),
|
||||
constraints: vec![],
|
||||
group_by: group_by,
|
||||
group_by,
|
||||
order: order_by,
|
||||
limit: limit,
|
||||
limit,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -449,10 +449,10 @@ fn re_project(mut inner: SelectQuery, projection: Projection) -> SelectQuery {
|
|||
// if there is.
|
||||
let subselect = SelectQuery {
|
||||
distinct: outer_distinct,
|
||||
projection: projection,
|
||||
projection,
|
||||
from: FromClause::TableList(TableList(vec![TableOrSubquery::Subquery(Box::new(inner))])),
|
||||
constraints: vec![],
|
||||
group_by: group_by,
|
||||
group_by,
|
||||
order: match &limit {
|
||||
&Limit::None => vec![],
|
||||
&Limit::Fixed(_) | &Limit::Variable(_) => order_by.clone(),
|
||||
|
@ -499,8 +499,7 @@ pub fn query_to_select(schema: &Schema, query: AlgebraicQuery) -> Result<Project
|
|||
query.order,
|
||||
query.limit,
|
||||
);
|
||||
let outer = re_project(inner, sql_projection);
|
||||
outer
|
||||
re_project(inner, sql_projection) // outer
|
||||
}
|
||||
None => cc_to_select_query(
|
||||
sql_projection,
|
||||
|
|
Loading…
Reference in a new issue