mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-15 13:04:20 +01:00
core: vbde coroutine generation with rowid insert
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user