From d908e78729c0a382e8a0035ff5fa7a5044d4037f Mon Sep 17 00:00:00 2001 From: PThorpe92 Date: Wed, 7 May 2025 15:51:52 -0400 Subject: [PATCH] Use positional offsets in translate::expr to remap parameters to their correct offsets --- core/translate/expr.rs | 21 ++++++++++++++++----- core/translate/insert.rs | 14 ++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/core/translate/expr.rs b/core/translate/expr.rs index 62f51d26e..37c25c401 100644 --- a/core/translate/expr.rs +++ b/core/translate/expr.rs @@ -1851,11 +1851,8 @@ pub fn translate_expr( } else { Some(program.resolve_cursor_id(&table_reference.identifier)) }; - let index_cursor_id = if let Some(index) = index { - Some(program.resolve_cursor_id(&index.name)) - } else { - None - }; + let index_cursor_id = + index.map(|index| program.resolve_cursor_id(&index.name)); if *is_rowid_alias { if let Some(index_cursor_id) = index_cursor_id { program.emit_insn(Insn::IdxRowId { @@ -2150,7 +2147,21 @@ pub fn translate_expr( } }, ast::Expr::Variable(name) => { + // Table t: (a,b,c) + // For 'insert' statements: + // INSERT INTO t (b,c,a) values (?,?,?) + // since we walk the columns in the tables column order, we have to store the value index that + // the parameter was given for an insert statement. Then, we may end up with something + // like: insert into (b,c,a) values (22,?,?), in which case we will get a = 2, c = 1 + // instead of previously we would have gotten a = 0, c = 1 + // where it instead should be c = 0, a = 1. So all we can do is store the value index + // alongside the index into the parameters list, then during bind_at: we can translate + // this value into the proper order. let index = program.parameters.push(name); + if let Some(ref mut indicies) = &mut program.param_positions { + // index of the parameter in the inserted values + index of the parameter relative + indicies.push((program.current_col_idx.unwrap_or(index.get()), index)); + } program.emit_insn(Insn::Variable { index, dest: target_register, diff --git a/core/translate/insert.rs b/core/translate/insert.rs index fced88768..96e1dac3b 100644 --- a/core/translate/insert.rs +++ b/core/translate/insert.rs @@ -1,3 +1,4 @@ +use std::num::NonZero; use std::ops::Deref; use std::rc::Rc; @@ -589,6 +590,7 @@ fn populate_column_registers( rowid_reg: usize, resolver: &Resolver, ) -> Result<()> { + program.param_positions = Some(vec![]); for (i, mapping) in column_mappings.iter().enumerate() { let target_reg = column_registers_start + i; @@ -643,6 +645,18 @@ fn populate_column_registers( } } } + // if there are any parameter positions, we sort them by the value_index position + // to ensure we are binding the parameters to the proper index later on + if let Some(ref mut params) = program.param_positions.as_mut() { + params.sort_by_key(|(val_pos, _)| *val_pos); + } + + let remap: Option>> = program + .param_positions + .as_ref() + .map(|pos| pos.iter().map(|&(_, internal_idx)| internal_idx).collect()); + + program.set_param_remap(remap); Ok(()) }