fix(postgresql): allow table edits with unchanged triggers

Closes #4218
This commit is contained in:
t8y2 2026-08-02 18:34:03 +00:00
parent 1f0e20e150
commit cc7b2b17c5
No known key found for this signature in database
2 changed files with 70 additions and 1 deletions

View File

@ -3558,6 +3558,69 @@ fn builds_mysql_trigger_changes() {
);
}
#[test]
fn unchanged_postgres_trigger_does_not_block_column_rename() {
let mut renamed = column("display_name");
renamed.original = Some(ColumnInfo {
name: "name".to_string(),
data_type: "varchar(255)".to_string(),
is_nullable: true,
column_default: None,
is_primary_key: false,
extra: None,
comment: None,
..Default::default()
});
let mut existing = trigger("users_audit", "AFTER", "UPDATE", "EXECUTE FUNCTION audit_users()");
existing.original = Some(TriggerInfo {
name: "users_audit".to_string(),
event: "UPDATE".to_string(),
timing: "AFTER".to_string(),
statement: Some("EXECUTE FUNCTION audit_users()".to_string()),
});
let result = build_table_structure_change_sql(TableStructureSqlOptions {
database_type: Some(DatabaseType::Postgres),
schema: Some("public".to_string()),
table_name: "users".to_string(),
columns: vec![renamed],
indexes: Vec::new(),
foreign_keys: Vec::new(),
triggers: vec![existing],
table_comment: None,
original_table_comment: None,
});
assert_eq!(result.warnings, Vec::<String>::new());
assert_eq!(result.statements, vec!["ALTER TABLE \"public\".\"users\" RENAME COLUMN \"name\" TO \"display_name\";"]);
}
#[test]
fn changed_postgres_trigger_remains_unsupported() {
let mut existing = trigger("users_audit", "AFTER", "INSERT", "EXECUTE FUNCTION audit_users()");
existing.original = Some(TriggerInfo {
name: "users_audit".to_string(),
event: "UPDATE".to_string(),
timing: "AFTER".to_string(),
statement: Some("EXECUTE FUNCTION audit_users()".to_string()),
});
let result = build_table_structure_change_sql(TableStructureSqlOptions {
database_type: Some(DatabaseType::Postgres),
schema: Some("public".to_string()),
table_name: "users".to_string(),
columns: Vec::new(),
indexes: Vec::new(),
foreign_keys: Vec::new(),
triggers: vec![existing],
table_comment: None,
original_table_comment: None,
});
assert!(result.statements.is_empty());
assert_eq!(result.warnings, vec!["Editing triggers is not supported for postgres from this editor."]);
}
#[test]
fn rejects_editing_existing_oracle_trigger_without_complete_source() {
let mut existing = trigger(

View File

@ -10,7 +10,9 @@ pub(super) fn build_trigger_sql(options: &TableStructureSqlOptions, warnings: &m
let dialect = super::dialect::capabilities_for(options.database_type).dialect;
let database_label = database_label(options.database_type);
if !matches!(dialect, StructureDialect::Mysql | StructureDialect::Oracle) {
warnings.push(format!("Editing triggers is not supported for {database_label} from this editor."));
if options.triggers.iter().any(has_trigger_edit) {
warnings.push(format!("Editing triggers is not supported for {database_label} from this editor."));
}
return Vec::new();
}
@ -52,6 +54,10 @@ pub(super) fn build_trigger_sql(options: &TableStructureSqlOptions, warnings: &m
statements
}
fn has_trigger_edit(trigger: &EditableStructureTrigger) -> bool {
trigger.marked_for_drop || trigger.original.as_ref().map_or(true, |original| has_trigger_change(trigger, original))
}
fn has_trigger_change(trigger: &EditableStructureTrigger, original: &TriggerInfo) -> bool {
clean(&trigger.name) != clean(&original.name)
|| normalize_keyword(&trigger.timing) != normalize_keyword(&original.timing)