Insn::Return: add possibility to fallthrough on non-integer values as per sqlite spec

This commit is contained in:
Jussi Saurio 2025-05-26 16:24:16 +03:00
parent a88e1c38f3
commit 70965f4b28
4 changed files with 23 additions and 6 deletions

View file

@ -760,6 +760,7 @@ pub fn group_by_emit_row_phase<'a>(
});
program.emit_insn(Insn::Return {
return_reg: registers.reg_subrtn_acc_output_return_offset,
can_fallthrough: false,
});
program.resolve_label(labels.label_subrtn_acc_output, program.offset());
@ -784,6 +785,7 @@ pub fn group_by_emit_row_phase<'a>(
}
program.emit_insn(Insn::Return {
return_reg: registers.reg_subrtn_acc_output_return_offset,
can_fallthrough: false,
});
// Finalize aggregate values for output
@ -916,6 +918,7 @@ pub fn group_by_emit_row_phase<'a>(
program.emit_insn(Insn::Return {
return_reg: registers.reg_subrtn_acc_output_return_offset,
can_fallthrough: false,
});
// Subroutine to clear accumulators for a new group
@ -955,6 +958,7 @@ pub fn group_by_emit_row_phase<'a>(
});
program.emit_insn(Insn::Return {
return_reg: registers.reg_subrtn_acc_clear_return_offset,
can_fallthrough: false,
});
program.preassign_label_to_next_insn(labels.label_group_by_end);
Ok(())

View file

@ -1809,7 +1809,11 @@ pub fn op_return(
pager: &Rc<Pager>,
mv_store: Option<&Rc<MvStore>>,
) -> Result<InsnFunctionStepResult> {
let Insn::Return { return_reg } = insn else {
let Insn::Return {
return_reg,
can_fallthrough,
} = insn
else {
unreachable!("unexpected Insn {:?}", insn)
};
if let Value::Integer(pc) = state.registers[*return_reg].get_owned_value() {
@ -1818,9 +1822,12 @@ pub fn op_return(
.unwrap_or_else(|_| panic!("Return register is negative: {}", pc));
state.pc = pc;
} else {
return Err(LimboError::InternalError(
"Return register is not an integer".to_string(),
));
if !*can_fallthrough {
return Err(LimboError::InternalError(
"Return register is not an integer".to_string(),
));
}
state.pc += 1;
}
Ok(InsnFunctionStepResult::Step)
}

View file

@ -625,11 +625,14 @@ pub fn insn_to_str(
0,
"".to_string(),
),
Insn::Return { return_reg } => (
Insn::Return {
return_reg,
can_fallthrough,
} => (
"Return",
*return_reg as i32,
0,
0,
*can_fallthrough as i32,
Value::build_text(""),
0,
"".to_string(),

View file

@ -429,8 +429,11 @@ pub enum Insn {
},
/// Returns to the program counter stored in register 'return_reg'.
/// If can_fallthrough is true, fall through to the next instruction
/// if return_reg does not contain an integer value. Otherwise raise an error.
Return {
return_reg: usize,
can_fallthrough: bool,
},
/// Write an integer value into a register.