From 5214cf985944b41520c569ab09c37c881e632029 Mon Sep 17 00:00:00 2001 From: "[B" Date: Fri, 14 Feb 2025 20:22:30 +0100 Subject: [PATCH 1/2] Added IdxLE and IdxLT opcodes --- COMPAT.md | 3 ++- core/vdbe/builder.rs | 6 ++++++ core/vdbe/explain.rs | 28 ++++++++++++++++++++++++++ core/vdbe/insn.rs | 18 +++++++++++++++++ core/vdbe/mod.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 1 deletion(-) diff --git a/COMPAT.md b/COMPAT.md index 331ff7054..a49ea9ad4 100644 --- a/COMPAT.md +++ b/COMPAT.md @@ -461,7 +461,8 @@ Modifiers: | IdxDelete | No | | | IdxGE | Yes | | | IdxInsert | No | | -| IdxLT | No | | +| IdxLE | Yes | | +| IdxLT | Yes | | | IdxRowid | No | | | If | Yes | | | IfNeg | No | | diff --git a/core/vdbe/builder.rs b/core/vdbe/builder.rs index b86d65b97..716610b71 100644 --- a/core/vdbe/builder.rs +++ b/core/vdbe/builder.rs @@ -399,9 +399,15 @@ impl ProgramBuilder { Insn::IdxGE { target_pc, .. } => { resolve(target_pc, "IdxGE"); } + Insn::IdxLE { target_pc, .. } => { + resolve(target_pc, "IdxLE"); + } Insn::IdxGT { target_pc, .. } => { resolve(target_pc, "IdxGT"); } + Insn::IdxLT { target_pc, .. } => { + resolve(target_pc, "IdxLT"); + } Insn::IsNull { reg: _, target_pc } => { resolve(target_pc, "IsNull"); } diff --git a/core/vdbe/explain.rs b/core/vdbe/explain.rs index 1b956cc9e..2b61310d5 100644 --- a/core/vdbe/explain.rs +++ b/core/vdbe/explain.rs @@ -759,6 +759,34 @@ pub fn insn_to_str( 0, "".to_string(), ), + Insn::IdxLT { + cursor_id, + start_reg, + num_regs: _, + target_pc, + } => ( + "IdxLT", + *cursor_id as i32, + target_pc.to_debug_int(), + *start_reg as i32, + OwnedValue::build_text(""), + 0, + "".to_string(), + ), + Insn::IdxLE { + cursor_id, + start_reg, + num_regs: _, + target_pc, + } => ( + "IdxLE", + *cursor_id as i32, + target_pc.to_debug_int(), + *start_reg as i32, + OwnedValue::build_text(""), + 0, + "".to_string(), + ), Insn::DecrJumpZero { reg, target_pc } => ( "DecrJumpZero", *reg as i32, diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index d1b27399d..aeae9f685 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -430,6 +430,24 @@ pub enum Insn { num_regs: usize, target_pc: BranchOffset, }, + + // The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end. + // If the P1 index entry is lesser or equal than the key value then jump to P2. Otherwise fall through to the next instruction. + IdxLE { + cursor_id: CursorID, + start_reg: usize, + num_regs: usize, + target_pc: BranchOffset, + }, + + // The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end. + // If the P1 index entry is lesser than the key value then jump to P2. Otherwise fall through to the next instruction. + IdxLT { + cursor_id: CursorID, + start_reg: usize, + num_regs: usize, + target_pc: BranchOffset, + }, // Decrement the given register and jump to the given PC if the result is zero. DecrJumpZero { diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs index 5fa53dd07..d86a488bd 100644 --- a/core/vdbe/mod.rs +++ b/core/vdbe/mod.rs @@ -1411,6 +1411,30 @@ impl Program { state.pc = target_pc.to_offset_int(); }; } + Insn::IdxLE { + cursor_id, + start_reg, + num_regs, + target_pc, + } => { + assert!(target_pc.is_offset()); + let mut cursors = state.cursors.borrow_mut(); + let cursor = get_cursor_as_index_mut(&mut cursors, *cursor_id); + let record_from_regs: Record = + make_owned_record(&state.registers, start_reg, num_regs); + if let Some(ref idx_record) = *cursor.record()? { + // omit the rowid from the idx_record, which is the last value + if idx_record.get_values()[..idx_record.len() - 1] + <= record_from_regs.get_values()[..] + { + state.pc = target_pc.to_offset_int(); + } else { + state.pc += 1; + } + } else { + state.pc = target_pc.to_offset_int(); + }; + } Insn::IdxGT { cursor_id, start_reg, @@ -1435,6 +1459,30 @@ impl Program { state.pc = target_pc.to_offset_int(); }; } + Insn::IdxLT { + cursor_id, + start_reg, + num_regs, + target_pc, + } => { + assert!(target_pc.is_offset()); + let mut cursors = state.cursors.borrow_mut(); + let cursor = get_cursor_as_index_mut(&mut cursors, *cursor_id); + let record_from_regs: Record = + make_owned_record(&state.registers, start_reg, num_regs); + if let Some(ref idx_record) = *cursor.record()? { + // omit the rowid from the idx_record, which is the last value + if idx_record.get_values()[..idx_record.len() - 1] + < record_from_regs.get_values()[..] + { + state.pc = target_pc.to_offset_int(); + } else { + state.pc += 1; + } + } else { + state.pc = target_pc.to_offset_int(); + }; + } Insn::DecrJumpZero { reg, target_pc } => { assert!(target_pc.is_offset()); match state.registers[*reg] { From e52f21813663b37a09bf88da717c29f5cdd67a0e Mon Sep 17 00:00:00 2001 From: "[B" Date: Fri, 14 Feb 2025 21:10:51 +0100 Subject: [PATCH 2/2] fix format --- core/vdbe/insn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index aeae9f685..1fad2c479 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -430,7 +430,7 @@ pub enum Insn { num_regs: usize, target_pc: BranchOffset, }, - + // The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end. // If the P1 index entry is lesser or equal than the key value then jump to P2. Otherwise fall through to the next instruction. IdxLE {