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

Commitf4e53e1

Browse files
committed
Add ALTER TABLE ... ALTER CONSTRAINT ... SET [NO] INHERIT
This allows to redefine an existing non-inheritable constraint to beinheritable, which allows to straighten up situations with NO INHERITconstraints so that thay can become normal constraints without having tore-verify existing data. For existing inheritance children this mayrequire creating additional constraints, if they don't exist already.It also allows to do the opposite, if only for symmetry.Author: Suraj Kharage <suraj.kharage@enterprisedb.com>Reviewed-by: jian he <jian.universality@gmail.com>Discussion:https://postgr.es/m/CAF1DzPVfOW6Kk=7SSh7LbneQDJWh=PbJrEC_Wkzc24tHOyQWGg@mail.gmail.com
1 parentf4694e0 commitf4e53e1

File tree

6 files changed

+359
-19
lines changed

6 files changed

+359
-19
lines changed

‎doc/src/sgml/ref/alter_table.sgml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
5959
ADD <replaceable class="parameter">table_constraint</replaceable> [ NOT VALID ]
6060
ADD <replaceable class="parameter">table_constraint_using_index</replaceable>
6161
ALTER CONSTRAINT <replaceable class="parameter">constraint_name</replaceable> [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
62+
ALTER CONSTRAINT <replaceable class="parameter">constraint_name</replaceable> SET [ INHERIT | NO INHERIT ]
6263
VALIDATE CONSTRAINT <replaceable class="parameter">constraint_name</replaceable>
6364
DROP CONSTRAINT [ IF EXISTS ] <replaceable class="parameter">constraint_name</replaceable> [ RESTRICT | CASCADE ]
6465
DISABLE TRIGGER [ <replaceable class="parameter">trigger_name</replaceable> | ALL | USER ]
@@ -556,11 +557,31 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
556557
<listitem>
557558
<para>
558559
This form alters the attributes of a constraint that was previously
559-
created. Currently only foreign key constraints may be altered.
560+
created. Currently only foreign key constraints may be altered in
561+
this fashion, but see below.
560562
</para>
561563
</listitem>
562564
</varlistentry>
563565

566+
<varlistentry id="sql-altertable-desc-alter-constraint-inherit">
567+
<term><literal>ALTER CONSTRAINT ... SET INHERIT</literal></term>
568+
<term><literal>ALTER CONSTRAINT ... SET NO INHERIT</literal></term>
569+
<listitem>
570+
<para>
571+
These forms modify a inheritable constraint so that it becomes not
572+
inheritable, or vice-versa. Only not-null constraints may be altered
573+
in this fashion at present.
574+
In addition to changing the inheritability status of the constraint,
575+
in the case where a non-inheritable constraint is being marked
576+
inheritable, if the table has children, an equivalent constraint
577+
will be added to them. If marking an inheritable constraint as
578+
non-inheritable on a table with children, then the corresponding
579+
constraint on children will be marked as no longer inherited,
580+
but not removed.
581+
</para>
582+
</listitem>
583+
</varlistentry>
584+
564585
<varlistentry id="sql-altertable-desc-validate-constraint">
565586
<term><literal>VALIDATE CONSTRAINT</literal></term>
566587
<listitem>

‎src/backend/commands/tablecmds.c

Lines changed: 100 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,10 @@ 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, ATAlterConstraint *cmdcon,
392+
static ObjectAddress ATExecAlterConstraint(List **wqueue, Relation rel,
393+
ATAlterConstraint *cmdcon,
393394
bool recurse, LOCKMODE lockmode);
394-
static bool ATExecAlterConstraintInternal(ATAlterConstraint *cmdcon, Relation conrel,
395+
static bool ATExecAlterConstraintInternal(List **wqueue,ATAlterConstraint *cmdcon, Relation conrel,
395396
Relation tgrel, Relation rel, HeapTuple contuple,
396397
bool recurse, List **otherrelids, LOCKMODE lockmode);
397398
static void AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
@@ -5437,8 +5438,8 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
54375438
lockmode);
54385439
break;
54395440
case AT_AlterConstraint:/* ALTER CONSTRAINT */
5440-
address = ATExecAlterConstraint(rel, castNode(ATAlterConstraint,
5441-
cmd->def),
5441+
address = ATExecAlterConstraint(wqueue, rel,
5442+
castNode(ATAlterConstraint, cmd->def),
54425443
cmd->recurse, lockmode);
54435444
break;
54445445
case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */
@@ -11813,14 +11814,14 @@ GetForeignKeyCheckTriggers(Relation trigrel,
1181311814
*
1181411815
* Update the attributes of a constraint.
1181511816
*
11816-
* Currently only works for Foreign Key constraints.
11817+
* Currently only works for Foreign Keyand not nullconstraints.
1181711818
*
1181811819
* If the constraint is modified, returns its address; otherwise, return
1181911820
* InvalidObjectAddress.
1182011821
*/
1182111822
static ObjectAddress
11822-
ATExecAlterConstraint(Relation rel, ATAlterConstraint *cmdcon, bool recurse,
11823-
LOCKMODE lockmode)
11823+
ATExecAlterConstraint(List **wqueue,Relation rel, ATAlterConstraint *cmdcon,
11824+
bool recurse,LOCKMODE lockmode)
1182411825
{
1182511826
Relationconrel;
1182611827
Relationtgrel;
@@ -11871,11 +11872,26 @@ ATExecAlterConstraint(Relation rel, ATAlterConstraint *cmdcon, bool recurse,
1187111872
cmdcon->conname, RelationGetRelationName(rel))));
1187211873

1187311874
currcon = (Form_pg_constraint) GETSTRUCT(contuple);
11874-
if (currcon->contype != CONSTRAINT_FOREIGN)
11875+
if (cmdcon->alterDeferrability &&currcon->contype != CONSTRAINT_FOREIGN)
1187511876
ereport(ERROR,
1187611877
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1187711878
errmsg("constraint \"%s\" of relation \"%s\" is not a foreign key constraint",
1187811879
cmdcon->conname, RelationGetRelationName(rel))));
11880+
if (cmdcon->alterInheritability &&
11881+
currcon->contype != CONSTRAINT_NOTNULL)
11882+
ereport(ERROR,
11883+
errcode(ERRCODE_WRONG_OBJECT_TYPE),
11884+
errmsg("constraint \"%s\" of relation \"%s\" is not a not-null constraint",
11885+
cmdcon->conname, RelationGetRelationName(rel)));
11886+
11887+
/* Refuse to modify inheritability of inherited constraints */
11888+
if (cmdcon->alterInheritability &&
11889+
cmdcon->noinherit && currcon->coninhcount > 0)
11890+
ereport(ERROR,
11891+
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
11892+
errmsg("cannot alter inherited constraint \"%s\" on relation \"%s\"",
11893+
NameStr(currcon->conname),
11894+
RelationGetRelationName(rel)));
1187911895

1188011896
/*
1188111897
* If it's not the topmost constraint, raise an error.
@@ -11926,8 +11942,8 @@ ATExecAlterConstraint(Relation rel, ATAlterConstraint *cmdcon, bool recurse,
1192611942
/*
1192711943
* Do the actual catalog work, and recurse if necessary.
1192811944
*/
11929-
if (ATExecAlterConstraintInternal(cmdcon, conrel, tgrel, rel, contuple,
11930-
recurse, &otherrelids, lockmode))
11945+
if (ATExecAlterConstraintInternal(wqueue,cmdcon, conrel, tgrel, rel,
11946+
contuple,recurse, &otherrelids, lockmode))
1193111947
ObjectAddressSet(address, ConstraintRelationId, currcon->oid);
1193211948

1193311949
/*
@@ -11958,9 +11974,10 @@ ATExecAlterConstraint(Relation rel, ATAlterConstraint *cmdcon, bool recurse,
1195811974
* but existing releases don't do that.)
1195911975
*/
1196011976
static bool
11961-
ATExecAlterConstraintInternal(ATAlterConstraint *cmdcon, Relation conrel,
11962-
Relation tgrel, Relation rel, HeapTuple contuple,
11963-
bool recurse, List **otherrelids, LOCKMODE lockmode)
11977+
ATExecAlterConstraintInternal(List **wqueue, ATAlterConstraint *cmdcon,
11978+
Relation conrel, Relation tgrel, Relation rel,
11979+
HeapTuple contuple, bool recurse,
11980+
List **otherrelids, LOCKMODE lockmode)
1196411981
{
1196511982
Form_pg_constraint currcon;
1196611983
Oidrefrelid = InvalidOid;
@@ -12040,14 +12057,82 @@ ATExecAlterConstraintInternal(ATAlterConstraint *cmdcon, Relation conrel,
1204012057
Relationchildrel;
1204112058

1204212059
childrel = table_open(childcon->conrelid, lockmode);
12043-
ATExecAlterConstraintInternal(cmdcon, conrel, tgrel, childrel, childtup,
12044-
recurse, otherrelids, lockmode);
12060+
ATExecAlterConstraintInternal(wqueue,cmdcon, conrel, tgrel, childrel,
12061+
childtup,recurse, otherrelids, lockmode);
1204512062
table_close(childrel, NoLock);
1204612063
}
1204712064

1204812065
systable_endscan(pscan);
1204912066
}
1205012067

12068+
/*
12069+
* Update the catalog for inheritability. No work if the constraint is
12070+
* already in the requested state.
12071+
*/
12072+
if (cmdcon->alterInheritability &&
12073+
(cmdcon->noinherit != currcon->connoinherit))
12074+
{
12075+
AttrNumbercolNum;
12076+
char *colName;
12077+
List *children;
12078+
HeapTuplecopyTuple;
12079+
Form_pg_constraint copy_con;
12080+
12081+
/* The current implementation only works for NOT NULL constraints */
12082+
Assert(currcon->contype == CONSTRAINT_NOTNULL);
12083+
12084+
copyTuple = heap_copytuple(contuple);
12085+
copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
12086+
copy_con->connoinherit = cmdcon->noinherit;
12087+
12088+
CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
12089+
CommandCounterIncrement();
12090+
heap_freetuple(copyTuple);
12091+
changed = true;
12092+
12093+
/* Fetch the column number and name */
12094+
colNum = extractNotNullColumn(contuple);
12095+
colName = get_attname(currcon->conrelid, colNum, false);
12096+
12097+
/*
12098+
* Propagate the change to children. For SET NO INHERIT, we don't
12099+
* recursively affect children, just the immediate level.
12100+
*/
12101+
children = find_inheritance_children(RelationGetRelid(rel),
12102+
lockmode);
12103+
foreach_oid(childoid, children)
12104+
{
12105+
ObjectAddress addr;
12106+
12107+
if (cmdcon->noinherit)
12108+
{
12109+
HeapTuplechildtup;
12110+
Form_pg_constraint childcon;
12111+
12112+
childtup = findNotNullConstraint(childoid, colName);
12113+
if (!childtup)
12114+
elog(ERROR, "cache lookup failed for not-null constraint on column \"%s\" of relation %u",
12115+
colName, childoid);
12116+
childcon = (Form_pg_constraint) GETSTRUCT(childtup);
12117+
Assert(childcon->coninhcount > 0);
12118+
childcon->coninhcount--;
12119+
childcon->conislocal = true;
12120+
CatalogTupleUpdate(conrel, &childtup->t_self, childtup);
12121+
heap_freetuple(childtup);
12122+
}
12123+
else
12124+
{
12125+
Relationchildrel = table_open(childoid, NoLock);
12126+
12127+
addr = ATExecSetNotNull(wqueue, childrel, NameStr(currcon->conname),
12128+
colName, true, true, lockmode);
12129+
if (OidIsValid(addr.objectId))
12130+
CommandCounterIncrement();
12131+
table_close(childrel, NoLock);
12132+
}
12133+
}
12134+
}
12135+
1205112136
return changed;
1205212137
}
1205312138

