Hi all, Running installcheck on an instance with log_min_messages = DEBUG1, I can bump into the following assertion failure: #2 0x000056145231e82c in ExceptionalCondition (conditionName=0x56145258ae0b "!(strvalue != ((void *)0))", errorType=0x56145258adfb "FailedAssertion", fileName=0x56145258adf0 "snprintf.c", lineNumber=440) at assert.c:54 [...] #7 0x000056145231f518 in errmsg (fmt=0x5614524dac60 "validating foreign key constraint \"%s\"") at elog.c:796 #8 0x0000561451f6ab54 in validateForeignKeyConstraint (conname=0x0, rel=0x7f12833ca750, pkrel=0x7f12833cc468, pkindOid=36449, constraintOid=36466) at tablecmds.c:8566 #9 0x0000561451f61589 in ATRewriteTables (parsetree=0x561453bde5e0, wqueue=0x7ffe8f1d55e8, lockmode=8) at tablecmds.c:4549
Looking at the stack trace there is this log in validateForeignKeyConstraint: ereport(DEBUG1, (errmsg("validating foreign key constraint \"%s\"", conname))); However conname is set to NULL in this code path. This test case allows to reproduce easily the failure: CREATE TABLE fk_notpartitioned_pk (a int, b int, PRIMARY KEY (a, b)); CREATE TABLE fk_partitioned_fk (b int, a int) PARTITION BY RANGE (a, b); CREATE TABLE fk_partitioned_fk_1 (b int, a int); ALTER TABLE fk_partitioned_fk ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk; -- crash ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_1 FOR VALUES FROM (1,1) TO (2,2); From what I can see the problem comes from CloneForeignKeyConstraint which forgets to assign the constraint name when cloning the FK definition. While looking at the ATTACH PARTITION code, I have noticed that a variable gets overridden, which is in my opinion bad style. So the problem is rather close to what Tom has fixed in 3d0f68dd it seems. Attached is a patch for all that, with which installcheck-world passes for me. I am surprised this was not noticed before, the recent snprintf stanza is nicely helping, and this would need to be back-patched down to v11. Thanks, -- Michael
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 6781b00c6e..2063abb8ae 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -574,6 +574,7 @@ CloneForeignKeyConstraints(Oid parentId, Oid relationId, List **cloned) fkconstraint = makeNode(Constraint); /* for now this is all we need */ + fkconstraint->conname = pstrdup(NameStr(constrForm->conname)); fkconstraint->fk_upd_action = constrForm->confupdtype; fkconstraint->fk_del_action = constrForm->confdeltype; fkconstraint->deferrable = constrForm->condeferrable; diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index c145385f84..7df1fc2a76 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -14275,21 +14275,21 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) RelationGetRelid(attachrel), &cloned); foreach(l, cloned) { - ClonedConstraint *cloned = lfirst(l); + ClonedConstraint *clonedcon = lfirst(l); NewConstraint *newcon; Relation clonedrel; AlteredTableInfo *parttab; - clonedrel = relation_open(cloned->relid, NoLock); + clonedrel = relation_open(clonedcon->relid, NoLock); parttab = ATGetQueueEntry(wqueue, clonedrel); newcon = (NewConstraint *) palloc0(sizeof(NewConstraint)); - newcon->name = cloned->constraint->conname; + newcon->name = clonedcon->constraint->conname; newcon->contype = CONSTR_FOREIGN; - newcon->refrelid = cloned->refrelid; - newcon->refindid = cloned->conindid; - newcon->conid = cloned->conid; - newcon->qual = (Node *) cloned->constraint; + newcon->refrelid = clonedcon->refrelid; + newcon->refindid = clonedcon->conindid; + newcon->conid = clonedcon->conid; + newcon->qual = (Node *) clonedcon->constraint; parttab->constraints = lappend(parttab->constraints, newcon);
signature.asc
Description: PGP signature