instruction emitted should be correct, but having an infinite loop bug

This commit is contained in:
pedrocarlo 2025-04-29 18:09:19 -03:00
parent 60a99851f8
commit 6457d7675a
2 changed files with 71 additions and 9 deletions

View file

@ -12,7 +12,7 @@ use crate::schema::Index;
use crate::translate::plan::{DeletePlan, Plan, Search};
use crate::util::exprs_are_equivalent;
use crate::vdbe::builder::{CursorType, ProgramBuilder};
use crate::vdbe::insn::{IdxInsertFlags, RegisterOrLiteral};
use crate::vdbe::insn::{CmpInsFlags, IdxInsertFlags, RegisterOrLiteral};
use crate::vdbe::{insn::Insn, BranchOffset};
use crate::{Result, SymbolTable};
@ -670,7 +670,6 @@ fn emit_update_insns(
_ => return Ok(()),
};
// dbg!(&plan.indexes);
// THIS IS SAME CODE AS WE HAVE ON INSERT
// allocate cursor id's for each btree index cursor we'll need to populate the indexes
// (idx name, root_page, idx cursor id)
@ -678,6 +677,7 @@ fn emit_update_insns(
.indexes_to_update
.iter()
.map(|idx| {
let record_reg = program.alloc_register();
(
&idx.name,
idx.root_page,
@ -685,9 +685,10 @@ fn emit_update_insns(
Some(idx.table_name.clone()),
CursorType::BTreeIndex(idx.clone()),
),
record_reg,
)
})
.collect::<Vec<(&String, usize, usize)>>();
.collect::<Vec<(&String, usize, usize, usize)>>();
let open_indices_label = program.allocate_label();
// Open all cursors Once
@ -759,9 +760,9 @@ fn emit_update_insns(
});
}
for (pos, index) in plan.indexes.iter().enumerate() {
for (pos, index) in plan.indexes_to_update.iter().enumerate() {
if index.unique {
let (idx_name, idx_root_page, idx_cursor_id) =
let (_, _, idx_cursor_id, record_reg) =
idx_cursors.get(pos).expect("index cursor should exist");
let num_cols = index.columns.len();
@ -772,7 +773,7 @@ fn emit_update_insns(
let idx_cols_start_reg = beg + 1;
// copy each index column from the table's column registers into these scratch regs
for (i, col) in index.columns.iter().enumerate() {
for i in 0..num_cols {
// copy from the table's column register over to the index's scratch register
program.emit_insn(Insn::Copy {
@ -788,6 +789,13 @@ fn emit_update_insns(
amount: 0,
});
program.emit_insn(Insn::MakeRecord {
start_reg: idx_start_reg,
count: num_cols + 1,
dest_reg: *record_reg,
index_name: Some(index.name.clone()),
});
let constraint_check = program.allocate_label();
program.emit_insn(Insn::NoConflict {
cursor_id: *idx_cursor_id,
@ -810,8 +818,18 @@ fn emit_update_insns(
},
);
// TODO: Emit IdxRowId to get the rowId of the last entry the index points to
// TODO: Emit Eq to see if rowId that index points to matches the rowId of current row
let idx_rowid_reg = program.alloc_register();
program.emit_insn(Insn::IdxRowId {
cursor_id: *idx_cursor_id,
dest: idx_rowid_reg,
});
program.emit_insn(Insn::Eq {
lhs: rowid_reg,
rhs: idx_rowid_reg,
target_pc: constraint_check,
flags: CmpInsFlags::default(), // TODO: not sure type of comparison flag is needed
});
program.emit_insn(Insn::Halt {
err_code: SQLITE_CONSTRAINT_PRIMARYKEY, // TODO: distinct between primary key and unique index
@ -946,6 +964,50 @@ fn emit_update_insns(
dest_reg: record_reg,
index_name: None,
});
// For each index -> insert
for (pos, index) in plan.indexes_to_update.iter().enumerate() {
let num_regs = index.columns.len() + 1;
let start_reg = program.alloc_registers(num_regs);
// Emit columns that are part of the index
index
.columns
.iter()
.enumerate()
.for_each(|(reg_offset, column_index)| {
program.emit_insn(Insn::Column {
cursor_id,
column: column_index.pos_in_table,
dest: start_reg + reg_offset,
});
});
program.emit_insn(Insn::RowId {
cursor_id,
dest: start_reg + num_regs - 1,
});
let (_, _, idx_cursor_id, record_reg) =
idx_cursors.get(pos).expect("index cursor should exist");
program.emit_insn(Insn::IdxDelete {
start_reg,
num_regs,
cursor_id: *idx_cursor_id,
});
program.emit_insn(Insn::IdxInsert {
cursor_id: *idx_cursor_id,
record_reg: *record_reg,
unpacked_start: Some(start),
unpacked_count: Some((index.columns.len() + 1) as u16),
flags: IdxInsertFlags::new(),
});
}
program.emit_insn(Insn::Delete { cursor_id });
// TODO: Delete opcode should be emitted here
program.emit_insn(Insn::Insert {
cursor: cursor_id,

View file

@ -531,7 +531,7 @@ pub fn insn_to_str(
dest_reg,
index_name,
} => {
let for_index = index_name.as_ref().map(|name| format!(" ;for {}", name));
let for_index = index_name.as_ref().map(|name| format!("; for {}", name));
(
"MakeRecord",
*start_reg as i32,