diff --git a/src/backend/parser/parse_partition_gp.c b/src/backend/parser/parse_partition_gp.c index 67d0122ab15..9b2923b1418 100644 --- a/src/backend/parser/parse_partition_gp.c +++ b/src/backend/parser/parse_partition_gp.c @@ -15,6 +15,7 @@ #include "postgres.h" #include "access/table.h" +#include "access/tableam.h" #include "catalog/partition.h" #include "catalog/pg_collation.h" #include "catalog/gp_partition_template.h" @@ -1607,11 +1608,16 @@ generatePartitions(Oid parentrelid, GpPartitionDefinition *gpPartSpec, /* if WITH has "tablename" then it will be used as name for partition */ partcomp.tablename = extract_tablename_from_options(&elem->options); - if (elem->options == NIL) - elem->options = parentoptions ? copyObject(parentoptions) : NIL; if (elem->accessMethod == NULL) elem->accessMethod = parentaccessmethod ? pstrdup(parentaccessmethod) : NULL; + /* if no options are specified AND child has same access method as parent, use parent options */ + if (elem->options == NIL && + (!elem->accessMethod || + (parentaccessmethod && strcmp(elem->accessMethod, parentaccessmethod) == 0) || + (!parentaccessmethod && strcmp(elem->accessMethod, default_table_access_method) == 0))) + elem->options = parentoptions ? copyObject(parentoptions) : NIL; + if (elem->accessMethod && strcmp(elem->accessMethod, "ao_column") == 0) elem->colencs = merge_partition_encoding(pstate, elem->colencs, penc_cls); else if (!elem->colencs) { diff --git a/src/test/regress/input/partition_ddl.source b/src/test/regress/input/partition_ddl.source index 147b3497131..5c41027b1aa 100644 --- a/src/test/regress/input/partition_ddl.source +++ b/src/test/regress/input/partition_ddl.source @@ -976,3 +976,45 @@ alter table root_part_1_prt_interior_1 add primary key using index root_part_1_p create unique index on root_part_1_prt_interior_1_2_prt_leaf(a, b); alter table root_part_1_prt_interior_1_2_prt_leaf add primary key using index root_part_1_prt_interior_1_2_prt_leaf_a_b_idx2; drop table root_part; + +-- The following tests verifies reloptions inheritance for partitioned tables. +-- When parent's reloptions are specified, a child partition's reloptions should be set as below: +-- 1) If child's reloptions are specified, then the child's reloptions override the parent's reloptions. +-- 2) If child's reloptions are not specified, and if parent's and child's table access methods are same, then the parent's reloptions are inherited. +-- 3) If child's reloptions are not specified, and if parent's and child's table access methods are different, then the child's reloptions are set to default. +-- 4) Note that "appendonly" and "orientation" reloptions are not "real" reloptions and are instead treated as table access method specifications. +-- So, if child's WITH clause has only "appendonly" and/or "orientation" specified, they are handled as in (2) and (3) above. + +-- Test 1: Parent's reloptions are explicitly specified, and parent's AM is explicitly specified as ao_row +create table part_ao(a int, b int) with (appendonly=true,compresstype=zlib,compresslevel=5,blocksize=65536) + partition by range(b) + (partition p1_heap start (0) end (10) with (appendonly=false), + partition p2_aoco start (10) end (20) with (appendonly=true, orientation=column), + partition p3_new_relopt start (20) end (30) with (compresstype=zstd, compresslevel=3), + default partition def); +select c.relname, am.amname, c.reloptions from pg_partition_tree('part_ao') as t join pg_class c on (t.relid::oid = c.oid) left join pg_am am on (c.relam = am.oid); + +-- Test 2: Parent's reloptions are explicitly specified, and parent's AM is explicitly specified as heap +create table part_heap1(a int, b int) using heap with (fillfactor=70) partition by range(b) (partition p1 start(0) end(10) with(appendonly=true)); +select c.relname, am.amname, c.reloptions from pg_partition_tree('part_heap1') as t join pg_class c on (t.relid::oid = c.oid) left join pg_am am on (c.relam = am.oid); + +-- Test 3: Parent's reloptions are explicitly specified, and parent's AM is implicitly specified as heap +create table part_heap2(a int, b int) with (fillfactor=70) partition by range(b) (partition p1 start(0) end(10) with(appendonly=true)); +select c.relname, am.amname, c.reloptions from pg_partition_tree('part_heap2') as t join pg_class c on (t.relid::oid = c.oid) left join pg_am am on (c.relam = am.oid); + +-- Test 4: Parent's reloptions are explicitly specified, and parent's AM is implicitly specified as ao_column +set default_table_access_method = 'ao_column'; +create table part_aoco(a int, b int) with (compresstype=zlib,compresslevel=5,blocksize=65536) + partition by range(b) + (partition p1_heap start (0) end (10) with (appendonly=false), + partition p2_ao start (10) end (20) with (appendonly=true, orientation=row), + partition p3_new_relopt start (20) end (30) with (compresstype=zstd, compresslevel=3), + default partition def); +select c.relname, am.amname, c.reloptions from pg_partition_tree('part_aoco') as t join pg_class c on (t.relid::oid = c.oid) left join pg_am am on (c.relam = am.oid); +reset default_table_access_method; + +-- cleanup +drop table part_ao; +drop table part_heap1; +drop table part_heap2; +drop table part_aoco; diff --git a/src/test/regress/output/partition_ddl.source b/src/test/regress/output/partition_ddl.source index da1d67ff1b6..7f0e332f2a9 100644 --- a/src/test/regress/output/partition_ddl.source +++ b/src/test/regress/output/partition_ddl.source @@ -2868,3 +2868,69 @@ ERROR: ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned create unique index on root_part_1_prt_interior_1_2_prt_leaf(a, b); alter table root_part_1_prt_interior_1_2_prt_leaf add primary key using index root_part_1_prt_interior_1_2_prt_leaf_a_b_idx2; drop table root_part; +-- The following tests verifies reloptions inheritance for partitioned tables. +-- When parent's reloptions are specified, a child partition's reloptions should be set as below: +-- 1) If child's reloptions are specified, then the child's reloptions override the parent's reloptions. +-- 2) If child's reloptions are not specified, and if parent's and child's table access methods are same, then the parent's reloptions are inherited. +-- 3) If child's reloptions are not specified, and if parent's and child's table access methods are different, then the child's reloptions are set to default. +-- 4) Note that "appendonly" and "orientation" reloptions are not "real" reloptions and are instead treated as table access method specifications. +-- So, if child's WITH clause has only "appendonly" and/or "orientation" specified, they are handled as in (2) and (3) above. +-- Test 1: Parent's reloptions are explicitly specified, and parent's AM is explicitly specified as ao_row +create table part_ao(a int, b int) with (appendonly=true,compresstype=zlib,compresslevel=5,blocksize=65536) + partition by range(b) + (partition p1_heap start (0) end (10) with (appendonly=false), + partition p2_aoco start (10) end (20) with (appendonly=true, orientation=column), + partition p3_new_relopt start (20) end (30) with (compresstype=zstd, compresslevel=3), + default partition def); +select c.relname, am.amname, c.reloptions from pg_partition_tree('part_ao') as t join pg_class c on (t.relid::oid = c.oid) left join pg_am am on (c.relam = am.oid); + relname | amname | reloptions +-----------------------------+-----------+----------------------------------------------------- + part_ao | | + part_ao_1_prt_def | ao_row | {compresstype=zlib,compresslevel=5,blocksize=65536} + part_ao_1_prt_p1_heap | heap | + part_ao_1_prt_p2_aoco | ao_column | + part_ao_1_prt_p3_new_relopt | ao_row | {compresstype=zstd,compresslevel=3} +(5 rows) + +-- Test 2: Parent's reloptions are explicitly specified, and parent's AM is explicitly specified as heap +create table part_heap1(a int, b int) using heap with (fillfactor=70) partition by range(b) (partition p1 start(0) end(10) with(appendonly=true)); +select c.relname, am.amname, c.reloptions from pg_partition_tree('part_heap1') as t join pg_class c on (t.relid::oid = c.oid) left join pg_am am on (c.relam = am.oid); + relname | amname | reloptions +---------------------+--------+------------ + part_heap1 | | + part_heap1_1_prt_p1 | ao_row | +(2 rows) + +-- Test 3: Parent's reloptions are explicitly specified, and parent's AM is implicitly specified as heap +create table part_heap2(a int, b int) with (fillfactor=70) partition by range(b) (partition p1 start(0) end(10) with(appendonly=true)); +select c.relname, am.amname, c.reloptions from pg_partition_tree('part_heap2') as t join pg_class c on (t.relid::oid = c.oid) left join pg_am am on (c.relam = am.oid); + relname | amname | reloptions +---------------------+--------+------------ + part_heap2 | | + part_heap2_1_prt_p1 | ao_row | +(2 rows) + +-- Test 4: Parent's reloptions are explicitly specified, and parent's AM is implicitly specified as ao_column +set default_table_access_method = 'ao_column'; +create table part_aoco(a int, b int) with (compresstype=zlib,compresslevel=5,blocksize=65536) + partition by range(b) + (partition p1_heap start (0) end (10) with (appendonly=false), + partition p2_ao start (10) end (20) with (appendonly=true, orientation=row), + partition p3_new_relopt start (20) end (30) with (compresstype=zstd, compresslevel=3), + default partition def); +select c.relname, am.amname, c.reloptions from pg_partition_tree('part_aoco') as t join pg_class c on (t.relid::oid = c.oid) left join pg_am am on (c.relam = am.oid); + relname | amname | reloptions +-------------------------------+-----------+----------------------------------------------------- + part_aoco | | + part_aoco_1_prt_def | ao_column | {compresstype=zlib,compresslevel=5,blocksize=65536} + part_aoco_1_prt_p1_heap | heap | + part_aoco_1_prt_p2_ao | ao_row | + part_aoco_1_prt_p3_new_relopt | ao_column | {compresstype=zstd,compresslevel=3} +(5 rows) + +reset default_table_access_method; +-- cleanup +drop table part_ao; +drop table part_heap1; +drop table part_heap2; +drop table part_aoco;