mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-20 15:35:29 +01:00
make values work in subquery
This commit is contained in:
@@ -196,6 +196,11 @@ pub fn emit_query<'a>(
|
||||
plan: &'a mut SelectPlan,
|
||||
t_ctx: &'a mut TranslateCtx<'a>,
|
||||
) -> Result<usize> {
|
||||
if !plan.values.is_empty() {
|
||||
let reg_result_cols_start = emit_values(program, &plan, &t_ctx.resolver)?;
|
||||
return Ok(reg_result_cols_start);
|
||||
}
|
||||
|
||||
// Emit subqueries first so the results can be read in the main query loop.
|
||||
emit_subqueries(program, t_ctx, &mut plan.table_references)?;
|
||||
|
||||
@@ -291,12 +296,8 @@ pub fn emit_query<'a>(
|
||||
&mut plan.where_clause,
|
||||
)?;
|
||||
|
||||
if !plan.values.is_empty() {
|
||||
emit_values(program, &plan.values, &t_ctx.resolver)?;
|
||||
} else {
|
||||
// Process result columns and expressions in the inner loop
|
||||
emit_loop(program, t_ctx, plan)?;
|
||||
}
|
||||
// Process result columns and expressions in the inner loop
|
||||
emit_loop(program, t_ctx, plan)?;
|
||||
|
||||
// Clean up and close the main execution loop
|
||||
close_loop(program, t_ctx, &plan.table_references, &plan.join_order)?;
|
||||
|
||||
@@ -404,10 +404,19 @@ pub fn prepare_select_plan<'a>(
|
||||
Ok(Plan::Select(plan))
|
||||
}
|
||||
ast::OneSelect::Values(values) => {
|
||||
let len = values[0].len();
|
||||
let mut result_columns = Vec::with_capacity(len);
|
||||
for i in 0..len {
|
||||
result_columns.push(ResultSetColumn {
|
||||
expr: ast::Expr::Literal(ast::Literal::Numeric(i.to_string())),
|
||||
alias: None,
|
||||
contains_aggregates: false,
|
||||
});
|
||||
}
|
||||
let plan = SelectPlan {
|
||||
join_order: vec![],
|
||||
table_references: vec![],
|
||||
result_columns: vec![],
|
||||
result_columns,
|
||||
where_clause: vec![],
|
||||
group_by: None,
|
||||
order_by: None,
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
use crate::translate::emitter::Resolver;
|
||||
use crate::translate::expr::{translate_expr_no_constant_opt, NoConstantOptReason};
|
||||
use crate::translate::plan::{SelectPlan, SelectQueryType};
|
||||
use crate::vdbe::builder::ProgramBuilder;
|
||||
use crate::vdbe::insn::Insn;
|
||||
use crate::vdbe::BranchOffset;
|
||||
use limbo_sqlite3_parser::ast::Expr;
|
||||
use crate::Result;
|
||||
|
||||
pub fn emit_values(
|
||||
program: &mut ProgramBuilder,
|
||||
values: &Vec<Vec<Expr>>,
|
||||
plan: &SelectPlan,
|
||||
resolver: &Resolver,
|
||||
) -> crate::Result<()> {
|
||||
if values.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
) -> Result<usize> {
|
||||
let values = &plan.values;
|
||||
if values.len() == 1 {
|
||||
let value = &values[0];
|
||||
let value_size = value.len();
|
||||
let start_reg = program.alloc_registers(value_size);
|
||||
for (i, v) in value.iter().enumerate() {
|
||||
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,
|
||||
@@ -28,11 +26,8 @@ pub fn emit_values(
|
||||
NoConstantOptReason::RegisterReuse,
|
||||
)?;
|
||||
}
|
||||
program.emit_insn(Insn::ResultRow {
|
||||
start_reg,
|
||||
count: value_size,
|
||||
});
|
||||
return Ok(());
|
||||
emit_result_row(program, plan, start_reg, row_len)?;
|
||||
return Ok(start_reg);
|
||||
}
|
||||
|
||||
let yield_reg = program.alloc_register();
|
||||
@@ -45,8 +40,8 @@ pub fn emit_values(
|
||||
});
|
||||
|
||||
program.preassign_label_to_next_insn(start_offset_label);
|
||||
let value_size = values[0].len();
|
||||
let start_reg = program.alloc_registers(value_size);
|
||||
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(
|
||||
@@ -78,20 +73,40 @@ pub fn emit_values(
|
||||
yield_reg,
|
||||
end_offset: end_label,
|
||||
});
|
||||
let copy_reg = program.alloc_registers(value_size);
|
||||
for i in 0..value_size {
|
||||
let copy_start_reg = program.alloc_registers(row_len);
|
||||
for i in 0..row_len {
|
||||
program.emit_insn(Insn::Copy {
|
||||
src_reg: start_reg + i,
|
||||
dst_reg: copy_reg + i,
|
||||
dst_reg: copy_start_reg + i,
|
||||
amount: 0,
|
||||
});
|
||||
}
|
||||
program.emit_insn(Insn::ResultRow {
|
||||
start_reg: copy_reg,
|
||||
count: value_size,
|
||||
emit_result_row(program, plan, copy_start_reg, row_len)?;
|
||||
program.emit_insn(Insn::Goto {
|
||||
target_pc: goto_label,
|
||||
});
|
||||
program.emit_goto(goto_label);
|
||||
program.preassign_label_to_next_insn(end_label);
|
||||
|
||||
Ok(())
|
||||
Ok(copy_start_reg)
|
||||
}
|
||||
|
||||
fn emit_result_row(
|
||||
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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1557,7 +1557,7 @@ pub fn op_result_row(
|
||||
};
|
||||
state.result_row = Some(row);
|
||||
state.pc += 1;
|
||||
return Ok(InsnFunctionStepResult::Row);
|
||||
Ok(InsnFunctionStepResult::Row)
|
||||
}
|
||||
|
||||
pub fn op_next(
|
||||
|
||||
@@ -35,3 +35,4 @@ source $testdir/literal.test
|
||||
source $testdir/null.test
|
||||
source $testdir/create_table.test
|
||||
source $testdir/collate.test
|
||||
source $testdir/values.test
|
||||
|
||||
19
testing/values.test
Executable file
19
testing/values.test
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env tclsh
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_execsql_test values-1 {
|
||||
values(1, 2);
|
||||
} {1|2};
|
||||
|
||||
do_execsql_test values-2 {
|
||||
values(1, 2), (3, 4);
|
||||
} {1|2
|
||||
3|4};
|
||||
|
||||
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};
|
||||
Reference in New Issue
Block a user