Merge 'Added IdxLE and IdxLT opcodes' from Omolola Olamide

I added the two opcodes as an initial step. They are pretty easy to
implement since we already have the counterparts i.e., IdxGE and IdxGT
Is there a design reason behind their omission @penberg @PThorpe92?
I noticed the same for SeekLE and SeekLT.

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #1010
This commit is contained in:
Pekka Enberg
2025-02-15 11:10:17 +02:00
5 changed files with 102 additions and 1 deletions

View File

@@ -461,7 +461,8 @@ Modifiers:
| IdxDelete | No | |
| IdxGE | Yes | |
| IdxInsert | No | |
| IdxLT | No | |
| IdxLE | Yes | |
| IdxLT | Yes | |
| IdxRowid | No | |
| If | Yes | |
| IfNeg | No | |

View File

@@ -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");
}

View File

@@ -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,

View File

@@ -431,6 +431,24 @@ pub enum Insn {
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 {
reg: usize,

View File

@@ -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] {