Skip to content

Commit 9755476

Browse files
craig[bot]spilchen
andcommitted
Merge #147773
147773: sql: skip dropped constraints in introspection queries r=spilchen a=spilchen Dropped constraints remain in table descriptors until the schema change job fully completes. During this time, introspection queries (such as crdb_internal.create_statements) may encounter these constraints, even if they reference columns that are also in the process of being dropped. This can result in errors. This change updates the introspection logic to ignore constraints that are marked for deletion, preventing such failures. Informs #147514 Epic: None Release note (bug fix): Fixed a bug where introspection queries could fail if a dropped constraint referenced a column that was also being dropped. Co-authored-by: Matt Spilchen <[email protected]>
2 parents 985dffd + 3bd1beb commit 9755476

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

pkg/sql/schemachanger/dml_injection_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,20 @@ func TestAlterTableDMLInjection(t *testing.T) {
410410
schemaChange: "ALTER TABLE tbl DROP COLUMN i",
411411
query: "select * from pg_catalog.pg_constraint",
412412
},
413+
{
414+
desc: "drop a column with a check constraint while querying crdb_internal.create_statements",
415+
setup: []string{
416+
"ALTER TABLE tbl ADD COLUMN i INT CHECK (i is NOT NULL) DEFAULT 10",
417+
},
418+
schemaChange: "ALTER TABLE tbl DROP COLUMN i",
419+
// Run a query against crdb_internal.create_statements. We don't
420+
// care about the result — only that it doesn't fail. This is
421+
// valuable when dropping constraints because create_statements performs
422+
// descriptor introspection, including rendering expressions for
423+
// check constraints. If a column in the check constraint is in the
424+
// process of being dropped it will have a placeholder name.
425+
query: `SELECT * FROM "".crdb_internal.create_statements`,
426+
},
413427
{
414428
desc: "create index",
415429
schemaChange: "CREATE INDEX idx ON tbl (val)",

pkg/sql/show_create_clauses.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,12 @@ func showConstraintClause(
826826
if e.IsHashShardingConstraint() && !e.IsConstraintUnvalidated() {
827827
continue
828828
}
829+
// Don't include the constraint if it's in the process of being dropped. If
830+
// the column is being dropped with the constraint, it might not even have a
831+
// valid name.
832+
if e.GetConstraintValidity() == descpb.ConstraintValidity_Dropping {
833+
continue
834+
}
829835
f.WriteString(",\n\t")
830836
if len(e.GetName()) > 0 {
831837
f.WriteString("CONSTRAINT ")
@@ -837,7 +843,7 @@ func showConstraintClause(
837843
ctx, desc, e.GetExpr(), evalCtx, semaCtx, sessionData, exprFmtFlags,
838844
)
839845
if err != nil {
840-
return err
846+
return errors.Wrapf(err, "failed to format check constraint for table %s", desc.GetName())
841847
}
842848
f.WriteString(expr)
843849
f.WriteString(")")
@@ -846,6 +852,9 @@ func showConstraintClause(
846852
}
847853
}
848854
for _, c := range desc.UniqueConstraintsWithoutIndex() {
855+
if c.GetConstraintValidity() == descpb.ConstraintValidity_Dropping {
856+
continue
857+
}
849858
f.WriteString(",\n\t")
850859
if len(c.GetName()) > 0 {
851860
f.WriteString("CONSTRAINT ")
@@ -865,7 +874,7 @@ func showConstraintClause(
865874
ctx, desc, c.GetPredicate(), evalCtx, semaCtx, sessionData, exprFmtFlags,
866875
)
867876
if err != nil {
868-
return err
877+
return errors.Wrapf(err, "failed to format unique constraint without index for table %s", desc.GetName())
869878
}
870879
f.WriteString(pred)
871880
}

0 commit comments

Comments
 (0)