use crate::checks::pg_helpers::{NodeEnum, ObjectType};
use crate::checks::{Check, Config, MigrationContext};
use crate::violation::Violation;
pub struct RenameSchemaCheck;
impl Check for RenameSchemaCheck {
fn check(&self, node: &NodeEnum, _config: &Config, _ctx: &MigrationContext) -> Vec<Violation> {
let NodeEnum::RenameStmt(rename) = node else {
return vec![];
};
if rename.rename_type != ObjectType::ObjectSchema as i32 {
return vec![];
}
let old_name = &rename.subname;
let new_name = &rename.newname;
vec![Violation::new(
"RENAME SCHEMA",
format!(
"Renaming schema '{old_name}' to '{new_name}' breaks all application code, ORM \
models, and connection strings that reference any object within the schema. Every \
qualified reference of the form '{old_name}.<object>' across the entire application \
will fail immediately after the rename is applied."
),
format!(
r"Avoid renaming schemas in production. If a rename is unavoidable:
1. Add a search_path alias so both names resolve temporarily:
ALTER DATABASE mydb SET search_path TO {new_name}, {old_name};
2. Update all application code, ORM models, and connection strings to use the new schema name.
3. Deploy the updated application.
4. Remove the search_path alias once all references have been updated."
),
)]
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{assert_allows, assert_detects_violation};
#[test]
fn test_detects_rename_schema() {
assert_detects_violation!(
RenameSchemaCheck,
"ALTER SCHEMA myschema RENAME TO newschema;",
"RENAME SCHEMA"
);
}
#[test]
fn test_detects_rename_public_schema() {
assert_detects_violation!(
RenameSchemaCheck,
"ALTER SCHEMA public RENAME TO app;",
"RENAME SCHEMA"
);
}
#[test]
fn test_ignores_rename_column() {
assert_allows!(
RenameSchemaCheck,
"ALTER TABLE users RENAME COLUMN email TO email_address;"
);
}
#[test]
fn test_ignores_rename_table() {
assert_allows!(RenameSchemaCheck, "ALTER TABLE users RENAME TO customers;");
}
#[test]
fn test_ignores_other_statements() {
assert_allows!(
RenameSchemaCheck,
"CREATE TABLE users (id SERIAL PRIMARY KEY);"
);
}
}