Skip to content

Commit

Permalink
sql: Skip constraints in pg_constraint that are being dropped.
Browse files Browse the repository at this point in the history
When querying the `pg_catalog.pg_constraint` table during the process of
dropping a constraint, the query could fail under certain conditions. For
example, if the declarative schema changer (DSC) is in the middle of dropping a
check constraint, the query could produce the following error:
```
ERROR: column "crdb_internal_column_2_name_placeholder" does not exist, referenced in "crdb_internal_column_2_name_placeholder IS NOT NULL" (SQLSTATE 42703)
```

This issue arises because, when the DSC is also dropping the column associated
with the constraint, it removes the column's name from the descriptor.
Consequently, any expressions referencing the column are updated with a
placeholder name. While the DSC ensures that the column is no longer visible,
the `pg_constraint` virtual table inspects the descriptor directly,
encountering the placeholder name and attempting to resolve it. This fix
ensures that constraints in the process of being dropped are skipped in
`pg_constraint`, preventing such errors.

This shows up in the schema changer workload because it uses pg_constraint when
building out the random op to run.

Epic: none
Closes #137513
Release note (bug fix): Fixed a bug where querying the
`pg_catalog.pg_constraint` table while the schema changer was dropping a
constraint could result in a query error.
  • Loading branch information
spilchen committed Dec 20, 2024
1 parent 6307ed7 commit 47f252f
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 0 deletions.
7 changes: 7 additions & 0 deletions pkg/sql/pg_catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,13 @@ func populateTableConstraints(
namespaceOid := schemaOid(sc.GetID())
tblOid := tableOid(table.GetID())
for _, c := range table.AllConstraints() {
// Ignore constraints that are being dropped. When a column is dropped alongside
// a constraint, the DSC may insert a placeholder name into the constraint,
// which can interfere with column name lookups in this function.
if c.GetConstraintValidity() == descpb.ConstraintValidity_Dropping {
continue
}

conoid := tree.DNull
contype := tree.DNull
conindid := oidZero
Expand Down
8 changes: 8 additions & 0 deletions pkg/sql/schemachanger/dml_injection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,14 @@ func TestAlterTableDMLInjection(t *testing.T) {
},
schemaChange: "ALTER TABLE tbl ALTER PRIMARY KEY USING COLUMNS (insert_phase_ordinal, operation_phase_ordinal, operation) USING HASH",
},
{
desc: "drop a column with a check constraint while querying pg_constraint",
setup: []string{
"ALTER TABLE tbl ADD COLUMN i INT CHECK (i is NOT NULL) DEFAULT 10",
},
schemaChange: "ALTER TABLE tbl DROP COLUMN i",
query: "select * from pg_catalog.pg_constraint",
},
{
desc: "create index",
schemaChange: "CREATE INDEX idx ON tbl (val)",
Expand Down

0 comments on commit 47f252f

Please sign in to comment.