## Code Analysis ### CASCADE is rejected during constraint-drop conversion `server/ast/constraint_table_def.go:65-90` ```go func nodeAlterTableDropConstraint( ctx *Context, node *tree.AlterTableDropConstraint, tableName vitess.TableName, ifExists bool) (*vitess.DDL, error) { if node.DropBehavior == tree.DropCascade { return nil, errors.Errorf("CASCADE is not yet supported for drop constraint") } return &vitess.DDL{ Action: "alter", Table: tableName, IfExists: ifExists, ConstraintAction: "drop", ConstraintIfExists: node.IfExists, TableSpec: &vitess.TableSpec{ Constraints: []*vitess.ConstraintDefinition{ {Name: node.Constraint.String()}, }, }, }, nil } ``` The parser-side conversion explicitly returns an unsupported-feature error whenever the requested drop behavior is CASCADE. RESTRICT is not encoded in this conversion; it is emitted as a generic constraint-drop DDL. ### Unique constraints are delegated to index dropping `server/analyzer/resolve_drop_constraint.go:75-110` ```go if it, ok := table.(sql.IndexAddressable); ok { indexes, err := it.GetIndexes(ctx) if err != nil { return nil, transform.SameTree, err } for _, index := range indexes { if index.ID() != "PRIMARY" && index.IsUnique() && index.ID() == dropConstraint.Name { newNode, err := plan.NewAlterDropIndex(rt.Database(), rt, dropConstraint.IfExists, index.ID()). WithTargetSchema(rt.Schema(ctx)) return newNode, transform.NewTree, err } } } ``` The analyzer resolves a named non-primary unique constraint to an index-drop plan. This excerpt contains no dependent-foreign-key handling or translation to PostgreSQL's dependent-object SQLSTATE, which explains why the RESTRICT operation can surface the storage/index error instead of 2BP01. ### Result The source path supports the reported outcomes: CASCADE is explicitly unsupported, while the RESTRICT path delegates the unique constraint to index handling without a visible dependency-error translation. ### Observed execution #### qualified drop requests ```sql ALTER TABLE ONLY auth.parent DROP CONSTRAINT parent_email_key RESTRICT; ALTER TABLE ONLY auth.parent DROP CONSTRAINT parent_email_key CASCADE; ``` #### RESTRICT response ```text ERROR: cannot drop index: `parent_email_key` is used by foreign key `child_parent_email_fkey` restrict_exit=1 ``` #### state after RESTRICT ```text schema_name | table_name | conname | contype -------------+------------+-------------------------+--------- auth | child | child_parent_email_fkey | f auth | child | child_pkey | p auth | parent | parent_email_key | u auth | parent | parent_pkey | p (4 rows) ``` ```text schemaname | tablename | indexname ------------+-----------+------------------------- auth | child | child_parent_email_fkey auth | child | child_pkey auth | parent | parent_email_key auth | parent | parent_lower_email_idx auth | parent | parent_pkey (5 rows) ``` The captured database evidence identifies the returned error as `XX000`, not the expected dependent-object code `2BP01`. The parent unique constraint, child foreign key, supporting indexes, and unrelated `parent_lower_email_idx` remained after the rejected operation. #### CASCADE response ```text ERROR: CASCADE is not yet supported for drop constraint cascade_exit=1 ``` #### state after CASCADE ```text schema_name | table_name | conname | contype -------------+------------+-------------------------+--------- auth | child | child_parent_email_fkey | f auth | child | child_pkey | p auth | parent | parent_email_key | u auth | parent | parent_pkey | p (4 rows) ``` The index catalog also still contained `parent_lower_email_idx` and the supporting indexes after CASCADE returned its unsupported-feature error. ### Final result REV-5 failed because RESTRICT rejected the dependent drop with `XX000` instead of `2BP01`, and CASCADE was unsupported; both operations preserved the existing constraints and indexes.