Pre: refactor projector code.

This commit is contained in:
Richard Newman 2017-04-13 11:44:37 -07:00
parent d8f761993d
commit 5f79932361

View file

@ -37,6 +37,7 @@ use mentat_db::{
use mentat_query::{
Element,
FindSpec,
Variable,
};
use mentat_query_algebrizer::{
@ -47,6 +48,7 @@ use mentat_query_algebrizer::{
use mentat_query_sql::{
ColumnOrExpression,
Name,
Projection,
ProjectedColumn,
};
@ -154,6 +156,29 @@ impl TypedIndex {
}
}
fn candidate_column(query: &AlgebraicQuery, var: &Variable) -> (ColumnOrExpression, Name) {
// Every variable should be bound by the top-level CC to at least
// one column in the query. If that constraint is violated it's a
// bug in our code, so it's appropriate to panic here.
let columns = query.cc
.column_bindings
.get(var)
.expect("Every variable has a binding");
let qa = columns[0].clone();
let name = VariableColumn::Variable(var.clone()).column_name();
(ColumnOrExpression::Column(qa), name)
}
fn candidate_type_column(query: &AlgebraicQuery, var: &Variable) -> (ColumnOrExpression, Name) {
let extracted_alias = query.cc
.extracted_types
.get(var)
.expect("Every variable has a known type or an extracted type");
let type_name = VariableColumn::VariableTypeTag(var.clone()).column_name();
(ColumnOrExpression::Column(extracted_alias.clone()), type_name)
}
/// Walk an iterator of `Element`s, collecting projector templates and columns.
///
/// Returns a pair: the SQL projection (which should always be a `Projection::Columns`)
@ -181,34 +206,20 @@ fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
// into the SQL projection, aliased to the name of the variable,
// and we push an annotated index into the projector.
&Element::Variable(ref var) => {
// Every variable should be bound by the top-level CC to at least
// one column in the query. If that constraint is violated it's a
// bug in our code, so it's appropriate to panic here.
let columns = query.cc
.column_bindings
.get(var)
.expect("Every variable has a binding");
let qa = columns[0].clone();
let name = VariableColumn::Variable(var.clone()).column_name();
let (column, name) = candidate_column(query, var);
cols.push(ProjectedColumn(column, name));
if let Some(t) = query.cc.known_type(var) {
cols.push(ProjectedColumn(ColumnOrExpression::Column(qa), name));
let tag = t.value_type_tag();
templates.push(TypedIndex::Known(i, tag));
i += 1; // We used one SQL column.
} else {
cols.push(ProjectedColumn(ColumnOrExpression::Column(qa), name));
templates.push(TypedIndex::Unknown(i, i + 1));
i += 2; // We used two SQL columns.
// Also project the type from the SQL query.
let extracted_alias = query.cc
.extracted_types
.get(var)
.expect("Every variable has a known type or an extracted type");
let type_name = VariableColumn::VariableTypeTag(var.clone()).column_name();
cols.push(ProjectedColumn(ColumnOrExpression::Column(extracted_alias.clone()), type_name));
let (type_column, type_name) = candidate_type_column(query, &var);
cols.push(ProjectedColumn(type_column, type_name));
}
}
}