Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit80d7f99

Browse files
committed
Add ATAlterConstraint struct for ALTER .. CONSTRAINT
Replace the use of Constraint with a new ATAlterConstraint struct, whichallows us to pass additional information. No functionality is added bythis commit. This is necessary for future work that allows alteringconstraints in other ways.I (Álvaro) took the liberty of restructuring the code for ALTERCONSTRAINT beyond what Amul did. The original coding before Amul'spatch was unnecessarily baroque, and this change makes things simplerby removing one level of subroutine. Also, partly remove the assumptionthat only partitioned tables are relevant (by passing sensible 'recurse'arguments) and no longer ignore whether ONLY was specified. I say'partly' because the current coding only walks down via the 'conparentid'relationship, which is only used for partitioned tables; but futurepatches could handle ONLY or not for other types of constraint changesfor legacy inheritance trees too.Author: Amul Sul <sulamul@gmail.com>Author: Álvaro Herrera <alvherre@alvh.no-ip.org>Discussion:https://postgr.es/m/CAAJ_b94bfgPV-8Mw_HwSBeheVwaK9=5s+7+KbBj_NpwXQFgDGg@mail.gmail.com
1 parente983ee9 commit80d7f99

File tree

4 files changed

+103
-106
lines changed

4 files changed

+103
-106
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 82 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -389,17 +389,14 @@ static void AlterIndexNamespaces(Relation classRel, Relation rel,
389389
static void AlterSeqNamespaces(Relation classRel, Relation rel,
390390
Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved,
391391
LOCKMODE lockmode);
392-
static ObjectAddress ATExecAlterConstraint(Relation rel,AlterTableCmd *cmd,
393-
bool recurse,bool recursing,LOCKMODE lockmode);
394-
static boolATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
395-
Relationrel, HeapTuple contuple, List **otherrelids,
396-
LOCKMODE lockmode);
392+
static ObjectAddress ATExecAlterConstraint(Relation rel,ATAlterConstraint *cmdcon,
393+
bool recurse, LOCKMODE lockmode);
394+
static boolATExecAlterConstraintInternal(ATAlterConstraint *cmdcon, Relation conrel,
395+
Relationtgrel, Relation rel, HeapTuple contuple,
396+
bool recurse, List **otherrelids, LOCKMODE lockmode);
397397
static void AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
398398
bool deferrable, bool initdeferred,
399399
List **otherrelids);
400-
static void ATExecAlterChildConstr(Constraint *cmdcon, Relation conrel, Relation tgrel,
401-
Relation rel, HeapTuple contuple, List **otherrelids,
402-
LOCKMODE lockmode);
403400
static ObjectAddress ATExecValidateConstraint(List **wqueue,
404401
Relation rel, char *constrName,
405402
bool recurse, bool recursing, LOCKMODE lockmode);
@@ -5170,6 +5167,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
51705167
ATSimplePermissions(cmd->subtype, rel,
51715168
ATT_TABLE | ATT_PARTITIONED_TABLE);
51725169
/* Recursion occurs during execution phase */
5170+
if (recurse)
5171+
cmd->recurse = true;
51735172
pass = AT_PASS_MISC;
51745173
break;
51755174
case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */
@@ -5450,7 +5449,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
54505449
lockmode);
54515450
break;
54525451
case AT_AlterConstraint:/* ALTER CONSTRAINT */
5453-
address = ATExecAlterConstraint(rel, cmd, false, false, lockmode);
5452+
address = ATExecAlterConstraint(rel, castNode(ATAlterConstraint,
5453+
cmd->def),
5454+
cmd->recurse, lockmode);
54545455
break;
54555456
case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */
54565457
address = ATExecValidateConstraint(wqueue, rel, cmd->name, cmd->recurse,
@@ -11801,10 +11802,9 @@ GetForeignKeyCheckTriggers(Relation trigrel,
1180111802
* InvalidObjectAddress.
1180211803
*/
1180311804
static ObjectAddress
11804-
ATExecAlterConstraint(Relation rel,AlterTableCmd *cmd, bool recurse,
11805-
bool recursing,LOCKMODE lockmode)
11805+
ATExecAlterConstraint(Relation rel,ATAlterConstraint *cmdcon, bool recurse,
11806+
LOCKMODE lockmode)
1180611807
{
11807-
Constraint *cmdcon;
1180811808
Relationconrel;
1180911809
Relationtgrel;
1181011810
SysScanDesc scan;
@@ -11813,9 +11813,17 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse,
1181311813
Form_pg_constraint currcon;
1181411814
ObjectAddress address;
1181511815
List *otherrelids = NIL;
11816-
ListCell *lc;
1181711816

11818-
cmdcon = castNode(Constraint, cmd->def);
11817+
/*
11818+
* Disallow altering ONLY a partitioned table, as it would make no sense.
11819+
* This is okay for legacy inheritance.
11820+
*/
11821+
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && !recurse)
11822+
ereport(ERROR,
11823+
errcode(ERRCODE_INVALID_TABLE_DEFINITION),
11824+
errmsg("constraint must be altered in child tables too"),
11825+
errhint("Do not specify the ONLY keyword."));
11826+
1181911827

1182011828
conrel = table_open(ConstraintRelationId, RowExclusiveLock);
1182111829
tgrel = table_open(TriggerRelationId, RowExclusiveLock);
@@ -11896,28 +11904,22 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse,
1189611904
errhint("You may alter the constraint it derives from instead.")));
1189711905
}
1189811906

11907+
address = InvalidObjectAddress;
11908+
1189911909
/*
11900-
* Do the actual catalog work. We can skip changing if already in the
11901-
* desired state, but not if a partitioned table: partitions need to be
11902-
* processed regardless, in case they had the constraint locally changed.
11910+
* Do the actual catalog work, and recurse if necessary.
1190311911
*/
11904-
address = InvalidObjectAddress;
11905-
if (currcon->condeferrable != cmdcon->deferrable ||
11906-
currcon->condeferred != cmdcon->initdeferred ||
11907-
rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
11908-
{
11909-
if (ATExecAlterConstrRecurse(cmdcon, conrel, tgrel, rel, contuple,
11910-
&otherrelids, lockmode))
11911-
ObjectAddressSet(address, ConstraintRelationId, currcon->oid);
11912-
}
11912+
if (ATExecAlterConstraintInternal(cmdcon, conrel, tgrel, rel, contuple,
11913+
recurse, &otherrelids, lockmode))
11914+
ObjectAddressSet(address, ConstraintRelationId, currcon->oid);
1191311915

1191411916
/*
11915-
*ATExecAlterConstrRecurse already invalidated relcache for the relations
11916-
* having the constraint itself; here we also invalidate for relations
11917-
* that have any triggers that are part of the constraint.
11917+
*ATExecAlterConstraintInternal already invalidated relcache for the
11918+
*relationshaving the constraint itself; here we also invalidate for
11919+
*relationsthat have any triggers that are part of the constraint.
1191811920
*/
11919-
foreach(lc, otherrelids)
11920-
CacheInvalidateRelcacheByRelid(lfirst_oid(lc));
11921+
foreach_oid(relid, otherrelids)
11922+
CacheInvalidateRelcacheByRelid(relid);
1192111923

1192211924
systable_endscan(scan);
1192311925

@@ -11939,30 +11941,30 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse,
1193911941
* but existing releases don't do that.)
1194011942
*/
1194111943
static bool
11942-
ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
11943-
Relationrel, HeapTuple contuple, List **otherrelids,
11944-
LOCKMODE lockmode)
11944+
ATExecAlterConstraintInternal(ATAlterConstraint *cmdcon, Relation conrel,
11945+
Relationtgrel, Relation rel, HeapTuple contuple,
11946+
bool recurse, List **otherrelids, LOCKMODE lockmode)
1194511947
{
1194611948
Form_pg_constraint currcon;
11947-
Oidconoid;
11948-
Oidrefrelid;
11949+
Oidrefrelid = InvalidOid;
1194911950
boolchanged = false;
1195011951

1195111952
/* since this function recurses, it could be driven to stack overflow */
1195211953
check_stack_depth();
1195311954

1195411955
currcon = (Form_pg_constraint) GETSTRUCT(contuple);
11955-
conoid =currcon->oid;
11956-
refrelid = currcon->confrelid;
11956+
if (currcon->contype == CONSTRAINT_FOREIGN)
11957+
refrelid = currcon->confrelid;
1195711958

1195811959
/*
1195911960
* Update pg_constraint with the flags from cmdcon.
1196011961
*
1196111962
* If called to modify a constraint that's already in the desired state,
1196211963
* silently do nothing.
1196311964
*/
11964-
if (currcon->condeferrable != cmdcon->deferrable ||
11965-
currcon->condeferred != cmdcon->initdeferred)
11965+
if (cmdcon->alterDeferrability &&
11966+
(currcon->condeferrable != cmdcon->deferrable ||
11967+
currcon->condeferred != cmdcon->initdeferred))
1196611968
{
1196711969
HeapTuplecopyTuple;
1196811970
Form_pg_constraint copy_con;
@@ -11973,8 +11975,7 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
1197311975
copy_con->condeferred = cmdcon->initdeferred;
1197411976
CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
1197511977

11976-
InvokeObjectPostAlterHook(ConstraintRelationId,
11977-
conoid, 0);
11978+
InvokeObjectPostAlterHook(ConstraintRelationId, currcon->oid, 0);
1197811979

1197911980
heap_freetuple(copyTuple);
1198011981
changed = true;
@@ -11986,32 +11987,59 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
1198611987
* Now we need to update the multiple entries in pg_trigger that
1198711988
* implement the constraint.
1198811989
*/
11989-
AlterConstrTriggerDeferrability(conoid, tgrel, rel, cmdcon->deferrable,
11990+
AlterConstrTriggerDeferrability(currcon->oid, tgrel, rel,
11991+
cmdcon->deferrable,
1199011992
cmdcon->initdeferred, otherrelids);
1199111993
}
1199211994

1199311995
/*
1199411996
* If the table at either end of the constraint is partitioned, we need to
11995-
*recurse andhandle every constraint that is a child of this one.
11997+
* handle every constraint that is a child of this one.
1199611998
*
11997-
*(This assumesthatthe recurse flag is forcibly set for partitioned
11998-
*tables, and not set for legacy inheritance, though we don't check for
11999-
*that here.)
11999+
*Notethatthis doesn't handle recursion the normal way, viz. by
12000+
*scanning the list of child relations and recursing; instead it uses the
12001+
*conparentid relationships. This may need to be reconsidered.
1200012002
*/
12001-
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
12002-
get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE)
12003-
ATExecAlterChildConstr(cmdcon, conrel, tgrel, rel, contuple,
12004-
otherrelids, lockmode);
12003+
if (recurse && changed &&
12004+
(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
12005+
(OidIsValid(refrelid) &&
12006+
get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE)))
12007+
{
12008+
ScanKeyData pkey;
12009+
SysScanDesc pscan;
12010+
HeapTuplechildtup;
12011+
12012+
ScanKeyInit(&pkey,
12013+
Anum_pg_constraint_conparentid,
12014+
BTEqualStrategyNumber, F_OIDEQ,
12015+
ObjectIdGetDatum(currcon->oid));
12016+
12017+
pscan = systable_beginscan(conrel, ConstraintParentIndexId,
12018+
true, NULL, 1, &pkey);
12019+
12020+
while (HeapTupleIsValid(childtup = systable_getnext(pscan)))
12021+
{
12022+
Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup);
12023+
Relationchildrel;
12024+
12025+
childrel = table_open(childcon->conrelid, lockmode);
12026+
ATExecAlterConstraintInternal(cmdcon, conrel, tgrel, childrel, childtup,
12027+
recurse, otherrelids, lockmode);
12028+
table_close(childrel, NoLock);
12029+
}
12030+
12031+
systable_endscan(pscan);
12032+
}
1200512033

1200612034
return changed;
1200712035
}
1200812036

1200912037
/*
12010-
* A subroutine ofATExecAlterConstrRecurse that updated constraint trigger's
12011-
* deferrability.
12038+
* A subroutine ofATExecAlterConstrDeferrability that updated constraint
12039+
*trigger'sdeferrability.
1201212040
*
1201312041
* The arguments to this function have the same meaning as the arguments to
12014-
*ATExecAlterConstrRecurse.
12042+
*ATExecAlterConstrDeferrability.
1201512043
*/
1201612044
static void
1201712045
AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
@@ -12071,49 +12099,6 @@ AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
1207112099
systable_endscan(tgscan);
1207212100
}
1207312101

12074-
/*
12075-
* Invokes ATExecAlterConstrRecurse for each constraint that is a child of the
12076-
* specified constraint.
12077-
*
12078-
* The arguments to this function have the same meaning as the arguments to
12079-
* ATExecAlterConstrRecurse.
12080-
*/
12081-
static void
12082-
ATExecAlterChildConstr(Constraint *cmdcon, Relation conrel, Relation tgrel,
12083-
Relation rel, HeapTuple contuple, List **otherrelids,
12084-
LOCKMODE lockmode)
12085-
{
12086-
Form_pg_constraint currcon;
12087-
Oidconoid;
12088-
ScanKeyData pkey;
12089-
SysScanDesc pscan;
12090-
HeapTuplechildtup;
12091-
12092-
currcon = (Form_pg_constraint) GETSTRUCT(contuple);
12093-
conoid = currcon->oid;
12094-
12095-
ScanKeyInit(&pkey,
12096-
Anum_pg_constraint_conparentid,
12097-
BTEqualStrategyNumber, F_OIDEQ,
12098-
ObjectIdGetDatum(conoid));
12099-
12100-
pscan = systable_beginscan(conrel, ConstraintParentIndexId,
12101-
true, NULL, 1, &pkey);
12102-
12103-
while (HeapTupleIsValid(childtup = systable_getnext(pscan)))
12104-
{
12105-
Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup);
12106-
Relationchildrel;
12107-
12108-
childrel = table_open(childcon->conrelid, lockmode);
12109-
ATExecAlterConstrRecurse(cmdcon, conrel, tgrel, childrel, childtup,
12110-
otherrelids, lockmode);
12111-
table_close(childrel, NoLock);
12112-
}
12113-
12114-
systable_endscan(pscan);
12115-
}
12116-
1211712102
/*
1211812103
* ALTER TABLE VALIDATE CONSTRAINT
1211912104
*

‎src/backend/parser/gram.y

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2657,12 +2657,12 @@ alter_table_cmd:
26572657
|ALTERCONSTRAINTnameConstraintAttributeSpec
26582658
{
26592659
AlterTableCmd *n = makeNode(AlterTableCmd);
2660-
Constraint *c = makeNode(Constraint);
2660+
ATAlterConstraint *c = makeNode(ATAlterConstraint);
26612661

26622662
n->subtype = AT_AlterConstraint;
26632663
n->def = (Node *) c;
2664-
c->contype = CONSTR_FOREIGN;/* others not supported, yet*/
26652664
c->conname =$3;
2665+
c->alterDeferrability =true;
26662666
processCASbits($4, @4,"ALTER CONSTRAINT statement",
26672667
&c->deferrable,
26682668
&c->initdeferred,

‎src/include/nodes/parsenodes.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2469,13 +2469,6 @@ typedef enum AlterTableType
24692469
AT_ReAddStatistics,/* internal to commands/tablecmds.c */
24702470
}AlterTableType;
24712471

