On Mon, Sep 09, 2024 at 03:56:14PM +0900, Michael Paquier wrote: > How about inventing a new ATT_PARTITIONED_TABLE and make a clean split > between both relkinds? I'd guess that blocking both SET LOGGED and > UNLOGGED for partitioned tables is the best move, even if it is > possible to block only one or the other, of course.
I gave it a try, and while it is much more invasive, it is also much more consistent with the rest of the file. Thoughts? -- Michael
From fefb821c033784a01c39d99d477982ded1aebf40 Mon Sep 17 00:00:00 2001 From: Michael Paquier <mich...@paquier.xyz> Date: Tue, 10 Sep 2024 09:16:43 +0900 Subject: [PATCH v4 1/2] Introduce ATT_PARTITIONED_TABLE in tablecmds.c --- src/backend/commands/tablecmds.c | 92 +++++++++++++++++--------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index b3cc6f8f69..f6a6e3e148 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -330,6 +330,7 @@ struct DropRelationCallbackState #define ATT_FOREIGN_TABLE 0x0020 #define ATT_PARTITIONED_INDEX 0x0040 #define ATT_SEQUENCE 0x0080 +#define ATT_PARTITIONED_TABLE 0x0100 /* * ForeignTruncateInfo @@ -4777,7 +4778,7 @@ 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 */ @@ -4798,7 +4799,7 @@ 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; @@ -4806,19 +4807,19 @@ 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; @@ -4826,82 +4827,82 @@ 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) @@ -4909,13 +4910,13 @@ 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 */ @@ -4925,7 +4926,7 @@ 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); @@ -4948,14 +4949,14 @@ 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), @@ -4964,11 +4965,11 @@ 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) @@ -4980,7 +4981,7 @@ 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 | + 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); @@ -4989,30 +4990,30 @@ 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) @@ -5020,7 +5021,7 @@ 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 */ @@ -5033,7 +5034,7 @@ 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; @@ -5049,7 +5050,7 @@ 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; @@ -5060,17 +5061,17 @@ 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; @@ -6486,9 +6487,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; @@ -6982,7 +6985,7 @@ 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, @@ -8906,7 +8909,7 @@ 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); @@ -9395,7 +9398,7 @@ 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 @@ -12400,7 +12403,7 @@ 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); @@ -15481,7 +15484,7 @@ 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 && @@ -18326,7 +18329,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) -- 2.45.2
From 996a52b7d49607ddd62bbe0534718bcba894ea9a Mon Sep 17 00:00:00 2001 From: Michael Paquier <mich...@paquier.xyz> Date: Tue, 10 Sep 2024 09:35:00 +0900 Subject: [PATCH v4 2/2] Remove support for ALTER TABLE .. SET [UN]LOGGED on partitioned tables --- src/backend/commands/tablecmds.c | 8 +++++++- src/bin/pg_dump/pg_dump.c | 7 ++++++- src/bin/pgbench/pgbench.c | 2 +- src/test/regress/expected/create_table.out | 10 ++++++++++ src/test/regress/sql/create_table.sql | 6 ++++++ doc/src/sgml/ref/alter_table.sgml | 4 ++++ doc/src/sgml/ref/create_table.sgml | 4 ++++ 7 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f6a6e3e148..f5d7f2b9f8 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -729,6 +729,12 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, else partitioned = false; + if (relkind == RELKIND_PARTITIONED_TABLE && + stmt->relation->relpersistence == RELPERSISTENCE_UNLOGGED) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("partitioned tables cannot be unlogged"))); + /* * Look up the namespace in which we are supposed to create the relation, * check we have permission to create there, lock it against concurrent @@ -4956,7 +4962,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, break; case AT_SetLogged: /* SET LOGGED */ case AT_SetUnLogged: /* SET UNLOGGED */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_SEQUENCE); + ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_SEQUENCE); if (tab->chgPersistence) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 546e7e4ce1..c207436f93 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -15899,8 +15899,13 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) binary_upgrade_set_pg_class_oids(fout, q, tbinfo->dobj.catId.oid); + /* + * PostgreSQL 18 has disabled UNLOGGED for partitioned tables, so + * ignore it when dumping if it was set in this case. + */ appendPQExpBuffer(q, "CREATE %s%s %s", - tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ? + tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED && + tbinfo->relkind != RELKIND_PARTITIONED_TABLE ? "UNLOGGED " : "", reltypename, qualrelname); diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 61618f2e18..dc4d7408cd 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -4865,7 +4865,7 @@ initCreateTables(PGconn *con) /* Construct new create table statement. */ printfPQExpBuffer(&query, "create%s table %s(%s)", - unlogged_tables ? " unlogged" : "", + unlogged_tables && partition_method == PART_NONE ? " unlogged" : "", ddl->table, (scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols); diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out index 284a7fb85c..c45e02d42f 100644 --- a/src/test/regress/expected/create_table.out +++ b/src/test/regress/expected/create_table.out @@ -50,6 +50,16 @@ ERROR: cannot create temporary relation in non-temporary schema LINE 1: CREATE TEMP TABLE public.temp_to_perm (a int primary key); ^ DROP TABLE unlogged1, public.unlogged2; +CREATE UNLOGGED TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- fail +ERROR: partitioned tables cannot be unlogged +CREATE TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- ok +ALTER TABLE unlogged1 SET LOGGED; -- fails +ERROR: ALTER action SET LOGGED cannot be performed on relation "unlogged1" +DETAIL: This operation is not supported for partitioned tables. +ALTER TABLE unlogged1 SET UNLOGGED; -- fails +ERROR: ALTER action SET UNLOGGED cannot be performed on relation "unlogged1" +DETAIL: This operation is not supported for partitioned tables. +DROP TABLE unlogged1; CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; ERROR: relation "as_select1" already exists diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql index 1fd4cbfa7e..37a227148e 100644 --- a/src/test/regress/sql/create_table.sql +++ b/src/test/regress/sql/create_table.sql @@ -30,6 +30,12 @@ CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key); -- also OK CREATE TEMP TABLE public.temp_to_perm (a int primary key); -- not OK DROP TABLE unlogged1, public.unlogged2; +CREATE UNLOGGED TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- fail +CREATE TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- ok +ALTER TABLE unlogged1 SET LOGGED; -- fails +ALTER TABLE unlogged1 SET UNLOGGED; -- fails +DROP TABLE unlogged1; + CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 1a49f321cf..19f29a0470 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -795,6 +795,10 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM (for identity or serial columns). However, it is also possible to change the persistence of such sequences separately. </para> + + <para> + This form is not supported for partitioned tables. + </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index 93b3f664f2..65715b13b8 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -220,6 +220,10 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM If this is specified, any sequences created together with the unlogged table (for identity or serial columns) are also created as unlogged. </para> + + <para> + This form is not supported for partitioned tables. + </para> </listitem> </varlistentry> -- 2.45.2
signature.asc
Description: PGP signature