Introduce ATT_PARTITIONED_TABLE in tablecmds.c
authorMichael Paquier <[email protected]>
Thu, 19 Sep 2024 03:22:56 +0000 (12:22 +0900)
committerMichael Paquier <[email protected]>
Thu, 19 Sep 2024 03:22:56 +0000 (12:22 +0900)
Partitioned tables and normal tables have been relying on ATT_TABLE in
ATSimplePermissions() to produce error messages that depend on the
relation's relkind, because both relkinds currently support the same set
of ALTER TABLE subcommands.

A patch to restrict SET LOGGED/UNLOGGED for partitioned tables is under
discussion, and introducing ATT_PARTITIONED_TABLE makes subcommand
restrictions for partitioned tables easier to deal with, so let's add
one.  There is no functional change.

Author: Michael Paquier
Reviewed-by: Nathan Bossart
Discussion: https://postgr.es/m/[email protected]

src/backend/commands/tablecmds.c

index 022ddf172a31c1ec580e5bbb02dfd321f75fa685..2d703aa22e2685c03fb6a5ef43c0daf82524d3f3 100644 (file)
@@ -332,6 +332,7 @@ struct DropRelationCallbackState
 #define        ATT_FOREIGN_TABLE       0x0020
 #define        ATT_PARTITIONED_INDEX   0x0040
 #define        ATT_SEQUENCE            0x0080
+#define        ATT_PARTITIONED_TABLE   0x0100
 
 /*
  * ForeignTruncateInfo
@@ -4783,7 +4784,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
    {
        case AT_AddColumn:      /* ADD COLUMN */
            ATSimplePermissions(cmd->subtype, rel,
-                               ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
+                               ATT_TABLE | ATT_PARTITIONED_TABLE |
+                               ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
            ATPrepAddColumn(wqueue, rel, recurse, recursing, false, cmd,
                            lockmode, context);
            /* Recursion occurs during execution phase */
@@ -4804,7 +4806,9 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
             * substitutes default values into INSERTs before it expands
             * rules.
             */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_VIEW |
+                               ATT_FOREIGN_TABLE);
            ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
            /* No command-specific prep needed */
            pass = cmd->def ? AT_PASS_ADD_OTHERCONSTR : AT_PASS_DROP;
@@ -4812,19 +4816,24 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
        case AT_CookedColumnDefault:    /* add a pre-cooked default */
            /* This is currently used only in CREATE TABLE */
            /* (so the permission check really isn't necessary) */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            /* This command never recurses */
            pass = AT_PASS_ADD_OTHERCONSTR;
            break;
        case AT_AddIdentity:
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_VIEW |
+                               ATT_FOREIGN_TABLE);
            /* Set up recursion for phase 2; no other prep needed */
            if (recurse)
                cmd->recurse = true;
            pass = AT_PASS_ADD_OTHERCONSTR;
            break;
        case AT_SetIdentity:
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_VIEW |
+                               ATT_FOREIGN_TABLE);
            /* Set up recursion for phase 2; no other prep needed */
            if (recurse)
                cmd->recurse = true;
@@ -4832,82 +4841,98 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
            pass = AT_PASS_MISC;
            break;
        case AT_DropIdentity:
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_VIEW |
+                               ATT_FOREIGN_TABLE);
            /* Set up recursion for phase 2; no other prep needed */
            if (recurse)
                cmd->recurse = true;
            pass = AT_PASS_DROP;
            break;
        case AT_DropNotNull:    /* ALTER COLUMN DROP NOT NULL */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            ATPrepDropNotNull(rel, recurse, recursing);
            ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
            pass = AT_PASS_DROP;
            break;
        case AT_SetNotNull:     /* ALTER COLUMN SET NOT NULL */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            /* Need command-specific recursion decision */
            ATPrepSetNotNull(wqueue, rel, cmd, recurse, recursing,
                             lockmode, context);
            pass = AT_PASS_COL_ATTRS;
            break;
        case AT_CheckNotNull:   /* check column is already marked NOT NULL */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
            /* No command-specific prep needed */
            pass = AT_PASS_COL_ATTRS;
            break;
        case AT_SetExpression:  /* ALTER COLUMN SET EXPRESSION */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
            pass = AT_PASS_SET_EXPRESSION;
            break;
        case AT_DropExpression: /* ALTER COLUMN DROP EXPRESSION */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
            ATPrepDropExpression(rel, cmd, recurse, recursing, lockmode);
            pass = AT_PASS_DROP;
            break;
        case AT_SetStatistics:  /* ALTER COLUMN SET STATISTICS */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW |
+                               ATT_INDEX | ATT_PARTITIONED_INDEX | ATT_FOREIGN_TABLE);
            ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
            /* No command-specific prep needed */
            pass = AT_PASS_MISC;
            break;
        case AT_SetOptions:     /* ALTER COLUMN SET ( options ) */
        case AT_ResetOptions:   /* ALTER COLUMN RESET ( options ) */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE |
+                               ATT_MATVIEW | ATT_FOREIGN_TABLE);
            /* This command never recurses */
            pass = AT_PASS_MISC;
            break;
        case AT_SetStorage:     /* ALTER COLUMN SET STORAGE */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE |
+                               ATT_MATVIEW | ATT_FOREIGN_TABLE);
            ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
            /* No command-specific prep needed */
            pass = AT_PASS_MISC;
            break;
        case AT_SetCompression: /* ALTER COLUMN SET COMPRESSION */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW);
            /* This command never recurses */
            /* No command-specific prep needed */
            pass = AT_PASS_MISC;
            break;
        case AT_DropColumn:     /* DROP COLUMN */
            ATSimplePermissions(cmd->subtype, rel,
-                               ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
+                               ATT_TABLE | ATT_PARTITIONED_TABLE |
+                               ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
            ATPrepDropColumn(wqueue, rel, recurse, recursing, cmd,
                             lockmode, context);
            /* Recursion occurs during execution phase */
            pass = AT_PASS_DROP;
            break;
        case AT_AddIndex:       /* ADD INDEX */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
+           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_PARTITIONED_TABLE);
            /* This command never recurses */
            /* No command-specific prep needed */
            pass = AT_PASS_ADD_INDEX;
            break;
        case AT_AddConstraint:  /* ADD CONSTRAINT */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            /* Recursion occurs during execution phase */
            /* No command-specific prep needed except saving recurse flag */
            if (recurse)
@@ -4915,13 +4940,14 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
            pass = AT_PASS_ADD_CONSTR;
            break;
        case AT_AddIndexConstraint: /* ADD CONSTRAINT USING INDEX */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
+           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_PARTITIONED_TABLE);
            /* This command never recurses */
            /* No command-specific prep needed */
            pass = AT_PASS_ADD_INDEXCONSTR;
            break;
        case AT_DropConstraint: /* DROP CONSTRAINT */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            ATCheckPartitionsNotInUse(rel, lockmode);
            /* Other recursion occurs during execution phase */
            /* No command-specific prep needed except saving recurse flag */
@@ -4931,7 +4957,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
            break;
        case AT_AlterColumnType:    /* ALTER COLUMN TYPE */
            ATSimplePermissions(cmd->subtype, rel,
-                               ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
+                               ATT_TABLE | ATT_PARTITIONED_TABLE |
+                               ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
            /* See comments for ATPrepAlterColumnType */
            cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, recurse, lockmode,
                                      AT_PASS_UNSET, context);
@@ -4954,14 +4981,16 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
            break;
        case AT_ClusterOn:      /* CLUSTER ON */
        case AT_DropCluster:    /* SET WITHOUT CLUSTER */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW);
            /* These commands never recurse */
            /* No command-specific prep needed */
            pass = AT_PASS_MISC;
            break;
        case AT_SetLogged:      /* SET LOGGED */
        case AT_SetUnLogged:    /* SET UNLOGGED */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_SEQUENCE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_SEQUENCE);
            if (tab->chgPersistence)
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -4970,11 +4999,13 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
            pass = AT_PASS_MISC;
            break;
        case AT_DropOids:       /* SET WITHOUT OIDS */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            pass = AT_PASS_DROP;
            break;
        case AT_SetAccessMethod:    /* SET ACCESS METHOD */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW);
 
            /* check if another access method change was already requested */
            if (tab->chgAccessMethod)
@@ -4986,8 +5017,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
            pass = AT_PASS_MISC;    /* does not matter; no work in Phase 2 */
            break;
        case AT_SetTableSpace:  /* SET TABLESPACE */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX |
-                               ATT_PARTITIONED_INDEX);
+           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_PARTITIONED_TABLE |
+                               ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX);
            /* This command never recurses */
            ATPrepSetTableSpace(tab, rel, cmd->name, lockmode);
            pass = AT_PASS_MISC;    /* doesn't actually matter */
@@ -4995,30 +5026,36 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
        case AT_SetRelOptions:  /* SET (...) */
        case AT_ResetRelOptions:    /* RESET (...) */
        case AT_ReplaceRelOptions:  /* reset them all, then set just these */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_MATVIEW | ATT_INDEX);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_VIEW |
+                               ATT_MATVIEW | ATT_INDEX);
            /* This command never recurses */
            /* No command-specific prep needed */
            pass = AT_PASS_MISC;
            break;
        case AT_AddInherit:     /* INHERIT */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            /* This command never recurses */
            ATPrepAddInherit(rel);
            pass = AT_PASS_MISC;
            break;
        case AT_DropInherit:    /* NO INHERIT */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            /* This command never recurses */
            /* No command-specific prep needed */
            pass = AT_PASS_MISC;
            break;
        case AT_AlterConstraint:    /* ALTER CONSTRAINT */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE);
            /* Recursion occurs during execution phase */
            pass = AT_PASS_MISC;
            break;
        case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            /* Recursion occurs during execution phase */
            /* No command-specific prep needed except saving recurse flag */
            if (recurse)
