core: vbde coroutine generation with rowid insert

This commit is contained in:
Pere Diaz Bou
2024-07-20 17:46:00 +02:00
parent bbed54d11c
commit affe3443cc
5 changed files with 166 additions and 47 deletions

View File

@@ -83,6 +83,13 @@ impl Table {
Table::Pseudo(table) => &table.columns,
}
}
pub fn has_rowid(&self) -> bool {
match self {
Table::BTree(table) => table.has_rowid,
Table::Pseudo(_) => todo!(),
}
}
}
impl PartialEq for Table {

View File

@@ -11,7 +11,7 @@ use crate::{
pub fn translate_expr(
program: &mut ProgramBuilder,
select: &Select,
select: Option<&Select>,
expr: &ast::Expr,
target_register: usize,
cursor_hint: Option<usize>,
@@ -435,7 +435,7 @@ pub fn translate_expr(
ast::Expr::Parenthesized(_) => todo!(),
ast::Expr::Qualified(tbl, ident) => {
let (idx, col_type, cursor_id, is_primary_key) =
resolve_ident_qualified(program, &tbl.0, &ident.0, select, cursor_hint)?;
resolve_ident_qualified(program, &tbl.0, &ident.0, select.unwrap(), cursor_hint)?;
if is_primary_key {
program.emit_insn(Insn::RowId {
cursor_id,
@@ -614,12 +614,12 @@ pub fn resolve_ident_qualified(
pub fn resolve_ident_table(
program: &ProgramBuilder,
ident: &String,
select: &Select,
select: Option<&Select>,
cursor_hint: Option<usize>,
) -> Result<(usize, Type, usize, bool)> {
let ident = normalize_ident(ident);
let mut found = Vec::new();
for join in &select.src_tables {
for join in &select.unwrap().src_tables {
match join.table {
Table::BTree(ref table) => {
let res = table

View File

@@ -7,7 +7,7 @@ use sqlite3_parser::ast::{
use crate::Result;
use crate::{
schema::{self, Schema, Table},
translate::expr::resolve_ident_qualified,
translate::expr::{resolve_ident_qualified, translate_expr},
vdbe::{builder::ProgramBuilder, Insn, Program},
};
@@ -37,31 +37,6 @@ pub fn translate_insert(
dbg!(returning);
dbg!(with);
dbg!(body);
let yield_reg = program.alloc_register();
let jump_on_definition_label = program.allocate_label();
program.emit_insn(Insn::InitCoroutine {
yield_reg,
jump_on_definition: jump_on_definition_label,
start_offset: program.offset() + 1,
});
match body {
InsertBody::Select(select, None) => match &select.body.select {
sqlite3_parser::ast::OneSelect::Select {
distinctness: _,
columns: _,
from: _,
where_clause: _,
group_by: _,
window_clause: _,
} => todo!(),
sqlite3_parser::ast::OneSelect::Values(values) => {}
},
InsertBody::DefaultValues => todo!("default values not yet supported"),
_ => todo!(),
}
program.emit_insn(Insn::EndCoroutine { yield_reg });
// open table
let table_name = &tbl_name.name;
@@ -78,12 +53,131 @@ pub fn translate_insert(
Table::BTree(btree) => btree.root_page,
Table::Pseudo(_) => todo!(),
};
let mut num_cols = table.columns().len();
if table.has_rowid() {
num_cols += 1;
}
// column_registers_start[0] == rowid if has rowid
let column_registers_start = program.alloc_registers(num_cols);
// Coroutine for values
let yield_reg = program.alloc_register();
let jump_on_definition_label = program.allocate_label();
{
program.emit_insn_with_label_dependency(
Insn::InitCoroutine {
yield_reg,
jump_on_definition: jump_on_definition_label,
start_offset: program.offset() + 1,
},
jump_on_definition_label,
);
match body {
InsertBody::Select(select, None) => match &select.body.select {
sqlite3_parser::ast::OneSelect::Select {
distinctness: _,
columns: _,
from: _,
where_clause: _,
group_by: _,
window_clause: _,
} => todo!(),
sqlite3_parser::ast::OneSelect::Values(values) => {
for value in values {
for (col, expr) in value.iter().enumerate() {
let mut col = col;
if table.has_rowid() {
col += 1;
}
translate_expr(
&mut program,
None,
expr,
column_registers_start + col,
None,
)?;
}
program.emit_insn(Insn::Yield {
yield_reg,
end_offset: 0,
});
}
}
},
InsertBody::DefaultValues => todo!("default values not yet supported"),
_ => todo!(),
}
program.emit_insn(Insn::EndCoroutine { yield_reg });
}
program.resolve_label(jump_on_definition_label, program.offset());
program.emit_insn(Insn::OpenWriteAsync {
cursor_id,
root_page,
});
program.emit_insn(Insn::OpenWriteAwait {});
// Main loop
let record_register = program.alloc_register();
let halt_label = program.allocate_label();
program.emit_insn_with_label_dependency(
Insn::Yield {
yield_reg,
end_offset: halt_label,
},
halt_label,
);
if table.has_rowid() {
let key_reg = column_registers_start + 1;
let row_id_reg = column_registers_start;
// copy key to rowid
program.emit_insn(Insn::Copy {
src_reg: key_reg,
dst_reg: row_id_reg,
amount: 0,
});
program.emit_insn(Insn::SoftNull { reg: key_reg });
let notnull_label = program.allocate_label();
program.emit_insn_with_label_dependency(
Insn::NotNull {
reg: row_id_reg,
target_pc: notnull_label,
},
notnull_label,
);
program.emit_insn(Insn::NewRowid { reg: row_id_reg });
program.resolve_label(notnull_label, program.offset());
program.emit_insn(Insn::MustBeInt { reg: row_id_reg });
let make_record_label = program.allocate_label();
program.emit_insn_with_label_dependency(
Insn::NotExists {
cursor: cursor_id,
rowid_reg: row_id_reg,
target_pc: make_record_label,
},
make_record_label,
);
program.emit_insn(Insn::Halt); // Add error code 1555 and rollback
program.resolve_label(make_record_label, program.offset());
program.emit_insn(Insn::MakeRecord {
start_reg: column_registers_start,
count: num_cols,
dest_reg: record_register,
});
program.emit_insn(Insn::InsertAsync {
cursor: cursor_id,
key_reg: column_registers_start,
record_reg: record_register,
flag: 0,
});
program.emit_insn(Insn::InsertAwait {});
}
program.resolve_label(halt_label, program.offset());
program.emit_insn(Insn::Halt);
program.resolve_label(init_label, program.offset());
program.emit_insn(Insn::Transaction);

View File

@@ -274,7 +274,13 @@ pub fn translate_select(mut select: Select) -> Result<Program> {
let limit_info = if let Some(limit) = &select.limit {
assert!(limit.offset.is_none());
let target_register = program.alloc_register();
let limit_reg = translate_expr(&mut program, &select, &limit.expr, target_register, None)?;
let limit_reg = translate_expr(
&mut program,
Some(&select),
&limit.expr,
target_register,
None,
)?;
let num = if let ast::Expr::Literal(ast::Literal::Numeric(num)) = &limit.expr {
num.parse::<i64>()?
} else {
@@ -326,7 +332,7 @@ pub fn translate_select(mut select: Select) -> Result<Program> {
} else {
&col.expr
};
translate_expr(&mut program, &select, sort_col_expr, target, None)?;
translate_expr(&mut program, Some(&select), sort_col_expr, target, None)?;
}
let (_, result_cols_count) = translate_columns(&mut program, &select, None)?;
sort_info
@@ -742,7 +748,7 @@ fn translate_column(
cursor_hint,
)?;
} else {
let _ = translate_expr(program, select, expr, target_register, cursor_hint)?;
let _ = translate_expr(program, Some(select), expr, target_register, cursor_hint)?;
}
}
ast::ResultColumn::Star => {
@@ -807,7 +813,7 @@ fn translate_aggregation(
}
let expr = &args[0];
let expr_reg = program.alloc_register();
let _ = translate_expr(program, select, expr, expr_reg, cursor_hint)?;
let _ = translate_expr(program, Some(select), expr, expr_reg, cursor_hint)?;
program.emit_insn(Insn::AggStep {
acc_reg: target_register,
col: expr_reg,
@@ -822,7 +828,7 @@ fn translate_aggregation(
} else {
let expr = &args[0];
let expr_reg = program.alloc_register();
let _ = translate_expr(program, select, expr, expr_reg, cursor_hint);
let _ = translate_expr(program, Some(select), expr, expr_reg, cursor_hint);
expr_reg
};
program.emit_insn(Insn::AggStep {
@@ -865,8 +871,14 @@ fn translate_aggregation(
ast::Expr::Literal(ast::Literal::String(String::from("\",\"")));
}
translate_expr(program, select, expr, expr_reg, cursor_hint)?;
translate_expr(program, select, &delimiter_expr, delimiter_reg, cursor_hint)?;
translate_expr(program, Some(select), expr, expr_reg, cursor_hint)?;
translate_expr(
program,
Some(select),
&delimiter_expr,
delimiter_reg,
cursor_hint,
)?;
program.emit_insn(Insn::AggStep {
acc_reg: target_register,
@@ -883,7 +895,7 @@ fn translate_aggregation(
}
let expr = &args[0];
let expr_reg = program.alloc_register();
let _ = translate_expr(program, select, expr, expr_reg, cursor_hint);
let _ = translate_expr(program, Some(select), expr, expr_reg, cursor_hint);
program.emit_insn(Insn::AggStep {
acc_reg: target_register,
col: expr_reg,
@@ -898,7 +910,7 @@ fn translate_aggregation(
}
let expr = &args[0];
let expr_reg = program.alloc_register();
let _ = translate_expr(program, select, expr, expr_reg, cursor_hint);
let _ = translate_expr(program, Some(select), expr, expr_reg, cursor_hint);
program.emit_insn(Insn::AggStep {
acc_reg: target_register,
col: expr_reg,
@@ -932,8 +944,14 @@ fn translate_aggregation(
_ => crate::bail_parse_error!("Incorrect delimiter parameter"),
};
translate_expr(program, select, expr, expr_reg, cursor_hint)?;
translate_expr(program, select, &delimiter_expr, delimiter_reg, cursor_hint)?;
translate_expr(program, Some(select), expr, expr_reg, cursor_hint)?;
translate_expr(
program,
Some(select),
&delimiter_expr,
delimiter_reg,
cursor_hint,
)?;
program.emit_insn(Insn::AggStep {
acc_reg: target_register,
@@ -950,7 +968,7 @@ fn translate_aggregation(
}
let expr = &args[0];
let expr_reg = program.alloc_register();
let _ = translate_expr(program, select, expr, expr_reg, cursor_hint)?;
let _ = translate_expr(program, Some(select), expr, expr_reg, cursor_hint)?;
program.emit_insn(Insn::AggStep {
acc_reg: target_register,
col: expr_reg,
@@ -965,7 +983,7 @@ fn translate_aggregation(
}
let expr = &args[0];
let expr_reg = program.alloc_register();
let _ = translate_expr(program, select, expr, expr_reg, cursor_hint)?;
let _ = translate_expr(program, Some(select), expr, expr_reg, cursor_hint)?;
program.emit_insn(Insn::AggStep {
acc_reg: target_register,
col: expr_reg,

View File

@@ -306,12 +306,12 @@ fn translate_condition_expr(
ast::Expr::Binary(lhs, op, rhs) => {
let lhs_reg = program.alloc_register();
let rhs_reg = program.alloc_register();
let _ = translate_expr(program, select, lhs, lhs_reg, cursor_hint);
let _ = translate_expr(program, Some(select), lhs, lhs_reg, cursor_hint);
match lhs.as_ref() {
ast::Expr::Literal(_) => program.mark_last_insn_constant(),
_ => {}
}
let _ = translate_expr(program, select, rhs, rhs_reg, cursor_hint);
let _ = translate_expr(program, Some(select), rhs, rhs_reg, cursor_hint);
match rhs.as_ref() {
ast::Expr::Literal(_) => program.mark_last_insn_constant(),
_ => {}
@@ -657,9 +657,9 @@ fn translate_condition_expr(
let pattern_reg = program.alloc_register();
let column_reg = program.alloc_register();
// LIKE(pattern, column). We should translate the pattern first before the column
let _ = translate_expr(program, select, rhs, pattern_reg, cursor_hint)?;
let _ = translate_expr(program, Some(select), rhs, pattern_reg, cursor_hint)?;
program.mark_last_insn_constant();
let _ = translate_expr(program, select, lhs, column_reg, cursor_hint)?;
let _ = translate_expr(program, Some(select), lhs, column_reg, cursor_hint)?;
program.emit_insn(Insn::Function {
func: ScalarFunc::Like,
start_reg: pattern_reg,