refactor+fix: precompute default values from schema

This commit is contained in:
Levy A. 2025-05-23 20:10:01 -03:00
parent 7638b0dab7
commit 15e0cab8d8
13 changed files with 123 additions and 172 deletions

View file

@ -10,6 +10,7 @@ use tracing::{instrument, Level};
use crate::{
fast_lock::SpinLock,
numeric::Numeric,
parameters::Parameters,
schema::{BTreeTable, Index, PseudoTable, Table},
storage::sqlite3_ondisk::DatabaseHeader,
@ -18,7 +19,8 @@ use crate::{
emitter::TransactionMode,
plan::{ResultSetColumn, TableReferences},
},
Connection, VirtualTable,
types::Text,
Connection, Value, VirtualTable,
};
pub struct TableRefIdCounter {
next_free: TableInternalId,
@ -791,6 +793,58 @@ impl ProgramBuilder {
self.preassign_label_to_next_insn(loop_end);
}
pub fn emit_column(&mut self, cursor_id: CursorID, column: usize, out: usize) {
let (_, cursor_type) = self.cursor_ref.get(cursor_id).unwrap();
use crate::translate::expr::sanitize_string;
let default = 'value: {
let default = match cursor_type {
CursorType::BTreeTable(btree) => &btree.columns[column].default,
CursorType::BTreeIndex(index) => &index.columns[column].default,
_ => break 'value None,
};
let Some(default) = default else {
break 'value None;
};
let ast::Expr::Literal(ref literal) = default else {
panic!("column added by ALTER TABLE should be constant")
};
Some(match literal {
ast::Literal::Numeric(s) => match Numeric::from(s) {
Numeric::Null => Value::Null,
Numeric::Integer(v) => Value::Integer(v),
Numeric::Float(v) => Value::Float(v.into()),
},
ast::Literal::Null => Value::Null,
ast::Literal::String(s) => Value::Text(Text::from_str(sanitize_string(s))),
ast::Literal::Blob(s) => Value::Blob(
// Taken from `translate_expr`
s.as_bytes()
.chunks_exact(2)
.map(|pair| {
// We assume that sqlite3-parser has already validated that
// the input is valid hex string, thus unwrap is safe.
let hex_byte = std::str::from_utf8(pair).unwrap();
u8::from_str_radix(hex_byte, 16).unwrap()
})
.collect(),
),
_ => break 'value None,
})
};
self.emit_insn(Insn::Column {
cursor_id,
column,
dest: out,
default,
});
}
pub fn build(
mut self,
database_header: Arc<SpinLock<DatabaseHeader>>,