@@ -5026,7 +5063,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
            pass = AT_PASS_MISC;
            break;
        case AT_ReplicaIdentity:    /* REPLICA IDENTITY ... */
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW);
            pass = AT_PASS_MISC;
            /* This command never recurses */
            /* No command-specific prep needed */
@@ -5039,7 +5077,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
        case AT_DisableTrig:    /* DISABLE TRIGGER variants */
        case AT_DisableTrigAll:
        case AT_DisableTrigUser:
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
            /* Set up recursion for phase 2; no other prep needed */
            if (recurse)
                cmd->recurse = true;
@@ -5055,7 +5094,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
        case AT_DisableRowSecurity:
        case AT_ForceRowSecurity:
        case AT_NoForceRowSecurity:
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE);
            /* These commands never recurse */
            /* No command-specific prep needed */
            pass = AT_PASS_MISC;
@@ -5066,17 +5106,20 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
            pass = AT_PASS_MISC;
            break;
        case AT_AttachPartition:
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_PARTITIONED_INDEX);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_PARTITIONED_INDEX);
            /* No command-specific prep needed */
            pass = AT_PASS_MISC;
            break;
        case AT_DetachPartition:
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE);
            /* No command-specific prep needed */
            pass = AT_PASS_MISC;
            break;
        case AT_DetachPartitionFinalize:
-           ATSimplePermissions(cmd->subtype, rel, ATT_TABLE);
+           ATSimplePermissions(cmd->subtype, rel,
+                               ATT_TABLE | ATT_PARTITIONED_TABLE);
            /* No command-specific prep needed */
            pass = AT_PASS_MISC;
            break;
@@ -6493,9 +6536,11 @@ ATSimplePermissions(AlterTableType cmdtype, Relation rel, int allowed_targets)
    switch (rel->rd_rel->relkind)
    {
        case RELKIND_RELATION:
-       case RELKIND_PARTITIONED_TABLE:
            actual_target = ATT_TABLE;
            break;
+       case RELKIND_PARTITIONED_TABLE:
+           actual_target = ATT_PARTITIONED_TABLE;
+           break;
        case RELKIND_VIEW:
            actual_target = ATT_VIEW;
            break;
@@ -6989,7 +7034,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 
    /* At top level, permission check was done in ATPrepCmd, else do it */
    if (recursing)
-       ATSimplePermissions((*cmd)->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+       ATSimplePermissions((*cmd)->subtype, rel,
+                           ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
 
    if (rel->rd_rel->relispartition && !recursing)
        ereport(ERROR,
@@ -8913,7 +8959,8 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
 
    /* At top level, permission check was done in ATPrepCmd, else do it */
    if (recursing)
-       ATSimplePermissions(AT_DropColumn, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+       ATSimplePermissions(AT_DropColumn, rel,
+                           ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
 
    /* Initialize addrs on the first invocation */
    Assert(!recursing || addrs != NULL);
@@ -9402,7 +9449,8 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 
    /* At top level, permission check was done in ATPrepCmd, else do it */
    if (recursing)
-       ATSimplePermissions(AT_AddConstraint, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+       ATSimplePermissions(AT_AddConstraint, rel,
+                           ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
 
    /*
     * Call AddRelationNewConstraints to do the work, making sure it works on
@@ -12549,7 +12597,8 @@ ATExecDropConstraint(Relation rel, const char *constrName,
 
    /* At top level, permission check was done in ATPrepCmd, else do it */
    if (recursing)
-       ATSimplePermissions(AT_DropConstraint, rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+       ATSimplePermissions(AT_DropConstraint, rel,
+                           ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
 
    conrel = table_open(ConstraintRelationId, RowExclusiveLock);
 
@@ -15631,7 +15680,8 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
     * Must be owner of both parent and child -- child was checked by
     * ATSimplePermissions call in ATPrepCmd
     */
-   ATSimplePermissions(AT_AddInherit, parent_rel, ATT_TABLE | ATT_FOREIGN_TABLE);
+   ATSimplePermissions(AT_AddInherit, parent_rel,
+                       ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
 
    /* Permanent rels cannot inherit from temporary ones */
    if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
@@ -18476,7 +18526,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd,
     * Must be owner of both parent and source table -- parent was checked by
     * ATSimplePermissions call in ATPrepCmd
     */
-   ATSimplePermissions(AT_AttachPartition, attachrel, ATT_TABLE | ATT_FOREIGN_TABLE);
+   ATSimplePermissions(AT_AttachPartition, attachrel,
+                       ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
 
    /* A partition can only have one parent */
    if (attachrel->rd_rel->relispartition)