Merge 'Handle limit zero case in query plan emitter' from Preston Thorpe

closes #1190
Don't emit full query plan and open table if 0 `LIMIT`
```console
limbo> explain select * from t limit 0;
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     2     0                    0   Start at 2
1     Halt               0     0     0                    0
2     Transaction        0     0     0                    0   write=false
3     Goto               0     1     0                    0
```
Surprisingly, sqlite will still emit the Open/Rewind/Column/etc, etc for
this case. Definitely feels super unnecessary.

Closes #1191
This commit is contained in:
Pekka Enberg
2025-03-27 08:59:54 +02:00

View File

@@ -180,12 +180,13 @@ fn emit_program_for_select(
if let Some(limit) = plan.limit {
if limit == 0 {
epilogue(program, init_label, start_offset)?;
program.result_columns = plan.result_columns;
program.table_references = plan.table_references;
return Ok(());
}
}
// Emit main parts of query
emit_query(program, &mut plan, &mut t_ctx)?;
// Finalize program
epilogue(program, init_label, start_offset)?;
program.result_columns = plan.result_columns;
@@ -302,6 +303,14 @@ fn emit_program_for_delete(
plan.result_columns.len(),
)?;
// exit early if LIMIT 0
if let Some(0) = plan.limit {
epilogue(program, init_label, start_offset)?;
program.result_columns = plan.result_columns;
program.table_references = plan.table_references;
return Ok(());
}
// No rows will be read from source table loops if there is a constant false condition eg. WHERE 0
let after_main_loop_label = program.allocate_label();
t_ctx.label_main_loop_end = Some(after_main_loop_label);