From 658405d6b3280bedb950951e33110e1c4e3d024a Mon Sep 17 00:00:00 2001 From: "Levy A." Date: Wed, 6 Aug 2025 22:06:38 -0300 Subject: [PATCH] feat: add `AddColumn` instruction --- core/translate/alter.rs | 8 +++--- core/vdbe/execute.rs | 59 ++++++++++++++++++++++++++++++----------- core/vdbe/explain.rs | 9 +++++++ core/vdbe/insn.rs | 7 ++++- 4 files changed, 63 insertions(+), 20 deletions(-) diff --git a/core/translate/alter.rs b/core/translate/alter.rs index 6c738b48b..fb95ec044 100644 --- a/core/translate/alter.rs +++ b/core/translate/alter.rs @@ -181,7 +181,7 @@ pub fn translate_alter_table( } } - btree.columns.push(column); + btree.columns.push(column.clone()); let sql = btree.to_sql(); let mut escaped = String::with_capacity(sql.len()); @@ -219,9 +219,9 @@ pub fn translate_alter_table( value: schema.schema_version as i32 + 1, p5: 0, }); - program.emit_insn(Insn::ParseSchema { - db: usize::MAX, // TODO: This value is unused, change when we do something with it - where_clause: None, + program.emit_insn(Insn::AddColumn { + table: table_name.to_owned(), + column, }); }, )? diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 0660cd535..10415eb64 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -6871,13 +6871,13 @@ pub fn op_drop_column( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::DropColumn { - table, - column_index, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + load_insn!( + DropColumn { + table, + column_index + }, + insn + ); let conn = program.connection.clone(); @@ -6887,16 +6887,45 @@ pub fn op_drop_column( .get_mut(table) .expect("table being renamed should be in schema"); - { - let table = Arc::make_mut(table); + let table = Arc::make_mut(table); - let Table::BTree(btree) = table else { - panic!("only btree tables can be renamed"); - }; + let Table::BTree(btree) = table else { + panic!("only btree tables can be renamed"); + }; - let btree = Arc::make_mut(btree); - btree.columns.remove(*column_index) - } + let btree = Arc::make_mut(btree); + btree.columns.remove(*column_index) + }); + + state.pc += 1; + Ok(InsnFunctionStepResult::Step) +} + +pub fn op_add_column( + program: &Program, + state: &mut ProgramState, + insn: &Insn, + pager: &Rc, + mv_store: Option<&Arc>, +) -> Result { + load_insn!(AddColumn { table, column }, insn); + + let conn = program.connection.clone(); + + conn.with_schema_mut(|schema| { + let table = schema + .tables + .get_mut(table) + .expect("table being renamed should be in schema"); + + let table = Arc::make_mut(table); + + let Table::BTree(btree) = table else { + panic!("only btree tables can be renamed"); + }; + + let btree = Arc::make_mut(btree); + btree.columns.push(column.clone()) }); state.pc += 1; diff --git a/core/vdbe/explain.rs b/core/vdbe/explain.rs index 2cd78ab9e..e4245aba6 100644 --- a/core/vdbe/explain.rs +++ b/core/vdbe/explain.rs @@ -1645,6 +1645,15 @@ pub fn insn_to_str( 0, format!("drop_column({table}, {column_index})"), ), + Insn::AddColumn { table, column } => ( + "AddColumn", + 0, + 0, + 0, + Value::build_text(""), + 0, + format!("add_column({table}, {column:?})"), + ), Insn::MaxPgcnt { db, dest, new_max } => ( "MaxPgcnt", *db as i32, diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index 3c2dedc0f..b7a7e680d 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -5,7 +5,7 @@ use std::{ use super::{execute, AggFunc, BranchOffset, CursorID, FuncCtx, InsnFunction, PageIdx}; use crate::{ - schema::{Affinity, BTreeTable, Index}, + schema::{Affinity, BTreeTable, Column, Index}, storage::{pager::CreateBTreeFlags, wal::CheckpointMode}, translate::collate::CollationSeq, Value, @@ -1034,6 +1034,10 @@ pub enum Insn { table: String, column_index: usize, }, + AddColumn { + table: String, + column: Column, + }, /// Try to set the maximum page count for database P1 to the value in P3. /// Do not let the maximum page count fall below the current page count and /// do not change the maximum page count value if P3==0. @@ -1182,6 +1186,7 @@ impl Insn { 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::MaxPgcnt { .. } => execute::op_max_pgcnt, Insn::JournalMode { .. } => execute::op_journal_mode, }