‎src/backend/parser/gram.y

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,6 +2669,34 @@ alter_table_cmd:
26692669
NULL,NULL,NULL, yyscanner);
26702670
$$ = (Node *) n;
26712671
}
2672+
/* ALTER TABLE <name> ALTER CONSTRAINT SET INHERIT*/
2673+
|ALTERCONSTRAINTnameSETINHERIT
2674+
{
2675+
AlterTableCmd *n = makeNode(AlterTableCmd);
2676+
ATAlterConstraint *c = makeNode(ATAlterConstraint);
2677+
2678+
n->subtype = AT_AlterConstraint;
2679+
n->def = (Node *) c;
2680+
c->conname =$3;
2681+
c->alterInheritability =true;
2682+
c->noinherit =false;
2683+
2684+
$$ = (Node *) n;
2685+
}
2686+
/* ALTER TABLE <name> ALTER CONSTRAINT SET NO INHERIT*/
2687+
|ALTERCONSTRAINTnameSETNOINHERIT
2688+
{
2689+
AlterTableCmd *n = makeNode(AlterTableCmd);
2690+
ATAlterConstraint *c = makeNode(ATAlterConstraint);
2691+
2692+
n->subtype = AT_AlterConstraint;
2693+
n->def = (Node *) c;
2694+
c->conname =$3;
2695+
c->alterInheritability =true;
2696+
c->noinherit =true;
2697+
2698+
$$ = (Node *) n;
2699+
}
26722700
/* ALTER TABLE <name> VALIDATE CONSTRAINT ...*/
26732701
|VALIDATECONSTRAINTname
26742702
{

‎src/include/nodes/parsenodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2493,6 +2493,8 @@ typedef struct ATAlterConstraint
24932493
boolalterDeferrability;/* changing deferrability properties? */
24942494
booldeferrable;/* DEFERRABLE? */
24952495
boolinitdeferred;/* INITIALLY DEFERRED? */
2496+
boolalterInheritability;/* changing inheritability properties */
2497+
boolnoinherit;
24962498
}ATAlterConstraint;
24972499

24982500
/* Ad-hoc node for AT_ReplicaIdentity */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp