diff --git a/core/translate/select.rs b/core/translate/select.rs index 46226abbd..6a9250296 100644 --- a/core/translate/select.rs +++ b/core/translate/select.rs @@ -1,12 +1,12 @@ use super::emitter::emit_program; use super::expr::get_name; -use super::plan::SelectQueryType; +use super::plan::{select_star, SelectQueryType}; use crate::function::{AggFunc, ExtFunc, Func}; use crate::translate::optimizer::optimize_plan; use crate::translate::plan::{Aggregate, Direction, GroupBy, Plan, ResultSetColumn, SelectPlan}; use crate::translate::planner::{ bind_column_references, break_predicate_at_and_boundaries, parse_from, parse_limit, - parse_where, resolve_aggregates, OperatorIdCounter, + parse_where, resolve_aggregates, }; use crate::util::normalize_ident; use crate::SymbolTable; @@ -43,52 +43,51 @@ pub fn prepare_select_plan( crate::bail_parse_error!("SELECT without columns is not allowed"); } - let mut operator_id_counter = OperatorIdCounter::new(); + let mut where_predicates = vec![]; - // Parse the FROM clause - let (source, referenced_tables) = - parse_from(schema, from, &mut operator_id_counter, syms)?; + // Parse the FROM clause into a vec of TableReferences. Fold all the join conditions expressions into the WHERE clause. + let table_references = parse_from(schema, from, syms, &mut where_predicates)?; let mut plan = SelectPlan { - source, + table_references, result_columns: vec![], - where_clause: None, + where_clause: where_predicates, group_by: None, order_by: None, aggregates: vec![], limit: None, offset: None, - referenced_tables, available_indexes: schema.indexes.clone().into_values().flatten().collect(), contains_constant_false_condition: false, query_type: SelectQueryType::TopLevel, }; - // Parse the WHERE clause - plan.where_clause = parse_where(where_clause, &plan.referenced_tables)?; + // Parse the actual WHERE clause and add its conditions to the plan WHERE clause that already contains the join conditions. + parse_where(where_clause, &plan.table_references, &mut plan.where_clause)?; let mut aggregate_expressions = Vec::new(); for (result_column_idx, column) in columns.iter_mut().enumerate() { match column { ResultColumn::Star => { - plan.source.select_star(&mut plan.result_columns); + select_star(&plan.table_references, &mut plan.result_columns); } ResultColumn::TableStar(name) => { let name_normalized = normalize_ident(name.0.as_str()); let referenced_table = plan - .referenced_tables + .table_references .iter() - .find(|t| t.table_identifier == name_normalized); + .enumerate() + .find(|(_, t)| t.identifier == name_normalized); if referenced_table.is_none() { crate::bail_parse_error!("Table {} not found", name.0); } - let table_reference = referenced_table.unwrap(); - for (idx, col) in table_reference.columns().iter().enumerate() { + let (table_index, table) = referenced_table.unwrap(); + for (idx, col) in table.columns().iter().enumerate() { plan.result_columns.push(ResultSetColumn { expr: ast::Expr::Column { database: None, // TODO: support different databases - table: table_reference.table_index, + table: table_index, column: idx, is_rowid_alias: col.is_rowid_alias, }, @@ -98,7 +97,7 @@ pub fn prepare_select_plan( } } ResultColumn::Expr(ref mut expr, maybe_alias) => { - bind_column_references(expr, &plan.referenced_tables)?; + bind_column_references(expr, &plan.table_references)?; match expr { ast::Expr::FunctionCall { name, @@ -141,7 +140,7 @@ pub fn prepare_select_plan( name: get_name( maybe_alias.as_ref(), expr, - &plan.referenced_tables, + &plan.table_references, || format!("expr_{}", result_column_idx), ), expr: expr.clone(), @@ -155,7 +154,7 @@ pub fn prepare_select_plan( name: get_name( maybe_alias.as_ref(), expr, - &plan.referenced_tables, + &plan.table_references, || format!("expr_{}", result_column_idx), ), expr: expr.clone(), @@ -174,7 +173,7 @@ pub fn prepare_select_plan( name: get_name( maybe_alias.as_ref(), expr, - &plan.referenced_tables, + &plan.table_references, || format!("expr_{}", result_column_idx), ), expr: expr.clone(), @@ -191,7 +190,7 @@ pub fn prepare_select_plan( name: get_name( maybe_alias.as_ref(), expr, - &plan.referenced_tables, + &plan.table_references, || format!("expr_{}", result_column_idx), ), expr: expr.clone(), @@ -225,7 +224,7 @@ pub fn prepare_select_plan( name: get_name( maybe_alias.as_ref(), expr, - &plan.referenced_tables, + &plan.table_references, || format!("expr_{}", result_column_idx), ), expr: expr.clone(), @@ -245,7 +244,7 @@ pub fn prepare_select_plan( name: get_name( maybe_alias.as_ref(), expr, - &plan.referenced_tables, + &plan.table_references, || format!("expr_{}", result_column_idx), ), expr: expr.clone(), @@ -258,7 +257,7 @@ pub fn prepare_select_plan( } if let Some(mut group_by) = group_by { for expr in group_by.exprs.iter_mut() { - bind_column_references(expr, &plan.referenced_tables)?; + bind_column_references(expr, &plan.table_references)?; } plan.group_by = Some(GroupBy { @@ -267,7 +266,7 @@ pub fn prepare_select_plan( let mut predicates = vec![]; break_predicate_at_and_boundaries(having, &mut predicates); for expr in predicates.iter_mut() { - bind_column_references(expr, &plan.referenced_tables)?; + bind_column_references(expr, &plan.table_references)?; let contains_aggregates = resolve_aggregates(expr, &mut aggregate_expressions); if !contains_aggregates { @@ -313,7 +312,7 @@ pub fn prepare_select_plan( o.expr }; - bind_column_references(&mut expr, &plan.referenced_tables)?; + bind_column_references(&mut expr, &plan.table_references)?; resolve_aggregates(&expr, &mut plan.aggregates); key.push((