From 088731e9dbcd2666977bce048241c61673e0f344 Mon Sep 17 00:00:00 2001 From: Colm Date: Wed, 18 Dec 2024 13:18:53 +0000 Subject: [PATCH] PG17 compatibility: account for identity columns in partitioned tables. (#7785) PG17 added support for identity columns in partitioned tables: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=699586315 A consequence is that a table with an identity column cannot be attached as a partition. But Citus on Postgres 17 will generate identity column for the partitions if the parent table has one (or more) identity columns when propagating distributed table DDL to worker nodes, as happens in the `generated_identity` regress test in #7768: ``` CREATE TABLE partitioned_table ( a bigint CONSTRAINT myconname GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10), b bigint GENERATED ALWAYS AS IDENTITY (START WITH 10 INCREMENT BY 10), c int ) PARTITION BY RANGE (c); CREATE TABLE partitioned_table_1_50 PARTITION OF partitioned_table FOR VALUES FROM (1) TO (50); CREATE TABLE partitioned_table_50_500 PARTITION OF partitioned_table FOR VALUES FROM (50) TO (1000); SELECT create_distributed_table('partitioned_table', 'a'); - create_distributed_table ---------------------------------------------------------------------- - -(1 row) - +ERROR: table "partitioned_table_1_50" being attached contains an identity column "a" +DETAIL: The new partition may not contain an identity column. ``` It is the Citus-generated ATTACH PARTITION statement that errors out, because the Citus-generated CREATE TABLE for the partitions included identity column definitions. The fix is straightforward - when propagating the CREATE TABLE ddl for a partition of a table with an identity column, don't include the identity column(s), they will be inherited on attaching the partition. In Citus on Postgres 16 (or less) partitions do not inherit identity; the partitions in the example would not have any identity columns so it was not an issue previously. --- .../distributed/deparser/citus_ruleutils.c | 12 +- src/test/regress/expected/pg17.out | 462 ++++++++++++++++++ src/test/regress/sql/pg17.sql | 189 +++++++ 3 files changed, 662 insertions(+), 1 deletion(-) diff --git a/src/backend/distributed/deparser/citus_ruleutils.c b/src/backend/distributed/deparser/citus_ruleutils.c index e5445b3df..d138f8859 100644 --- a/src/backend/distributed/deparser/citus_ruleutils.c +++ b/src/backend/distributed/deparser/citus_ruleutils.c @@ -315,6 +315,7 @@ pg_get_tableschemadef_string(Oid tableRelationId, IncludeSequenceDefaults AttrNumber defaultValueIndex = 0; AttrNumber constraintIndex = 0; AttrNumber constraintCount = 0; + bool relIsPartition = false; StringInfoData buffer = { NULL, 0, 0, 0 }; /* @@ -342,6 +343,8 @@ pg_get_tableschemadef_string(Oid tableRelationId, IncludeSequenceDefaults } appendStringInfo(&buffer, "TABLE %s (", relationName); + + relIsPartition = relation->rd_rel->relispartition; } else { @@ -392,7 +395,14 @@ pg_get_tableschemadef_string(Oid tableRelationId, IncludeSequenceDefaults GetCompressionMethodName(attributeForm->attcompression)); } - if (attributeForm->attidentity && includeIdentityDefaults) + /* + * If this is an identity column include its identity definition in the + * DDL only if its relation is not a partition. If it is a partition, any + * identity is inherited from the parent table by ATTACH PARTITION. This + * is Postgres 17+ behavior (commit 699586315); prior PG versions did not + * support identity columns in partitioned tables. + */ + if (attributeForm->attidentity && includeIdentityDefaults && !relIsPartition) { bool missing_ok = false; Oid seqOid = getIdentitySequence(identitySequenceRelation_compat( diff --git a/src/test/regress/expected/pg17.out b/src/test/regress/expected/pg17.out index aa4ccb64c..35b4aa326 100644 --- a/src/test/regress/expected/pg17.out +++ b/src/test/regress/expected/pg17.out @@ -492,7 +492,469 @@ NOTICE: issuing VACUUM pg17.dist_test_20240023 DETAIL: on server regress_maintain@localhost:xxxxx connectionId: xxxxxxx RESET ROLE; -- End of MAINTAIN privilege tests +-- Partitions inherit identity column RESET citus.log_remote_commands; +-- PG17 added support for identity columns in partioned tables: +-- https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=699586315 +-- In particular, partitions with their own identity columns are not allowed. +-- Citus does not need to propagate identity columns in partitions; the identity +-- is inherited by PG17 behavior, as shown in this test. +CREATE TABLE partitioned_table ( + a bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10), + c int +) +PARTITION BY RANGE (c); +CREATE TABLE pt_1 PARTITION OF partitioned_table FOR VALUES FROM (1) TO (50); +SELECT create_distributed_table('partitioned_table', 'a'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +CREATE TABLE pt_2 PARTITION OF partitioned_table FOR VALUES FROM (50) TO (1000); +-- (1) The partitioned table has pt_1 and pt_2 as its partitions +\d+ partitioned_table; + Partitioned table "pg17.partitioned_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: pt_1 FOR VALUES FROM (1) TO (50), + pt_2 FOR VALUES FROM (50) TO (1000) + +-- (2) The partitions have the same identity column as the parent table; +-- This is PG17 behavior for support for identity in partitioned tables. +\d pt_1; + Table "pg17.pt_1" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: partitioned_table FOR VALUES FROM (1) TO (50) + +\d pt_2; + Table "pg17.pt_2" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: partitioned_table FOR VALUES FROM (50) TO (1000) + +-- Attaching a partition inherits the identity column from the parent table +CREATE TABLE pt_3 (a bigint not null, c int); +ALTER TABLE partitioned_table ATTACH PARTITION pt_3 FOR VALUES FROM (1000) TO (2000); +\d+ partitioned_table; + Partitioned table "pg17.partitioned_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: pt_1 FOR VALUES FROM (1) TO (50), + pt_2 FOR VALUES FROM (50) TO (1000), + pt_3 FOR VALUES FROM (1000) TO (2000) + +\d pt_3; + Table "pg17.pt_3" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: partitioned_table FOR VALUES FROM (1000) TO (2000) + +-- Partition pt_4 has its own identity column, which is not allowed in PG17 +-- and will produce an error on attempting to attach it to the partitioned table +CREATE TABLE pt_4 (a bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10), c int); +ALTER TABLE partitioned_table ATTACH PARTITION pt_4 FOR VALUES FROM (2000) TO (3000); +ERROR: table "pt_4" being attached contains an identity column "a" +DETAIL: The new partition may not contain an identity column. +\c - - - :worker_1_port +SET search_path TO pg17; +-- Show that DDL for partitioned_table has correctly propagated to the worker node; +-- (1) The partitioned table has pt_1, pt_2 and pt_3 as its partitions +\d+ partitioned_table; + Partitioned table "pg17.partitioned_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: pt_1 FOR VALUES FROM (1) TO (50), + pt_2 FOR VALUES FROM (50) TO (1000), + pt_3 FOR VALUES FROM (1000) TO (2000) + +-- (2) The partititions have the same identity column as the parent table +\d pt_1; + Table "pg17.pt_1" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: partitioned_table FOR VALUES FROM (1) TO (50) + +\d pt_2; + Table "pg17.pt_2" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: partitioned_table FOR VALUES FROM (50) TO (1000) + +\d pt_3; + Table "pg17.pt_3" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: partitioned_table FOR VALUES FROM (1000) TO (2000) + +\c - - - :master_port +SET search_path TO pg17; +-- Test detaching a partition with an identity column +ALTER TABLE partitioned_table DETACH PARTITION pt_3; +-- partitioned_table has pt_1, pt_2 as its partitions +-- and pt_3 does not have an identity column +\d+ partitioned_table; + Partitioned table "pg17.partitioned_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: pt_1 FOR VALUES FROM (1) TO (50), + pt_2 FOR VALUES FROM (50) TO (1000) + +\d pt_3; + Table "pg17.pt_3" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | + c | integer | | | + +-- Verify that the detach has propagated to the worker node +\c - - - :worker_1_port +SET search_path TO pg17; +\d+ partitioned_table; + Partitioned table "pg17.partitioned_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: pt_1 FOR VALUES FROM (1) TO (50), + pt_2 FOR VALUES FROM (50) TO (1000) + +\d pt_3; + Table "pg17.pt_3" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | + c | integer | | | + +\c - - - :master_port +SET search_path TO pg17; +CREATE TABLE alt_test (a int, b date, c int) PARTITION BY RANGE(c); +SELECT create_distributed_table('alt_test', 'a'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +CREATE TABLE alt_test_pt_1 PARTITION OF alt_test FOR VALUES FROM (1) TO (50); +CREATE TABLE alt_test_pt_2 PARTITION OF alt_test FOR VALUES FROM (50) TO (100); +-- Citus does not support adding an identity column for a distributed table (#6738) +-- Attempting to add a column with identity produces an error +ALTER TABLE alt_test ADD COLUMN d bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10); +ERROR: cannot execute ADD COLUMN commands involving identity columns when metadata is synchronized to workers +-- alter table set identity is currently not supported, so adding identity to +-- an existing column generates an error +ALTER TABLE alt_test ALTER COLUMN a SET GENERATED BY DEFAULT SET INCREMENT BY 2 SET START WITH 75 RESTART; +ERROR: alter table command is currently unsupported +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ENABLE|DISABLE|NO FORCE|FORCE ROW LEVEL SECURITY, ATTACH|DETACH PARTITION and TYPE subcommands are supported. +-- Verify that the identity column was not added, on coordinator and worker nodes +\d+ alt_test; + Partitioned table "pg17.alt_test" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | integer | | | | plain | | + b | date | | | | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: alt_test_pt_1 FOR VALUES FROM (1) TO (50), + alt_test_pt_2 FOR VALUES FROM (50) TO (100) + +\d alt_test_pt_1; + Table "pg17.alt_test_pt_1" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | integer | | | + b | date | | | + c | integer | | | +Partition of: alt_test FOR VALUES FROM (1) TO (50) + +\d alt_test_pt_2; + Table "pg17.alt_test_pt_2" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | integer | | | + b | date | | | + c | integer | | | +Partition of: alt_test FOR VALUES FROM (50) TO (100) + +\c - - - :worker_1_port +SET search_path TO pg17; +\d+ alt_test; + Partitioned table "pg17.alt_test" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | integer | | | | plain | | + b | date | | | | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: alt_test_pt_1 FOR VALUES FROM (1) TO (50), + alt_test_pt_2 FOR VALUES FROM (50) TO (100) + +\d alt_test_pt_1; + Table "pg17.alt_test_pt_1" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | integer | | | + b | date | | | + c | integer | | | +Partition of: alt_test FOR VALUES FROM (1) TO (50) + +\d alt_test_pt_2; + Table "pg17.alt_test_pt_2" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | integer | | | + b | date | | | + c | integer | | | +Partition of: alt_test FOR VALUES FROM (50) TO (100) + +\c - - - :master_port +SET search_path TO pg17; +DROP TABLE alt_test; +CREATE TABLE alt_test (a bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10), + b int, + c int) +PARTITION BY RANGE(c); +SELECT create_distributed_table('alt_test', 'b'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +CREATE TABLE alt_test_pt_1 PARTITION OF alt_test FOR VALUES FROM (1) TO (50); +CREATE TABLE alt_test_pt_2 PARTITION OF alt_test FOR VALUES FROM (50) TO (100); +-- Dropping of the identity property from a column is currently not supported; +-- Attempting to drop identity produces an error +ALTER TABLE alt_test ALTER COLUMN a DROP IDENTITY; +ERROR: alter table command is currently unsupported +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ENABLE|DISABLE|NO FORCE|FORCE ROW LEVEL SECURITY, ATTACH|DETACH PARTITION and TYPE subcommands are supported. +-- Verify that alt_test still has identity on column a +\d+ alt_test; + Partitioned table "pg17.alt_test" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + b | integer | | | | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: alt_test_pt_1 FOR VALUES FROM (1) TO (50), + alt_test_pt_2 FOR VALUES FROM (50) TO (100) + +\d alt_test_pt_1; + Table "pg17.alt_test_pt_1" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + b | integer | | | + c | integer | | | +Partition of: alt_test FOR VALUES FROM (1) TO (50) + +\d alt_test_pt_2; + Table "pg17.alt_test_pt_2" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + b | integer | | | + c | integer | | | +Partition of: alt_test FOR VALUES FROM (50) TO (100) + +\c - - - :worker_1_port +SET search_path TO pg17; +\d+ alt_test; + Partitioned table "pg17.alt_test" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + b | integer | | | | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: alt_test_pt_1 FOR VALUES FROM (1) TO (50), + alt_test_pt_2 FOR VALUES FROM (50) TO (100) + +\d alt_test_pt_1; + Table "pg17.alt_test_pt_1" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + b | integer | | | + c | integer | | | +Partition of: alt_test FOR VALUES FROM (1) TO (50) + +\d alt_test_pt_2 + Table "pg17.alt_test_pt_2" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + b | integer | | | + c | integer | | | +Partition of: alt_test FOR VALUES FROM (50) TO (100) + +\c - - - :master_port +SET search_path TO pg17; +-- Repeat testing of partitions with identity column on a citus local table +CREATE TABLE local_partitioned_table ( + a bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10), + c int +) +PARTITION BY RANGE (c); +CREATE TABLE lpt_1 PARTITION OF local_partitioned_table FOR VALUES FROM (1) TO (50); +SELECT citus_add_local_table_to_metadata('local_partitioned_table'); + citus_add_local_table_to_metadata +--------------------------------------------------------------------- + +(1 row) + +-- Can create tables as partitions and attach tables as partitions to a citus local table: +CREATE TABLE lpt_2 PARTITION OF local_partitioned_table FOR VALUES FROM (50) TO (1000); +CREATE TABLE lpt_3 (a bigint not null, c int); +ALTER TABLE local_partitioned_table ATTACH PARTITION lpt_3 FOR VALUES FROM (1000) TO (2000); +-- The partitions have the same identity column as the parent table, on coordinator and worker nodes +\d+ local_partitioned_table; + Partitioned table "pg17.local_partitioned_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: lpt_1 FOR VALUES FROM (1) TO (50), + lpt_2 FOR VALUES FROM (50) TO (1000), + lpt_3 FOR VALUES FROM (1000) TO (2000) + +\d lpt_1; + Table "pg17.lpt_1" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: local_partitioned_table FOR VALUES FROM (1) TO (50) + +\d lpt_2; + Table "pg17.lpt_2" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: local_partitioned_table FOR VALUES FROM (50) TO (1000) + +\d lpt_3; + Table "pg17.lpt_3" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: local_partitioned_table FOR VALUES FROM (1000) TO (2000) + +\c - - - :worker_1_port +SET search_path TO pg17; +\d+ local_partitioned_table; + Partitioned table "pg17.local_partitioned_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: lpt_1 FOR VALUES FROM (1) TO (50), + lpt_2 FOR VALUES FROM (50) TO (1000), + lpt_3 FOR VALUES FROM (1000) TO (2000) + +\d lpt_1; + Table "pg17.lpt_1" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: local_partitioned_table FOR VALUES FROM (1) TO (50) + +\d lpt_2; + Table "pg17.lpt_2" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: local_partitioned_table FOR VALUES FROM (50) TO (1000) + +\d lpt_3; + Table "pg17.lpt_3" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity + c | integer | | | +Partition of: local_partitioned_table FOR VALUES FROM (1000) TO (2000) + +\c - - - :master_port +SET search_path TO pg17; +-- Test detaching a partition with an identity column from a citus local table +ALTER TABLE local_partitioned_table DETACH PARTITION lpt_3; +\d+ local_partitioned_table; + Partitioned table "pg17.local_partitioned_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: lpt_1 FOR VALUES FROM (1) TO (50), + lpt_2 FOR VALUES FROM (50) TO (1000) + +\d lpt_3; + Table "pg17.lpt_3" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | + c | integer | | | + +\c - - - :worker_1_port +SET search_path TO pg17; +\d+ local_partitioned_table; + Partitioned table "pg17.local_partitioned_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------------------------------------------------------------------- + a | bigint | | not null | generated by default as identity | plain | | + c | integer | | | | plain | | +Partition key: RANGE (c) +Partitions: lpt_1 FOR VALUES FROM (1) TO (50), + lpt_2 FOR VALUES FROM (50) TO (1000) + +\d lpt_3; + Table "pg17.lpt_3" + Column | Type | Collation | Nullable | Default +--------------------------------------------------------------------- + a | bigint | | not null | + c | integer | | | + +\c - - - :master_port +SET search_path TO pg17; +DROP TABLE partitioned_table; +DROP TABLE local_partitioned_table; +DROP TABLE lpt_3; +DROP TABLE pt_3; +DROP TABLE pt_4; +DROP TABLE alt_test; +-- End of partition with identity columns testing RESET citus.next_shard_id; RESET citus.shard_count; RESET citus.shard_replication_factor; diff --git a/src/test/regress/sql/pg17.sql b/src/test/regress/sql/pg17.sql index 3c9a2541c..4730426eb 100644 --- a/src/test/regress/sql/pg17.sql +++ b/src/test/regress/sql/pg17.sql @@ -274,7 +274,196 @@ RESET ROLE; -- End of MAINTAIN privilege tests +-- Partitions inherit identity column + RESET citus.log_remote_commands; + +-- PG17 added support for identity columns in partioned tables: +-- https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=699586315 +-- In particular, partitions with their own identity columns are not allowed. +-- Citus does not need to propagate identity columns in partitions; the identity +-- is inherited by PG17 behavior, as shown in this test. + +CREATE TABLE partitioned_table ( + a bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10), + c int +) +PARTITION BY RANGE (c); +CREATE TABLE pt_1 PARTITION OF partitioned_table FOR VALUES FROM (1) TO (50); + +SELECT create_distributed_table('partitioned_table', 'a'); + +CREATE TABLE pt_2 PARTITION OF partitioned_table FOR VALUES FROM (50) TO (1000); + +-- (1) The partitioned table has pt_1 and pt_2 as its partitions +\d+ partitioned_table; + +-- (2) The partitions have the same identity column as the parent table; +-- This is PG17 behavior for support for identity in partitioned tables. +\d pt_1; +\d pt_2; + +-- Attaching a partition inherits the identity column from the parent table +CREATE TABLE pt_3 (a bigint not null, c int); +ALTER TABLE partitioned_table ATTACH PARTITION pt_3 FOR VALUES FROM (1000) TO (2000); + +\d+ partitioned_table; +\d pt_3; + +-- Partition pt_4 has its own identity column, which is not allowed in PG17 +-- and will produce an error on attempting to attach it to the partitioned table +CREATE TABLE pt_4 (a bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10), c int); +ALTER TABLE partitioned_table ATTACH PARTITION pt_4 FOR VALUES FROM (2000) TO (3000); + +\c - - - :worker_1_port + +SET search_path TO pg17; +-- Show that DDL for partitioned_table has correctly propagated to the worker node; +-- (1) The partitioned table has pt_1, pt_2 and pt_3 as its partitions +\d+ partitioned_table; + +-- (2) The partititions have the same identity column as the parent table +\d pt_1; +\d pt_2; +\d pt_3; + +\c - - - :master_port +SET search_path TO pg17; + +-- Test detaching a partition with an identity column +ALTER TABLE partitioned_table DETACH PARTITION pt_3; + +-- partitioned_table has pt_1, pt_2 as its partitions +-- and pt_3 does not have an identity column +\d+ partitioned_table; +\d pt_3; + +-- Verify that the detach has propagated to the worker node +\c - - - :worker_1_port +SET search_path TO pg17; + +\d+ partitioned_table; +\d pt_3; + +\c - - - :master_port +SET search_path TO pg17; + +CREATE TABLE alt_test (a int, b date, c int) PARTITION BY RANGE(c); +SELECT create_distributed_table('alt_test', 'a'); + +CREATE TABLE alt_test_pt_1 PARTITION OF alt_test FOR VALUES FROM (1) TO (50); +CREATE TABLE alt_test_pt_2 PARTITION OF alt_test FOR VALUES FROM (50) TO (100); + +-- Citus does not support adding an identity column for a distributed table (#6738) +-- Attempting to add a column with identity produces an error +ALTER TABLE alt_test ADD COLUMN d bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10); + +-- alter table set identity is currently not supported, so adding identity to +-- an existing column generates an error +ALTER TABLE alt_test ALTER COLUMN a SET GENERATED BY DEFAULT SET INCREMENT BY 2 SET START WITH 75 RESTART; + +-- Verify that the identity column was not added, on coordinator and worker nodes +\d+ alt_test; +\d alt_test_pt_1; +\d alt_test_pt_2; + +\c - - - :worker_1_port +SET search_path TO pg17; + +\d+ alt_test; +\d alt_test_pt_1; +\d alt_test_pt_2; + +\c - - - :master_port +SET search_path TO pg17; + +DROP TABLE alt_test; +CREATE TABLE alt_test (a bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10), + b int, + c int) +PARTITION BY RANGE(c); + +SELECT create_distributed_table('alt_test', 'b'); +CREATE TABLE alt_test_pt_1 PARTITION OF alt_test FOR VALUES FROM (1) TO (50); +CREATE TABLE alt_test_pt_2 PARTITION OF alt_test FOR VALUES FROM (50) TO (100); + +-- Dropping of the identity property from a column is currently not supported; +-- Attempting to drop identity produces an error +ALTER TABLE alt_test ALTER COLUMN a DROP IDENTITY; + +-- Verify that alt_test still has identity on column a +\d+ alt_test; +\d alt_test_pt_1; +\d alt_test_pt_2; + +\c - - - :worker_1_port +SET search_path TO pg17; + +\d+ alt_test; +\d alt_test_pt_1; +\d alt_test_pt_2 + +\c - - - :master_port +SET search_path TO pg17; + +-- Repeat testing of partitions with identity column on a citus local table + +CREATE TABLE local_partitioned_table ( + a bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 10 INCREMENT BY 10), + c int +) +PARTITION BY RANGE (c); +CREATE TABLE lpt_1 PARTITION OF local_partitioned_table FOR VALUES FROM (1) TO (50); + +SELECT citus_add_local_table_to_metadata('local_partitioned_table'); + +-- Can create tables as partitions and attach tables as partitions to a citus local table: +CREATE TABLE lpt_2 PARTITION OF local_partitioned_table FOR VALUES FROM (50) TO (1000); + +CREATE TABLE lpt_3 (a bigint not null, c int); +ALTER TABLE local_partitioned_table ATTACH PARTITION lpt_3 FOR VALUES FROM (1000) TO (2000); + +-- The partitions have the same identity column as the parent table, on coordinator and worker nodes +\d+ local_partitioned_table; +\d lpt_1; +\d lpt_2; +\d lpt_3; + +\c - - - :worker_1_port +SET search_path TO pg17; + +\d+ local_partitioned_table; +\d lpt_1; +\d lpt_2; +\d lpt_3; + +\c - - - :master_port +SET search_path TO pg17; + +-- Test detaching a partition with an identity column from a citus local table +ALTER TABLE local_partitioned_table DETACH PARTITION lpt_3; + +\d+ local_partitioned_table; +\d lpt_3; + +\c - - - :worker_1_port +SET search_path TO pg17; + +\d+ local_partitioned_table; +\d lpt_3; + +\c - - - :master_port +SET search_path TO pg17; + +DROP TABLE partitioned_table; +DROP TABLE local_partitioned_table; +DROP TABLE lpt_3; +DROP TABLE pt_3; +DROP TABLE pt_4; +DROP TABLE alt_test; + +-- End of partition with identity columns testing + RESET citus.next_shard_id; RESET citus.shard_count; RESET citus.shard_replication_factor;