From 01c8a4ca63294b06c848d37f3424d309339a4805 Mon Sep 17 00:00:00 2001 From: meteorgan Date: Fri, 23 May 2025 17:45:56 +0800 Subject: [PATCH] simpify values when it's subquery --- core/translate/values.rs | 133 ++++++++++++++++++++++++--------------- testing/values.test | 11 +++- 2 files changed, 92 insertions(+), 52 deletions(-) diff --git a/core/translate/values.rs b/core/translate/values.rs index db008254..390c6bb7 100644 --- a/core/translate/values.rs +++ b/core/translate/values.rs @@ -11,25 +11,60 @@ pub fn emit_values( plan: &SelectPlan, resolver: &Resolver, ) -> Result { - 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 { + 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 { 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 { + 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) } diff --git a/testing/values.test b/testing/values.test index dcd163fc..664fd4a3 100755 --- a/testing/values.test +++ b/testing/values.test @@ -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}; \ No newline at end of file + 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}; \ No newline at end of file