Skip to content

Commit b5cfc9d

Browse files
rebeliceclaude
andcommitted
pg/catalog: cascade-drop indexes and constraints when dropping a column
When a column that is part of an index or constraint is dropped with CASCADE, properly remove the dependent indexes and constraints. Without CASCADE, return an error about dependent objects. pg: src/backend/commands/tablecmds.c — ATExecDropColumn Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8a7af47 commit b5cfc9d

1 file changed

Lines changed: 54 additions & 0 deletions

File tree

pg/catalog/alter.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,60 @@ func (c *Catalog) atDropColumn(schema *Schema, rel *Relation, colName string, ca
972972
c.dropDependents('r', rel.OID)
973973
}
974974

975+
// Drop indexes that reference this column.
976+
// pg: src/backend/commands/tablecmds.c — ATExecDropColumn (dependency check)
977+
attNum := col.AttNum
978+
var indexesToDrop []*Index
979+
for _, ix := range c.indexesByRel[rel.OID] {
980+
for _, a := range ix.Columns {
981+
if a == attNum {
982+
indexesToDrop = append(indexesToDrop, ix)
983+
break
984+
}
985+
}
986+
}
987+
if len(indexesToDrop) > 0 && !cascade {
988+
// Without CASCADE, PG errors if there are dependent indexes/constraints.
989+
// Find the first constraint-backed index to give a helpful error.
990+
for _, ix := range indexesToDrop {
991+
if ix.ConstraintOID != 0 {
992+
if con := c.constraints[ix.ConstraintOID]; con != nil {
993+
return errDependentObjects("column", fmt.Sprintf("%s, constraint %s depends on column %q", colName, con.Name, colName))
994+
}
995+
}
996+
}
997+
return errDependentObjects("column", colName)
998+
}
999+
for _, ix := range indexesToDrop {
1000+
// If the index backs a constraint, drop the constraint too.
1001+
if ix.ConstraintOID != 0 {
1002+
if con := c.constraints[ix.ConstraintOID]; con != nil {
1003+
c.removeConstraint(schema, con)
1004+
}
1005+
}
1006+
c.removeIndex(schema, ix.Name, ix)
1007+
}
1008+
1009+
// Drop constraints that reference this column (non-index-backed, e.g. CHECK).
1010+
var consToDrop []*Constraint
1011+
for _, con := range c.consByRel[rel.OID] {
1012+
if con.IndexOID != 0 {
1013+
continue // already handled above
1014+
}
1015+
for _, a := range con.Columns {
1016+
if a == attNum {
1017+
consToDrop = append(consToDrop, con)
1018+
break
1019+
}
1020+
}
1021+
}
1022+
if len(consToDrop) > 0 && !cascade {
1023+
return errDependentObjects("column", colName)
1024+
}
1025+
for _, con := range consToDrop {
1026+
c.removeConstraint(schema, con)
1027+
}
1028+
9751029
// Remove the column.
9761030
rel.Columns = append(rel.Columns[:idx], rel.Columns[idx+1:]...)
9771031
c.renumberColumns(rel)

0 commit comments

Comments
 (0)