mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-27 04:54:21 +01:00
Move where clause literal out of loop
This commit is contained in:
@@ -269,6 +269,7 @@ fn translate_select(mut select: Select) -> Result<Program> {
|
||||
}
|
||||
program.resolve_label(init_label, program.offset());
|
||||
program.emit_insn(Insn::Transaction);
|
||||
program.emit_run_once_insns();
|
||||
program.emit_insn(Insn::Goto {
|
||||
target_pc: start_offset,
|
||||
});
|
||||
@@ -501,7 +502,15 @@ fn translate_condition_expr(
|
||||
let e1_reg = program.alloc_register();
|
||||
let e2_reg = program.alloc_register();
|
||||
let _ = translate_expr(program, select, e1, e1_reg)?;
|
||||
match e1.as_ref() {
|
||||
ast::Expr::Literal(_) => program.move_last_insn_out_of_loop(),
|
||||
_ => {}
|
||||
}
|
||||
let _ = translate_expr(program, select, e2, e2_reg)?;
|
||||
match e2.as_ref() {
|
||||
ast::Expr::Literal(_) => program.move_last_insn_out_of_loop(),
|
||||
_ => {}
|
||||
}
|
||||
if jump_target < 0 {
|
||||
program.add_label_dependency(jump_target, program.offset());
|
||||
}
|
||||
@@ -1030,6 +1039,7 @@ fn translate_pragma(
|
||||
program.emit_insn(Insn::Halt);
|
||||
program.resolve_label(init_label, program.offset());
|
||||
program.emit_insn(Insn::Transaction);
|
||||
program.emit_run_once_insns();
|
||||
program.emit_insn(Insn::Goto {
|
||||
target_pc: start_offset,
|
||||
});
|
||||
|
||||
19
core/vdbe.rs
19
core/vdbe.rs
@@ -225,6 +225,8 @@ pub struct ProgramBuilder {
|
||||
next_free_label: BranchOffset,
|
||||
next_free_cursor_id: usize,
|
||||
insns: Vec<Insn>,
|
||||
// for temporarily storing instructions that will be put after Transaction opcode
|
||||
run_once_insns: Vec<Insn>,
|
||||
// Each label has a list of InsnReferences that must
|
||||
// be resolved. Lists are indexed by: label.abs() - 1
|
||||
unresolved_labels: Vec<Vec<InsnReference>>,
|
||||
@@ -243,6 +245,7 @@ impl ProgramBuilder {
|
||||
unresolved_labels: Vec::new(),
|
||||
next_insn_label: None,
|
||||
cursor_ref: Vec::new(),
|
||||
run_once_insns: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,6 +284,18 @@ impl ProgramBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
// Emit an instruction that will be put at the end of the program (after Transaction statement).
|
||||
// This is useful for instructions that otherwise will be unnecessarily repeated in a loop.
|
||||
// Example: In `SELECT * from users where name='John'`, it is unnecessary to set r[1]='John' as we SCAN users table.
|
||||
// We could simply set it once before the SCAN started.
|
||||
pub fn move_last_insn_out_of_loop(&mut self) {
|
||||
self.run_once_insns.push(self.insns.pop().unwrap());
|
||||
}
|
||||
|
||||
pub fn emit_run_once_insns(&mut self) {
|
||||
self.insns.extend(self.run_once_insns.drain(..));
|
||||
}
|
||||
|
||||
pub fn emit_insn_with_label_dependency(&mut self, insn: Insn, label: BranchOffset) {
|
||||
self.insns.push(insn);
|
||||
self.add_label_dependency(label, (self.insns.len() - 1) as BranchOffset);
|
||||
@@ -430,6 +445,10 @@ impl ProgramBuilder {
|
||||
}
|
||||
|
||||
pub fn build(self) -> Program {
|
||||
assert!(
|
||||
self.run_once_insns.is_empty(),
|
||||
"run_once_insns is not empty when build() is called, did you forget to call emit_run_once_insns()?"
|
||||
);
|
||||
Program {
|
||||
max_registers: self.next_free_register,
|
||||
insns: self.insns,
|
||||
|
||||
Reference in New Issue
Block a user