aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/tablecmds.c
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2024-05-02 17:26:30 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2024-05-02 17:26:30 +0200
commitd45597f72fe53a53f6271d5ba4e7acf8fc9308a1 (patch)
treeaab07183fc9955a5f382ae5f9325c83bd638b7fd /src/backend/commands/tablecmds.c
parent42510c031b070228bfa024f6a4365dffd60086de (diff)
downloadpostgresql-d45597f72fe53a53f6271d5ba4e7acf8fc9308a1.tar.gz
postgresql-d45597f72fe53a53f6271d5ba4e7acf8fc9308a1.zip
Disallow direct change of NO INHERIT of not-null constraints
We support changing NO INHERIT constraint to INHERIT for constraints in child relations when adding a constraint to some ancestor relation, and also during pg_upgrade's schema restore; but other than those special cases, command ALTER TABLE ADD CONSTRAINT should not be allowed to change an existing constraint from NO INHERIT to INHERIT, as that would require to process child relations so that they also acquire an appropriate constraint, which we may not be in a position to do. (It'd also be surprising behavior.) It is conceivable that we want to allow ALTER TABLE SET NOT NULL to make such a change; but in that case some more code is needed to implement it correctly, so for now I've made that throw the same error message. Also, during the prep phase of ALTER TABLE ADD CONSTRAINT, acquire locks on all descendant tables; otherwise we might operate on child tables on which no locks are held, particularly in the mode where a primary key causes not-null constraints to be created on children. Reported-by: Alexander Lakhin <exclusion@gmail.com> Discussion: https://postgr.es/m/7d923a66-55f0-3395-cd40-81c142b5448b@gmail.com
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r--src/backend/commands/tablecmds.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 08c87e60293..c31783373f0 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4980,10 +4980,12 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
break;
case AT_AddConstraint: /* ADD CONSTRAINT */
ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
- /* Recursion occurs during execution phase */
- /* No command-specific prep needed except saving recurse flag */
if (recurse)
+ {
+ /* recurses at exec time; lock descendants and set flag */
+ (void) find_all_inheritors(RelationGetRelid(rel), lockmode, NULL);
cmd->recurse = true;
+ }
pass = AT_PASS_ADD_CONSTR;
break;
case AT_AddIndexConstraint: /* ADD CONSTRAINT USING INDEX */
@@ -7893,6 +7895,17 @@ ATExecSetNotNull(List **wqueue, Relation rel, char *conName, char *colName,
conForm = (Form_pg_constraint) GETSTRUCT(copytup);
/*
+ * Don't let a NO INHERIT constraint be changed into inherit.
+ */
+ if (conForm->connoinherit && recurse)
+ ereport(ERROR,
+ errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot change NO INHERIT status of NOT NULL constraint \"%s\" in relation \"%s\"",
+ NameStr(conForm->conname),
+ RelationGetRelationName(rel)));
+
+
+ /*
* If we find an appropriate constraint, we're almost done, but just
* need to change some properties on it: if we're recursing, increment
* coninhcount; if not, set conislocal if not already set.