Skip to content

Commit

Permalink
Drop constraints before dropping tables
Browse files Browse the repository at this point in the history
  • Loading branch information
jayvdb committed Apr 20, 2024
1 parent 3cfc92e commit 6ce56c8
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 18 deletions.
47 changes: 31 additions & 16 deletions butane_core/src/db/pg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,9 +551,22 @@ fn sql_for_op(current: &mut ADB, op: &Operation) -> Result<String> {
Operation::AddTableConstraints(table) => Ok(create_table_constraints(table)),
Operation::AddTableIfNotExists(table) => Ok(create_table(table, true)?),
Operation::RemoveTable(name) => Ok(drop_table(name)),
Operation::RemoveTableConstraints(table) => remove_table_constraints(table),
Operation::AddColumn(tbl, col) => add_column(tbl, col),
Operation::RemoveColumn(tbl, name) => Ok(remove_column(tbl, name)),
Operation::ChangeColumn(tbl, old, new) => change_column(current, tbl, old, new),
Operation::ChangeColumn(tbl, old, new) => {
let table = current.get_table(tbl);
if let Some(table) = table {
change_column(table, old, new)
} else {
crate::warn!(
"Cannot alter column {} from table {} that does not exist",
&old.name(),
tbl
);
Ok(String::new())
}
}
}
}

Expand Down Expand Up @@ -583,6 +596,16 @@ fn create_table_constraints(table: &ATable) -> String {
.join("\n")
}

fn remove_table_constraints(table: &ATable) -> Result<String> {
Ok(table
.columns
.iter()
.filter(|column| column.reference().is_some())
.map(|column| drop_fk_constraints(&table, column))
.collect::<Result<Vec<String>>>()?
.join("\n"))
}

fn define_column(col: &AColumn) -> Result<String> {
let mut constraints: Vec<String> = Vec::new();
if !col.nullable() {
Expand Down Expand Up @@ -628,6 +651,11 @@ fn define_constraint(table_name: &str, column: &AColumn) -> String {
}
}

fn drop_fk_constraints(table: &ATable, column: &AColumn) -> Result<String> {
let mut modified_column = column.clone();
modified_column.remove_reference();
change_column(table, column, &modified_column)
}
fn col_sqltype(col: &AColumn) -> Result<Cow<str>> {
match col.typeid()? {
TypeIdentifier::Name(name) => Ok(Cow::Owned(name)),
Expand Down Expand Up @@ -686,22 +714,9 @@ fn remove_column(tbl_name: &str, name: &str) -> String {
)
}

fn change_column(
current: &mut ADB,
tbl_name: &str,
old: &AColumn,
new: &AColumn,
) -> Result<String> {
fn change_column(table: &ATable, old: &AColumn, new: &AColumn) -> Result<String> {
use helper::quote_reserved_word;
let table = current.get_table(tbl_name);
if table.is_none() {
crate::warn!(
"Cannot alter column {} from table {} that does not exist",
&old.name(),
tbl_name
);
return Ok(String::new());
}
let tbl_name = &table.name;

// Let's figure out what changed about the column
let mut stmts: Vec<String> = Vec::new();
Expand Down
1 change: 1 addition & 0 deletions butane_core/src/db/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ fn sql_for_op(current: &mut ADB, op: &Operation) -> Result<String> {
Operation::AddTableConstraints(_table) => Ok("".to_owned()),
Operation::AddTableIfNotExists(table) => Ok(create_table(table, true)),
Operation::RemoveTable(name) => Ok(drop_table(name)),
Operation::RemoveTableConstraints(_table) => Ok("".to_owned()),
Operation::AddColumn(tbl, col) => add_column(tbl, col),
Operation::RemoveColumn(tbl, name) => Ok(remove_column(current, tbl, name)),
Operation::ChangeColumn(tbl, old, new) => Ok(change_column(current, tbl, old, Some(new))),
Expand Down
16 changes: 15 additions & 1 deletion butane_core/src/migrations/adb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ impl ADB {
self.tables.insert(table.name.clone(), table);
}
RemoveTable(name) => self.remove_table(&name),
RemoveTableConstraints(_) => {}
AddColumn(table, col) => {
if let Some(t) = self.tables.get_mut(&table) {
t.add_column(col);
Expand Down Expand Up @@ -483,6 +484,11 @@ impl AColumn {
pub fn add_reference(&mut self, reference: &ARef) {
self.reference = Some(reference.clone())
}
/// Remove the column that this column refers to.
pub fn remove_reference(&mut self) {
self.reference = None
}
/// Get the type identifier.
pub fn typeid(&self) -> Result<TypeIdentifier> {
match &self.sqltype {
DeferredSqlType::KnownId(t) => Ok(t.clone()),
Expand Down Expand Up @@ -581,6 +587,8 @@ pub enum Operation {
AddTableConstraints(ATable),
/// Add a table, if it doesnt already exist.
AddTableIfNotExists(ATable),
/// Remove table constraints referring to other tables, if the backend supports it.
RemoveTableConstraints(ATable),
/// Remove named table.
RemoveTable(String),
/// Add a table column.
Expand All @@ -607,7 +615,13 @@ pub fn diff(old: &ADB, new: &ADB) -> Vec<Operation> {
}

// Remove tables
for removed in old_names.difference(&new_names) {
let removed_tables = old_names.difference(&new_names);
for removed in removed_tables.clone() {
let removed: &str = removed.as_ref();
let table = old.tables.get(removed).expect("no table").clone();
ops.push(Operation::RemoveTableConstraints(table));
}
for removed in removed_tables {
ops.push(Operation::RemoveTable((*removed).to_string()));
}

Expand Down
2 changes: 1 addition & 1 deletion butane_core/src/migrations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ where
Operation::ChangeColumn(table_name, _, _) => {
modified_tables.push(table_name.clone())
}
Operation::RemoveTable(_) => {}
Operation::RemoveTable(_) | Operation::RemoveTableConstraints(_) => {}
}
}

Expand Down

0 comments on commit 6ce56c8

Please sign in to comment.