diff --git a/core/translate.rs b/core/translate.rs index fea1096d8..59c7e76fb 100644 --- a/core/translate.rs +++ b/core/translate.rs @@ -10,13 +10,13 @@ use crate::vdbe::{BranchOffset, Insn, Program, ProgramBuilder}; use anyhow::Result; use sqlite3_parser::ast::{self, Expr, Literal}; -struct Select { - columns: Vec, - column_info: Vec, - src_tables: Vec, // Tables we use to get data from. This includes "from" and "joins" - limit: Option, +struct Select<'a> { + columns: &'a Vec, + column_info: Vec>, + src_tables: Vec>, // Tables we use to get data from. This includes "from" and "joins" + limit: &'a Option, exist_aggregation: bool, - where_clause: Option, + where_clause: &'a Option, /// Ordered list of opened read table loops /// Used for generating a loop that looks like this: /// cursor 0 = open table 0 @@ -35,23 +35,23 @@ struct LoopInfo { open_cursor: usize, } -struct SrcTable { +struct SrcTable<'a> { table: Table, - alias: Option, - join_info: Option, // FIXME: preferably this should be a reference with lifetime == Select ast expr + alias: Option<&'a String>, + join_info: Option<&'a ast::JoinedSelectTable>, // FIXME: preferably this should be a reference with lifetime == Select ast expr } -struct ColumnInfo { +struct ColumnInfo<'a> { func: Option, - args: Option>, + args: &'a Option>, columns_to_allocate: usize, /* number of result columns this col will result on */ } -impl ColumnInfo { +impl<'a> ColumnInfo<'a> { pub fn new() -> Self { Self { func: None, - args: None, + args: &None, columns_to_allocate: 1, } } @@ -76,7 +76,7 @@ pub fn translate( ) -> Result { match stmt { ast::Stmt::Select(select) => { - let select = build_select(schema, select)?; + let select = build_select(schema, &select)?; translate_select(select) } ast::Stmt::Pragma(name, body) => translate_pragma(&name, body, database_header, pager), @@ -84,19 +84,19 @@ pub fn translate( } } -fn build_select(schema: &Schema, select: ast::Select) -> Result { }, None => todo!(), }; - let table_name = table_name.0; - let maybe_alias = maybe_alias.map(|als| als.0); + let table_name = &table_name.0; + let maybe_alias = maybe_alias.map(|als| &als.0); let table = match schema.get_table(&table_name) { Some(table) => table, None => anyhow::bail!("Parse error: no such table: {}", table_name), @@ -117,12 +117,12 @@ fn build_select(schema: &Schema, select: ast::Select) -> Result { _ => todo!(), }; let table_name = &table_name.0; - let maybe_alias = maybe_alias.map(|als| als.0); + let maybe_alias = maybe_alias.as_ref().map(|als| &als.0); let table = match schema.get_table(table_name) { Some(table) => table, None => anyhow::bail!("Parse error: no such table: {}", table_name), @@ -138,13 +138,13 @@ fn build_select(schema: &Schema, select: ast::Select) -> Result { columns, column_info, src_tables: joins, - limit: select.limit.clone(), + limit: &select.limit, exist_aggregation, where_clause, loops: Vec::new(), @@ -164,7 +164,7 @@ fn build_select(schema: &Schema, select: ast::Select) -> Result { columns, column_info, src_tables: Vec::new(), - limit: select.limit.clone(), + limit: &select.limit, where_clause, exist_aggregation, loops: Vec::new(), @@ -323,7 +323,7 @@ fn translate_conditions( .src_tables .iter() .map(|v| v.join_info.clone()) - .filter_map(|v| v.map(|v| v.constraint)) + .filter_map(|v| v.map(|v| v.constraint.clone())) .flatten() .collect::>(); // TODO: only supports one JOIN; -> add support for multiple JOINs, e.g. SELECT * FROM a JOIN b ON a.id = b.id JOIN c ON b.id = c.id @@ -397,7 +397,7 @@ fn translate_tables_end(program: &mut ProgramBuilder, select: &Select) { } fn translate_table_open_cursor(program: &mut ProgramBuilder, table: &SrcTable) -> LoopInfo { - let table_identifier = match &table.alias { + let table_identifier = match table.alias { Some(alias) => alias.clone(), None => table.table.get_name().to_string(), }; @@ -482,7 +482,7 @@ fn translate_column( } fn translate_table_star(table: &SrcTable, program: &mut ProgramBuilder, target_register: usize) { - let table_identifier = match &table.alias { + let table_identifier = match table.alias { Some(alias) => alias.clone(), None => table.table.get_name().to_string(), }; @@ -506,7 +506,10 @@ fn translate_table_star(table: &SrcTable, program: &mut ProgramBuilder, target_r } } -fn analyze_columns(columns: &Vec, joins: &Vec) -> Vec { +fn analyze_columns<'a>( + columns: &'a Vec, + joins: &Vec, +) -> Vec> { let mut column_information_list = Vec::with_capacity(columns.len()); for column in columns { let mut info = ColumnInfo::new(); @@ -528,7 +531,7 @@ fn analyze_columns(columns: &Vec, joins: &Vec) -> V /// /// This function will walk all columns and find information about: /// * Aggregation functions. -fn analyze_column(column: &ast::ResultColumn, column_info_out: &mut ColumnInfo) { +fn analyze_column<'a>(column: &'a ast::ResultColumn, column_info_out: &mut ColumnInfo<'a>) { match column { ast::ResultColumn::Expr(expr, _) => analyze_expr(expr, column_info_out), ast::ResultColumn::Star => {} @@ -536,7 +539,7 @@ fn analyze_column(column: &ast::ResultColumn, column_info_out: &mut ColumnInfo) } } -fn analyze_expr(expr: &Expr, column_info_out: &mut ColumnInfo) { +fn analyze_expr<'a>(expr: &'a Expr, column_info_out: &mut ColumnInfo<'a>) { match expr { ast::Expr::FunctionCall { name, @@ -556,7 +559,7 @@ fn analyze_expr(expr: &Expr, column_info_out: &mut ColumnInfo) { } else { column_info_out.func = func_type; // TODO(pere): use lifetimes for args? Arenas would be lovely here :( - column_info_out.args.clone_from(args); + column_info_out.args = args; } } ast::Expr::FunctionCallStar { .. } => todo!(), @@ -1046,7 +1049,7 @@ fn resolve_ident_qualified<'a>( for join in &select.src_tables { match join.table { Table::BTree(ref table) => { - let table_identifier = match &join.alias { + let table_identifier = match join.alias { Some(alias) => alias.clone(), None => table.name.to_string(), }; @@ -1082,7 +1085,7 @@ fn resolve_ident_table<'a>( for join in &select.src_tables { match join.table { Table::BTree(ref table) => { - let table_identifier = match &join.alias { + let table_identifier = match join.alias { Some(alias) => alias.clone(), None => table.name.to_string(), };