mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 10:08:20 +00:00
fix+refactor: incorrect label placement
also added a `cursor_loop` helper on `ProgramBuilder` to avoid making this mistake in the future. this is zero-cost, and will be optimized to the same thing (hopefully).
This commit is contained in:
parent
6d0a3c95c6
commit
6945c0c09e
3 changed files with 73 additions and 54 deletions
|
@ -188,9 +188,6 @@ pub fn translate_inner(
|
|||
syms,
|
||||
program,
|
||||
|program| {
|
||||
let loop_start = program.allocate_label();
|
||||
let loop_end = program.allocate_label();
|
||||
|
||||
let column_count = btree.columns.len();
|
||||
let root_page = btree.root_page;
|
||||
let table_name = btree.name.clone();
|
||||
|
@ -205,62 +202,50 @@ pub fn translate_inner(
|
|||
name: table_name.clone(),
|
||||
});
|
||||
|
||||
program.emit_insn(Insn::Rewind {
|
||||
cursor_id,
|
||||
pc_if_empty: loop_end,
|
||||
});
|
||||
program.cursor_loop(cursor_id, |program| {
|
||||
let rowid = program.alloc_register();
|
||||
|
||||
let rowid = program.alloc_register();
|
||||
|
||||
program.emit_insn(Insn::RowId {
|
||||
cursor_id,
|
||||
dest: rowid,
|
||||
});
|
||||
|
||||
program.preassign_label_to_next_insn(loop_start);
|
||||
|
||||
let first_column = program.alloc_registers(column_count);
|
||||
|
||||
let mut iter = first_column;
|
||||
|
||||
for i in 0..(column_count + 1) {
|
||||
if i == dropped_col {
|
||||
continue;
|
||||
}
|
||||
|
||||
program.emit_insn(Insn::Column {
|
||||
program.emit_insn(Insn::RowId {
|
||||
cursor_id,
|
||||
column: i,
|
||||
dest: iter,
|
||||
dest: rowid,
|
||||
});
|
||||
|
||||
iter += 1;
|
||||
}
|
||||
let first_column = program.alloc_registers(column_count);
|
||||
|
||||
let record = program.alloc_register();
|
||||
let mut iter = first_column;
|
||||
|
||||
program.emit_insn(Insn::MakeRecord {
|
||||
start_reg: first_column,
|
||||
count: column_count,
|
||||
dest_reg: record,
|
||||
index_name: None,
|
||||
for i in 0..(column_count + 1) {
|
||||
if i == dropped_col {
|
||||
continue;
|
||||
}
|
||||
|
||||
program.emit_insn(Insn::Column {
|
||||
cursor_id,
|
||||
column: i,
|
||||
dest: iter,
|
||||
});
|
||||
|
||||
iter += 1;
|
||||
}
|
||||
|
||||
let record = program.alloc_register();
|
||||
|
||||
program.emit_insn(Insn::MakeRecord {
|
||||
start_reg: first_column,
|
||||
count: column_count,
|
||||
dest_reg: record,
|
||||
index_name: None,
|
||||
});
|
||||
|
||||
program.emit_insn(Insn::Insert {
|
||||
cursor: cursor_id,
|
||||
key_reg: rowid,
|
||||
record_reg: record,
|
||||
flag: 0,
|
||||
table_name: table_name.clone(),
|
||||
});
|
||||
});
|
||||
|
||||
program.emit_insn(Insn::Insert {
|
||||
cursor: cursor_id,
|
||||
key_reg: rowid,
|
||||
record_reg: record,
|
||||
flag: 0,
|
||||
table_name: table_name.clone(),
|
||||
});
|
||||
|
||||
program.emit_insn(Insn::Next {
|
||||
cursor_id,
|
||||
pc_if_next: loop_start,
|
||||
});
|
||||
|
||||
program.preassign_label_to_next_insn(loop_end);
|
||||
|
||||
program.emit_insn(Insn::ParseSchema {
|
||||
db: usize::MAX, // TODO: This value is unused, change when we do something with it
|
||||
where_clause: None,
|
||||
|
@ -291,6 +276,7 @@ pub fn translate_inner(
|
|||
schema,
|
||||
&mut update,
|
||||
syms,
|
||||
program,
|
||||
|program| {
|
||||
program.emit_insn(Insn::ParseSchema {
|
||||
db: usize::MAX, // TODO: This value is unused, change when we do something with it
|
||||
|
@ -330,6 +316,7 @@ pub fn translate_inner(
|
|||
schema,
|
||||
&mut update,
|
||||
syms,
|
||||
program,
|
||||
|program| {
|
||||
program.emit_insn(Insn::ParseSchema {
|
||||
db: usize::MAX, // TODO: This value is unused, change when we do something with it
|
||||
|
|
|
@ -771,6 +771,26 @@ impl ProgramBuilder {
|
|||
self.table_references.contains_table(table)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn cursor_loop(&mut self, cursor_id: CursorID, f: impl Fn(&mut ProgramBuilder)) {
|
||||
let loop_start = self.allocate_label();
|
||||
let loop_end = self.allocate_label();
|
||||
|
||||
self.emit_insn(Insn::Rewind {
|
||||
cursor_id,
|
||||
pc_if_empty: loop_end,
|
||||
});
|
||||
self.preassign_label_to_next_insn(loop_start);
|
||||
|
||||
f(self);
|
||||
|
||||
self.emit_insn(Insn::Next {
|
||||
cursor_id,
|
||||
pc_if_next: loop_start,
|
||||
});
|
||||
self.preassign_label_to_next_insn(loop_end);
|
||||
}
|
||||
|
||||
pub fn build(
|
||||
mut self,
|
||||
database_header: Arc<SpinLock<DatabaseHeader>>,
|
||||
|
|
|
@ -32,24 +32,36 @@ do_execsql_test_on_specific_db {:memory:} alter-table-add-column {
|
|||
do_execsql_test_on_specific_db {:memory:} alter-table-add-column-typed {
|
||||
CREATE TABLE t(a);
|
||||
ALTER TABLE t ADD b TEXT;
|
||||
ALTER TABLE t ADD c INTEGER DEFAULT(0);
|
||||
ALTER TABLE t ADD c INTEGER DEFAULT 0;
|
||||
|
||||
SELECT sql FROM sqlite_schema;
|
||||
|
||||
INSERT INTO t VALUES (1, 'a');
|
||||
SELECT * FROM t;
|
||||
} {
|
||||
"CREATE TABLE t(a, b TEXT, c INTEGER DEFAULT(0))"
|
||||
"1|a|0"
|
||||
}
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} alter-table-drop-column {
|
||||
CREATE TABLE t(a, b);
|
||||
INSERT INTO t VALUES (1, 2);
|
||||
INSERT INTO t VALUES (1, 1), (2, 2), (3, 3);
|
||||
SELECT * FROM t;
|
||||
|
||||
ALTER TABLE t DROP b;
|
||||
SELECT sql FROM sqlite_schema;
|
||||
|
||||
SELECT * FROM t;
|
||||
} {
|
||||
"1|2"
|
||||
"1|1"
|
||||
"2|2"
|
||||
"3|3"
|
||||
|
||||
"CREATE TABLE t(a)"
|
||||
|
||||
"1"
|
||||
"2"
|
||||
"3"
|
||||
}
|
||||
|
||||
do_execsql_test_in_memory_any_error fail-alter-table-drop-unique-column {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue