From 5fc0bcb59f1f40a2d10dd191d208b074145bd4c4 Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Mon, 22 Apr 2024 13:21:14 +0300 Subject: [PATCH v8 6/7] Inherit parent's AM for partition MERGE/SPLIT operations This commit makes new partitions created by ALTER TABLE ... SPLIT PARTITION and ALTER TABLE ... MERGE PARTITIONS commands inherit the paret table access method. Reported-by: Alexander Lakhin Discussion: https://postgr.es/m/84ada05b-be5c-473e-6d1c-ebe5dd21b190%40gmail.com --- doc/src/sgml/ref/alter_table.sgml | 8 +++---- src/backend/commands/tablecmds.c | 6 +++++ src/test/regress/expected/partition_merge.out | 18 +++++++++++++++ src/test/regress/expected/partition_split.out | 23 +++++++++++++++++-- src/test/regress/sql/partition_merge.sql | 13 +++++++++++ src/test/regress/sql/partition_split.sql | 14 +++++++++++ 6 files changed, 76 insertions(+), 6 deletions(-) diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index a793899b69b..dba49a7ac8f 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -1158,8 +1158,8 @@ WITH ( MODULUS numeric_literal, REM in the parent table are cloned on new partitions partition_name1, partition_name2, ... . - New partitions will have the same column names and types as the - partitioned table to which they belong. + New partitions will have the same table access method, + same column names and types as the partitioned table to which they belong. If the parent table is persistent then new partitions are created persistent. If the parent table is temporary then new partitions are also created temporary. @@ -1228,8 +1228,8 @@ WITH ( MODULUS numeric_literal, REM Any indexes, constraints and user-defined row-level triggers that exist in the parent table are cloned on the new partition partition_name. - The new partition will have the same column names and types as the - partitioned table to which it belongs. + The new partition will have the same table access method, + same column names and types as the partitioned table to which it belongs. If the parent table is persistent then the new partition is created persistent. If the parent table is temporary then the new partition is also created temporary. diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 1b89e18eb7e..fd0812cd649 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -21187,6 +21187,11 @@ moveSplitTableRows(Relation rel, Relation splitRel, List *partlist, List *newPar * * Emulates command: CREATE [TEMP] TABLE (LIKE * INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY) + * + * Also, this function sets the new partition access method same as parent + * table access methods (similarly to CREATE TABLE ... PARTITION OF). It + * checks that parent and child tables have compatible persistence. + * * Function returns the created relation (locked in AccessExclusiveLock mode). */ static Relation @@ -21217,6 +21222,7 @@ createPartitionTable(RangeVar *newPartName, Relation modelRel, createStmt->oncommit = ONCOMMIT_NOOP; createStmt->tablespacename = NULL; createStmt->if_not_exists = false; + createStmt->accessMethod = get_am_name(modelRel->rd_rel->relam); tlc = makeNode(TableLikeClause); tlc->relation = makeRangeVar(get_namespace_name(RelationGetNamespace(modelRel)), diff --git a/src/test/regress/expected/partition_merge.out b/src/test/regress/expected/partition_merge.out index a92a270c591..92999703217 100644 --- a/src/test/regress/expected/partition_merge.out +++ b/src/test/regress/expected/partition_merge.out @@ -862,6 +862,24 @@ SET search_path = partitions_merge_schema, pg_temp, public; -- Can't merge temporary partitions into a persistent partition ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; ROLLBACK; +-- Check the new partition inherits parent's table access method +SET search_path = partitions_merge_schema, public; +CREATE ACCESS METHOD partitions_merge_heap TYPE TABLE HANDLER heap_tableam_handler; +CREATE TABLE t (i int) PARTITION BY RANGE (i) USING partitions_merge_heap; +CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); +CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); +ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; +SELECT c.relname, a.amname +FROM pg_class c JOIN pg_am a ON c.relam = a.oid +WHERE c.oid IN ('t'::regclass, 'tp_0_2'::regclass); + relname | amname +---------+----------------------- + tp_0_2 | partitions_merge_heap + t | partitions_merge_heap +(2 rows) + +DROP TABLE t; +DROP ACCESS METHOD partitions_merge_heap; RESET search_path; -- DROP SCHEMA partitions_merge_schema; diff --git a/src/test/regress/expected/partition_split.out b/src/test/regress/expected/partition_split.out index 55ae37ad370..326fa1bd400 100644 --- a/src/test/regress/expected/partition_split.out +++ b/src/test/regress/expected/partition_split.out @@ -85,8 +85,8 @@ ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-06-01')); ERROR: upper bound of partition "sales_apr2022" is greater than upper bound of split partition -LINE 4: PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO... - ^ +LINE 4: ... sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-06-0... + ^ -- ERROR: lower bound of partition "sales_mar2022" conflicts with upper bound of previous partition "sales_feb2022" ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), @@ -1494,6 +1494,25 @@ SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid) (2 rows) DROP TABLE t; +-- Check new partitions inherits parent's table access method +CREATE ACCESS METHOD partition_split_heap TYPE TABLE HANDLER heap_tableam_handler; +CREATE TABLE t (i int) PARTITION BY RANGE (i) USING partition_split_heap; +CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); +ALTER TABLE t SPLIT PARTITION tp_0_2 INTO + (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), + PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); +SELECT c.relname, a.amname +FROM pg_class c JOIN pg_am a ON c.relam = a.oid +WHERE c.oid IN ('t'::regclass, 'tp_0_1'::regclass, 'tp_1_2'::regclass); + relname | amname +---------+---------------------- + t | partition_split_heap + tp_0_1 | partition_split_heap + tp_1_2 | partition_split_heap +(3 rows) + +DROP TABLE t; +DROP ACCESS METHOD partition_split_heap; -- DROP SCHEMA partition_split_schema; DROP SCHEMA partition_split_schema2; diff --git a/src/test/regress/sql/partition_merge.sql b/src/test/regress/sql/partition_merge.sql index 085c422d540..23795cf9d94 100644 --- a/src/test/regress/sql/partition_merge.sql +++ b/src/test/regress/sql/partition_merge.sql @@ -535,6 +535,19 @@ SET search_path = partitions_merge_schema, pg_temp, public; ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; ROLLBACK; +-- Check the new partition inherits parent's table access method +SET search_path = partitions_merge_schema, public; +CREATE ACCESS METHOD partitions_merge_heap TYPE TABLE HANDLER heap_tableam_handler; +CREATE TABLE t (i int) PARTITION BY RANGE (i) USING partitions_merge_heap; +CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); +CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); +ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; +SELECT c.relname, a.amname +FROM pg_class c JOIN pg_am a ON c.relam = a.oid +WHERE c.oid IN ('t'::regclass, 'tp_0_2'::regclass); +DROP TABLE t; +DROP ACCESS METHOD partitions_merge_heap; + RESET search_path; -- diff --git a/src/test/regress/sql/partition_split.sql b/src/test/regress/sql/partition_split.sql index 3a7f2f9c294..73e8c2fbeb9 100644 --- a/src/test/regress/sql/partition_split.sql +++ b/src/test/regress/sql/partition_split.sql @@ -880,6 +880,20 @@ SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid) DROP TABLE t; +-- Check new partitions inherits parent's table access method +CREATE ACCESS METHOD partition_split_heap TYPE TABLE HANDLER heap_tableam_handler; +CREATE TABLE t (i int) PARTITION BY RANGE (i) USING partition_split_heap; +CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); +ALTER TABLE t SPLIT PARTITION tp_0_2 INTO + (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), + PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); +SELECT c.relname, a.amname +FROM pg_class c JOIN pg_am a ON c.relam = a.oid +WHERE c.oid IN ('t'::regclass, 'tp_0_1'::regclass, 'tp_1_2'::regclass); +DROP TABLE t; +DROP ACCESS METHOD partition_split_heap; + + -- DROP SCHEMA partition_split_schema; DROP SCHEMA partition_split_schema2; -- 2.39.3 (Apple Git-145)