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::{
|
use crate::{
|
||||||
function::{AlterTableFunc, Func},
|
function::{AlterTableFunc, Func},
|
||||||
schema::{Column, Table, RESERVED_TABLE_PREFIXES},
|
schema::{Column, ForeignKey, Table, RESERVED_TABLE_PREFIXES},
|
||||||
translate::{
|
translate::{
|
||||||
emitter::Resolver,
|
emitter::Resolver,
|
||||||
expr::{walk_expr, WalkControl},
|
expr::{walk_expr, WalkControl},
|
||||||
@@ -280,6 +280,16 @@ pub fn translate_alter_table(
|
|||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
ast::AlterTableBody::AddColumn(col_def) => {
|
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);
|
let column = Column::from(&col_def);
|
||||||
|
|
||||||
if let Some(default) = &column.default {
|
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
|
// TODO: All quoted ids will be quoted with `[]`, we should store some info from the parsed AST
|
||||||
btree.columns.push(column.clone());
|
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 sql = btree.to_sql();
|
||||||
let mut escaped = String::with_capacity(sql.len());
|
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';
|
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))}}
|
} {{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