From 01da48fde946df425da32b0db61b371323cb255c Mon Sep 17 00:00:00 2001 From: TcMits Date: Sat, 13 Sep 2025 16:35:17 +0700 Subject: [PATCH 01/10] introduce instruction virtual table --- core/incremental/expr_compiler.rs | 3 +- core/storage/wal.rs | 3 +- core/vdbe/builder.rs | 33 ++- core/vdbe/insn.rs | 324 +++++++++++++++++------------- core/vdbe/mod.rs | 10 +- 5 files changed, 213 insertions(+), 160 deletions(-) diff --git a/core/incremental/expr_compiler.rs b/core/incremental/expr_compiler.rs index f94d72a2a..a022f2157 100644 --- a/core/incremental/expr_compiler.rs +++ b/core/incremental/expr_compiler.rs @@ -412,7 +412,8 @@ impl CompiledExpression { // Execute the program let mut pc = 0usize; while pc < program.insns.len() { - let (insn, insn_fn) = &program.insns[pc]; + let (insn, _) = &program.insns[pc]; + let insn_fn = insn.to_function_fast(); state.pc = pc as u32; // Execute the instruction diff --git a/core/storage/wal.rs b/core/storage/wal.rs index 8fbf8eaa2..d4361c340 100644 --- a/core/storage/wal.rs +++ b/core/storage/wal.rs @@ -64,7 +64,7 @@ impl CheckpointResult { } } -#[derive(Debug, Copy, Clone, EnumString)] +#[derive(Debug, Copy, Clone, Default, EnumString)] #[strum(ascii_case_insensitive)] pub enum CheckpointMode { /// Checkpoint as many frames as possible without waiting for any database readers or writers to finish, then sync the database file if all frames in the log were checkpointed. @@ -73,6 +73,7 @@ pub enum CheckpointMode { /// Optional upper_bound_inclusive parameter can be set in order to checkpoint frames with number no larger than the parameter Passive { upper_bound_inclusive: Option }, /// This mode blocks until there is no database writer and all readers are reading from the most recent database snapshot. It then checkpoints all frames in the log file and syncs the database file. This mode blocks new database writers while it is pending, but new database readers are allowed to continue unimpeded. + #[default] Full, /// This mode works the same way as `Full` with the addition that after checkpointing the log file it blocks (calls the busy-handler callback) until all readers are reading from the database file only. This ensures that the next writer will restart the log file from the beginning. Like `Full`, this mode blocks new database writer attempts while it is pending, but does not impede readers. Restart, diff --git a/core/vdbe/builder.rs b/core/vdbe/builder.rs index 2a3711059..4ea0b283e 100644 --- a/core/vdbe/builder.rs +++ b/core/vdbe/builder.rs @@ -34,7 +34,7 @@ impl TableRefIdCounter { } } -use super::{BranchOffset, CursorID, Insn, InsnFunction, InsnReference, JumpTarget, Program}; +use super::{BranchOffset, CursorID, Insn, InsnReference, JumpTarget, Program}; /// A key that uniquely identifies a cursor. /// The key is a pair of table reference id and index. @@ -85,7 +85,7 @@ pub struct ProgramBuilder { next_free_register: usize, next_free_cursor_id: usize, /// Instruction, the function to execute it with, and its original index in the vector. - insns: Vec<(Insn, InsnFunction, usize)>, + insns: Vec<(Insn, usize)>, /// A span of instructions from (offset_start_inclusive, offset_end_exclusive), /// that are deemed to be compile-time constant and can be hoisted out of loops /// so that they get evaluated only once at the start of the program. @@ -328,10 +328,9 @@ impl ProgramBuilder { #[instrument(skip(self), level = Level::DEBUG)] pub fn emit_insn(&mut self, insn: Insn) { - let function = insn.to_function(); // This seemingly empty trace here is needed so that a function span is emmited with it tracing::trace!(""); - self.insns.push((insn, function, self.insns.len())); + self.insns.push((insn, self.insns.len())); } pub fn close_cursors(&mut self, cursors: &[CursorID]) { @@ -419,7 +418,7 @@ impl ProgramBuilder { pub fn pop_current_parent_explain(&mut self) { if let QueryMode::ExplainQueryPlan = self.query_mode { if let Some(current) = self.current_parent_explain_idx { - let (Insn::Explain { p2, .. }, _, _) = &self.insns[current] else { + let (Insn::Explain { p2, .. }, _) = &self.insns[current] else { unreachable!("current_parent_explain_idx must point to an Explain insn"); }; self.current_parent_explain_idx = *p2; @@ -447,7 +446,7 @@ impl ProgramBuilder { // 1. if insn not in any constant span, it stays where it is // 2. if insn is in a constant span, it is after other insns, except those that are in a later constant span // 3. within a single constant span the order is preserver - self.insns.sort_by(|(_, _, index_a), (_, _, index_b)| { + self.insns.sort_by(|(_, index_a), (_, index_b)| { let a_span = self .constant_spans .iter() @@ -471,7 +470,7 @@ impl ProgramBuilder { let new_offset = self .insns .iter() - .position(|(_, _, index)| *old_offset == *index as u32) + .position(|(_, index)| *old_offset == *index as u32) .unwrap() as u32; *resolved_offset = Some((new_offset, *target)); } @@ -482,7 +481,7 @@ impl ProgramBuilder { let new_offset = self .insns .iter() - .position(|(_, _, index)| *old_offset == *index as u32) + .position(|(_, index)| *old_offset == *index as u32) .expect("comment must exist") as u32; *old_offset = new_offset; } @@ -492,25 +491,23 @@ impl ProgramBuilder { if let Some(old_parent) = self.current_parent_explain_idx { self.insns .iter() - .position(|(_, _, index)| old_parent == *index) + .position(|(_, index)| old_parent == *index) } else { None }; for i in 0..self.insns.len() { - let (Insn::Explain { p2, .. }, _, _) = &self.insns[i] else { + let (Insn::Explain { p2, .. }, _) = &self.insns[i] else { continue; }; let new_p2 = if p2.is_some() { - self.insns - .iter() - .position(|(_, _, index)| *p2 == Some(*index)) + self.insns.iter().position(|(_, index)| *p2 == Some(*index)) } else { None }; - let (Insn::Explain { p1, p2, .. }, _, _) = &mut self.insns[i] else { + let (Insn::Explain { p1, p2, .. }, _) = &mut self.insns[i] else { unreachable!(); }; @@ -591,7 +588,7 @@ impl ProgramBuilder { ); } }; - for (insn, _, _) in self.insns.iter_mut() { + for (insn, _) in self.insns.iter_mut() { match insn { Insn::Init { target_pc } => { resolve(target_pc, "Init"); @@ -997,11 +994,7 @@ impl ProgramBuilder { self.parameters.list.dedup(); Program { max_registers: self.next_free_register, - insns: self - .insns - .into_iter() - .map(|(insn, function, _)| (insn, function)) - .collect(), + insns: self.insns, cursor_ref: self.cursor_ref, comments: self.comments, connection, diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index d9b86a513..601e2ef81 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -10,6 +10,10 @@ use crate::{ translate::{collate::CollationSeq, emitter::TransactionMode}, Value, }; +use std::sync::LazyLock; +use strum::EnumCount; +use strum::VariantArray as _; +use strum_macros::{EnumDiscriminants, VariantArray}; use turso_macros::Description; use turso_parser::ast::SortOrder; @@ -150,7 +154,11 @@ impl std::fmt::Display for RegisterOrLiteral { } } -#[derive(Description, Debug)] +#[derive(Description, Debug, EnumDiscriminants)] +#[strum_discriminants(vis(pub(crate)))] +#[strum_discriminants(derive(VariantArray, EnumCount))] +#[strum_discriminants(repr(u8))] +#[strum_discriminants(name(InsnVariants))] pub enum Insn { /// Initialize the program state and jump to the given PC. Init { @@ -1095,147 +1103,175 @@ pub enum Insn { }, } -impl Insn { - pub fn to_function(&self) -> InsnFunction { +static INSN_VIRTUAL_TABLE: LazyLock<[InsnFunction; InsnVariants::COUNT]> = LazyLock::new(|| { + let mut result: [InsnFunction; InsnVariants::COUNT] = [execute::op_null; InsnVariants::COUNT]; + + for variant in InsnVariants::VARIANTS { + result[*variant as u8 as usize] = variant.to_function(); + } + + result +}); + +impl InsnVariants { + pub(crate) fn to_function_fast(&self) -> InsnFunction { + INSN_VIRTUAL_TABLE[*self as u8 as usize] + } + + pub(crate) fn to_function(&self) -> InsnFunction { match self { - Insn::Init { .. } => execute::op_init, - Insn::Null { .. } => execute::op_null, - Insn::BeginSubrtn { .. } => execute::op_null, - Insn::NullRow { .. } => execute::op_null_row, - Insn::Add { .. } => execute::op_add, - Insn::Subtract { .. } => execute::op_subtract, - Insn::Multiply { .. } => execute::op_multiply, - Insn::Divide { .. } => execute::op_divide, - Insn::DropIndex { .. } => execute::op_drop_index, - Insn::Compare { .. } => execute::op_compare, - Insn::BitAnd { .. } => execute::op_bit_and, - Insn::BitOr { .. } => execute::op_bit_or, - Insn::BitNot { .. } => execute::op_bit_not, - Insn::Checkpoint { .. } => execute::op_checkpoint, - Insn::Remainder { .. } => execute::op_remainder, - Insn::Jump { .. } => execute::op_jump, - Insn::Move { .. } => execute::op_move, - Insn::IfPos { .. } => execute::op_if_pos, - Insn::NotNull { .. } => execute::op_not_null, - Insn::Eq { .. } - | Insn::Ne { .. } - | Insn::Lt { .. } - | Insn::Le { .. } - | Insn::Gt { .. } - | Insn::Ge { .. } => execute::op_comparison, - Insn::If { .. } => execute::op_if, - Insn::IfNot { .. } => execute::op_if_not, - Insn::OpenRead { .. } => execute::op_open_read, - Insn::VOpen { .. } => execute::op_vopen, - Insn::VCreate { .. } => execute::op_vcreate, - Insn::VFilter { .. } => execute::op_vfilter, - Insn::VColumn { .. } => execute::op_vcolumn, - Insn::VUpdate { .. } => execute::op_vupdate, - Insn::VNext { .. } => execute::op_vnext, - Insn::VDestroy { .. } => execute::op_vdestroy, + InsnVariants::Init { .. } => execute::op_init, + InsnVariants::Null { .. } => execute::op_null, + InsnVariants::BeginSubrtn { .. } => execute::op_null, + InsnVariants::NullRow { .. } => execute::op_null_row, + InsnVariants::Add { .. } => execute::op_add, + InsnVariants::Subtract { .. } => execute::op_subtract, + InsnVariants::Multiply { .. } => execute::op_multiply, + InsnVariants::Divide { .. } => execute::op_divide, + InsnVariants::DropIndex { .. } => execute::op_drop_index, + InsnVariants::Compare { .. } => execute::op_compare, + InsnVariants::BitAnd { .. } => execute::op_bit_and, + InsnVariants::BitOr { .. } => execute::op_bit_or, + InsnVariants::BitNot { .. } => execute::op_bit_not, + InsnVariants::Checkpoint { .. } => execute::op_checkpoint, + InsnVariants::Remainder { .. } => execute::op_remainder, + InsnVariants::Jump { .. } => execute::op_jump, + InsnVariants::Move { .. } => execute::op_move, + InsnVariants::IfPos { .. } => execute::op_if_pos, + InsnVariants::NotNull { .. } => execute::op_not_null, + InsnVariants::Eq { .. } + | InsnVariants::Ne { .. } + | InsnVariants::Lt { .. } + | InsnVariants::Le { .. } + | InsnVariants::Gt { .. } + | InsnVariants::Ge { .. } => execute::op_comparison, + InsnVariants::If { .. } => execute::op_if, + InsnVariants::IfNot { .. } => execute::op_if_not, + InsnVariants::OpenRead { .. } => execute::op_open_read, + InsnVariants::VOpen { .. } => execute::op_vopen, + InsnVariants::VCreate { .. } => execute::op_vcreate, + InsnVariants::VFilter { .. } => execute::op_vfilter, + InsnVariants::VColumn { .. } => execute::op_vcolumn, + InsnVariants::VUpdate { .. } => execute::op_vupdate, + InsnVariants::VNext { .. } => execute::op_vnext, + InsnVariants::VDestroy { .. } => execute::op_vdestroy, - Insn::OpenPseudo { .. } => execute::op_open_pseudo, - Insn::Rewind { .. } => execute::op_rewind, - Insn::Last { .. } => execute::op_last, - Insn::Column { .. } => execute::op_column, - Insn::TypeCheck { .. } => execute::op_type_check, - Insn::MakeRecord { .. } => execute::op_make_record, - Insn::ResultRow { .. } => execute::op_result_row, - Insn::Next { .. } => execute::op_next, - Insn::Prev { .. } => execute::op_prev, - Insn::Halt { .. } => execute::op_halt, - Insn::HaltIfNull { .. } => execute::op_halt_if_null, - Insn::Transaction { .. } => execute::op_transaction, - Insn::AutoCommit { .. } => execute::op_auto_commit, - Insn::Goto { .. } => execute::op_goto, - Insn::Gosub { .. } => execute::op_gosub, - Insn::Return { .. } => execute::op_return, - Insn::Integer { .. } => execute::op_integer, - Insn::Real { .. } => execute::op_real, - Insn::RealAffinity { .. } => execute::op_real_affinity, - Insn::String8 { .. } => execute::op_string8, - Insn::Blob { .. } => execute::op_blob, - Insn::RowData { .. } => execute::op_row_data, - Insn::RowId { .. } => execute::op_row_id, - Insn::IdxRowId { .. } => execute::op_idx_row_id, - Insn::SeekRowid { .. } => execute::op_seek_rowid, - Insn::DeferredSeek { .. } => execute::op_deferred_seek, - Insn::SeekGE { .. } - | Insn::SeekGT { .. } - | Insn::SeekLE { .. } - | Insn::SeekLT { .. } => execute::op_seek, - Insn::SeekEnd { .. } => execute::op_seek_end, - Insn::IdxGE { .. } => execute::op_idx_ge, - Insn::IdxGT { .. } => execute::op_idx_gt, - Insn::IdxLE { .. } => execute::op_idx_le, - Insn::IdxLT { .. } => execute::op_idx_lt, - Insn::DecrJumpZero { .. } => execute::op_decr_jump_zero, - Insn::AggStep { .. } => execute::op_agg_step, - Insn::AggFinal { .. } => execute::op_agg_final, - Insn::SorterOpen { .. } => execute::op_sorter_open, - Insn::SorterInsert { .. } => execute::op_sorter_insert, - Insn::SorterSort { .. } => execute::op_sorter_sort, - Insn::SorterData { .. } => execute::op_sorter_data, - Insn::SorterNext { .. } => execute::op_sorter_next, - Insn::Function { .. } => execute::op_function, - Insn::Cast { .. } => execute::op_cast, - Insn::InitCoroutine { .. } => execute::op_init_coroutine, - Insn::EndCoroutine { .. } => execute::op_end_coroutine, - Insn::Yield { .. } => execute::op_yield, - Insn::Insert { .. } => execute::op_insert, - Insn::Int64 { .. } => execute::op_int_64, - Insn::IdxInsert { .. } => execute::op_idx_insert, - Insn::Delete { .. } => execute::op_delete, - Insn::NewRowid { .. } => execute::op_new_rowid, - Insn::MustBeInt { .. } => execute::op_must_be_int, - Insn::SoftNull { .. } => execute::op_soft_null, - Insn::NoConflict { .. } => execute::op_no_conflict, - Insn::NotExists { .. } => execute::op_not_exists, - Insn::OffsetLimit { .. } => execute::op_offset_limit, - Insn::OpenWrite { .. } => execute::op_open_write, - Insn::Copy { .. } => execute::op_copy, - Insn::CreateBtree { .. } => execute::op_create_btree, - Insn::Destroy { .. } => execute::op_destroy, + InsnVariants::OpenPseudo { .. } => execute::op_open_pseudo, + InsnVariants::Rewind { .. } => execute::op_rewind, + InsnVariants::Last { .. } => execute::op_last, + InsnVariants::Column { .. } => execute::op_column, + InsnVariants::TypeCheck { .. } => execute::op_type_check, + InsnVariants::MakeRecord { .. } => execute::op_make_record, + InsnVariants::ResultRow { .. } => execute::op_result_row, + InsnVariants::Next { .. } => execute::op_next, + InsnVariants::Prev { .. } => execute::op_prev, + InsnVariants::Halt { .. } => execute::op_halt, + InsnVariants::HaltIfNull { .. } => execute::op_halt_if_null, + InsnVariants::Transaction { .. } => execute::op_transaction, + InsnVariants::AutoCommit { .. } => execute::op_auto_commit, + InsnVariants::Goto { .. } => execute::op_goto, + InsnVariants::Gosub { .. } => execute::op_gosub, + InsnVariants::Return { .. } => execute::op_return, + InsnVariants::Integer { .. } => execute::op_integer, + InsnVariants::Real { .. } => execute::op_real, + InsnVariants::RealAffinity { .. } => execute::op_real_affinity, + InsnVariants::String8 { .. } => execute::op_string8, + InsnVariants::Blob { .. } => execute::op_blob, + InsnVariants::RowData { .. } => execute::op_row_data, + InsnVariants::RowId { .. } => execute::op_row_id, + InsnVariants::IdxRowId { .. } => execute::op_idx_row_id, + InsnVariants::SeekRowid { .. } => execute::op_seek_rowid, + InsnVariants::DeferredSeek { .. } => execute::op_deferred_seek, + InsnVariants::SeekGE { .. } + | InsnVariants::SeekGT { .. } + | InsnVariants::SeekLE { .. } + | InsnVariants::SeekLT { .. } => execute::op_seek, + InsnVariants::SeekEnd { .. } => execute::op_seek_end, + InsnVariants::IdxGE { .. } => execute::op_idx_ge, + InsnVariants::IdxGT { .. } => execute::op_idx_gt, + InsnVariants::IdxLE { .. } => execute::op_idx_le, + InsnVariants::IdxLT { .. } => execute::op_idx_lt, + InsnVariants::DecrJumpZero { .. } => execute::op_decr_jump_zero, + InsnVariants::AggStep { .. } => execute::op_agg_step, + InsnVariants::AggFinal { .. } => execute::op_agg_final, + InsnVariants::SorterOpen { .. } => execute::op_sorter_open, + InsnVariants::SorterInsert { .. } => execute::op_sorter_insert, + InsnVariants::SorterSort { .. } => execute::op_sorter_sort, + InsnVariants::SorterData { .. } => execute::op_sorter_data, + InsnVariants::SorterNext { .. } => execute::op_sorter_next, + InsnVariants::Function { .. } => execute::op_function, + InsnVariants::Cast { .. } => execute::op_cast, + InsnVariants::InitCoroutine { .. } => execute::op_init_coroutine, + InsnVariants::EndCoroutine { .. } => execute::op_end_coroutine, + InsnVariants::Yield { .. } => execute::op_yield, + InsnVariants::Insert { .. } => execute::op_insert, + InsnVariants::Int64 { .. } => execute::op_int_64, + InsnVariants::IdxInsert { .. } => execute::op_idx_insert, + InsnVariants::Delete { .. } => execute::op_delete, + InsnVariants::NewRowid { .. } => execute::op_new_rowid, + InsnVariants::MustBeInt { .. } => execute::op_must_be_int, + InsnVariants::SoftNull { .. } => execute::op_soft_null, + InsnVariants::NoConflict { .. } => execute::op_no_conflict, + InsnVariants::NotExists { .. } => execute::op_not_exists, + InsnVariants::OffsetLimit { .. } => execute::op_offset_limit, + InsnVariants::OpenWrite { .. } => execute::op_open_write, + InsnVariants::Copy { .. } => execute::op_copy, + InsnVariants::CreateBtree { .. } => execute::op_create_btree, + InsnVariants::Destroy { .. } => execute::op_destroy, - Insn::DropTable { .. } => execute::op_drop_table, - Insn::DropView { .. } => execute::op_drop_view, - Insn::Close { .. } => execute::op_close, - Insn::IsNull { .. } => execute::op_is_null, - Insn::CollSeq { .. } => execute::op_coll_seq, - Insn::ParseSchema { .. } => execute::op_parse_schema, - Insn::PopulateMaterializedViews { .. } => execute::op_populate_materialized_views, - Insn::ShiftRight { .. } => execute::op_shift_right, - Insn::ShiftLeft { .. } => execute::op_shift_left, - Insn::AddImm { .. } => execute::op_add_imm, - Insn::Variable { .. } => execute::op_variable, - Insn::ZeroOrNull { .. } => execute::op_zero_or_null, - Insn::Not { .. } => execute::op_not, - Insn::Concat { .. } => execute::op_concat, - Insn::And { .. } => execute::op_and, - Insn::Or { .. } => execute::op_or, - Insn::Noop => execute::op_noop, - Insn::PageCount { .. } => execute::op_page_count, - Insn::ReadCookie { .. } => execute::op_read_cookie, - Insn::SetCookie { .. } => execute::op_set_cookie, - Insn::OpenEphemeral { .. } | Insn::OpenAutoindex { .. } => execute::op_open_ephemeral, - Insn::Once { .. } => execute::op_once, - Insn::Found { .. } | Insn::NotFound { .. } => execute::op_found, - Insn::Affinity { .. } => execute::op_affinity, - Insn::IdxDelete { .. } => execute::op_idx_delete, - Insn::Count { .. } => execute::op_count, - Insn::IntegrityCk { .. } => execute::op_integrity_check, - Insn::RenameTable { .. } => execute::op_rename_table, - Insn::DropColumn { .. } => execute::op_drop_column, - Insn::AddColumn { .. } => execute::op_add_column, - Insn::AlterColumn { .. } => execute::op_alter_column, - Insn::MaxPgcnt { .. } => execute::op_max_pgcnt, - Insn::JournalMode { .. } => execute::op_journal_mode, - Insn::IfNeg { .. } => execute::op_if_neg, - Insn::Explain { .. } => execute::op_noop, + InsnVariants::DropTable { .. } => execute::op_drop_table, + InsnVariants::DropView { .. } => execute::op_drop_view, + InsnVariants::Close { .. } => execute::op_close, + InsnVariants::IsNull { .. } => execute::op_is_null, + InsnVariants::CollSeq { .. } => execute::op_coll_seq, + InsnVariants::ParseSchema { .. } => execute::op_parse_schema, + InsnVariants::PopulateMaterializedViews { .. } => { + execute::op_populate_materialized_views + } + InsnVariants::ShiftRight { .. } => execute::op_shift_right, + InsnVariants::ShiftLeft { .. } => execute::op_shift_left, + InsnVariants::AddImm { .. } => execute::op_add_imm, + InsnVariants::Variable { .. } => execute::op_variable, + InsnVariants::ZeroOrNull { .. } => execute::op_zero_or_null, + InsnVariants::Not { .. } => execute::op_not, + InsnVariants::Concat { .. } => execute::op_concat, + InsnVariants::And { .. } => execute::op_and, + InsnVariants::Or { .. } => execute::op_or, + InsnVariants::Noop => execute::op_noop, + InsnVariants::PageCount { .. } => execute::op_page_count, + InsnVariants::ReadCookie { .. } => execute::op_read_cookie, + InsnVariants::SetCookie { .. } => execute::op_set_cookie, + InsnVariants::OpenEphemeral { .. } | InsnVariants::OpenAutoindex { .. } => { + execute::op_open_ephemeral + } + InsnVariants::Once { .. } => execute::op_once, + InsnVariants::Found { .. } | InsnVariants::NotFound { .. } => execute::op_found, + InsnVariants::Affinity { .. } => execute::op_affinity, + InsnVariants::IdxDelete { .. } => execute::op_idx_delete, + InsnVariants::Count { .. } => execute::op_count, + InsnVariants::IntegrityCk { .. } => execute::op_integrity_check, + InsnVariants::RenameTable { .. } => execute::op_rename_table, + InsnVariants::DropColumn { .. } => execute::op_drop_column, + InsnVariants::AddColumn { .. } => execute::op_add_column, + InsnVariants::AlterColumn { .. } => execute::op_alter_column, + InsnVariants::MaxPgcnt { .. } => execute::op_max_pgcnt, + InsnVariants::JournalMode { .. } => execute::op_journal_mode, + InsnVariants::IfNeg { .. } => execute::op_if_neg, + InsnVariants::Explain { .. } => execute::op_noop, } } } +impl Insn { + pub fn to_function_fast(&self) -> InsnFunction { + InsnVariants::from(self).to_function_fast() + } + + pub fn to_function(&self) -> InsnFunction { + InsnVariants::from(self).to_function() + } +} + // TODO: Add remaining cookies. #[derive(Description, Debug, Clone, Copy)] pub enum Cookie { @@ -1256,3 +1292,21 @@ pub enum Cookie { /// The application ID as set by the application_id pragma. ApplicationId = 8, } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_make_sure_correct_insn_table() { + for variant in super::InsnVariants::VARIANTS { + let func1 = variant.to_function(); + let func2 = variant.to_function_fast(); + assert_eq!( + func1 as usize, func2 as usize, + "Variant {:?} does not match in fast table", + variant + ); + } + } +} diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs index 52b7bf080..78ee74519 100644 --- a/core/vdbe/mod.rs +++ b/core/vdbe/mod.rs @@ -96,7 +96,7 @@ pub enum JumpTarget { AfterThisInsn, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] /// Represents a target for a jump instruction. /// Stores 32-bit ints to keep the enum word-sized. pub enum BranchOffset { @@ -108,6 +108,7 @@ pub enum BranchOffset { Offset(InsnReference), /// A placeholder is a temporary value to satisfy the compiler. /// It must be set later. + #[default] Placeholder, } @@ -475,7 +476,9 @@ macro_rules! get_cursor { pub struct Program { pub max_registers: usize, - pub insns: Vec<(Insn, InsnFunction)>, + // we store original indices because we don't want to create new vec from + // ProgramBuilder + pub insns: Vec<(Insn, usize)>, pub cursor_ref: Vec<(Option, CursorType)>, pub comments: Vec<(InsnReference, &'static str)>, pub parameters: crate::parameters::Parameters, @@ -644,7 +647,8 @@ impl Program { } // invalidate row let _ = state.result_row.take(); - let (insn, insn_function) = &self.insns[state.pc as usize]; + let (insn, _) = &self.insns[state.pc as usize]; + let insn_function = insn.to_function_fast(); if enable_tracing { trace_insn(self, state.pc as InsnReference, insn); } From 17ee9795838c73be40bd5441191bbda280030a1e Mon Sep 17 00:00:00 2001 From: TcMits Date: Sat, 13 Sep 2025 16:35:58 +0700 Subject: [PATCH 02/10] fix macro --- macros/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 4269ffd1c..1cefb64c5 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -42,6 +42,10 @@ pub fn derive_description_from_doc(item: TokenStream) -> TokenStream { TokenTree::Ident(ident) => { // Capture the enum variant name and associate it with its description let ident_str = ident.to_string(); + // this is a quick fix for derive(EnumDiscriminants) + if ident_str == "strum_discriminants" { + continue; + } if let Some(desc) = &last_seen_desc { variant_description_map.insert(ident_str.clone(), desc.clone()); } From e18b6b0b566b27e4efaf4d91ace1f45eb55c9ca6 Mon Sep 17 00:00:00 2001 From: TcMits Date: Sat, 13 Sep 2025 18:07:45 +0700 Subject: [PATCH 03/10] inline --- core/vdbe/insn.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index 601e2ef81..926453f00 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -157,7 +157,7 @@ impl std::fmt::Display for RegisterOrLiteral { #[derive(Description, Debug, EnumDiscriminants)] #[strum_discriminants(vis(pub(crate)))] #[strum_discriminants(derive(VariantArray, EnumCount))] -#[strum_discriminants(repr(u8))] +#[strum_discriminants(repr(usize))] #[strum_discriminants(name(InsnVariants))] pub enum Insn { /// Initialize the program state and jump to the given PC. @@ -1107,15 +1107,16 @@ static INSN_VIRTUAL_TABLE: LazyLock<[InsnFunction; InsnVariants::COUNT]> = LazyL let mut result: [InsnFunction; InsnVariants::COUNT] = [execute::op_null; InsnVariants::COUNT]; for variant in InsnVariants::VARIANTS { - result[*variant as u8 as usize] = variant.to_function(); + result[*variant as usize] = variant.to_function(); } result }); impl InsnVariants { + #[inline(always)] pub(crate) fn to_function_fast(&self) -> InsnFunction { - INSN_VIRTUAL_TABLE[*self as u8 as usize] + INSN_VIRTUAL_TABLE[*self as usize] } pub(crate) fn to_function(&self) -> InsnFunction { @@ -1263,6 +1264,7 @@ impl InsnVariants { } impl Insn { + #[inline(always)] pub fn to_function_fast(&self) -> InsnFunction { InsnVariants::from(self).to_function_fast() } From cab0c7b5450fd6bcc130de55278f6c851bba2645 Mon Sep 17 00:00:00 2001 From: TcMits Date: Sun, 14 Sep 2025 18:53:53 +0700 Subject: [PATCH 04/10] peft tuning --- core/incremental/expr_compiler.rs | 2 +- core/vdbe/insn.rs | 48 +++++++++++++++++++------------ core/vdbe/mod.rs | 2 +- macros/src/lib.rs | 6 ++++ 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/core/incremental/expr_compiler.rs b/core/incremental/expr_compiler.rs index a022f2157..9407e2db9 100644 --- a/core/incremental/expr_compiler.rs +++ b/core/incremental/expr_compiler.rs @@ -413,7 +413,7 @@ impl CompiledExpression { let mut pc = 0usize; while pc < program.insns.len() { let (insn, _) = &program.insns[pc]; - let insn_fn = insn.to_function_fast(); + let insn_fn = insn.to_function(); state.pc = pc as u32; // Execute the instruction diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index 926453f00..1cb83bd2c 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -10,10 +10,8 @@ use crate::{ translate::{collate::CollationSeq, emitter::TransactionMode}, Value, }; -use std::sync::LazyLock; use strum::EnumCount; -use strum::VariantArray as _; -use strum_macros::{EnumDiscriminants, VariantArray}; +use strum_macros::{EnumDiscriminants, FromRepr, VariantArray}; use turso_macros::Description; use turso_parser::ast::SortOrder; @@ -154,10 +152,11 @@ impl std::fmt::Display for RegisterOrLiteral { } } +// There are currently 190 opcodes in sqlite +#[repr(u8)] #[derive(Description, Debug, EnumDiscriminants)] #[strum_discriminants(vis(pub(crate)))] -#[strum_discriminants(derive(VariantArray, EnumCount))] -#[strum_discriminants(repr(usize))] +#[strum_discriminants(derive(VariantArray, EnumCount, FromRepr))] #[strum_discriminants(name(InsnVariants))] pub enum Insn { /// Initialize the program state and jump to the given PC. @@ -1103,23 +1102,31 @@ pub enum Insn { }, } -static INSN_VIRTUAL_TABLE: LazyLock<[InsnFunction; InsnVariants::COUNT]> = LazyLock::new(|| { - let mut result: [InsnFunction; InsnVariants::COUNT] = [execute::op_null; InsnVariants::COUNT]; +const fn get_insn_virtual_table() -> [InsnFunction; InsnVariants::COUNT] { + let mut result: [InsnFunction; InsnVariants::COUNT] = [execute::op_init; InsnVariants::COUNT]; - for variant in InsnVariants::VARIANTS { - result[*variant as usize] = variant.to_function(); + let mut insn = 0; + while insn < InsnVariants::COUNT { + result[insn] = InsnVariants::from_repr(insn as u8).unwrap().to_function(); + insn += 1; } result -}); +} + +static INSN_VIRTUAL_TABLE: [InsnFunction; InsnVariants::COUNT] = get_insn_virtual_table(); impl InsnVariants { + // This function is used for testing + #[allow(dead_code)] #[inline(always)] - pub(crate) fn to_function_fast(&self) -> InsnFunction { + pub(crate) const fn to_function_fast(&self) -> InsnFunction { INSN_VIRTUAL_TABLE[*self as usize] } - pub(crate) fn to_function(&self) -> InsnFunction { + // This function is used for generating the virtual table. + // We need to keep this function to make sure we implement all opcodes + pub(crate) const fn to_function(&self) -> InsnFunction { match self { InsnVariants::Init { .. } => execute::op_init, InsnVariants::Null { .. } => execute::op_null, @@ -1264,13 +1271,18 @@ impl InsnVariants { } impl Insn { + // SAFETY: If the enumeration specifies a primitive representation, + // then the discriminant may be reliably accessed via unsafe pointer casting #[inline(always)] - pub fn to_function_fast(&self) -> InsnFunction { - InsnVariants::from(self).to_function_fast() + fn discriminant(&self) -> u8 { + unsafe { *(self as *const Self as *const u8) } } + #[inline(always)] pub fn to_function(&self) -> InsnFunction { - InsnVariants::from(self).to_function() + // dont use this because its still using match + // InsnVariants::from(self).to_function_fast() + INSN_VIRTUAL_TABLE[self.discriminant() as usize] } } @@ -1297,7 +1309,7 @@ pub enum Cookie { #[cfg(test)] mod tests { - use super::*; + use strum::VariantArray; #[test] fn test_make_sure_correct_insn_table() { @@ -1306,8 +1318,8 @@ mod tests { let func2 = variant.to_function_fast(); assert_eq!( func1 as usize, func2 as usize, - "Variant {:?} does not match in fast table", - variant + "Variant {:?} does not match in fast table at index {}", + variant, *variant as usize ); } } diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs index 78ee74519..a827e13db 100644 --- a/core/vdbe/mod.rs +++ b/core/vdbe/mod.rs @@ -648,7 +648,7 @@ impl Program { // invalidate row let _ = state.result_row.take(); let (insn, _) = &self.insns[state.pc as usize]; - let insn_function = insn.to_function_fast(); + let insn_function = insn.to_function(); if enable_tracing { trace_insn(self, state.pc as InsnReference, insn); } diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 1cefb64c5..716c289f7 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -46,6 +46,12 @@ pub fn derive_description_from_doc(item: TokenStream) -> TokenStream { if ident_str == "strum_discriminants" { continue; } + + // this is a quick fix for + if ident_str == "repr" { + continue; + } + if let Some(desc) = &last_seen_desc { variant_description_map.insert(ident_str.clone(), desc.clone()); } From a658273c63b556e8d73137b11d1affe436ed5510 Mon Sep 17 00:00:00 2001 From: TcMits Date: Sun, 14 Sep 2025 18:59:57 +0700 Subject: [PATCH 05/10] fmt --- core/vdbe/insn.rs | 272 +++++++++++++++++++++++----------------------- macros/src/lib.rs | 2 +- 2 files changed, 135 insertions(+), 139 deletions(-) diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index 1cb83bd2c..82a92968e 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -1120,152 +1120,148 @@ impl InsnVariants { // This function is used for testing #[allow(dead_code)] #[inline(always)] - pub(crate) const fn to_function_fast(&self) -> InsnFunction { - INSN_VIRTUAL_TABLE[*self as usize] + pub(crate) const fn to_function_fast(self) -> InsnFunction { + INSN_VIRTUAL_TABLE[self as usize] } // This function is used for generating the virtual table. // We need to keep this function to make sure we implement all opcodes - pub(crate) const fn to_function(&self) -> InsnFunction { + pub(crate) const fn to_function(self) -> InsnFunction { match self { - InsnVariants::Init { .. } => execute::op_init, - InsnVariants::Null { .. } => execute::op_null, - InsnVariants::BeginSubrtn { .. } => execute::op_null, - InsnVariants::NullRow { .. } => execute::op_null_row, - InsnVariants::Add { .. } => execute::op_add, - InsnVariants::Subtract { .. } => execute::op_subtract, - InsnVariants::Multiply { .. } => execute::op_multiply, - InsnVariants::Divide { .. } => execute::op_divide, - InsnVariants::DropIndex { .. } => execute::op_drop_index, - InsnVariants::Compare { .. } => execute::op_compare, - InsnVariants::BitAnd { .. } => execute::op_bit_and, - InsnVariants::BitOr { .. } => execute::op_bit_or, - InsnVariants::BitNot { .. } => execute::op_bit_not, - InsnVariants::Checkpoint { .. } => execute::op_checkpoint, - InsnVariants::Remainder { .. } => execute::op_remainder, - InsnVariants::Jump { .. } => execute::op_jump, - InsnVariants::Move { .. } => execute::op_move, - InsnVariants::IfPos { .. } => execute::op_if_pos, - InsnVariants::NotNull { .. } => execute::op_not_null, - InsnVariants::Eq { .. } - | InsnVariants::Ne { .. } - | InsnVariants::Lt { .. } - | InsnVariants::Le { .. } - | InsnVariants::Gt { .. } - | InsnVariants::Ge { .. } => execute::op_comparison, - InsnVariants::If { .. } => execute::op_if, - InsnVariants::IfNot { .. } => execute::op_if_not, - InsnVariants::OpenRead { .. } => execute::op_open_read, - InsnVariants::VOpen { .. } => execute::op_vopen, - InsnVariants::VCreate { .. } => execute::op_vcreate, - InsnVariants::VFilter { .. } => execute::op_vfilter, - InsnVariants::VColumn { .. } => execute::op_vcolumn, - InsnVariants::VUpdate { .. } => execute::op_vupdate, - InsnVariants::VNext { .. } => execute::op_vnext, - InsnVariants::VDestroy { .. } => execute::op_vdestroy, + InsnVariants::Init => execute::op_init, + InsnVariants::Null => execute::op_null, + InsnVariants::BeginSubrtn => execute::op_null, + InsnVariants::NullRow => execute::op_null_row, + InsnVariants::Add => execute::op_add, + InsnVariants::Subtract => execute::op_subtract, + InsnVariants::Multiply => execute::op_multiply, + InsnVariants::Divide => execute::op_divide, + InsnVariants::DropIndex => execute::op_drop_index, + InsnVariants::Compare => execute::op_compare, + InsnVariants::BitAnd => execute::op_bit_and, + InsnVariants::BitOr => execute::op_bit_or, + InsnVariants::BitNot => execute::op_bit_not, + InsnVariants::Checkpoint => execute::op_checkpoint, + InsnVariants::Remainder => execute::op_remainder, + InsnVariants::Jump => execute::op_jump, + InsnVariants::Move => execute::op_move, + InsnVariants::IfPos => execute::op_if_pos, + InsnVariants::NotNull => execute::op_not_null, + InsnVariants::Eq + | InsnVariants::Ne + | InsnVariants::Lt + | InsnVariants::Le + | InsnVariants::Gt + | InsnVariants::Ge => execute::op_comparison, + InsnVariants::If => execute::op_if, + InsnVariants::IfNot => execute::op_if_not, + InsnVariants::OpenRead => execute::op_open_read, + InsnVariants::VOpen => execute::op_vopen, + InsnVariants::VCreate => execute::op_vcreate, + InsnVariants::VFilter => execute::op_vfilter, + InsnVariants::VColumn => execute::op_vcolumn, + InsnVariants::VUpdate => execute::op_vupdate, + InsnVariants::VNext => execute::op_vnext, + InsnVariants::VDestroy => execute::op_vdestroy, - InsnVariants::OpenPseudo { .. } => execute::op_open_pseudo, - InsnVariants::Rewind { .. } => execute::op_rewind, - InsnVariants::Last { .. } => execute::op_last, - InsnVariants::Column { .. } => execute::op_column, - InsnVariants::TypeCheck { .. } => execute::op_type_check, - InsnVariants::MakeRecord { .. } => execute::op_make_record, - InsnVariants::ResultRow { .. } => execute::op_result_row, - InsnVariants::Next { .. } => execute::op_next, - InsnVariants::Prev { .. } => execute::op_prev, - InsnVariants::Halt { .. } => execute::op_halt, - InsnVariants::HaltIfNull { .. } => execute::op_halt_if_null, - InsnVariants::Transaction { .. } => execute::op_transaction, - InsnVariants::AutoCommit { .. } => execute::op_auto_commit, - InsnVariants::Goto { .. } => execute::op_goto, - InsnVariants::Gosub { .. } => execute::op_gosub, - InsnVariants::Return { .. } => execute::op_return, - InsnVariants::Integer { .. } => execute::op_integer, - InsnVariants::Real { .. } => execute::op_real, - InsnVariants::RealAffinity { .. } => execute::op_real_affinity, - InsnVariants::String8 { .. } => execute::op_string8, - InsnVariants::Blob { .. } => execute::op_blob, - InsnVariants::RowData { .. } => execute::op_row_data, - InsnVariants::RowId { .. } => execute::op_row_id, - InsnVariants::IdxRowId { .. } => execute::op_idx_row_id, - InsnVariants::SeekRowid { .. } => execute::op_seek_rowid, - InsnVariants::DeferredSeek { .. } => execute::op_deferred_seek, - InsnVariants::SeekGE { .. } - | InsnVariants::SeekGT { .. } - | InsnVariants::SeekLE { .. } - | InsnVariants::SeekLT { .. } => execute::op_seek, - InsnVariants::SeekEnd { .. } => execute::op_seek_end, - InsnVariants::IdxGE { .. } => execute::op_idx_ge, - InsnVariants::IdxGT { .. } => execute::op_idx_gt, - InsnVariants::IdxLE { .. } => execute::op_idx_le, - InsnVariants::IdxLT { .. } => execute::op_idx_lt, - InsnVariants::DecrJumpZero { .. } => execute::op_decr_jump_zero, - InsnVariants::AggStep { .. } => execute::op_agg_step, - InsnVariants::AggFinal { .. } => execute::op_agg_final, - InsnVariants::SorterOpen { .. } => execute::op_sorter_open, - InsnVariants::SorterInsert { .. } => execute::op_sorter_insert, - InsnVariants::SorterSort { .. } => execute::op_sorter_sort, - InsnVariants::SorterData { .. } => execute::op_sorter_data, - InsnVariants::SorterNext { .. } => execute::op_sorter_next, - InsnVariants::Function { .. } => execute::op_function, - InsnVariants::Cast { .. } => execute::op_cast, - InsnVariants::InitCoroutine { .. } => execute::op_init_coroutine, - InsnVariants::EndCoroutine { .. } => execute::op_end_coroutine, - InsnVariants::Yield { .. } => execute::op_yield, - InsnVariants::Insert { .. } => execute::op_insert, - InsnVariants::Int64 { .. } => execute::op_int_64, - InsnVariants::IdxInsert { .. } => execute::op_idx_insert, - InsnVariants::Delete { .. } => execute::op_delete, - InsnVariants::NewRowid { .. } => execute::op_new_rowid, - InsnVariants::MustBeInt { .. } => execute::op_must_be_int, - InsnVariants::SoftNull { .. } => execute::op_soft_null, - InsnVariants::NoConflict { .. } => execute::op_no_conflict, - InsnVariants::NotExists { .. } => execute::op_not_exists, - InsnVariants::OffsetLimit { .. } => execute::op_offset_limit, - InsnVariants::OpenWrite { .. } => execute::op_open_write, - InsnVariants::Copy { .. } => execute::op_copy, - InsnVariants::CreateBtree { .. } => execute::op_create_btree, - InsnVariants::Destroy { .. } => execute::op_destroy, + InsnVariants::OpenPseudo => execute::op_open_pseudo, + InsnVariants::Rewind => execute::op_rewind, + InsnVariants::Last => execute::op_last, + InsnVariants::Column => execute::op_column, + InsnVariants::TypeCheck => execute::op_type_check, + InsnVariants::MakeRecord => execute::op_make_record, + InsnVariants::ResultRow => execute::op_result_row, + InsnVariants::Next => execute::op_next, + InsnVariants::Prev => execute::op_prev, + InsnVariants::Halt => execute::op_halt, + InsnVariants::HaltIfNull => execute::op_halt_if_null, + InsnVariants::Transaction => execute::op_transaction, + InsnVariants::AutoCommit => execute::op_auto_commit, + InsnVariants::Goto => execute::op_goto, + InsnVariants::Gosub => execute::op_gosub, + InsnVariants::Return => execute::op_return, + InsnVariants::Integer => execute::op_integer, + InsnVariants::Real => execute::op_real, + InsnVariants::RealAffinity => execute::op_real_affinity, + InsnVariants::String8 => execute::op_string8, + InsnVariants::Blob => execute::op_blob, + InsnVariants::RowData => execute::op_row_data, + InsnVariants::RowId => execute::op_row_id, + InsnVariants::IdxRowId => execute::op_idx_row_id, + InsnVariants::SeekRowid => execute::op_seek_rowid, + InsnVariants::DeferredSeek => execute::op_deferred_seek, + InsnVariants::SeekGE + | InsnVariants::SeekGT + | InsnVariants::SeekLE + | InsnVariants::SeekLT => execute::op_seek, + InsnVariants::SeekEnd => execute::op_seek_end, + InsnVariants::IdxGE => execute::op_idx_ge, + InsnVariants::IdxGT => execute::op_idx_gt, + InsnVariants::IdxLE => execute::op_idx_le, + InsnVariants::IdxLT => execute::op_idx_lt, + InsnVariants::DecrJumpZero => execute::op_decr_jump_zero, + InsnVariants::AggStep => execute::op_agg_step, + InsnVariants::AggFinal => execute::op_agg_final, + InsnVariants::SorterOpen => execute::op_sorter_open, + InsnVariants::SorterInsert => execute::op_sorter_insert, + InsnVariants::SorterSort => execute::op_sorter_sort, + InsnVariants::SorterData => execute::op_sorter_data, + InsnVariants::SorterNext => execute::op_sorter_next, + InsnVariants::Function => execute::op_function, + InsnVariants::Cast => execute::op_cast, + InsnVariants::InitCoroutine => execute::op_init_coroutine, + InsnVariants::EndCoroutine => execute::op_end_coroutine, + InsnVariants::Yield => execute::op_yield, + InsnVariants::Insert => execute::op_insert, + InsnVariants::Int64 => execute::op_int_64, + InsnVariants::IdxInsert => execute::op_idx_insert, + InsnVariants::Delete => execute::op_delete, + InsnVariants::NewRowid => execute::op_new_rowid, + InsnVariants::MustBeInt => execute::op_must_be_int, + InsnVariants::SoftNull => execute::op_soft_null, + InsnVariants::NoConflict => execute::op_no_conflict, + InsnVariants::NotExists => execute::op_not_exists, + InsnVariants::OffsetLimit => execute::op_offset_limit, + InsnVariants::OpenWrite => execute::op_open_write, + InsnVariants::Copy => execute::op_copy, + InsnVariants::CreateBtree => execute::op_create_btree, + InsnVariants::Destroy => execute::op_destroy, - InsnVariants::DropTable { .. } => execute::op_drop_table, - InsnVariants::DropView { .. } => execute::op_drop_view, - InsnVariants::Close { .. } => execute::op_close, - InsnVariants::IsNull { .. } => execute::op_is_null, - InsnVariants::CollSeq { .. } => execute::op_coll_seq, - InsnVariants::ParseSchema { .. } => execute::op_parse_schema, - InsnVariants::PopulateMaterializedViews { .. } => { - execute::op_populate_materialized_views - } - InsnVariants::ShiftRight { .. } => execute::op_shift_right, - InsnVariants::ShiftLeft { .. } => execute::op_shift_left, - InsnVariants::AddImm { .. } => execute::op_add_imm, - InsnVariants::Variable { .. } => execute::op_variable, - InsnVariants::ZeroOrNull { .. } => execute::op_zero_or_null, - InsnVariants::Not { .. } => execute::op_not, - InsnVariants::Concat { .. } => execute::op_concat, - InsnVariants::And { .. } => execute::op_and, - InsnVariants::Or { .. } => execute::op_or, + InsnVariants::DropTable => execute::op_drop_table, + InsnVariants::DropView => execute::op_drop_view, + InsnVariants::Close => execute::op_close, + InsnVariants::IsNull => execute::op_is_null, + InsnVariants::CollSeq => execute::op_coll_seq, + InsnVariants::ParseSchema => execute::op_parse_schema, + InsnVariants::PopulateMaterializedViews => execute::op_populate_materialized_views, + InsnVariants::ShiftRight => execute::op_shift_right, + InsnVariants::ShiftLeft => execute::op_shift_left, + InsnVariants::AddImm => execute::op_add_imm, + InsnVariants::Variable => execute::op_variable, + InsnVariants::ZeroOrNull => execute::op_zero_or_null, + InsnVariants::Not => execute::op_not, + InsnVariants::Concat => execute::op_concat, + InsnVariants::And => execute::op_and, + InsnVariants::Or => execute::op_or, InsnVariants::Noop => execute::op_noop, - InsnVariants::PageCount { .. } => execute::op_page_count, - InsnVariants::ReadCookie { .. } => execute::op_read_cookie, - InsnVariants::SetCookie { .. } => execute::op_set_cookie, - InsnVariants::OpenEphemeral { .. } | InsnVariants::OpenAutoindex { .. } => { - execute::op_open_ephemeral - } - InsnVariants::Once { .. } => execute::op_once, - InsnVariants::Found { .. } | InsnVariants::NotFound { .. } => execute::op_found, - InsnVariants::Affinity { .. } => execute::op_affinity, - InsnVariants::IdxDelete { .. } => execute::op_idx_delete, - InsnVariants::Count { .. } => execute::op_count, - InsnVariants::IntegrityCk { .. } => execute::op_integrity_check, - InsnVariants::RenameTable { .. } => execute::op_rename_table, - InsnVariants::DropColumn { .. } => execute::op_drop_column, - InsnVariants::AddColumn { .. } => execute::op_add_column, - InsnVariants::AlterColumn { .. } => execute::op_alter_column, - InsnVariants::MaxPgcnt { .. } => execute::op_max_pgcnt, - InsnVariants::JournalMode { .. } => execute::op_journal_mode, - InsnVariants::IfNeg { .. } => execute::op_if_neg, - InsnVariants::Explain { .. } => execute::op_noop, + InsnVariants::PageCount => execute::op_page_count, + InsnVariants::ReadCookie => execute::op_read_cookie, + InsnVariants::SetCookie => execute::op_set_cookie, + InsnVariants::OpenEphemeral | InsnVariants::OpenAutoindex => execute::op_open_ephemeral, + InsnVariants::Once => execute::op_once, + InsnVariants::Found | InsnVariants::NotFound => execute::op_found, + InsnVariants::Affinity => execute::op_affinity, + InsnVariants::IdxDelete => execute::op_idx_delete, + InsnVariants::Count => execute::op_count, + InsnVariants::IntegrityCk => execute::op_integrity_check, + InsnVariants::RenameTable => execute::op_rename_table, + InsnVariants::DropColumn => execute::op_drop_column, + InsnVariants::AddColumn => execute::op_add_column, + InsnVariants::AlterColumn => execute::op_alter_column, + InsnVariants::MaxPgcnt => execute::op_max_pgcnt, + InsnVariants::JournalMode => execute::op_journal_mode, + InsnVariants::IfNeg => execute::op_if_neg, + InsnVariants::Explain => execute::op_noop, } } } diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 716c289f7..d83df0ab1 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -47,7 +47,7 @@ pub fn derive_description_from_doc(item: TokenStream) -> TokenStream { continue; } - // this is a quick fix for + // this is a quick fix for if ident_str == "repr" { continue; } From 4bb6b02b65fc1a183b75fe9d9da85a5048009b62 Mon Sep 17 00:00:00 2001 From: TcMits Date: Sun, 14 Sep 2025 19:03:09 +0700 Subject: [PATCH 06/10] clean PR --- core/storage/wal.rs | 3 +-- macros/src/lib.rs | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/storage/wal.rs b/core/storage/wal.rs index d4361c340..8fbf8eaa2 100644 --- a/core/storage/wal.rs +++ b/core/storage/wal.rs @@ -64,7 +64,7 @@ impl CheckpointResult { } } -#[derive(Debug, Copy, Clone, Default, EnumString)] +#[derive(Debug, Copy, Clone, EnumString)] #[strum(ascii_case_insensitive)] pub enum CheckpointMode { /// Checkpoint as many frames as possible without waiting for any database readers or writers to finish, then sync the database file if all frames in the log were checkpointed. @@ -73,7 +73,6 @@ pub enum CheckpointMode { /// Optional upper_bound_inclusive parameter can be set in order to checkpoint frames with number no larger than the parameter Passive { upper_bound_inclusive: Option }, /// This mode blocks until there is no database writer and all readers are reading from the most recent database snapshot. It then checkpoints all frames in the log file and syncs the database file. This mode blocks new database writers while it is pending, but new database readers are allowed to continue unimpeded. - #[default] Full, /// This mode works the same way as `Full` with the addition that after checkpointing the log file it blocks (calls the busy-handler callback) until all readers are reading from the database file only. This ensures that the next writer will restart the log file from the beginning. Like `Full`, this mode blocks new database writer attempts while it is pending, but does not impede readers. Restart, diff --git a/macros/src/lib.rs b/macros/src/lib.rs index d83df0ab1..8df01da22 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -42,12 +42,13 @@ pub fn derive_description_from_doc(item: TokenStream) -> TokenStream { TokenTree::Ident(ident) => { // Capture the enum variant name and associate it with its description let ident_str = ident.to_string(); + // this is a quick fix for derive(EnumDiscriminants) if ident_str == "strum_discriminants" { continue; } - // this is a quick fix for + // this is a quick fix for repr if ident_str == "repr" { continue; } From 0e2c043535a38c887f708d3e131f0c34a5b1a081 Mon Sep 17 00:00:00 2001 From: TcMits Date: Sun, 14 Sep 2025 19:04:41 +0700 Subject: [PATCH 07/10] unrelated changes --- core/vdbe/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs index a827e13db..c41280c97 100644 --- a/core/vdbe/mod.rs +++ b/core/vdbe/mod.rs @@ -96,7 +96,7 @@ pub enum JumpTarget { AfterThisInsn, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] /// Represents a target for a jump instruction. /// Stores 32-bit ints to keep the enum word-sized. pub enum BranchOffset { @@ -108,7 +108,6 @@ pub enum BranchOffset { Offset(InsnReference), /// A placeholder is a temporary value to satisfy the compiler. /// It must be set later. - #[default] Placeholder, } From 4b9e36c4b6c2302e12f805e0f881e83e9a7089e0 Mon Sep 17 00:00:00 2001 From: TcMits Date: Tue, 16 Sep 2025 11:29:19 +0700 Subject: [PATCH 08/10] rename to VTABLE --- core/vdbe/insn.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index 82a92968e..732238a2e 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -1114,17 +1114,17 @@ const fn get_insn_virtual_table() -> [InsnFunction; InsnVariants::COUNT] { result } -static INSN_VIRTUAL_TABLE: [InsnFunction; InsnVariants::COUNT] = get_insn_virtual_table(); +static INSN_VTABLE: [InsnFunction; InsnVariants::COUNT] = get_insn_virtual_table(); impl InsnVariants { // This function is used for testing #[allow(dead_code)] #[inline(always)] pub(crate) const fn to_function_fast(self) -> InsnFunction { - INSN_VIRTUAL_TABLE[self as usize] + INSN_VTABLE[self as usize] } - // This function is used for generating the virtual table. + // This function is used for generating `INSN_VTABLE`. // We need to keep this function to make sure we implement all opcodes pub(crate) const fn to_function(self) -> InsnFunction { match self { @@ -1278,7 +1278,7 @@ impl Insn { pub fn to_function(&self) -> InsnFunction { // dont use this because its still using match // InsnVariants::from(self).to_function_fast() - INSN_VIRTUAL_TABLE[self.discriminant() as usize] + INSN_VTABLE[self.discriminant() as usize] } } From 84da3c31dacf742e22a8e480e1737675ed66dadb Mon Sep 17 00:00:00 2001 From: TcMits Date: Tue, 16 Sep 2025 20:32:36 +0700 Subject: [PATCH 09/10] const instead --- core/vdbe/insn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index 732238a2e..317555083 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -1114,7 +1114,7 @@ const fn get_insn_virtual_table() -> [InsnFunction; InsnVariants::COUNT] { result } -static INSN_VTABLE: [InsnFunction; InsnVariants::COUNT] = get_insn_virtual_table(); +const INSN_VTABLE: [InsnFunction; InsnVariants::COUNT] = get_insn_virtual_table(); impl InsnVariants { // This function is used for testing From 3bd1198bd934771e5c34e5973d68b2c36bff7d6a Mon Sep 17 00:00:00 2001 From: TcMits Date: Wed, 17 Sep 2025 15:38:21 +0700 Subject: [PATCH 10/10] fmt --- core/vdbe/insn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index bf2c72d80..738c667ca 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -1232,7 +1232,7 @@ impl InsnVariants { InsnVariants::IdxLT => execute::op_idx_lt, InsnVariants::DecrJumpZero => execute::op_decr_jump_zero, InsnVariants::AggStep => execute::op_agg_step, - InsnVariants::AggFinal | InsnVariants::AggValue => execute::op_agg_final, + InsnVariants::AggFinal | InsnVariants::AggValue => execute::op_agg_final, InsnVariants::SorterOpen => execute::op_sorter_open, InsnVariants::SorterInsert => execute::op_sorter_insert, InsnVariants::SorterSort => execute::op_sorter_sort,