Use positional offsets in translate::expr to remap parameters to their correct offsets

This commit is contained in:
PThorpe92
2025-05-07 15:51:52 -04:00
parent 9c8dd7ebae
commit d908e78729
2 changed files with 30 additions and 5 deletions

View File

@@ -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,

View File

@@ -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<Vec<NonZero<usize>>> = program
.param_positions
.as_ref()
.map(|pos| pos.iter().map(|&(_, internal_idx)| internal_idx).collect());
program.set_param_remap(remap);
Ok(())
}