On Tue, Oct 28, 2025 at 11:24 PM Kirill Reshke <[email protected]> wrote:
>
> I can see that 0 - FirstLowInvalidHeapAttributeNumber is an existing
> coding practise in sources, but so is
> InvalidAttrNumber - FirstLowInvalidHeapAttributeNumber (sepgsql
> contrib extension). I'm voting for the second one, even though it is
> less used.
>
hi.
now it's:
+ /*
+ * If the partition expression contains a whole-row reference,
+ * then all columns are indirectly associated with that
+ * expression.
+ */
+ if (bms_is_member(InvalidAttrNumber -
FirstLowInvalidHeapAttributeNumber,
+ expr_attrs))
+ {
+ if (used_in_expr)
+ *used_in_expr = true;
+ return true;
+ }
also polished the commit message. below is the commit message:
--------------------------
For partition key expressions containing whole-row reference, we cannot rely on
pg_depend lookups to determine whether an individual column can be altered
(drop, set data type).
As noted in the comments for find_expr_references_walker, no dependency entries
are recorded for whole-row expressions. Therefore whole-row reference check is
needed in has_partition_attrs.
Partition key expressions contain whole-row reference, it is effectively
equivalent to all user columns being indirectly associated with that expression.
Since columns that in a partition key cannot be altered in any way, the same
restriction should be applied to whole-row reference expressions in the
partition key.
--------------------------
--
jian
https://www.enterprisedb.com/
From 8eee74af121b2a9cc8f72111f15d94c3086138a2 Mon Sep 17 00:00:00 2001
From: jian he <[email protected]>
Date: Wed, 31 Dec 2025 10:54:54 +0800
Subject: [PATCH v3 1/1] disallow altering column if partition key contains
wholerow reference
For partition key expressions containing whole-row reference, we cannot rely on
pg_depend lookups to determine whether an individual column can be altered
(drop, set data type).
As noted in the comments for find_expr_references_walker, no dependency entries
are recorded for whole-row expressions. Therefore whole-row reference check is
needed in has_partition_attrs.
Partition key expressions contain whole-row reference, it is effectively
equivalent to all user columns being indirectly associated with that expression.
Since columns that in a partition key cannot be altered in any way, the same
restriction should be applied to whole-row reference expressions in the
partition key.
Author: jian he <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: Matt Dailis <[email protected]>
Reviewed-by: Kirill Reshke <[email protected]>
discussion: https://postgr.es/m/CACJufxG5wLiATocRTaC=z+kw4mUaasC-50+q9K=fOdAr3=o...@mail.gmail.com
---
src/backend/catalog/partition.c | 14 ++++++++++++++
src/test/regress/expected/alter_table.out | 16 ++++++++++++++++
src/test/regress/sql/alter_table.sql | 9 +++++++++
3 files changed, 39 insertions(+)
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 93d72157a46..5d5fdf5dd77 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -290,6 +290,20 @@ has_partition_attrs(Relation rel, Bitmapset *attnums, bool *used_in_expr)
/* Find all attributes referenced */
pull_varattnos(expr, 1, &expr_attrs);
+
+ /*
+ * If the partition expression contains a whole-row reference,
+ * then all columns are indirectly associated with that
+ * expression.
+ */
+ if (bms_is_member(InvalidAttrNumber - FirstLowInvalidHeapAttributeNumber,
+ expr_attrs))
+ {
+ if (used_in_expr)
+ *used_in_expr = true;
+ return true;
+ }
+
partexprs_item = lnext(partexprs, partexprs_item);
if (bms_overlap(attnums, expr_attrs))
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 5e98bbf2425..e740f178c11 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -3988,6 +3988,22 @@ LINE 1: ALTER TABLE partitioned ALTER COLUMN b TYPE char(5);
ALTER TABLE partitioned SET (fillfactor=100);
ERROR: cannot specify storage parameters for a partitioned table
HINT: Specify storage parameters for its leaf partitions instead.
+-- If the partition expression contains a whole-row reference, altering a
+-- column’s data type or dropping the column is not allowed.
+CREATE TABLE partitioned1(a int, b int) PARTITION BY list((partitioned1));
+ALTER TABLE partitioned1 DROP COLUMN a; --error
+ERROR: cannot drop column "a" because it is part of the partition key of relation "partitioned1"
+ALTER TABLE partitioned1 DROP COLUMN b; --error
+ERROR: cannot drop column "b" because it is part of the partition key of relation "partitioned1"
+ALTER TABLE partitioned1 ALTER COLUMN a TYPE text; --error
+ERROR: cannot alter column "a" because it is part of the partition key of relation "partitioned1"
+LINE 1: ALTER TABLE partitioned1 ALTER COLUMN a TYPE text;
+ ^
+ALTER TABLE partitioned1 ALTER COLUMN b TYPE text; --error
+ERROR: cannot alter column "b" because it is part of the partition key of relation "partitioned1"
+LINE 1: ALTER TABLE partitioned1 ALTER COLUMN b TYPE text;
+ ^
+DROP TABLE partitioned1;
-- partitioned table cannot participate in regular inheritance
CREATE TABLE nonpartitioned (
a int,
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 417202430a5..cce2ac8ea57 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -2392,6 +2392,15 @@ ALTER TABLE partitioned ALTER COLUMN b TYPE char(5);
-- specifying storage parameters for partitioned tables is not supported
ALTER TABLE partitioned SET (fillfactor=100);
+-- If the partition expression contains a whole-row reference, altering a
+-- column’s data type or dropping the column is not allowed.
+CREATE TABLE partitioned1(a int, b int) PARTITION BY list((partitioned1));
+ALTER TABLE partitioned1 DROP COLUMN a; --error
+ALTER TABLE partitioned1 DROP COLUMN b; --error
+ALTER TABLE partitioned1 ALTER COLUMN a TYPE text; --error
+ALTER TABLE partitioned1 ALTER COLUMN b TYPE text; --error
+DROP TABLE partitioned1;
+
-- partitioned table cannot participate in regular inheritance
CREATE TABLE nonpartitioned (
a int,
--
2.34.1