mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-17 08:34:19 +01:00
feat: alter table disallow generated columns, support foreign keys for alter table
This commit is contained in:
@@ -6,7 +6,7 @@ use turso_parser::{
|
||||
|
||||
use crate::{
|
||||
function::{AlterTableFunc, Func},
|
||||
schema::{Column, Table, RESERVED_TABLE_PREFIXES},
|
||||
schema::{Column, ForeignKey, Table, RESERVED_TABLE_PREFIXES},
|
||||
translate::{
|
||||
emitter::Resolver,
|
||||
expr::{walk_expr, WalkControl},
|
||||
@@ -280,6 +280,16 @@ pub fn translate_alter_table(
|
||||
)?
|
||||
}
|
||||
ast::AlterTableBody::AddColumn(col_def) => {
|
||||
if col_def
|
||||
.constraints
|
||||
.iter()
|
||||
.any(|c| matches!(c.constraint, ast::ColumnConstraint::Generated { .. }))
|
||||
{
|
||||
return Err(LimboError::ParseError(
|
||||
"Alter table does not support adding generated columns".to_string(),
|
||||
));
|
||||
}
|
||||
let constraints = col_def.constraints.clone();
|
||||
let column = Column::from(&col_def);
|
||||
|
||||
if let Some(default) = &column.default {
|
||||
@@ -310,6 +320,58 @@ pub fn translate_alter_table(
|
||||
// TODO: All quoted ids will be quoted with `[]`, we should store some info from the parsed AST
|
||||
btree.columns.push(column.clone());
|
||||
|
||||
// Add foreign key constraints to the btree table
|
||||
for constraint in constraints {
|
||||
if let ast::ColumnConstraint::ForeignKey {
|
||||
clause,
|
||||
defer_clause,
|
||||
} = constraint.constraint
|
||||
{
|
||||
let fk = ForeignKey {
|
||||
parent_table: normalize_ident(clause.tbl_name.as_str()),
|
||||
parent_columns: clause
|
||||
.columns
|
||||
.iter()
|
||||
.map(|c| normalize_ident(c.col_name.as_str()))
|
||||
.collect(),
|
||||
on_delete: clause
|
||||
.args
|
||||
.iter()
|
||||
.find_map(|arg| {
|
||||
if let ast::RefArg::OnDelete(act) = arg {
|
||||
Some(*act)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or(ast::RefAct::NoAction),
|
||||
on_update: clause
|
||||
.args
|
||||
.iter()
|
||||
.find_map(|arg| {
|
||||
if let ast::RefArg::OnUpdate(act) = arg {
|
||||
Some(*act)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or(ast::RefAct::NoAction),
|
||||
child_columns: vec![new_column_name.to_string()],
|
||||
deferred: match defer_clause {
|
||||
Some(d) => {
|
||||
d.deferrable
|
||||
&& matches!(
|
||||
d.init_deferred,
|
||||
Some(ast::InitDeferredPred::InitiallyDeferred)
|
||||
)
|
||||
}
|
||||
None => false,
|
||||
},
|
||||
};
|
||||
btree.foreign_keys.push(Arc::new(fk));
|
||||
}
|
||||
}
|
||||
|
||||
let sql = btree.to_sql();
|
||||
let mut escaped = String::with_capacity(sql.len());
|
||||
|
||||
|
||||
@@ -299,3 +299,37 @@ do_execsql_test_on_specific_db {:memory:} rename-parent-3-composite {
|
||||
SELECT sql FROM sqlite_schema WHERE type='table' AND name='c3';
|
||||
} {{CREATE TABLE c3 (x INTEGER PRIMARY KEY, fa INTEGER, fb INTEGER, FOREIGN KEY (fa, fb) REFERENCES p3_new (a, b))}}
|
||||
|
||||
# Adding a generated column via ALTER TABLE should error
|
||||
do_execsql_test_in_memory_error_content alter-table-add-generated-column-error {
|
||||
CREATE TABLE t(a);
|
||||
ALTER TABLE t ADD COLUMN b AS (NULL);
|
||||
} {
|
||||
"Parse error: Alter table does not support adding generated columns"
|
||||
}
|
||||
|
||||
# Add column with a foreign key reference and verify schema SQL
|
||||
do_execsql_test_on_specific_db {:memory:} alter-table-add-column-with-fk-updates-schema {
|
||||
CREATE TABLE t(a);
|
||||
CREATE TABLE s(a);
|
||||
ALTER TABLE s ADD COLUMN b REFERENCES t(a);
|
||||
SELECT sql FROM sqlite_schema WHERE name = 's';
|
||||
} {
|
||||
"CREATE TABLE s (a, b, FOREIGN KEY (b) REFERENCES t(a))"
|
||||
}
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} alter-table-add-self-ref-fk-updates-schema {
|
||||
CREATE TABLE s(a);
|
||||
ALTER TABLE s ADD COLUMN b REFERENCES s(a);
|
||||
SELECT sql FROM sqlite_schema WHERE name = 's';
|
||||
} {
|
||||
"CREATE TABLE s (a, b, FOREIGN KEY (b) REFERENCES s(a))"
|
||||
}
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} alter-table-add-column-with-composite-fk-updates-schema {
|
||||
CREATE TABLE t(a, c);
|
||||
CREATE TABLE s(a);
|
||||
ALTER TABLE s ADD COLUMN b REFERENCES t(a, c);
|
||||
SELECT sql FROM sqlite_schema WHERE name = 's';
|
||||
} {
|
||||
"CREATE TABLE s (a, b, FOREIGN KEY (b) REFERENCES t(a, c))"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user