mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-07-07 12:35:00 +00:00
simpify values when it's subquery
This commit is contained in:
parent
34e05ef974
commit
01c8a4ca63
2 changed files with 92 additions and 52 deletions
|
@ -11,25 +11,60 @@ pub fn emit_values(
|
|||
plan: &SelectPlan,
|
||||
resolver: &Resolver,
|
||||
) -> Result<usize> {
|
||||
let values = &plan.values;
|
||||
if values.len() == 1 {
|
||||
let first_row = &values[0];
|
||||
let row_len = first_row.len();
|
||||
let start_reg = program.alloc_registers(row_len);
|
||||
for (i, v) in first_row.iter().enumerate() {
|
||||
translate_expr_no_constant_opt(
|
||||
program,
|
||||
None,
|
||||
&v,
|
||||
start_reg + i,
|
||||
resolver,
|
||||
NoConstantOptReason::RegisterReuse,
|
||||
)?;
|
||||
}
|
||||
emit_result_row(program, plan, start_reg, row_len)?;
|
||||
if plan.values.len() == 1 {
|
||||
let start_reg = emit_values_when_single_row(program, plan, resolver)?;
|
||||
return Ok(start_reg);
|
||||
}
|
||||
|
||||
let reg_result_cols_start = match plan.query_type {
|
||||
SelectQueryType::TopLevel => emit_toplevel_values(program, plan, resolver)?,
|
||||
SelectQueryType::Subquery { yield_reg, .. } => {
|
||||
emit_values_in_subquery(program, plan, resolver, yield_reg)?
|
||||
}
|
||||
};
|
||||
Ok(reg_result_cols_start)
|
||||
}
|
||||
|
||||
fn emit_values_when_single_row(
|
||||
program: &mut ProgramBuilder,
|
||||
plan: &SelectPlan,
|
||||
resolver: &Resolver,
|
||||
) -> Result<usize> {
|
||||
let first_row = &plan.values[0];
|
||||
let row_len = first_row.len();
|
||||
let start_reg = program.alloc_registers(row_len);
|
||||
for (i, v) in first_row.iter().enumerate() {
|
||||
translate_expr_no_constant_opt(
|
||||
program,
|
||||
None,
|
||||
&v,
|
||||
start_reg + i,
|
||||
resolver,
|
||||
NoConstantOptReason::RegisterReuse,
|
||||
)?;
|
||||
}
|
||||
match plan.query_type {
|
||||
SelectQueryType::TopLevel => {
|
||||
program.emit_insn(Insn::ResultRow {
|
||||
start_reg,
|
||||
count: row_len,
|
||||
});
|
||||
}
|
||||
SelectQueryType::Subquery { yield_reg, .. } => {
|
||||
program.emit_insn(Insn::Yield {
|
||||
yield_reg,
|
||||
end_offset: BranchOffset::Offset(0),
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(start_reg)
|
||||
}
|
||||
|
||||
fn emit_toplevel_values(
|
||||
program: &mut ProgramBuilder,
|
||||
plan: &SelectPlan,
|
||||
resolver: &Resolver,
|
||||
) -> Result<usize> {
|
||||
let yield_reg = program.alloc_register();
|
||||
let definition_label = program.allocate_label();
|
||||
let start_offset_label = program.allocate_label();
|
||||
|
@ -38,26 +73,10 @@ pub fn emit_values(
|
|||
jump_on_definition: definition_label,
|
||||
start_offset: start_offset_label,
|
||||
});
|
||||
|
||||
program.preassign_label_to_next_insn(start_offset_label);
|
||||
let row_len = values[0].len();
|
||||
let start_reg = program.alloc_registers(row_len);
|
||||
for value in values {
|
||||
for (i, v) in value.iter().enumerate() {
|
||||
translate_expr_no_constant_opt(
|
||||
program,
|
||||
None,
|
||||
&v,
|
||||
start_reg + i,
|
||||
resolver,
|
||||
NoConstantOptReason::RegisterReuse,
|
||||
)?;
|
||||
}
|
||||
program.emit_insn(Insn::Yield {
|
||||
yield_reg,
|
||||
end_offset: BranchOffset::Offset(0),
|
||||
});
|
||||
}
|
||||
|
||||
let start_reg = emit_values_in_subquery(program, plan, resolver, yield_reg)?;
|
||||
|
||||
program.emit_insn(Insn::EndCoroutine { yield_reg });
|
||||
program.preassign_label_to_next_insn(definition_label);
|
||||
|
||||
|
@ -73,6 +92,7 @@ pub fn emit_values(
|
|||
yield_reg,
|
||||
end_offset: end_label,
|
||||
});
|
||||
let row_len = plan.values[0].len();
|
||||
let copy_start_reg = program.alloc_registers(row_len);
|
||||
for i in 0..row_len {
|
||||
program.emit_insn(Insn::Copy {
|
||||
|
@ -81,7 +101,11 @@ pub fn emit_values(
|
|||
amount: 0,
|
||||
});
|
||||
}
|
||||
emit_result_row(program, plan, copy_start_reg, row_len)?;
|
||||
|
||||
program.emit_insn(Insn::ResultRow {
|
||||
start_reg: copy_start_reg,
|
||||
count: row_len,
|
||||
});
|
||||
program.emit_insn(Insn::Goto {
|
||||
target_pc: goto_label,
|
||||
});
|
||||
|
@ -90,23 +114,30 @@ pub fn emit_values(
|
|||
Ok(copy_start_reg)
|
||||
}
|
||||
|
||||
fn emit_result_row(
|
||||
fn emit_values_in_subquery(
|
||||
program: &mut ProgramBuilder,
|
||||
plan: &SelectPlan,
|
||||
start_reg: usize,
|
||||
count: usize,
|
||||
) -> Result<()> {
|
||||
match plan.query_type {
|
||||
SelectQueryType::TopLevel => {
|
||||
program.emit_insn(Insn::ResultRow { start_reg, count });
|
||||
Ok(())
|
||||
}
|
||||
SelectQueryType::Subquery { yield_reg, .. } => {
|
||||
program.emit_insn(Insn::Yield {
|
||||
yield_reg,
|
||||
end_offset: BranchOffset::Offset(0),
|
||||
});
|
||||
Ok(())
|
||||
resolver: &Resolver,
|
||||
yield_reg: usize,
|
||||
) -> Result<usize> {
|
||||
let row_len = plan.values[0].len();
|
||||
let start_reg = program.alloc_registers(row_len);
|
||||
for value in &plan.values {
|
||||
for (i, v) in value.iter().enumerate() {
|
||||
translate_expr_no_constant_opt(
|
||||
program,
|
||||
None,
|
||||
&v,
|
||||
start_reg + i,
|
||||
resolver,
|
||||
NoConstantOptReason::RegisterReuse,
|
||||
)?;
|
||||
}
|
||||
program.emit_insn(Insn::Yield {
|
||||
yield_reg,
|
||||
end_offset: BranchOffset::Offset(0),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(start_reg)
|
||||
}
|
||||
|
|
|
@ -12,8 +12,17 @@ do_execsql_test values-2 {
|
|||
} {1|2
|
||||
3|4};
|
||||
|
||||
do_execsql_test values-3 {
|
||||
values(1+1, 2*3);
|
||||
} {2|6};
|
||||
|
||||
do_execsql_test values-in-from {
|
||||
select * from (values(3, 4, 5), (5, 6, 7), (8, 9, 10));
|
||||
} {3|4|5
|
||||
5|6|7
|
||||
8|9|10};
|
||||
8|9|10};
|
||||
|
||||
do_execsql_test values-in-join {
|
||||
select * from (values(1, 2)) join (values(3, 4), (5, 6));
|
||||
} {1|2|3|4
|
||||
1|2|5|6};
|
Loading…
Add table
Add a link
Reference in a new issue