From 5bd3d283d1c5ed9434aa4d7058713f3031cfeaf7 Mon Sep 17 00:00:00 2001 From: Piotr Sarna Date: Sat, 6 Jul 2024 10:43:41 +0200 Subject: [PATCH] translate: special case for LIMIT 0 Fixes #55 --- core/translate.rs | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/core/translate.rs b/core/translate.rs index 06b64d741..d17b09ad0 100644 --- a/core/translate.rs +++ b/core/translate.rs @@ -122,8 +122,16 @@ fn translate_select(select: Select) -> Result { None }; let cursor_id = program.alloc_cursor_id(); - let limit_decr_insn = match select.from { - Some(table) => { + let parsed_limit = select.limit.as_ref().and_then(|limit| { + if let ast::Expr::Literal(ast::Literal::Numeric(num)) = &limit.expr { + num.parse::().ok() + } else { + None + } + }); + let limit_insn = match (parsed_limit, select.from) { + (Some(0), _) => Some(program.emit_placeholder()), + (_, Some(table)) => { let root_page = table.root_page; program.emit_insn(Insn::OpenReadAsync { cursor_id, @@ -134,7 +142,7 @@ fn translate_select(select: Select) -> Result { let rewind_await_offset = program.emit_placeholder(); let (register_start, register_end) = translate_columns(&mut program, Some(cursor_id), &select); - let limit_decr_insn = if select.exist_aggregation { + let limit_insn = if select.exist_aggregation { program.emit_insn(Insn::NextAsync { cursor_id }); program.emit_insn(Insn::NextAwait { cursor_id, @@ -161,13 +169,13 @@ fn translate_select(select: Select) -> Result { start_reg: register_start, count: register_end - register_start, }); - let limit_decr_insn = limit_reg.map(|_| program.emit_placeholder()); + let limit_insn = limit_reg.map(|_| program.emit_placeholder()); program.emit_insn(Insn::NextAsync { cursor_id }); program.emit_insn(Insn::NextAwait { cursor_id, pc_if_next: rewind_await_offset, }); - limit_decr_insn + limit_insn }; program.fixup_insn( rewind_await_offset, @@ -176,9 +184,9 @@ fn translate_select(select: Select) -> Result { pc_if_empty: program.offset(), }, ); - limit_decr_insn + limit_insn } - None => { + (_, None) => { assert!(!select.exist_aggregation); let (register_start, register_end) = translate_columns(&mut program, None, &select); program.emit_insn(Insn::ResultRow { @@ -188,16 +196,20 @@ fn translate_select(select: Select) -> Result { limit_reg.map(|_| program.emit_placeholder()) } }; - if let Some(limit_decr_insn) = limit_decr_insn { - program.fixup_insn( - limit_decr_insn, - Insn::DecrJumpZero { - reg: limit_reg.unwrap(), - target_pc: program.offset(), - }, - ); - } program.emit_insn(Insn::Halt); + let halt_offset = program.offset() - 1; + if let Some(limit_insn) = limit_insn { + let insn = match parsed_limit { + Some(0) => Insn::Goto { + target_pc: halt_offset, + }, + _ => Insn::DecrJumpZero { + reg: limit_reg.unwrap(), + target_pc: halt_offset, + }, + }; + program.fixup_insn(limit_insn, insn); + } program.fixup_insn( init_offset, Insn::Init {