mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 10:08:20 +00:00
Merge 'Emit IdxDelete
instruction and some fixes on seek after deletion' from Pere Diaz Bou
Previously `DELETE FROM ...` only emitted deletes for main table, but this is incorrect as we want to remove entries from index tables as well. Closes #1383
This commit is contained in:
commit
63a94e7c62
8 changed files with 335 additions and 8 deletions
|
@ -1810,11 +1810,17 @@ pub fn op_row_id(
|
|||
let rowid = {
|
||||
let mut index_cursor = state.get_cursor(index_cursor_id);
|
||||
let index_cursor = index_cursor.as_btree_mut();
|
||||
index_cursor.rowid()?
|
||||
let record = index_cursor.record();
|
||||
let record = record.as_ref().unwrap();
|
||||
let rowid = record.get_values().last().unwrap();
|
||||
match rowid {
|
||||
RefValue::Integer(rowid) => *rowid as u64,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
let mut table_cursor = state.get_cursor(table_cursor_id);
|
||||
let table_cursor = table_cursor.as_btree_mut();
|
||||
match table_cursor.seek(SeekKey::TableRowId(rowid.unwrap()), SeekOp::EQ)? {
|
||||
match table_cursor.seek(SeekKey::TableRowId(rowid), SeekOp::EQ)? {
|
||||
CursorResult::Ok(_) => None,
|
||||
CursorResult::IO => Some((index_cursor_id, table_cursor_id)),
|
||||
}
|
||||
|
@ -2069,7 +2075,6 @@ pub fn op_idx_ge(
|
|||
let idx_values = idx_record.get_values();
|
||||
let idx_values = &idx_values[..record_from_regs.len()];
|
||||
let record_values = record_from_regs.get_values();
|
||||
let record_values = &record_values[..idx_values.len()];
|
||||
let ord = compare_immutable(&idx_values, &record_values, cursor.index_key_sort_order);
|
||||
if ord.is_ge() {
|
||||
target_pc.to_offset_int()
|
||||
|
@ -3759,6 +3764,46 @@ pub fn op_delete(
|
|||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
pub fn op_idx_delete(
|
||||
program: &Program,
|
||||
state: &mut ProgramState,
|
||||
insn: &Insn,
|
||||
pager: &Rc<Pager>,
|
||||
mv_store: Option<&Rc<MvStore>>,
|
||||
) -> Result<InsnFunctionStepResult> {
|
||||
let Insn::IdxDelete {
|
||||
cursor_id,
|
||||
start_reg,
|
||||
num_regs,
|
||||
} = insn
|
||||
else {
|
||||
unreachable!("unexpected Insn {:?}", insn)
|
||||
};
|
||||
let record = make_record(&state.registers, start_reg, num_regs);
|
||||
{
|
||||
let mut cursor = state.get_cursor(*cursor_id);
|
||||
let cursor = cursor.as_btree_mut();
|
||||
return_if_io!(cursor.seek(SeekKey::IndexKey(&record), SeekOp::EQ));
|
||||
|
||||
if cursor.rowid()?.is_none() {
|
||||
// If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error if no matching
|
||||
// index entry is found. This happens when running an UPDATE or DELETE statement and the
|
||||
// index entry to be updated or deleted is not found. For some uses of IdxDelete
|
||||
// (example: the EXCEPT operator) it does not matter that no matching entry is found.
|
||||
// For those cases, P5 is zero. Also, do not raise this (self-correcting and non-critical) error if in writable_schema mode.
|
||||
return Err(LimboError::Corrupt(format!(
|
||||
"IdxDelete: no matching index entry found for record {:?}",
|
||||
record
|
||||
)));
|
||||
}
|
||||
return_if_io!(cursor.delete());
|
||||
}
|
||||
let n_change = program.n_change.get();
|
||||
program.n_change.set(n_change + 1);
|
||||
state.pc += 1;
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
pub fn op_idx_insert(
|
||||
program: &Program,
|
||||
state: &mut ProgramState,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue