Merge 'Fix column order for multi-row insertion' from Nikita Sivukhin

Column order handled incorrectly for multi-rows insert case
```sql
turso> CREATE TABLE t(x, y, z);
turso> INSERT INTO t(z, x) VALUES (1, 2), (3, 4);
turso> SELECT * FROM t;
┌───┬───┬───┐
│ x │ y │ z │
├───┼───┼───┤
│   │ 2 │   │
├───┼───┼───┤
│   │ 4 │   │
└───┴───┴───┘
```

Closes #2109
This commit is contained in:
Jussi Saurio
2025-07-21 00:02:43 +03:00
2 changed files with 27 additions and 11 deletions

View File

@@ -787,36 +787,29 @@ fn resolve_indicies_for_insert(
fn populate_columns_multiple_rows(
program: &mut ProgramBuilder,
column_mappings: &[ColumnMapping],
column_mappings: &[ColumnMapping], // columns in order of table definition
column_registers_start: usize,
yield_reg: usize,
resolver: &Resolver,
temp_table_ctx: &Option<TempTableCtx>,
) -> Result<()> {
let mut value_index_seen = 0;
let mut other_values_seen = 0;
for (i, mapping) in column_mappings.iter().enumerate() {
let target_reg = column_registers_start + i;
other_values_seen += 1;
if let Some(value_index) = mapping.value_index {
// Decrement as we have now seen a value index instead
other_values_seen -= 1;
if let Some(temp_table_ctx) = temp_table_ctx {
program.emit_column(
temp_table_ctx.cursor_id,
value_index_seen,
value_index,
column_registers_start + i,
);
} else {
program.emit_insn(Insn::Copy {
src_reg: yield_reg + value_index_seen,
dst_reg: column_registers_start + value_index + other_values_seen,
src_reg: yield_reg + value_index,
dst_reg: column_registers_start + i,
extra_amount: 0,
});
}
value_index_seen += 1;
} else if mapping.column.is_rowid_alias {
program.emit_insn(Insn::SoftNull { reg: target_reg });
} else if let Some(default_expr) = mapping.default_value {

View File

@@ -458,3 +458,26 @@ do_execsql_test_skip_lines_on_specific_db 1 {:memory:} double-quote-inner-quotes
SELECT id, content FROM inner_quotes_test ORDER BY id;
} {1|"foo"
2|'bar'}
# regression test for incorrect order of column in insert
do_execsql_test_on_specific_db {:memory:} insert-tricky-column-order-values {
create table t(x, y, z);
insert into t(z, x) values (1, 2), (3, 4);
insert into t(y, z) values (5, 6), (7, 8);
select * from t;
} {2||1
4||3
|5|6
|7|8}
do_execsql_test_on_specific_db {:memory:} insert-tricky-column-order-table {
create table t(x, y, z);
create table q(x, y, z);
insert into q values (1, 2, 3), (4, 5, 6);
insert into t(z, x) select y, x from q;
insert into t(y, z) select z, y from q;
select * from t;
} {1||2
4||5
|3|2
|6|5}