mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-11 19:24:21 +01:00
Emit Integer, OffsetLimit instructions, and emit IfPos instruction to
skip rows Emit Integer, OffsetLimit instructions for offset, and define function to emit IfPosinstruction to skip rows Emit IfPos instructions to handle offset for simple select Emit IfPos to handle offset for select with order by Moved repeated emit_offset function call into emit_select_result
This commit is contained in:
@@ -41,7 +41,7 @@ pub fn emit_ungrouped_aggregation<'a>(
|
||||
|
||||
// This always emits a ResultRow because currently it can only be used for a single row result
|
||||
// Limit is None because we early exit on limit 0 and the max rows here is 1
|
||||
emit_select_result(program, t_ctx, plan, None)?;
|
||||
emit_select_result(program, t_ctx, plan, None, None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -394,7 +394,13 @@ pub fn emit_group_by<'a>(
|
||||
|
||||
match &plan.order_by {
|
||||
None => {
|
||||
emit_select_result(program, t_ctx, plan, Some(label_group_by_end))?;
|
||||
emit_select_result(
|
||||
program,
|
||||
t_ctx,
|
||||
plan,
|
||||
Some(label_group_by_end),
|
||||
Some(group_by_end_without_emitting_row_label),
|
||||
)?;
|
||||
}
|
||||
Some(_) => {
|
||||
order_by_sorter_insert(program, t_ctx, plan)?;
|
||||
|
||||
@@ -705,7 +705,17 @@ fn emit_loop_source(
|
||||
plan.aggregates.is_empty(),
|
||||
"We should not get here with aggregates"
|
||||
);
|
||||
emit_select_result(program, t_ctx, plan, t_ctx.label_main_loop_end)?;
|
||||
let loop_labels = *t_ctx
|
||||
.labels_main_loop
|
||||
.get(&plan.source.id())
|
||||
.expect("source has no loop labels");
|
||||
emit_select_result(
|
||||
program,
|
||||
t_ctx,
|
||||
plan,
|
||||
t_ctx.label_main_loop_end,
|
||||
Some(loop_labels.next),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ use super::{
|
||||
emitter::TranslateCtx,
|
||||
expr::translate_expr,
|
||||
plan::{Direction, ResultSetColumn, SelectPlan},
|
||||
result_row::emit_result_row_and_limit,
|
||||
result_row::{emit_offset, emit_result_row_and_limit},
|
||||
};
|
||||
|
||||
// Metadata for handling ORDER BY operations
|
||||
@@ -63,6 +63,7 @@ pub fn emit_order_by(
|
||||
let order_by = plan.order_by.as_ref().unwrap();
|
||||
let result_columns = &plan.result_columns;
|
||||
let sort_loop_start_label = program.allocate_label();
|
||||
let sort_loop_next_label = program.allocate_label();
|
||||
let sort_loop_end_label = program.allocate_label();
|
||||
let mut pseudo_columns = vec![];
|
||||
for (i, _) in order_by.iter().enumerate() {
|
||||
@@ -117,6 +118,8 @@ pub fn emit_order_by(
|
||||
});
|
||||
|
||||
program.resolve_label(sort_loop_start_label, program.offset());
|
||||
emit_offset(program, t_ctx, plan, sort_loop_next_label)?;
|
||||
|
||||
program.emit_insn(Insn::SorterData {
|
||||
cursor_id: sort_cursor,
|
||||
dest_reg: reg_sorter_data,
|
||||
@@ -138,6 +141,7 @@ pub fn emit_order_by(
|
||||
|
||||
emit_result_row_and_limit(program, t_ctx, plan, start_reg, Some(sort_loop_end_label))?;
|
||||
|
||||
program.resolve_label(sort_loop_next_label, program.offset());
|
||||
program.emit_insn(Insn::SorterNext {
|
||||
cursor_id: sort_cursor,
|
||||
pc_if_next: sort_loop_start_label,
|
||||
|
||||
@@ -18,7 +18,12 @@ pub fn emit_select_result(
|
||||
t_ctx: &mut TranslateCtx,
|
||||
plan: &SelectPlan,
|
||||
label_on_limit_reached: Option<BranchOffset>,
|
||||
offset_jump_to: Option<BranchOffset>,
|
||||
) -> Result<()> {
|
||||
if let (Some(jump_to), Some(_)) = (offset_jump_to, label_on_limit_reached) {
|
||||
emit_offset(program, t_ctx, plan, jump_to)?;
|
||||
}
|
||||
|
||||
let start_reg = t_ctx.reg_result_cols_start.unwrap();
|
||||
for (i, rc) in plan.result_columns.iter().enumerate() {
|
||||
let reg = start_reg + i;
|
||||
@@ -71,6 +76,22 @@ pub fn emit_result_row_and_limit(
|
||||
dest: t_ctx.reg_limit.unwrap(),
|
||||
});
|
||||
program.mark_last_insn_constant();
|
||||
|
||||
if let Some(offset) = plan.offset {
|
||||
program.emit_insn(Insn::Integer {
|
||||
value: offset as i64,
|
||||
dest: t_ctx.reg_offset.unwrap(),
|
||||
});
|
||||
program.mark_last_insn_constant();
|
||||
|
||||
program.emit_insn(Insn::OffsetLimit {
|
||||
limit_reg: t_ctx.reg_limit.unwrap(),
|
||||
combined_reg: t_ctx.reg_limit_offset_sum.unwrap(),
|
||||
offset_reg: t_ctx.reg_offset.unwrap(),
|
||||
});
|
||||
program.mark_last_insn_constant();
|
||||
}
|
||||
|
||||
program.emit_insn(Insn::DecrJumpZero {
|
||||
reg: t_ctx.reg_limit.unwrap(),
|
||||
target_pc: label_on_limit_reached.unwrap(),
|
||||
@@ -78,3 +99,23 @@ pub fn emit_result_row_and_limit(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn emit_offset(
|
||||
program: &mut ProgramBuilder,
|
||||
t_ctx: &mut TranslateCtx,
|
||||
plan: &SelectPlan,
|
||||
jump_to: BranchOffset,
|
||||
) -> Result<()> {
|
||||
match plan.offset {
|
||||
Some(offset) if offset > 0 => {
|
||||
program.add_comment(program.offset(), "OFFSET");
|
||||
program.emit_insn(Insn::IfPos {
|
||||
reg: t_ctx.reg_offset.unwrap(),
|
||||
target_pc: jump_to,
|
||||
decrement_by: 1,
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user