=== Applying patches on top of PostgreSQL commit ID 3e4d868615408370fe6c2977c32f45a47c372b00 === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Thu Feb 20 19:28:25 UTC 2025 On branch cf/5285 nothing to commit, working tree clean === applying patch ./0001-Add-ATAlterConstraint-struct-for-ALTER-.-CONSTRAINT.patch Applied patch to 'src/backend/commands/tablecmds.c' with conflicts. Applied patch to 'src/backend/parser/gram.y' with conflicts. Applied patch to 'src/include/nodes/parsenodes.h' with conflicts. Applied patch to 'src/tools/pgindent/typedefs.list' cleanly. U src/backend/commands/tablecmds.c U src/backend/parser/gram.y U src/include/nodes/parsenodes.h diff --cc src/backend/commands/tablecmds.c index 9d8754be7e,072a612996..0000000000 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@@ -390,10 -390,13 +390,20 @@@ static void AlterSeqNamespaces(Relatio Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved, LOCKMODE lockmode); static ObjectAddress ATExecAlterConstraint(Relation rel, ATAlterConstraint *cmdcon, ++<<<<<<< ours + bool recurse, LOCKMODE lockmode); +static bool ATExecAlterConstraintInternal(ATAlterConstraint *cmdcon, Relation conrel, + Relation tgrel, Relation rel, HeapTuple contuple, + bool recurse, List **otherrelids, LOCKMODE lockmode); ++======= + bool recurse, bool recursing, LOCKMODE lockmode); + static bool ATExecAlterConstrDeferrability(ATAlterConstraint *cmdcon, Relation conrel, + Relation tgrel, Relation rel, HeapTuple contuple, + List **otherrelids, LOCKMODE lockmode); + static void ATExecAlterConstrDeferrabilityRecurse(ATAlterConstraint *cmdcon, Relation conrel, + Relation tgrel, Relation rel, HeapTuple contuple, + List **otherrelids, LOCKMODE lockmode); ++>>>>>>> theirs static void AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel, bool deferrable, bool initdeferred, List **otherrelids); @@@ -5451,7 -5452,7 +5461,11 @@@ ATExecCmd(List **wqueue, AlteredTableIn case AT_AlterConstraint: /* ALTER CONSTRAINT */ address = ATExecAlterConstraint(rel, castNode(ATAlterConstraint, cmd->def), ++<<<<<<< ours + cmd->recurse, lockmode); ++======= + false, false, lockmode); ++>>>>>>> theirs break; case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */ address = ATExecValidateConstraint(wqueue, rel, cmd->name, cmd->recurse, @@@ -11803,7 -11804,7 +11817,11 @@@ GetForeignKeyCheckTriggers(Relation tri */ static ObjectAddress ATExecAlterConstraint(Relation rel, ATAlterConstraint *cmdcon, bool recurse, ++<<<<<<< ours + LOCKMODE lockmode) ++======= + bool recursing, LOCKMODE lockmode) ++>>>>>>> theirs { Relation conrel; Relation tgrel; @@@ -11813,17 -11814,6 +11831,20 @@@ Form_pg_constraint currcon; ObjectAddress address; List *otherrelids = NIL; ++<<<<<<< ours + + /* + * Disallow altering ONLY a partitioned table, as it would make no sense. + * This is okay for legacy inheritance. + */ + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && !recurse) + ereport(ERROR, + errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("constraint must be altered in child tables too"), + errhint("Do not specify the ONLY keyword.")); + ++======= ++>>>>>>> theirs conrel = table_open(ConstraintRelationId, RowExclusiveLock); tgrel = table_open(TriggerRelationId, RowExclusiveLock); @@@ -11907,19 -11897,29 +11928,41 @@@ address = InvalidObjectAddress; /* - * Do the actual catalog work. We can skip changing if already in the - * desired state, but not if a partitioned table: partitions need to be - * processed regardless, in case they had the constraint locally changed. + * Do the actual catalog work, and recurse if necessary. + */ ++<<<<<<< ours + if (ATExecAlterConstraintInternal(cmdcon, conrel, tgrel, rel, contuple, + recurse, &otherrelids, lockmode)) + ObjectAddressSet(address, ConstraintRelationId, currcon->oid); + + /* + * ATExecAlterConstraintInternal already invalidated relcache for the + * relations having the constraint itself; here we also invalidate for + * relations that have any triggers that are part of the constraint. */ + foreach_oid(relid, otherrelids) + CacheInvalidateRelcacheByRelid(relid); ++======= + if (cmdcon->deferrability) + { + if (currcon->condeferrable != cmdcon->deferrable || + currcon->condeferred != cmdcon->initdeferred || + rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + { + if (ATExecAlterConstrDeferrability(cmdcon, conrel, tgrel, rel, contuple, + &otherrelids, lockmode)) + ObjectAddressSet(address, ConstraintRelationId, currcon->oid); + } + + /* + * ATExecAlterConstrDeferrability already invalidated relcache for the + * relations having the constraint itself; here we also invalidate for + * relations that have any triggers that are part of the constraint. + */ + foreach_oid(relid, otherrelids) + CacheInvalidateRelcacheByRelid(relid); + } ++>>>>>>> theirs systable_endscan(scan); @@@ -11941,12 -11941,13 +11984,18 @@@ * but existing releases don't do that.) */ static bool ++<<<<<<< ours +ATExecAlterConstraintInternal(ATAlterConstraint *cmdcon, Relation conrel, + Relation tgrel, Relation rel, HeapTuple contuple, + bool recurse, List **otherrelids, LOCKMODE lockmode) ++======= + ATExecAlterConstrDeferrability(ATAlterConstraint *cmdcon, Relation conrel, + Relation tgrel, Relation rel, HeapTuple contuple, + List **otherrelids, LOCKMODE lockmode) ++>>>>>>> theirs { Form_pg_constraint currcon; - Oid conoid; - Oid refrelid; + Oid refrelid = InvalidOid; bool changed = false; /* since this function recurses, it could be driven to stack overflow */ @@@ -11994,47 -11994,64 +12043,100 @@@ /* * If the table at either end of the constraint is partitioned, we need to - * recurse and handle every constraint that is a child of this one. + * handle every constraint that is a child of this one. * - * (This assumes that the recurse flag is forcibly set for partitioned - * tables, and not set for legacy inheritance, though we don't check for - * that here.) - */ + * Note that this doesn't handle recursion the normal way, viz. by + * scanning the list of child relations and recursing; instead it uses the + * conparentid relationships. This may need to be reconsidered. + */ ++<<<<<<< ours + if (recurse && changed && + (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE || + (OidIsValid(refrelid) && + get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE))) + { + ScanKeyData pkey; + SysScanDesc pscan; + HeapTuple childtup; + + ScanKeyInit(&pkey, + Anum_pg_constraint_conparentid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(currcon->oid)); + + pscan = systable_beginscan(conrel, ConstraintParentIndexId, + true, NULL, 1, &pkey); + + while (HeapTupleIsValid(childtup = systable_getnext(pscan))) + { + Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup); + Relation childrel; + + childrel = table_open(childcon->conrelid, lockmode); + ATExecAlterConstraintInternal(cmdcon, conrel, tgrel, childrel, childtup, + recurse, otherrelids, lockmode); + table_close(childrel, NoLock); + } + + systable_endscan(pscan); + } ++======= + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE || + get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE) + ATExecAlterConstrDeferrabilityRecurse(cmdcon, conrel, tgrel, rel, contuple, + otherrelids, lockmode); ++>>>>>>> theirs return changed; } /* ++<<<<<<< ours ++======= + * Invokes ATExecAlterConstrDeferrability for each constraint that is a child + * of the specified constraint. + * + * The arguments to this function have the same meaning as the arguments to + * ATExecAlterConstrDeferrability. + */ + static void + ATExecAlterConstrDeferrabilityRecurse(ATAlterConstraint *cmdcon, Relation conrel, + Relation tgrel, Relation rel, HeapTuple contuple, + List **otherrelids, LOCKMODE lockmode) + { + Form_pg_constraint currcon; + Oid conoid; + ScanKeyData pkey; + SysScanDesc pscan; + HeapTuple childtup; + + currcon = (Form_pg_constraint) GETSTRUCT(contuple); + conoid = currcon->oid; + + ScanKeyInit(&pkey, + Anum_pg_constraint_conparentid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(conoid)); + + pscan = systable_beginscan(conrel, ConstraintParentIndexId, + true, NULL, 1, &pkey); + + while (HeapTupleIsValid(childtup = systable_getnext(pscan))) + { + Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup); + Relation childrel; + + childrel = table_open(childcon->conrelid, lockmode); + ATExecAlterConstrDeferrability(cmdcon, conrel, tgrel, childrel, childtup, + otherrelids, lockmode); + table_close(childrel, NoLock); + } + + systable_endscan(pscan); + } + + /* ++>>>>>>> theirs * A subroutine of ATExecAlterConstrDeferrability that updated constraint * trigger's deferrability. * diff --cc src/backend/parser/gram.y index 7d99c9355c,268db669c8..0000000000 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@@ -2662,7 -2662,7 +2662,11 @@@ alter_table_cmd n->subtype = AT_AlterConstraint; n->def = (Node *) c; c->conname = $3; ++<<<<<<< ours + c->alterDeferrability = true; ++======= + c->deferrability = true; ++>>>>>>> theirs processCASbits($4, @4, "ALTER CONSTRAINT statement", &c->deferrable, &c->initdeferred, diff --cc src/include/nodes/parsenodes.h index 0b208f51bd,eec7b22d0b..0000000000 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@@ -2490,7 -2490,7 +2490,11 @@@ typedef struct ATAlterConstrain { NodeTag type; char *conname; /* Constraint name */ ++<<<<<<< ours + bool alterDeferrability; /* changing deferrability properties? */ ++======= + bool deferrability; /* changing deferrability properties? */ ++>>>>>>> theirs bool deferrable; /* DEFERRABLE? */ bool initdeferred; /* INITIALLY DEFERRED? */ } ATAlterConstraint;