fix: IdxDelete shouldn't raise error if P5 == 0

This commit is contained in:
meteorgan
2025-06-24 22:05:55 +08:00
parent 4a516ab414
commit c6ef4898b0
6 changed files with 15 additions and 8 deletions

View File

@@ -255,7 +255,7 @@ fn emit_compound_select(
} => (cursor_id, index),
_ => {
new_index = true;
create_dedupe_index(program, &right_most)?
create_dedupe_index(program, &right_most, schema)?
}
};
plan.query_destination = QueryDestination::EphemeralIndex {

View File

@@ -565,6 +565,7 @@ fn emit_delete_insns(
start_reg,
num_regs,
cursor_id: index_cursor_id,
raise_error_if_no_matching_entry: true,
});
}
}
@@ -1083,6 +1084,7 @@ fn emit_update_insns(
start_reg,
num_regs,
cursor_id: idx_cursor_id,
raise_error_if_no_matching_entry: true,
});
// Insert new index key (filled further above with values from set_clauses)

View File

@@ -92,6 +92,7 @@ pub fn emit_result_row_and_limit(
start_reg: result_columns_start_reg,
num_regs: plan.result_columns.len(),
cursor_id: *index_cursor_id,
raise_error_if_no_matching_entry: false,
});
} else {
let record_reg = program.alloc_register();

View File

@@ -4362,6 +4362,7 @@ pub fn op_idx_delete(
cursor_id,
start_reg,
num_regs,
raise_error_if_no_matching_entry,
} = insn
else {
unreachable!("unexpected Insn {:?}", insn)
@@ -4399,12 +4400,9 @@ pub fn op_idx_delete(
return_if_io!(cursor.rowid())
};
if 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.
// If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
// Also, do not raise this (self-correcting and non-critical) error if in writable_schema mode.
if rowid.is_none() && *raise_error_if_no_matching_entry {
return Err(LimboError::Corrupt(format!(
"IdxDelete: no matching index entry found for record {:?}",
make_record(&state.registers, start_reg, num_regs)

View File

@@ -1120,13 +1120,14 @@ pub fn insn_to_str(
cursor_id,
start_reg,
num_regs,
raise_error_if_no_matching_entry
} => (
"IdxDelete",
*cursor_id as i32,
*start_reg as i32,
*num_regs as i32,
Value::build_text(""),
0,
*raise_error_if_no_matching_entry as u16,
"".to_string(),
),
Insn::NewRowid {

View File

@@ -742,10 +742,15 @@ pub enum Insn {
cursor_id: CursorID,
},
/// 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.
IdxDelete {
start_reg: usize,
num_regs: usize,
cursor_id: CursorID,
raise_error_if_no_matching_entry: bool, // P5
},
NewRowid {