From df230dc830a457ffa52b86f7637a6c9b225266e7 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 24 Jun 2024 21:43:19 +0300 Subject: [PATCH] Fix DecrJumpZero usage in translate_select() SQLite special-cases `LIMIT 0` by emitting an explicit `Goto` to avoid executing any `ResultRow` statements. We, however, hacked around this in DecrJumpZero but also the placement of the generated instruction. Let's follow SQLite codegen here. We still need to fix `LIMIT 0`, though. --- core/translate.rs | 2 +- core/vdbe.rs | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/core/translate.rs b/core/translate.rs index 6d76f131d..54a4f88e8 100644 --- a/core/translate.rs +++ b/core/translate.rs @@ -97,13 +97,13 @@ fn translate_select(schema: &Schema, select: Select) -> Result { program.emit_insn(Insn::OpenReadAwait); program.emit_insn(Insn::RewindAsync { cursor_id }); let rewind_await_offset = program.emit_placeholder(); - let limit_decr_insn = limit_reg.map(|_| program.emit_placeholder()); let (register_start, register_end) = translate_columns(&mut program, Some(cursor_id), Some(table), columns); program.emit_insn(Insn::ResultRow { register_start, register_end, }); + let limit_decr_insn = limit_reg.map(|_| program.emit_placeholder()); program.emit_insn(Insn::NextAsync { cursor_id }); program.emit_insn(Insn::NextAwait { cursor_id, diff --git a/core/vdbe.rs b/core/vdbe.rs index 6b39a5ed1..26c69ca93 100644 --- a/core/vdbe.rs +++ b/core/vdbe.rs @@ -94,8 +94,6 @@ pub enum Insn { }, // Decrement the given register and jump to the given PC if the result is zero. - // - // Unlike in SQLite, if register is already zero, we don't decrement, but take the jump. DecrJumpZero { reg: usize, target_pc: BranchOffset, @@ -326,11 +324,12 @@ impl Program { } Insn::DecrJumpZero { reg, target_pc } => match state.registers[*reg] { OwnedValue::Integer(n) => { - if n > 0 { - state.registers[*reg] = OwnedValue::Integer(n - 1); - state.pc += 1; - } else { + let n = n - 1; + if n == 0 { state.pc = *target_pc; + } else { + state.registers[*reg] = OwnedValue::Integer(n); + state.pc += 1; } } _ => unreachable!("DecrJumpZero on non-integer register"),