2472-
typedefstructReplicaIdentityStmt
2473-
{
2474-
NodeTagtype;
2475-
charidentity_type;
2476-
char*name;
2477-
}ReplicaIdentityStmt;
2478-
24792472
typedefstructAlterTableCmd/* one subcommand of an ALTER TABLE */
24802473
{
24812474
NodeTagtype;
@@ -2492,6 +2485,24 @@ typedef struct AlterTableCmd/* one subcommand of an ALTER TABLE */
24922485
boolrecurse;/* exec-time recursion */
24932486
}AlterTableCmd;
24942487

2488+
/* Ad-hoc node for AT_AlterConstraint */
2489+
typedefstructATAlterConstraint
2490+
{
2491+
NodeTagtype;
2492+
char*conname;/* Constraint name */
2493+
boolalterDeferrability;/* changing deferrability properties? */
2494+
booldeferrable;/* DEFERRABLE? */
2495+
boolinitdeferred;/* INITIALLY DEFERRED? */
2496+
}ATAlterConstraint;
2497+
2498+
/* Ad-hoc node for AT_ReplicaIdentity */
2499+
typedefstructReplicaIdentityStmt
2500+
{
2501+
NodeTagtype;
2502+
charidentity_type;
2503+
char*name;
2504+
}ReplicaIdentityStmt;
2505+
24952506

24962507
/* ----------------------
24972508
* Alter Collation

‎src/tools/pgindent/typedefs.list

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ ArrayType
157157
AsyncQueueControl
158158
AsyncQueueEntry
159159
AsyncRequest
160+
ATAlterConstraint
160161
AttInMetadata
161162
AttStatsSlot
162163
AttoptCacheEntry

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp