mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-07-07 20:45:01 +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,
|
plan: &SelectPlan,
|
||||||
resolver: &Resolver,
|
resolver: &Resolver,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
let values = &plan.values;
|
if plan.values.len() == 1 {
|
||||||
if values.len() == 1 {
|
let start_reg = emit_values_when_single_row(program, plan, resolver)?;
|
||||||
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)?;
|
|
||||||
return Ok(start_reg);
|
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 yield_reg = program.alloc_register();
|
||||||
let definition_label = program.allocate_label();
|
let definition_label = program.allocate_label();
|
||||||
let start_offset_label = program.allocate_label();
|
let start_offset_label = program.allocate_label();
|
||||||
|
@ -38,26 +73,10 @@ pub fn emit_values(
|
||||||
jump_on_definition: definition_label,
|
jump_on_definition: definition_label,
|
||||||
start_offset: start_offset_label,
|
start_offset: start_offset_label,
|
||||||
});
|
});
|
||||||
|
|
||||||
program.preassign_label_to_next_insn(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);
|
let start_reg = emit_values_in_subquery(program, plan, resolver, yield_reg)?;
|
||||||
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),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
program.emit_insn(Insn::EndCoroutine { yield_reg });
|
program.emit_insn(Insn::EndCoroutine { yield_reg });
|
||||||
program.preassign_label_to_next_insn(definition_label);
|
program.preassign_label_to_next_insn(definition_label);
|
||||||
|
|
||||||
|
@ -73,6 +92,7 @@ pub fn emit_values(
|
||||||
yield_reg,
|
yield_reg,
|
||||||
end_offset: end_label,
|
end_offset: end_label,
|
||||||
});
|
});
|
||||||
|
let row_len = plan.values[0].len();
|
||||||
let copy_start_reg = program.alloc_registers(row_len);
|
let copy_start_reg = program.alloc_registers(row_len);
|
||||||
for i in 0..row_len {
|
for i in 0..row_len {
|
||||||
program.emit_insn(Insn::Copy {
|
program.emit_insn(Insn::Copy {
|
||||||
|
@ -81,7 +101,11 @@ pub fn emit_values(
|
||||||
amount: 0,
|
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 {
|
program.emit_insn(Insn::Goto {
|
||||||
target_pc: goto_label,
|
target_pc: goto_label,
|
||||||
});
|
});
|
||||||
|
@ -90,23 +114,30 @@ pub fn emit_values(
|
||||||
Ok(copy_start_reg)
|
Ok(copy_start_reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_result_row(
|
fn emit_values_in_subquery(
|
||||||
program: &mut ProgramBuilder,
|
program: &mut ProgramBuilder,
|
||||||
plan: &SelectPlan,
|
plan: &SelectPlan,
|
||||||
start_reg: usize,
|
resolver: &Resolver,
|
||||||
count: usize,
|
yield_reg: usize,
|
||||||
) -> Result<()> {
|
) -> Result<usize> {
|
||||||
match plan.query_type {
|
let row_len = plan.values[0].len();
|
||||||
SelectQueryType::TopLevel => {
|
let start_reg = program.alloc_registers(row_len);
|
||||||
program.emit_insn(Insn::ResultRow { start_reg, count });
|
for value in &plan.values {
|
||||||
Ok(())
|
for (i, v) in value.iter().enumerate() {
|
||||||
}
|
translate_expr_no_constant_opt(
|
||||||
SelectQueryType::Subquery { yield_reg, .. } => {
|
program,
|
||||||
program.emit_insn(Insn::Yield {
|
None,
|
||||||
yield_reg,
|
&v,
|
||||||
end_offset: BranchOffset::Offset(0),
|
start_reg + i,
|
||||||
});
|
resolver,
|
||||||
Ok(())
|
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
|
} {1|2
|
||||||
3|4};
|
3|4};
|
||||||
|
|
||||||
|
do_execsql_test values-3 {
|
||||||
|
values(1+1, 2*3);
|
||||||
|
} {2|6};
|
||||||
|
|
||||||
do_execsql_test values-in-from {
|
do_execsql_test values-in-from {
|
||||||
select * from (values(3, 4, 5), (5, 6, 7), (8, 9, 10));
|
select * from (values(3, 4, 5), (5, 6, 7), (8, 9, 10));
|
||||||
} {3|4|5
|
} {3|4|5
|
||||||
5|6|7
|
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