vibesql_executor/alter/
mod.rs

1//! ALTER TABLE executor
2
3mod columns;
4mod constraints;
5mod table_options;
6mod validation;
7
8use vibesql_ast::*;
9use vibesql_storage::Database;
10
11use crate::{errors::ExecutorError, privilege_checker::PrivilegeChecker};
12
13/// Executor for ALTER TABLE statements
14pub struct AlterTableExecutor;
15
16impl AlterTableExecutor {
17    /// Execute an ALTER TABLE statement
18    pub fn execute(
19        stmt: &AlterTableStmt,
20        database: &mut Database,
21    ) -> Result<String, ExecutorError> {
22        // Get table name from the statement and check ALTER privilege
23        let table_name = match stmt {
24            AlterTableStmt::AddColumn(s) => &s.table_name,
25            AlterTableStmt::DropColumn(s) => &s.table_name,
26            AlterTableStmt::AlterColumn(s) => match s {
27                AlterColumnStmt::SetDefault { table_name, .. } => table_name,
28                AlterColumnStmt::DropDefault { table_name, .. } => table_name,
29                AlterColumnStmt::SetNotNull { table_name, .. } => table_name,
30                AlterColumnStmt::DropNotNull { table_name, .. } => table_name,
31            },
32            AlterTableStmt::AddConstraint(s) => &s.table_name,
33            AlterTableStmt::DropConstraint(s) => &s.table_name,
34            AlterTableStmt::RenameTable(s) => &s.table_name,
35            AlterTableStmt::ModifyColumn(s) => &s.table_name,
36            AlterTableStmt::ChangeColumn(s) => &s.table_name,
37        };
38        PrivilegeChecker::check_alter(database, table_name)?;
39
40        let result = match stmt {
41            AlterTableStmt::AddColumn(add_column) => {
42                columns::execute_add_column(add_column, database)
43            }
44            AlterTableStmt::DropColumn(drop_column) => {
45                columns::execute_drop_column(drop_column, database)
46            }
47            AlterTableStmt::AlterColumn(alter_column) => {
48                columns::execute_alter_column(alter_column, database)
49            }
50            AlterTableStmt::AddConstraint(add_constraint) => {
51                constraints::execute_add_constraint(add_constraint, database)
52            }
53            AlterTableStmt::DropConstraint(drop_constraint) => {
54                constraints::execute_drop_constraint(drop_constraint, database)
55            }
56            AlterTableStmt::RenameTable(rename_table) => {
57                // For RENAME TABLE, invalidate both old and new table names
58                let old_name = &rename_table.table_name;
59                let new_name = &rename_table.new_table_name;
60                let result = table_options::execute_rename_table(rename_table, database);
61                if result.is_ok() {
62                    // Invalidate the database-level columnar cache for both table names
63                    // since the cache key is based on table name
64                    database.invalidate_columnar_cache(old_name);
65                    database.invalidate_columnar_cache(new_name);
66                }
67                return result;
68            }
69            AlterTableStmt::ModifyColumn(modify_column) => {
70                columns::execute_modify_column(modify_column, database)
71            }
72            AlterTableStmt::ChangeColumn(change_column) => {
73                columns::execute_change_column(change_column, database)
74            }
75        };
76
77        // Invalidate the database-level columnar cache since table structure changed.
78        // This ensures subsequent reads via `database.get_columnar()` return
79        // fresh data with the updated schema rather than stale cached data.
80        if result.is_ok() {
81            database.invalidate_columnar_cache(table_name);
82        }
83
84        result
85    }
86}