From d8078d5e1936efa9ef272c1e4a061f8219217204 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Thu, 11 Jul 2024 09:42:24 +0300 Subject: [PATCH] Simplify `LIMIT 0` handling in translate_select() It's a special-case so let's make it special like SQLite does. Simplifies the logic in `translate_select()` quite a bit. --- core/translate.rs | 99 +++++++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 46 deletions(-) diff --git a/core/translate.rs b/core/translate.rs index 450888813..cc868d604 100644 --- a/core/translate.rs +++ b/core/translate.rs @@ -177,59 +177,66 @@ fn translate_select(mut select: Select) -> Result { None } }); - let limit_insn = match parsed_limit { + let limit_goto = match parsed_limit { Some(0) => Some(program.emit_placeholder()), - _ => { - if !select.src_tables.is_empty() { - translate_tables_begin(&mut program, &mut select); + _ => None, + }; + let limit_insn = if !select.src_tables.is_empty() { + translate_tables_begin(&mut program, &mut select); - let (register_start, register_end) = - translate_columns(&mut program, &select)?; + let (register_start, register_end) = + translate_columns(&mut program, &select)?; - let mut limit_insn: Option = None; - if !select.exist_aggregation { - program.emit_insn(Insn::ResultRow { - start_reg: register_start, - count: register_end - register_start, - }); - limit_insn = limit_reg.map(|_| program.emit_placeholder()); - } - - translate_tables_end(&mut program, &select); - - if select.exist_aggregation { - let mut target = register_start; - for info in &select.column_info { - if let Some(func) = &info.func { - program.emit_insn(Insn::AggFinal { - register: target, - func: func.clone(), - }); - } - target += info.columns_to_allocate; - } - // only one result row - program.emit_insn(Insn::ResultRow { - start_reg: register_start, - count: register_end - register_start, - }); - limit_insn = limit_reg.map(|_| program.emit_placeholder()); - } - limit_insn - } else{ - assert!(!select.exist_aggregation); - let (register_start, register_end) = - translate_columns(&mut program, &select)?; - program.emit_insn(Insn::ResultRow { - start_reg: register_start, - count: register_end - register_start, - }); - limit_reg.map(|_| program.emit_placeholder()) - } + let mut limit_insn: Option = None; + if !select.exist_aggregation { + program.emit_insn(Insn::ResultRow { + start_reg: register_start, + count: register_end - register_start, + }); + limit_insn = limit_reg.map(|_| program.emit_placeholder()); } + + translate_tables_end(&mut program, &select); + + if select.exist_aggregation { + let mut target = register_start; + for info in &select.column_info { + if let Some(func) = &info.func { + program.emit_insn(Insn::AggFinal { + register: target, + func: func.clone(), + }); + } + target += info.columns_to_allocate; + } + // only one result row + program.emit_insn(Insn::ResultRow { + start_reg: register_start, + count: register_end - register_start, + }); + limit_insn = limit_reg.map(|_| program.emit_placeholder()); + } + limit_insn + } else{ + assert!(!select.exist_aggregation); + let (register_start, register_end) = + translate_columns(&mut program, &select)?; + program.emit_insn(Insn::ResultRow { + start_reg: register_start, + count: register_end - register_start, + }); + limit_reg.map(|_| program.emit_placeholder()) }; program.emit_insn(Insn::Halt); let halt_offset = program.offset() - 1; + if let Some(limit_goto) = limit_goto { + program.fixup_insn( + limit_goto, + Insn::Goto { + target_pc: halt_offset, + }, + ); + } if let Some(limit_insn) = limit_insn { let insn = match parsed_limit { Some(0) => Insn::Goto {