From 6139dde081a6111893e517f3a8cec31bbfc608f8 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 21 Oct 2025 16:00:04 +0300 Subject: [PATCH] Revert "Merge 'core/translate: fix ALTER COLUMN to propagate other constraint references' from Preston Thorpe" This reverts commit 1151f49ff40a191dfed68ab32beb4c80da6bd291, reversing changes made to f4da2194f4c207681430f70e698a55de9cebcbeb. --- core/schema.rs | 67 +--------- core/util.rs | 32 ----- core/vdbe/execute.rs | 269 +++++++------------------------------- testing/alter_column.test | 216 ------------------------------ 4 files changed, 52 insertions(+), 532 deletions(-) diff --git a/core/schema.rs b/core/schema.rs index a367e47a8..ce30d3950 100644 --- a/core/schema.rs +++ b/core/schema.rs @@ -1358,13 +1358,12 @@ impl BTreeTable { /// `CREATE TABLE t (x)`, whereas sqlite stores it with the original extra whitespace. pub fn to_sql(&self) -> String { let mut sql = format!("CREATE TABLE {} (", self.name); - - // Add columns for (i, column) in self.columns.iter().enumerate() { if i > 0 { sql.push_str(", "); } - // Wrap column name in square brackets if it contains special characters + + // we need to wrap the column name in square brackets if it contains special characters let column_name = column.name.as_ref().expect("column name is None"); if identifier_contains_special_chars(column_name) { sql.push('['); @@ -1373,6 +1372,7 @@ impl BTreeTable { } else { sql.push_str(column_name); } + if !column.ty_str.is_empty() { sql.push(' '); sql.push_str(&column.ty_str); @@ -1380,75 +1380,20 @@ impl BTreeTable { if column.notnull { sql.push_str(" NOT NULL"); } + if column.unique { sql.push_str(" UNIQUE"); } + if column.primary_key { sql.push_str(" PRIMARY KEY"); } + if let Some(default) = &column.default { sql.push_str(" DEFAULT "); sql.push_str(&default.to_string()); } } - - let has_table_pk = !self.primary_key_columns.is_empty(); - // Add table-level PRIMARY KEY constraint if exists - if has_table_pk { - sql.push_str(", PRIMARY KEY ("); - for (i, col) in self.primary_key_columns.iter().enumerate() { - if i > 0 { - sql.push_str(", "); - } - sql.push_str(&col.0); - } - sql.push(')'); - } - - for fk in &self.foreign_keys { - sql.push_str(", FOREIGN KEY ("); - for (i, col) in fk.child_columns.iter().enumerate() { - if i > 0 { - sql.push_str(", "); - } - sql.push_str(col); - } - sql.push_str(") REFERENCES "); - sql.push_str(&fk.parent_table); - sql.push('('); - for (i, col) in fk.parent_columns.iter().enumerate() { - if i > 0 { - sql.push_str(", "); - } - sql.push_str(col); - } - sql.push(')'); - - // Add ON DELETE/UPDATE actions, NoAction is default so just make empty in that case - if fk.on_delete != RefAct::NoAction { - sql.push_str(" ON DELETE "); - sql.push_str(match fk.on_delete { - RefAct::SetNull => "SET NULL", - RefAct::SetDefault => "SET DEFAULT", - RefAct::Cascade => "CASCADE", - RefAct::Restrict => "RESTRICT", - _ => "", - }); - } - if fk.on_update != RefAct::NoAction { - sql.push_str(" ON UPDATE "); - sql.push_str(match fk.on_update { - RefAct::SetNull => "SET NULL", - RefAct::SetDefault => "SET DEFAULT", - RefAct::Cascade => "CASCADE", - RefAct::Restrict => "RESTRICT", - _ => "", - }); - } - if fk.deferred { - sql.push_str(" DEFERRABLE INITIALLY DEFERRED"); - } - } sql.push(')'); sql } diff --git a/core/util.rs b/core/util.rs index 6caad2e05..1093c61ba 100644 --- a/core/util.rs +++ b/core/util.rs @@ -1331,38 +1331,6 @@ pub fn extract_view_columns( Ok(ViewColumnSchema { tables, columns }) } -pub fn rewrite_fk_parent_cols_if_self_ref( - clause: &mut ast::ForeignKeyClause, - table: &str, - from: &str, - to: &str, -) { - if normalize_ident(clause.tbl_name.as_str()) == normalize_ident(table) { - for c in &mut clause.columns { - if normalize_ident(c.col_name.as_str()) == normalize_ident(from) { - c.col_name = ast::Name::exact(to.to_owned()); - } - } - } -} -/// Update a column-level REFERENCES (col,...) constraint too. -pub fn rewrite_column_references_if_needed( - col: &mut ast::ColumnDefinition, - table: &str, - from: &str, - to: &str, -) { - for cc in &mut col.constraints { - if let ast::NamedColumnConstraint { - constraint: ast::ColumnConstraint::ForeignKey { clause, .. }, - .. - } = cc - { - rewrite_fk_parent_cols_if_self_ref(clause, table, from, to); - } - } -} - #[cfg(test)] pub mod tests { use super::*; diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 9291ead56..974538de0 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -17,9 +17,7 @@ use crate::types::{ compare_immutable, compare_records_generic, Extendable, IOCompletions, ImmutableRecord, SeekResult, Text, }; -use crate::util::{ - normalize_ident, rewrite_column_references_if_needed, rewrite_fk_parent_cols_if_self_ref, -}; +use crate::util::normalize_ident; use crate::vdbe::insn::InsertFlags; use crate::vdbe::{registers_to_ref_values, TxnCleanup}; use crate::vector::{vector32_sparse, vector_concat, vector_distance_jaccard, vector_slice}; @@ -75,7 +73,7 @@ use super::{ }; use parking_lot::RwLock; use rand::{thread_rng, Rng}; -use turso_parser::ast::{self, ForeignKeyClause, Name, SortOrder}; +use turso_parser::ast::{self, Name, SortOrder}; use turso_parser::parser::Parser; use super::{ @@ -5465,9 +5463,11 @@ pub fn op_function( .parse_column_definition(true) .unwrap(); - let rename_to = normalize_ident(column_def.col_name.as_str()); - let new_sql = 'sql: { + if table != tbl_name { + break 'sql None; + } + let Value::Text(sql) = sql else { break 'sql None; }; @@ -5521,160 +5521,34 @@ pub fn op_function( temporary, if_not_exists, } => { + if table != normalize_ident(tbl_name.name.as_str()) { + break 'sql None; + } + let ast::CreateTableBody::ColumnsAndConstraints { mut columns, - mut constraints, + constraints, options, } = body else { todo!() }; - let normalized_tbl_name = normalize_ident(tbl_name.name.as_str()); + let column = columns + .iter_mut() + .find(|column| { + column.col_name.as_str() == original_rename_from.as_str() + }) + .expect("column being renamed should be present"); - if normalized_tbl_name == table { - // This is the table being altered - update its column - let column = columns - .iter_mut() - .find(|column| { - column.col_name.as_str() - == original_rename_from.as_str() - }) - .expect("column being renamed should be present"); - - match alter_func { - AlterTableFunc::AlterColumn => *column = column_def.clone(), - AlterTableFunc::RenameColumn => { - column.col_name = column_def.col_name.clone() - } - _ => unreachable!(), - } - - // Update table-level constraints (PRIMARY KEY, UNIQUE, FOREIGN KEY) - for constraint in &mut constraints { - match &mut constraint.constraint { - ast::TableConstraint::PrimaryKey { - columns: pk_cols, - .. - } => { - for col in pk_cols { - let (ast::Expr::Name(ref name) - | ast::Expr::Id(ref name)) = *col.expr - else { - return Err(LimboError::ParseError("Unexpected expression in PRIMARY KEY constraint".to_string())); - }; - if normalize_ident(name.as_str()) == rename_from - { - *col.expr = ast::Expr::Name(Name::exact( - column_def.col_name.as_str().to_owned(), - )); - } - } - } - ast::TableConstraint::Unique { - columns: uniq_cols, - .. - } => { - for col in uniq_cols { - let (ast::Expr::Name(ref name) - | ast::Expr::Id(ref name)) = *col.expr - else { - return Err(LimboError::ParseError("Unexpected expression in UNIQUE constraint".to_string())); - }; - if normalize_ident(name.as_str()) == rename_from - { - *col.expr = ast::Expr::Name(Name::exact( - column_def.col_name.as_str().to_owned(), - )); - } - } - } - ast::TableConstraint::ForeignKey { - columns: child_cols, - clause, - .. - } => { - // Update child columns in this table's FK definitions - for child_col in child_cols { - if normalize_ident(child_col.col_name.as_str()) - == rename_from - { - child_col.col_name = Name::exact( - column_def.col_name.as_str().to_owned(), - ); - } - } - rewrite_fk_parent_cols_if_self_ref( - clause, - &normalized_tbl_name, - &rename_from, - column_def.col_name.as_str(), - ); - } - _ => {} - } - - for col in &mut columns { - rewrite_column_references_if_needed( - col, - &normalized_tbl_name, - &rename_from, - column_def.col_name.as_str(), - ); - } - } - } else { - // This is a different table, check if it has FKs referencing the renamed column - let mut fk_updated = false; - - for constraint in &mut constraints { - if let ast::TableConstraint::ForeignKey { - columns: _, - clause: - ForeignKeyClause { - tbl_name, - columns: parent_cols, - .. - }, - .. - } = &mut constraint.constraint - { - // Check if this FK references the table being altered - if normalize_ident(tbl_name.as_str()) == table { - // Update parent column references if they match the renamed column - for parent_col in parent_cols { - if normalize_ident(parent_col.col_name.as_str()) - == rename_from - { - parent_col.col_name = Name::exact( - column_def.col_name.as_str().to_owned(), - ); - fk_updated = true; - } - } - } - } - } - for col in &mut columns { - let before = fk_updated; - let mut local_col = col.clone(); - rewrite_column_references_if_needed( - &mut local_col, - &table, - &rename_from, - column_def.col_name.as_str(), - ); - if local_col != *col { - *col = local_col; - fk_updated = true; - } - } - - // Only return updated SQL if we actually changed something - if !fk_updated { - break 'sql None; + match alter_func { + AlterTableFunc::AlterColumn => *column = column_def, + AlterTableFunc::RenameColumn => { + column.col_name = column_def.col_name } + _ => unreachable!(), } + Some( ast::Stmt::CreateTable { tbl_name, @@ -5689,7 +5563,7 @@ pub fn op_function( .to_string(), ) } - _ => None, + _ => todo!(), } }; @@ -8364,94 +8238,43 @@ pub fn op_alter_column( .clone() }; let new_column = crate::schema::Column::from(definition); - let new_name = definition.col_name.as_str().to_owned(); conn.with_schema_mut(|schema| { - let table_arc = schema + let table = schema .tables .get_mut(&normalized_table_name) - .expect("table being ALTERed should be in schema"); - let table = Arc::make_mut(table_arc); + .expect("table being renamed should be in schema"); - let Table::BTree(ref mut btree_arc) = table else { - panic!("only btree tables can be altered"); + 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_arc); - let col = btree + + let btree = Arc::make_mut(btree); + + let column = btree .columns .get_mut(*column_index) - .expect("column being ALTERed should be in schema"); + .expect("renamed column should be in schema"); - // Update indexes on THIS table that name the old column (you already had this) - if let Some(idxs) = schema.indexes.get_mut(&normalized_table_name) { - for idx in idxs { - let idx = Arc::make_mut(idx); - for ic in &mut idx.columns { - if ic.name.eq_ignore_ascii_case( - col.name.as_ref().expect("btree column should be named"), - ) { - ic.name = new_name.clone(); + if let Some(indexes) = schema.indexes.get_mut(&normalized_table_name) { + for index in indexes { + let index = Arc::make_mut(index); + for index_column in &mut index.columns { + if index_column.name + == *column.name.as_ref().expect("btree column should be named") + { + index_column.name = definition.col_name.as_str().to_owned(); } } } } + if *rename { - col.name = Some(new_name.clone()); + column.name = new_column.name; } else { - *col = new_column.clone(); - } - - // Keep primary_key_columns consistent (names may change on rename) - for (pk_name, _ord) in &mut btree.primary_key_columns { - if pk_name.eq_ignore_ascii_case(&old_column_name) { - *pk_name = new_name.clone(); - } - } - - // Maintain rowid-alias bit after change/rename (INTEGER PRIMARY KEY) - if !*rename { - // recompute alias from `new_column` - btree.columns[*column_index].is_rowid_alias = new_column.is_rowid_alias; - } - - // Update this table’s OWN foreign keys - for fk_arc in &mut btree.foreign_keys { - let fk = Arc::make_mut(fk_arc); - // child side: rename child column if it matches - for cc in &mut fk.child_columns { - if cc.eq_ignore_ascii_case(&old_column_name) { - *cc = new_name.clone(); - } - } - // parent side: if self-referencing, rename parent column too - if normalize_ident(&fk.parent_table) == normalized_table_name { - for pc in &mut fk.parent_columns { - if pc.eq_ignore_ascii_case(&old_column_name) { - *pc = new_name.clone(); - } - } - } - } - - // fix OTHER tables that reference this table as parent - for (tname, t_arc) in schema.tables.iter_mut() { - if normalize_ident(tname) == normalized_table_name { - continue; - } - if let Table::BTree(ref mut child_btree_arc) = Arc::make_mut(t_arc) { - let child_btree = Arc::make_mut(child_btree_arc); - for fk_arc in &mut child_btree.foreign_keys { - if normalize_ident(&fk_arc.parent_table) != normalized_table_name { - continue; - } - let fk = Arc::make_mut(fk_arc); - for pc in &mut fk.parent_columns { - if pc.eq_ignore_ascii_case(&old_column_name) { - *pc = new_name.clone(); - } - } - } - } + *column = new_column; } }); diff --git a/testing/alter_column.test b/testing/alter_column.test index 1b4da6dd0..3672497ab 100755 --- a/testing/alter_column.test +++ b/testing/alter_column.test @@ -22,219 +22,3 @@ do_execsql_test_in_memory_any_error fail-alter-column-unique { CREATE TABLE t (a); ALTER TABLE t ALTER COLUMN a TO a UNIQUE; } - -do_execsql_test_on_specific_db {:memory:} alter-table-rename-pk-column { - CREATE TABLE customers (cust_id INTEGER PRIMARY KEY, cust_name TEXT); - INSERT INTO customers VALUES (1, 'Alice'), (2, 'Bob'); - - ALTER TABLE customers RENAME COLUMN cust_id TO customer_id; - - SELECT sql FROM sqlite_schema WHERE name = 'customers'; - SELECT customer_id, cust_name FROM customers ORDER BY customer_id; -} { - "CREATE TABLE customers (customer_id INTEGER PRIMARY KEY, cust_name TEXT)" - "1|Alice" - "2|Bob" -} - -do_execsql_test_on_specific_db {:memory:} alter-table-rename-composite-pk { - CREATE TABLE products (category TEXT, prod_code TEXT, name TEXT, PRIMARY KEY (category, prod_code)); - INSERT INTO products VALUES ('Electronics', 'E001', 'Laptop'); - - ALTER TABLE products RENAME COLUMN prod_code TO product_code; - - SELECT sql FROM sqlite_schema WHERE name = 'products'; - SELECT category, product_code, name FROM products; -} { - "CREATE TABLE products (category TEXT, product_code TEXT, name TEXT, PRIMARY KEY (category, product_code))" - "Electronics|E001|Laptop" -} - -# Foreign key child column rename -do_execsql_test_on_specific_db {:memory:} alter-table-rename-fk-child { - CREATE TABLE parent (id INTEGER PRIMARY KEY); - CREATE TABLE child (cid INTEGER PRIMARY KEY, pid INTEGER, FOREIGN KEY (pid) REFERENCES parent(id)); - INSERT INTO parent VALUES (1); - INSERT INTO child VALUES (1, 1); - - ALTER TABLE child RENAME COLUMN pid TO parent_id; - - SELECT sql FROM sqlite_schema WHERE name = 'child'; -} { - "CREATE TABLE child (cid INTEGER PRIMARY KEY, parent_id INTEGER, FOREIGN KEY (parent_id) REFERENCES parent (id))" -} - -# Foreign key parent column rename - critical test -do_execsql_test_on_specific_db {:memory:} alter-table-rename-fk-parent { - CREATE TABLE orders (order_id INTEGER PRIMARY KEY, date TEXT); - CREATE TABLE items (item_id INTEGER PRIMARY KEY, oid INTEGER, FOREIGN KEY (oid) REFERENCES orders(order_id)); - - ALTER TABLE orders RENAME COLUMN order_id TO ord_id; - - SELECT sql FROM sqlite_schema WHERE name = 'orders'; - SELECT sql FROM sqlite_schema WHERE name = 'items'; -} { - "CREATE TABLE orders (ord_id INTEGER PRIMARY KEY, date TEXT)" - "CREATE TABLE items (item_id INTEGER PRIMARY KEY, oid INTEGER, FOREIGN KEY (oid) REFERENCES orders (ord_id))" -} - -# Composite foreign key parent rename -do_execsql_test_on_specific_db {:memory:} alter-table-rename-composite-fk-parent { - CREATE TABLE products (cat TEXT, code TEXT, PRIMARY KEY (cat, code)); - CREATE TABLE inventory (id INTEGER PRIMARY KEY, cat TEXT, code TEXT, FOREIGN KEY (cat, code) REFERENCES products(cat, code)); - - ALTER TABLE products RENAME COLUMN code TO sku; - - SELECT sql FROM sqlite_schema WHERE name = 'products'; - SELECT sql FROM sqlite_schema WHERE name = 'inventory'; -} { - "CREATE TABLE products (cat TEXT, sku TEXT, PRIMARY KEY (cat, sku))" - "CREATE TABLE inventory (id INTEGER PRIMARY KEY, cat TEXT, code TEXT, FOREIGN KEY (cat, code) REFERENCES products (cat, sku))" -} - -# Multiple foreign keys to same parent -do_execsql_test_on_specific_db {:memory:} alter-table-rename-multiple-fks { - CREATE TABLE users (uid INTEGER PRIMARY KEY); - CREATE TABLE messages (mid INTEGER PRIMARY KEY, sender INTEGER, receiver INTEGER, - FOREIGN KEY (sender) REFERENCES users(uid), - FOREIGN KEY (receiver) REFERENCES users(uid)); - - ALTER TABLE users RENAME COLUMN uid TO user_id; - - SELECT sql FROM sqlite_schema WHERE name = 'messages'; -} { - "CREATE TABLE messages (mid INTEGER PRIMARY KEY, sender INTEGER, receiver INTEGER, FOREIGN KEY (sender) REFERENCES users (user_id), FOREIGN KEY (receiver) REFERENCES users (user_id))" -} - -# Self-referencing foreign key -do_execsql_test_on_specific_db {:memory:} alter-table-rename-self-ref-fk { - CREATE TABLE employees (emp_id INTEGER PRIMARY KEY, manager_id INTEGER, - FOREIGN KEY (manager_id) REFERENCES employees(emp_id)); - - ALTER TABLE employees RENAME COLUMN emp_id TO employee_id; - - SELECT sql FROM sqlite_schema WHERE name = 'employees'; -} { - "CREATE TABLE employees (employee_id INTEGER PRIMARY KEY, manager_id INTEGER, FOREIGN KEY (manager_id) REFERENCES employees (employee_id))" -} - -# Chain of FK renames - parent is both PK and referenced -do_execsql_test_on_specific_db {:memory:} alter-table-rename-fk-chain { - CREATE TABLE t1 (a INTEGER PRIMARY KEY); - CREATE TABLE t2 (b INTEGER PRIMARY KEY, a_ref INTEGER, FOREIGN KEY (a_ref) REFERENCES t1(a)); - CREATE TABLE t3 (c INTEGER PRIMARY KEY, b_ref INTEGER, FOREIGN KEY (b_ref) REFERENCES t2(b)); - - ALTER TABLE t1 RENAME COLUMN a TO a_new; - ALTER TABLE t2 RENAME COLUMN b TO b_new; - - SELECT sql FROM sqlite_schema WHERE name = 't2'; - SELECT sql FROM sqlite_schema WHERE name = 't3'; -} { - "CREATE TABLE t2 (b_new INTEGER PRIMARY KEY, a_ref INTEGER, FOREIGN KEY (a_ref) REFERENCES t1 (a_new))" - "CREATE TABLE t3 (c INTEGER PRIMARY KEY, b_ref INTEGER, FOREIGN KEY (b_ref) REFERENCES t2 (b_new))" -} - -# FK with ON DELETE/UPDATE actions -do_execsql_test_on_specific_db {:memory:} alter-table-rename-fk-actions { - CREATE TABLE parent (pid INTEGER PRIMARY KEY); - CREATE TABLE child (cid INTEGER PRIMARY KEY, pid INTEGER, - FOREIGN KEY (pid) REFERENCES parent(pid) ON DELETE CASCADE ON UPDATE RESTRICT); - - ALTER TABLE parent RENAME COLUMN pid TO parent_id; - - SELECT sql FROM sqlite_schema WHERE name = 'child'; -} { - "CREATE TABLE child (cid INTEGER PRIMARY KEY, pid INTEGER, FOREIGN KEY (pid) REFERENCES parent (parent_id) ON DELETE CASCADE ON UPDATE RESTRICT)" -} - -# FK with DEFERRABLE -do_execsql_test_on_specific_db {:memory:} alter-table-rename-fk-deferrable { - CREATE TABLE parent (id INTEGER PRIMARY KEY); - CREATE TABLE child (id INTEGER PRIMARY KEY, pid INTEGER, - FOREIGN KEY (pid) REFERENCES parent(id) DEFERRABLE INITIALLY DEFERRED); - - ALTER TABLE parent RENAME COLUMN id TO parent_id; - - SELECT sql FROM sqlite_schema WHERE name = 'child'; -} { - "CREATE TABLE child (id INTEGER PRIMARY KEY, pid INTEGER, FOREIGN KEY (pid) REFERENCES parent (parent_id) DEFERRABLE INITIALLY DEFERRED)" -} - -# Rename with quoted identifiers in FK -do_execsql_test_on_specific_db {:memory:} alter-table-rename-fk-quoted { - CREATE TABLE "parent table" ("parent id" INTEGER PRIMARY KEY); - CREATE TABLE child (id INTEGER PRIMARY KEY, pid INTEGER, - FOREIGN KEY (pid) REFERENCES "parent table"("parent id")); - - ALTER TABLE "parent table" RENAME COLUMN "parent id" TO "new id"; - - SELECT sql FROM sqlite_schema WHERE name = 'child'; -} { - "CREATE TABLE child (id INTEGER PRIMARY KEY, pid INTEGER, FOREIGN KEY (pid) REFERENCES \"parent table\" (\"new id\"))" -} - -# Verify FK constraint still works after rename -do_execsql_test_on_specific_db {:memory:} alter-table-fk-constraint-after-rename { - PRAGMA foreign_keys = ON; - CREATE TABLE parent (id INTEGER PRIMARY KEY); - CREATE TABLE child (id INTEGER PRIMARY KEY, pid INTEGER, FOREIGN KEY (pid) REFERENCES parent(id)); - INSERT INTO parent VALUES (1); - INSERT INTO child VALUES (1, 1); - - ALTER TABLE parent RENAME COLUMN id TO parent_id; - - -- This should work - INSERT INTO child VALUES (2, 1); - SELECT COUNT(*) FROM child; -} { - "2" -} - -# FK constraint violation after rename should still fail -do_execsql_test_in_memory_any_error alter-table-fk-violation-after-rename { - PRAGMA foreign_keys = ON; - CREATE TABLE parent (id INTEGER PRIMARY KEY); - CREATE TABLE child (id INTEGER PRIMARY KEY, pid INTEGER, FOREIGN KEY (pid) REFERENCES parent(id)); - INSERT INTO parent VALUES (1); - - ALTER TABLE parent RENAME COLUMN id TO parent_id; - - -- This should fail with FK violation - INSERT INTO child VALUES (1, 999); -} - -# Complex scenario with multiple table constraints -do_execsql_test_on_specific_db {:memory:} alter-table-rename-complex-constraints { - CREATE TABLE t ( - a INTEGER, - b TEXT, - c REAL, - PRIMARY KEY (a, b), - UNIQUE (b, c), - FOREIGN KEY (a) REFERENCES t(a) - ); - - ALTER TABLE t RENAME COLUMN a TO x; - ALTER TABLE t RENAME COLUMN b TO y; - - SELECT sql FROM sqlite_schema WHERE name = 't'; -} { - "CREATE TABLE t (x INTEGER, y TEXT, c REAL, PRIMARY KEY (x, y), UNIQUE (y, c), FOREIGN KEY (x) REFERENCES t (x))" -} - -# Rename column that appears in both PK and FK -do_execsql_test_on_specific_db {:memory:} alter-table-rename-pk-and-fk { - CREATE TABLE parent (id INTEGER PRIMARY KEY); - CREATE TABLE child ( - id INTEGER PRIMARY KEY, - parent_ref INTEGER, - FOREIGN KEY (id) REFERENCES parent(id), - FOREIGN KEY (parent_ref) REFERENCES parent(id) - ); - - ALTER TABLE parent RENAME COLUMN id TO pid; - - SELECT sql FROM sqlite_schema WHERE name = 'child'; -} { - "CREATE TABLE child (id INTEGER PRIMARY KEY, parent_ref INTEGER, FOREIGN KEY (id) REFERENCES parent (pid), FOREIGN KEY (parent_ref) REFERENCES parent (pid))" -}