public inbox for [email protected]  
help / color / mirror / Atom feed
From: Chao Li <[email protected]>
To: Postgres hackers <[email protected]>
Subject: Re: tablecmds: reject CLUSTER ON for partitioned tables earlier
Date: Fri, 23 Jan 2026 07:30:55 +0800
Message-ID: <[email protected]> (raw)
In-Reply-To: <CAEoWx2k5800OjHO5KhTDv4JFYpDmyfh3MTtuB=7PP-0hLmG8yQ@mail.gmail.com>
References: <CAEoWx2kggo1N2kDH6OSfXHL_5gKg3DqQ0PdNuL4LH4XSTKJ3-g@mail.gmail.com>
	<CAEoWx2k5800OjHO5KhTDv4JFYpDmyfh3MTtuB=7PP-0hLmG8yQ@mail.gmail.com>



> On Jan 22, 2026, at 17:01, Chao Li <[email protected]> wrote:
> 
> 
> 
>> On Jan 21, 2026, at 11:55, Chao Li <[email protected]> wrote:
>> 
>> Hi Hacker,
>> 
>> I noticed this while working other patches related to “ALTER TABLE”.
>> 
>> “ALTER TABLE … CLUSTER ON” and "SET WITHOUT CLUSTER" are not supported for partitioned tables, but currently ATPrepCmd() allows them through and they only fail later at execution time.
>> 
>> This patch rejects these commands earlier by using the existing ATSimplePermissions() infrastructure in ATPrepCmd(), matching the handling of other unsupported ALTER TABLE actions on partitioned tables (such as SET LOGGED / SET UNLOGGED). This makes the behavior more consistent and simplifies the code path.
>> 
>> As a result, the error reported for partitioned tables changes:
>> 
>> Before the patch:
>> ```
>> evantest=# ALTER TABLE p_test CLUSTER ON idx_p_test_id;
>> ERROR:  cannot mark index clustered in partitioned table
>> ```
>> 
>> With the patch:
>> ```
>> evantest=# ALTER TABLE p_test CLUSTER ON idx_p_test_id;
>> ERROR:  ALTER action CLUSTER ON cannot be performed on relation "p_test"
>> DETAIL:  This operation is not supported for partitioned tables.
>> ```
>> 
>> Best regards,
>> --
>> Chao Li (Evan)
>> HighGo Software Co., Ltd.
>> https://www.highgo.com/
>> 
>> 
>> 
>> 
>> <v1-0001-tablecmds-reject-CLUSTER-ON-for-partitioned-table.patch>
> 
> 
> 
> Applying the same change to INHERIT/NO INHeRIT in v2-0002. Other than that, fixing 2 more things for INHERIT/NO INHERIT:
> 
> * The header comment of ATPrepAddInherit() was a copy-paste mistake, it described something totally unrelated.
> * NO INHERIT didn’t call ATPrepAddInherit() to check early, so it had to go deeper and run unnecessary checks.
> 
> Basically, 0001 and 0002 do the same thing on two sub-commands. If accepted, they can be squashed.
> 
> Best regards,
> --
> Chao Li (Evan)
> HighGo Software Co., Ltd.
> https://www.highgo.com/
> 
> <v2-0001-tablecmds-reject-CLUSTER-ON-for-partitioned-table.patch><v2-0002-tablecmds-reject-INHERIT-NO-INHERIT-for-partition.patch>

PFA v3:

0001 is the same as v2. In 0002:

* Restored the header comment of ATPrepAddInherit, because I realized the should belong to ATExecAddInherit.
* Renamed ATPrepAddInherit to ATPrepChangeInherit.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/






Attachments:

  [application/octet-stream] v3-0001-tablecmds-reject-CLUSTER-ON-for-partitioned-table.patch (2.6K, 2-v3-0001-tablecmds-reject-CLUSTER-ON-for-partitioned-table.patch)
  download | inline diff:
From 75a3d94296e83ec5cc82b98f606227503f2c575e Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <[email protected]>
Date: Wed, 21 Jan 2026 11:27:03 +0800
Subject: [PATCH v3 1/2] tablecmds: reject CLUSTER ON for partitioned tables
 earlier

ALTER TABLE ... CLUSTER ON and SET WITHOUT CLUSTER are not supported for
partitioned tables and already fail today, but only at exec time.

Reject these commands earlier via ATSimplePermissions(), matching the
handling of other unsupported ALTER TABLE actions on partitioned tables
(such as SET LOGGED / SET UNLOGGED). This centralizes the relation-kind
check in the ALTER TABLE preparation phase, improving consistency and
maintainability.

As a result, partitioned tables now report the standard ATSimplePermissions()
error for unsupported ALTER TABLE actions.

Author: Chao Li <[email protected]>
---
 src/backend/commands/tablecmds.c      | 2 +-
 src/test/regress/expected/cluster.out | 6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index f976c0e5c7e..3e9f62e9d37 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5142,7 +5142,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
 		case AT_ClusterOn:		/* CLUSTER ON */
 		case AT_DropCluster:	/* SET WITHOUT CLUSTER */
 			ATSimplePermissions(cmd->subtype, rel,
-								ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW);
+								ATT_TABLE | ATT_MATVIEW);
 			/* These commands never recurse */
 			/* No command-specific prep needed */
 			pass = AT_PASS_MISC;
diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expected/cluster.out
index 4d40a6809ab..07c52e647f7 100644
--- a/src/test/regress/expected/cluster.out
+++ b/src/test/regress/expected/cluster.out
@@ -492,9 +492,11 @@ Number of partitions: 3 (Use \d+ to list them.)
 CLUSTER clstrpart;
 ERROR:  there is no previously clustered index for table "clstrpart"
 ALTER TABLE clstrpart SET WITHOUT CLUSTER;
-ERROR:  cannot mark index clustered in partitioned table
+ERROR:  ALTER action SET WITHOUT CLUSTER cannot be performed on relation "clstrpart"
+DETAIL:  This operation is not supported for partitioned tables.
 ALTER TABLE clstrpart CLUSTER ON clstrpart_idx;
-ERROR:  cannot mark index clustered in partitioned table
+ERROR:  ALTER action CLUSTER ON cannot be performed on relation "clstrpart"
+DETAIL:  This operation is not supported for partitioned tables.
 DROP TABLE clstrpart;
 -- Ownership of partitions is checked
 CREATE TABLE ptnowner(i int unique) PARTITION BY LIST (i);
-- 
2.50.1 (Apple Git-155)



  [application/octet-stream] v3-0002-tablecmds-reject-INHERIT-NO-INHERIT-for-partition.patch (4.5K, 3-v3-0002-tablecmds-reject-INHERIT-NO-INHERIT-for-partition.patch)
  download | inline diff:
From 1c690132583361730b4ebd9cffb63cb53ee643c4 Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <[email protected]>
Date: Thu, 22 Jan 2026 16:47:58 +0800
Subject: [PATCH v3 2/2] tablecmds: reject INHERIT / NO INHERIT for partitioned
 tables earlier

ALTER TABLE ... INHERIT and NO INHERIT are not supported for partitioned
tables and already fail today, but only via ad-hoc checks in command-
specific preparation code or later at execution time.

Reject these commands earlier via ATSimplePermissions(), matching the
handling of other unsupported ALTER TABLE actions on partitioned tables.
This centralizes relation-kind checks in the common permission framework
and produces the standard, consistent error message.

While doing this, fix two related issues in the preparation logic:
- The header comment of ATPrepAddInherit was a stale copy-paste that
  described behavior no longer implemented there.
- NO INHERIT previously didn't use ATPrepAddInherit, causing it to reach
  execution-time checks unnecessarily. Consolidate preparation into a
  shared helper used by both INHERIT and NO INHERIT, ensuring both are
  rejected uniformly and as early as possible.

Author: Chao Li <[email protected]>
---
 src/backend/commands/tablecmds.c          | 22 ++++++++--------------
 src/test/regress/expected/alter_table.out |  3 ++-
 2 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 3e9f62e9d37..a255edd9531 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -686,7 +686,7 @@ static void ATExecEnableDisableTrigger(Relation rel, const char *trigname,
 									   LOCKMODE lockmode);
 static void ATExecEnableDisableRule(Relation rel, const char *rulename,
 									char fires_when, LOCKMODE lockmode);
-static void ATPrepAddInherit(Relation child_rel);
+static void ATPrepAddDropInherit(Relation child_rel);
 static ObjectAddress ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode);
 static ObjectAddress ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode);
 static void drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid,
@@ -5194,15 +5194,16 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
 			break;
 		case AT_AddInherit:		/* INHERIT */
 			ATSimplePermissions(cmd->subtype, rel,
-								ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
+								ATT_TABLE | ATT_FOREIGN_TABLE);
 			/* This command never recurses */
-			ATPrepAddInherit(rel);
+			ATPrepAddDropInherit(rel);
 			pass = AT_PASS_MISC;
 			break;
 		case AT_DropInherit:	/* NO INHERIT */
 			ATSimplePermissions(cmd->subtype, rel,
-								ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE);
+								ATT_TABLE | ATT_FOREIGN_TABLE);
 			/* This command never recurses */
+			ATPrepAddDropInherit(rel);
 			/* No command-specific prep needed */
 			pass = AT_PASS_MISC;
 			break;
@@ -17259,14 +17260,12 @@ ATExecEnableDisableRule(Relation rel, const char *rulename,
 }
 
 /*
- * ALTER TABLE INHERIT
+ * ALTER TABLE INHERIT / NO INHERIT
  *
- * Add a parent to the child's parents. This verifies that all the columns and
- * check constraints of the parent appear in the child and that they have the
- * same data types and expressions.
+ * A child table cannot be a typed table or a partition.
  */
 static void
-ATPrepAddInherit(Relation child_rel)
+ATPrepAddDropInherit(Relation child_rel)
 {
 	if (child_rel->rd_rel->reloftype)
 		ereport(ERROR,
@@ -17277,11 +17276,6 @@ ATPrepAddInherit(Relation child_rel)
 		ereport(ERROR,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("cannot change inheritance of a partition")));
-
-	if (child_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot change inheritance of partitioned table")));
 }
 
 /*
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index ac1a7345d0f..b8150aab08b 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -3998,7 +3998,8 @@ CREATE TABLE nonpartitioned (
 	b int
 );
 ALTER TABLE partitioned INHERIT nonpartitioned;
-ERROR:  cannot change inheritance of partitioned table
+ERROR:  ALTER action INHERIT cannot be performed on relation "partitioned"
+DETAIL:  This operation is not supported for partitioned tables.
 ALTER TABLE nonpartitioned INHERIT partitioned;
 ERROR:  cannot inherit from partitioned table "partitioned"
 -- cannot add NO INHERIT constraint to partitioned tables
-- 
2.50.1 (Apple Git-155)



view thread (11+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected]
  Subject: Re: tablecmds: reject CLUSTER ON for partitioned tables earlier
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox