diff --git a/core/translate/group_by.rs b/core/translate/group_by.rs index 971ebe403..7b54ab3ef 100644 --- a/core/translate/group_by.rs +++ b/core/translate/group_by.rs @@ -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(()) diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 2071434bc..f4123004a 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -322,15 +322,17 @@ pub fn op_null( pager: &Rc, mv_store: Option<&Rc>, ) -> Result { - let Insn::Null { dest, dest_end } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; - if let Some(dest_end) = dest_end { - for i in *dest..=*dest_end { - state.registers[i] = Register::Value(Value::Null); + match insn { + Insn::Null { dest, dest_end } | Insn::BeginSubrtn { dest, dest_end } => { + if let Some(dest_end) = dest_end { + for i in *dest..=*dest_end { + state.registers[i] = Register::Value(Value::Null); + } + } else { + state.registers[*dest] = Register::Value(Value::Null); + } } - } else { - state.registers[*dest] = Register::Value(Value::Null); + _ => unreachable!("unexpected Insn {:?}", insn), } state.pc += 1; Ok(InsnFunctionStepResult::Step) @@ -1809,7 +1811,11 @@ pub fn op_return( pager: &Rc, mv_store: Option<&Rc>, ) -> Result { - 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 +1824,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) } diff --git a/core/vdbe/explain.rs b/core/vdbe/explain.rs index 425efee2d..e2e9bf979 100644 --- a/core/vdbe/explain.rs +++ b/core/vdbe/explain.rs @@ -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(), diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index b6c70efe4..976f6aba4 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -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.