From d2a287f67f3dcb687d736c7e739e303a11552c03 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Mon, 26 May 2025 12:24:52 +0300 Subject: [PATCH] Add Schema reference to Resolver - needed for adhoc subquery planning --- core/translate/delete.rs | 2 +- core/translate/emitter.rs | 37 +++++++++++++++++++++++++++---------- core/translate/insert.rs | 2 +- core/translate/select.rs | 2 +- core/translate/subquery.rs | 2 +- core/translate/update.rs | 2 +- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/core/translate/delete.rs b/core/translate/delete.rs index a576c6cc6..8f3485ce6 100644 --- a/core/translate/delete.rs +++ b/core/translate/delete.rs @@ -36,7 +36,7 @@ pub fn translate_delete( approx_num_labels: 0, }; program.extend(&opts); - emit_program(&mut program, delete_plan, syms)?; + emit_program(&mut program, delete_plan, schema, syms)?; Ok(program) } diff --git a/core/translate/emitter.rs b/core/translate/emitter.rs index d8717cd8f..7d7498d3b 100644 --- a/core/translate/emitter.rs +++ b/core/translate/emitter.rs @@ -23,7 +23,7 @@ use super::select::emit_simple_count; use super::subquery::emit_subqueries; use crate::error::SQLITE_CONSTRAINT_PRIMARYKEY; use crate::function::Func; -use crate::schema::{Index, IndexColumn}; +use crate::schema::{Index, IndexColumn, Schema}; use crate::translate::plan::{DeletePlan, Plan, Search}; use crate::translate::values::emit_values; use crate::util::exprs_are_equivalent; @@ -32,15 +32,16 @@ use crate::vdbe::insn::{CmpInsFlags, IdxInsertFlags, RegisterOrLiteral}; use crate::vdbe::{insn::Insn, BranchOffset}; use crate::{Result, SymbolTable}; -#[derive(Debug)] pub struct Resolver<'a> { + pub schema: &'a Schema, pub symbol_table: &'a SymbolTable, pub expr_to_reg_cache: Vec<(&'a ast::Expr, usize)>, } impl<'a> Resolver<'a> { - pub fn new(symbol_table: &'a SymbolTable) -> Self { + pub fn new(schema: &'a Schema, symbol_table: &'a SymbolTable) -> Self { Self { + schema, symbol_table, expr_to_reg_cache: Vec::new(), } @@ -93,7 +94,6 @@ impl LimitCtx { /// The TranslateCtx struct holds various information and labels used during bytecode generation. /// It is used for maintaining state and control flow during the bytecode /// generation process. -#[derive(Debug)] pub struct TranslateCtx<'a> { // A typical query plan is a nested loop. Each loop has its own LoopLabels (see the definition of LoopLabels for more details) pub labels_main_loop: Vec, @@ -132,6 +132,7 @@ pub struct TranslateCtx<'a> { impl<'a> TranslateCtx<'a> { pub fn new( program: &mut ProgramBuilder, + schema: &'a Schema, syms: &'a SymbolTable, table_count: usize, result_column_count: usize, @@ -150,7 +151,7 @@ impl<'a> TranslateCtx<'a> { meta_sort: None, result_column_indexes_in_orderby_sorter: (0..result_column_count).collect(), result_columns_to_skip_in_orderby_sorter: None, - resolver: Resolver::new(syms), + resolver: Resolver::new(schema, syms), } } } @@ -174,18 +175,26 @@ pub enum TransactionMode { /// Main entry point for emitting bytecode for a SQL query /// Takes a query plan and generates the corresponding bytecode program -pub fn emit_program(program: &mut ProgramBuilder, plan: Plan, syms: &SymbolTable) -> Result<()> { +pub fn emit_program( + program: &mut ProgramBuilder, + plan: Plan, + schema: &Schema, + syms: &SymbolTable, +) -> Result<()> { match plan { - Plan::Select(plan) => emit_program_for_select(program, plan, syms), - Plan::Delete(plan) => emit_program_for_delete(program, plan, syms), - Plan::Update(plan) => emit_program_for_update(program, plan, syms), - Plan::CompoundSelect { .. } => emit_program_for_compound_select(program, plan, syms), + Plan::Select(plan) => emit_program_for_select(program, plan, schema, syms), + Plan::Delete(plan) => emit_program_for_delete(program, plan, schema, syms), + Plan::Update(plan) => emit_program_for_update(program, plan, schema, syms), + Plan::CompoundSelect { .. } => { + emit_program_for_compound_select(program, plan, schema, syms) + } } } fn emit_program_for_compound_select( program: &mut ProgramBuilder, plan: Plan, + schema: &Schema, syms: &SymbolTable, ) -> Result<()> { let Plan::CompoundSelect { @@ -227,6 +236,7 @@ fn emit_program_for_compound_select( let mut t_ctx_list = Vec::with_capacity(rest.len() + 1); t_ctx_list.push(TranslateCtx::new( program, + schema, syms, first.table_references.len(), first.result_columns.len(), @@ -234,6 +244,7 @@ fn emit_program_for_compound_select( rest.iter().for_each(|(select, _)| { let t_ctx = TranslateCtx::new( program, + schema, syms, select.table_references.len(), select.result_columns.len(), @@ -460,10 +471,12 @@ fn read_deduplicated_union_rows( fn emit_program_for_select( program: &mut ProgramBuilder, mut plan: SelectPlan, + schema: &Schema, syms: &SymbolTable, ) -> Result<()> { let mut t_ctx = TranslateCtx::new( program, + schema, syms, plan.table_references.len(), plan.result_columns.len(), @@ -644,10 +657,12 @@ pub fn emit_query<'a>( fn emit_program_for_delete( program: &mut ProgramBuilder, mut plan: DeletePlan, + schema: &Schema, syms: &SymbolTable, ) -> Result<()> { let mut t_ctx = TranslateCtx::new( program, + schema, syms, plan.table_references.len(), plan.result_columns.len(), @@ -814,10 +829,12 @@ fn emit_delete_insns( fn emit_program_for_update( program: &mut ProgramBuilder, mut plan: UpdatePlan, + schema: &Schema, syms: &SymbolTable, ) -> Result<()> { let mut t_ctx = TranslateCtx::new( program, + schema, syms, plan.table_references.len(), plan.returning.as_ref().map_or(0, |r| r.len()), diff --git a/core/translate/insert.rs b/core/translate/insert.rs index 022a23f28..60a386651 100644 --- a/core/translate/insert.rs +++ b/core/translate/insert.rs @@ -64,7 +64,7 @@ pub fn translate_insert( None => crate::bail_corrupt_error!("Parse error: no such table: {}", table_name), }; - let resolver = Resolver::new(syms); + let resolver = Resolver::new(schema, syms); if let Some(virtual_table) = &table.virtual_table() { program = translate_virtual_table_insert( diff --git a/core/translate/select.rs b/core/translate/select.rs index efedb00fa..5e02d9e25 100644 --- a/core/translate/select.rs +++ b/core/translate/select.rs @@ -79,7 +79,7 @@ pub fn translate_select( }; program.extend(&opts); - emit_program(&mut program, select_plan, syms)?; + emit_program(&mut program, select_plan, schema, syms)?; Ok(TranslateSelectResult { program, num_result_cols, diff --git a/core/translate/subquery.rs b/core/translate/subquery.rs index e0c10a84c..ed8ab24c6 100644 --- a/core/translate/subquery.rs +++ b/core/translate/subquery.rs @@ -80,7 +80,7 @@ pub fn emit_subquery<'a>( limit_ctx: plan.limit.map(|_| LimitCtx::new(program)), reg_offset: plan.offset.map(|_| program.alloc_register()), reg_limit_offset_sum: plan.offset.map(|_| program.alloc_register()), - resolver: Resolver::new(t_ctx.resolver.symbol_table), + resolver: Resolver::new(t_ctx.resolver.schema, t_ctx.resolver.symbol_table), }; let subquery_body_end_label = program.allocate_label(); program.emit_insn(Insn::InitCoroutine { diff --git a/core/translate/update.rs b/core/translate/update.rs index 44be69d3d..b6f6d3486 100644 --- a/core/translate/update.rs +++ b/core/translate/update.rs @@ -70,7 +70,7 @@ pub fn translate_update( approx_num_labels: 4, }; program.extend(&opts); - emit_program(&mut program, plan, syms)?; + emit_program(&mut program, plan, schema, syms)?; Ok(program) }