diff --git a/src/common/backend/catalog/heap.cpp b/src/common/backend/catalog/heap.cpp index 1f423a924..3c1abc0a8 100644 --- a/src/common/backend/catalog/heap.cpp +++ b/src/common/backend/catalog/heap.cpp @@ -145,10 +145,10 @@ static void addNewPartitionTuplesForPartition(Relation pg_partition_rel, Oid relid, Oid reltablespace, Oid bucketOid, PartitionState* partTableState, Oid ownerid, Datum reloptions, const TupleDesc tupledesc, char strategy, StorageType storage_type, LOCKMODE partLockMode, - bool partkeyexprIsNull = true, bool partkeyIsFunc = false); + PartitionExprKeyInfo *partExprKeyInfo = NULL); static void addNewPartitionTupleForTable(Relation pg_partition_rel, const char* relname, const Oid reloid, const Oid reltablespaceid, const TupleDesc reltupledesc, const PartitionState* partTableState, Oid ownerid, - Datum reloptions, bool partkeyexprIsNull = true, bool partkeyIsFunc = false); + Datum reloptions, PartitionExprKeyInfo *partExprKeyInfo = NULL); static void addNewPartitionTupleForValuePartitionedTable(Relation pg_partition_rel, const char* relname, const Oid reloid, const Oid reltablespaceid, const TupleDesc reltupledesc, const PartitionState* partTableState, @@ -2804,12 +2804,11 @@ Oid heap_create_with_catalog(const char *relname, Oid relnamespace, Oid reltable /* Get uids info from reloptions */ relhasuids = StdRdOptionsHasUids(hreloptions, relkind); - bool partkeyexprIsNull = true; + PartitionExprKeyInfo partExprKeyInfo = PartitionExprKeyInfo(); bool subpartkeyexprIsNull = true; - bool partkeyIsFunc = false; bool subpartkeyIsFunc = false; if (partTableState) { - partkeyexprIsNull = CheckPartitionExprKey(partTableState->partitionKey, partTableState->partitionStrategy, &partkeyIsFunc); + partExprKeyInfo.partkeyexprIsNull = CheckPartitionExprKey(partTableState->partitionKey, partTableState->partitionStrategy, &(partExprKeyInfo.partkeyIsFunc)); if (partTableState->subPartitionState) subpartkeyexprIsNull = CheckPartitionExprKey(partTableState->subPartitionState->partitionKey, partTableState->subPartitionState->partitionStrategy, &subpartkeyIsFunc); @@ -3022,9 +3021,10 @@ Oid heap_create_with_catalog(const char *relname, Oid relnamespace, Oid reltable partTableState, /*partition schema of partitioned table*/ ownerid, /*partitioned table's owner id*/ reloptions, - partkeyexprIsNull, - partkeyIsFunc); + &partExprKeyInfo); + partExprKeyInfo.partkeyexprIsNull = subpartkeyexprIsNull; + partExprKeyInfo.partkeyIsFunc = subpartkeyIsFunc; /* add partition entry to pg_partition */ addNewPartitionTuplesForPartition(pg_partition_desc, /*RelationData pointer for pg_partition*/ relid, /*partitioned table's oid in pg_class*/ @@ -3037,8 +3037,7 @@ Oid heap_create_with_catalog(const char *relname, Oid relnamespace, Oid reltable partTableState->partitionStrategy, storage_type, partLockMode, - subpartkeyexprIsNull, - subpartkeyIsFunc); + &partExprKeyInfo); } } @@ -6093,8 +6092,8 @@ void GetNewPartitionOidAndNewPartrelfileOid(List *subPartitionDefState, Oid *new */ Oid heapAddRangePartition(Relation pgPartRel, Oid partTableOid, Oid partTablespace, Oid bucketOid, RangePartitionDefState *newPartDef, Oid ownerid, Datum reloptions, const bool *isTimestamptz, - StorageType storage_type, LOCKMODE partLockMode, int2vector* subpartition_key, bool isSubpartition, bool partkeyexprIsNull, - bool partkeyIsFunc) + StorageType storage_type, LOCKMODE partLockMode, int2vector* subpartition_key, bool isSubpartition, + PartitionExprKeyInfo *partExprKeyInfo) { Datum boundaryValue = (Datum)0; Oid newPartitionOid = InvalidOid; @@ -6184,8 +6183,11 @@ Oid heapAddRangePartition(Relation pgPartRel, Oid partTableOid, Oid partTablespa partTupleInfo.pkey = subpartition_key; partTupleInfo.boundaries = boundaryValue; partTupleInfo.reloptions = reloptions; - partTupleInfo.partkeyexprIsNull = partkeyexprIsNull; - partTupleInfo.partkeyIsFunc = partkeyIsFunc; + if (partExprKeyInfo) { + partTupleInfo.partexprkeyinfo.partkeyexprIsNull = partExprKeyInfo->partkeyexprIsNull; + partTupleInfo.partexprkeyinfo.partkeyIsFunc = partExprKeyInfo->partkeyIsFunc; + partTupleInfo.partexprkeyinfo.partExprKeyStr = partExprKeyInfo->partExprKeyStr; + } /* step 3: insert into pg_partition tuple */ addNewPartitionTuple(pgPartRel, newPartition, &partTupleInfo); @@ -6416,8 +6418,8 @@ Oid HeapAddIntervalPartition(Relation pgPartRel, Relation rel, Oid partTableOid, Oid HeapAddListPartition(Relation pgPartRel, Oid partTableOid, Oid partTablespace, Oid bucketOid, ListPartitionDefState* newListPartDef, Oid ownerid, Datum reloptions, const bool* isTimestamptz, - StorageType storage_type, int2vector* subpartition_key, bool isSubpartition, bool partkeyexprIsNull, - bool partkeyIsFunc) + StorageType storage_type, int2vector* subpartition_key, bool isSubpartition, + PartitionExprKeyInfo *partExprKeyInfo) { Datum boundaryValue = (Datum)0; Oid newListPartitionOid = InvalidOid; @@ -6496,8 +6498,11 @@ Oid HeapAddListPartition(Relation pgPartRel, Oid partTableOid, Oid partTablespac partTupleInfo.pkey = subpartition_key; partTupleInfo.boundaries = boundaryValue; partTupleInfo.reloptions = reloptions; - partTupleInfo.partkeyexprIsNull = partkeyexprIsNull; - partTupleInfo.partkeyIsFunc = partkeyIsFunc; + if (partExprKeyInfo) { + partTupleInfo.partexprkeyinfo.partkeyexprIsNull = partExprKeyInfo->partkeyexprIsNull; + partTupleInfo.partexprkeyinfo.partkeyIsFunc = partExprKeyInfo->partkeyIsFunc; + partTupleInfo.partexprkeyinfo.partExprKeyStr = partExprKeyInfo->partExprKeyStr; + } /* step 3: insert into pg_partition tuple */ addNewPartitionTuple(pgPartRel, newListPartition, &partTupleInfo); @@ -6718,8 +6723,8 @@ Oid AddNewIntervalPartition(Relation rel, void* insertTuple, int *partitionno, b Oid HeapAddHashPartition(Relation pgPartRel, Oid partTableOid, Oid partTablespace, Oid bucketOid, HashPartitionDefState* newHashPartDef, Oid ownerid, Datum reloptions, const bool* isTimestamptz, - StorageType storage_type, int2vector* subpartition_key, bool isSubpartition, bool partkeyexprIsNull, - bool partkeyIsFunc) + StorageType storage_type, int2vector* subpartition_key, bool isSubpartition, + PartitionExprKeyInfo *partExprKeyInfo) { Datum boundaryValue = (Datum)0; Oid newHashPartitionOid = InvalidOid; @@ -6809,8 +6814,11 @@ Oid HeapAddHashPartition(Relation pgPartRel, Oid partTableOid, Oid partTablespac partTupleInfo.pkey = subpartition_key; partTupleInfo.boundaries = boundaryValue; partTupleInfo.reloptions = reloptions; - partTupleInfo.partkeyexprIsNull = partkeyexprIsNull; - partTupleInfo.partkeyIsFunc = partkeyIsFunc; + if (partExprKeyInfo) { + partTupleInfo.partexprkeyinfo.partkeyexprIsNull = partExprKeyInfo->partkeyexprIsNull; + partTupleInfo.partexprkeyinfo.partkeyIsFunc = partExprKeyInfo->partkeyIsFunc; + partTupleInfo.partexprkeyinfo.partExprKeyStr = partExprKeyInfo->partExprKeyStr; + } /* step 3: insert into pg_partition tuple */ addNewPartitionTuple(pgPartRel, newHashPartition, &partTupleInfo); @@ -6923,7 +6931,7 @@ static void addNewPartitionTupleForValuePartitionedTable(Relation pg_partition_r */ static void addNewPartitionTupleForTable(Relation pg_partition_rel, const char* relname, const Oid reloid, const Oid reltablespaceid, const TupleDesc reltupledesc, const PartitionState* partTableState, Oid ownerid, - Datum reloptions, bool partkeyexprIsNull, bool partkeyIsFunc) + Datum reloptions, PartitionExprKeyInfo *partExprKeyInfo) { Datum interval = (Datum)0; Datum transition_point = (Datum)0; @@ -7000,10 +7008,13 @@ static void addNewPartitionTupleForTable(Relation pg_partition_rel, const char* partTupleInfo.boundaries = (Datum)0; partTupleInfo.transitionPoint = transition_point; partTupleInfo.reloptions = newOptions; - partTupleInfo.partkeyexprIsNull = partkeyexprIsNull; - partTupleInfo.partkeyIsFunc = partkeyIsFunc; partTupleInfo.partitionno = -list_length(partTableState->partitionList); partTupleInfo.subpartitionno = INVALID_PARTITION_NO; + if (partExprKeyInfo) { + partTupleInfo.partexprkeyinfo.partkeyexprIsNull = partExprKeyInfo->partkeyexprIsNull; + partTupleInfo.partexprkeyinfo.partkeyIsFunc = partExprKeyInfo->partkeyIsFunc; + partTupleInfo.partexprkeyinfo.partExprKeyStr = partExprKeyInfo->partExprKeyStr; + } /*step 2: insert into pg_partition tuple*/ addNewPartitionTuple(pg_partition_rel, new_partition, &partTupleInfo); @@ -7237,8 +7248,7 @@ Oid GetPartTablespaceOidForSubpartition(Oid reltablespace, const char* partTable */ static void addNewPartitionTuplesForPartition(Relation pg_partition_rel, Oid relid, Oid reltablespace, Oid bucketOid, PartitionState* partTableState, Oid ownerid, Datum reloptions, - const TupleDesc tupledesc, char strategy, StorageType storage_type, LOCKMODE partLockMode, bool partkeyexprIsNull, - bool partkeyIsFunc) + const TupleDesc tupledesc, char strategy, StorageType storage_type, LOCKMODE partLockMode, PartitionExprKeyInfo *partExprKeyInfo) { int partKeyNum = list_length(partTableState->partitionKey); bool isTimestamptzForPartKey[partKeyNum]; @@ -7285,8 +7295,7 @@ static void addNewPartitionTuplesForPartition(Relation pg_partition_rel, Oid rel storage_type, subpartition_key_attr_no, false, - partkeyexprIsNull, - partkeyIsFunc); + partExprKeyInfo); Oid partTablespaceOid = GetPartTablespaceOidForSubpartition(reltablespace, partitionDefState->tablespacename); @@ -7315,8 +7324,7 @@ static void addNewPartitionTuplesForPartition(Relation pg_partition_rel, Oid rel storage_type, subpartition_key_attr_no, false, - partkeyexprIsNull, - partkeyIsFunc); + partExprKeyInfo); Oid partTablespaceOid = GetPartTablespaceOidForSubpartition(reltablespace, partitionDefState->tablespacename); @@ -7346,8 +7354,7 @@ static void addNewPartitionTuplesForPartition(Relation pg_partition_rel, Oid rel partLockMode, subpartition_key_attr_no, false, - partkeyexprIsNull, - partkeyIsFunc); + partExprKeyInfo); Oid partTablespaceOid = GetPartTablespaceOidForSubpartition(reltablespace, partitionDefState->tablespacename); diff --git a/src/common/backend/catalog/pg_partition.cpp b/src/common/backend/catalog/pg_partition.cpp index 408ec9b6a..526867739 100644 --- a/src/common/backend/catalog/pg_partition.cpp +++ b/src/common/backend/catalog/pg_partition.cpp @@ -154,12 +154,18 @@ void insertPartitionEntry(Relation pg_partition_desc, Partition new_part_desc, O values[Anum_pg_partition_relminmxid - 1] = InvalidMultiXactId; #endif } - if (partTupleInfo->partkeyexprIsNull) { + if (partTupleInfo->partexprkeyinfo.partkeyexprIsNull) { nulls[Anum_pg_partition_partkeyexpr - 1] = true; - } else if (partTupleInfo->partkeyIsFunc) { - values[Anum_pg_partition_partkeyexpr - 1] = CStringGetTextDatum("partkeyisfunc"); + } else if (partTupleInfo->partexprkeyinfo.partkeyIsFunc) { + if (partTupleInfo->partexprkeyinfo.partExprKeyStr) + values[Anum_pg_partition_partkeyexpr - 1] = CStringGetTextDatum(partTupleInfo->partexprkeyinfo.partExprKeyStr); + else + values[Anum_pg_partition_partkeyexpr - 1] = CStringGetTextDatum("partkeyisfunc"); } else { - values[Anum_pg_partition_partkeyexpr - 1] = CStringGetTextDatum(""); + if (partTupleInfo->partexprkeyinfo.partExprKeyStr) + values[Anum_pg_partition_partkeyexpr - 1] = CStringGetTextDatum(partTupleInfo->partexprkeyinfo.partExprKeyStr); + else + values[Anum_pg_partition_partkeyexpr - 1] = CStringGetTextDatum(""); } if (partTupleInfo->partitionno != INVALID_PARTITION_NO) { diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index 4ac9d2a6e..207f45501 100755 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -23379,7 +23379,7 @@ static void CheckPartitionValueConflictForAddPartition(Relation rel, Node *partD decre_partmap_refcount(rel->partMap); } -bool IsPartKeyFunc(Relation rel, bool isPartRel, bool forSubPartition) +bool IsPartKeyFunc(Relation rel, bool isPartRel, bool forSubPartition, PartitionExprKeyInfo* partExprKeyInfo) { HeapTuple partTuple = NULL; if (forSubPartition) { @@ -23403,10 +23403,12 @@ bool IsPartKeyFunc(Relation rel, bool isPartRel, bool forSubPartition) if (!partTuple) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("The partTuple for oid %d can't be found", rel->rd_id))); - bool isPartExprKeyNull = false; + bool isNull = false; Datum datum = 0; - datum = SysCacheGetAttr(PARTRELID, partTuple, Anum_pg_partition_partkeyexpr, &isPartExprKeyNull); - if (isPartExprKeyNull) { + datum = SysCacheGetAttr(PARTRELID, partTuple, Anum_pg_partition_partkeyexpr, &isNull); + if (partExprKeyInfo) + partExprKeyInfo->partkeyexprIsNull = isNull; + if (isNull) { if (forSubPartition) ReleaseSysCache(partTuple); else @@ -23414,15 +23416,19 @@ bool IsPartKeyFunc(Relation rel, bool isPartRel, bool forSubPartition) return false; } - char* partkeystr = TextDatumGetCString(datum); + char* partKeyStr = TextDatumGetCString(datum); Node* partkeyexpr = NULL; if (forSubPartition) ReleaseSysCache(partTuple); else heap_freetuple(partTuple); - partkeyexpr = (Node*)stringToNode_skip_extern_fields(partkeystr); - pfree_ext(partkeystr); + partkeyexpr = (Node*)stringToNode_skip_extern_fields(partKeyStr); + if (!partExprKeyInfo) + pfree_ext(partKeyStr); + else + partExprKeyInfo->partExprKeyStr = partKeyStr; + if (!partkeyexpr) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("The partkeyexpr can't be NULL"))); @@ -23687,6 +23693,9 @@ static void ATExecAddPartitionInternal(Relation rel, AddPartitionState *partStat bucketOid = RelationGetBucketOid(rel); + PartitionExprKeyInfo partExprKeyInfo = PartitionExprKeyInfo(); + partExprKeyInfo.partkeyIsFunc = IsPartKeyFunc(rel, false, true, &partExprKeyInfo); + List *partitionNameList = list_concat(GetPartitionNameList(partState->partitionList), RelationGetPartitionNameList(rel)); foreach (cell, partState->partitionList) { @@ -23715,7 +23724,8 @@ static void ATExecAddPartitionInternal(Relation rel, AddPartitionState *partStat isTimestamptz, RelationGetStorageType(rel), subpartitionKey, - RelationIsPartitionOfSubPartitionTable(rel)); + RelationIsPartitionOfSubPartitionTable(rel), + &partExprKeyInfo); } else { newPartOid = heapAddRangePartition(pgPartRel, rel->rd_id, @@ -23728,7 +23738,8 @@ static void ATExecAddPartitionInternal(Relation rel, AddPartitionState *partStat RelationGetStorageType(rel), AccessExclusiveLock, subpartitionKey, - RelationIsPartitionOfSubPartitionTable(rel)); + RelationIsPartitionOfSubPartitionTable(rel), + &partExprKeyInfo); } Oid partTablespaceOid = diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 145a4de6f..698ca750b 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -22,6 +22,7 @@ #include "catalog/objectaddress.h" #include "utils/partcache.h" #include "utils/partitionmap.h" +#include "catalog/pg_partition_fn.h" #define PSORT_RESERVE_COLUMN "tid" #define CHCHK_PSORT_RESERVE_COLUMN(attname) (strcmp(PSORT_RESERVE_COLUMN, (attname)) == 0) @@ -150,17 +151,17 @@ extern void heapDropPartitionList(Relation rel, List* partitionList); extern Oid heapAddRangePartition(Relation pgPartRel, Oid partTableOid, Oid partTablespace, Oid bucketOid, RangePartitionDefState *newPartDef, Oid ownerid, Datum reloptions, const bool* isTimestamptz, StorageType storage_type, LOCKMODE partLockMode, int2vector* subpartition_key = NULL, bool isSubPartition = false, - bool partkeyexprIsNull = true, bool partkeyIsFunc = false); + PartitionExprKeyInfo *partExprKeyInfo = NULL); extern Oid HeapAddListPartition(Relation pgPartRel, Oid partTableOid, Oid partTablespace, Oid bucketOid, ListPartitionDefState *newPartDef, Oid ownerid, Datum reloptions, const bool* isTimestamptz, StorageType storage_type, int2vector* subpartition_key = NULL, bool isSubPartition = false, - bool partkeyexprIsNull = true, bool partkeyIsFunc = false); + PartitionExprKeyInfo *partExprKeyInfo = NULL); extern Oid HeapAddHashPartition(Relation pgPartRel, Oid partTableOid, Oid partTablespace, Oid bucketOid, HashPartitionDefState *newPartDef, Oid ownerid, Datum reloptions, const bool* isTimestamptz, StorageType storage_type, int2vector* subpartition_key = NULL, bool isSubPartition = false, - bool partkeyexprIsNull = true, bool partkeyIsFunc = false); + PartitionExprKeyInfo *partExprKeyInfo = NULL); extern Node *MakeDefaultSubpartition(PartitionState *partitionState, PartitionDefState *partitionDefState); extern List *addNewSubPartitionTuplesForPartition(Relation pgPartRel, Oid partTableOid, Oid partTablespace, Oid bucketOid, Oid ownerid, Datum reloptions, const bool *isTimestamptz, StorageType storage_type, @@ -169,8 +170,7 @@ extern List *addNewSubPartitionTuplesForPartition(Relation pgPartRel, Oid partTa extern Oid GetPartTablespaceOidForSubpartition(Oid reltablespace, const char* partTablespacename); extern void heapDropPartitionIndex(Relation parentIndex, Oid partIndexId); -extern void addNewPartitionTuple(Relation pg_part_desc, Partition new_part_desc, int2vector* pkey, oidvector *intablespace, - Datum interval, Datum maxValues, Datum transitionPoint, Datum reloptions, bool partkeyexprIsNull = true, bool partkeyIsFunc = false); +extern void addNewPartitionTuple(Relation pg_part_desc, Partition new_part_desc, PartitionTupleInfo *partTupleInfo); extern void heap_truncate_one_part(Relation rel , Oid partOid); extern Oid heapTupleGetPartitionId(Relation rel, void *tuple, int *partitionno, bool isDDL = false, diff --git a/src/include/catalog/pg_partition_fn.h b/src/include/catalog/pg_partition_fn.h index 39c467c6f..4e601cbde 100644 --- a/src/include/catalog/pg_partition_fn.h +++ b/src/include/catalog/pg_partition_fn.h @@ -168,6 +168,20 @@ extern const uint32 PARTITION_ENHANCE_VERSION_NUM; typedef void (*PartitionNameGetPartidCallback) (Oid partitioned_relation, const char *partition_name, Oid partId, Oid oldPartId, char partition_type, void *callback_arg, LOCKMODE callbackobj_lockMode); +/* some partition expr key info */ +struct PartitionExprKeyInfo { + bool partkeyexprIsNull; + bool partkeyIsFunc; + char* partExprKeyStr; + + PartitionExprKeyInfo() + { + partkeyexprIsNull = true; + partkeyIsFunc = false; + partExprKeyStr = NULL; + } +}; + /* some pg_partition tuple info */ struct PartitionTupleInfo { int2vector* pkey; @@ -176,10 +190,9 @@ struct PartitionTupleInfo { Datum boundaries; Datum transitionPoint; Datum reloptions; - bool partkeyexprIsNull; - bool partkeyIsFunc; int partitionno; int subpartitionno; + PartitionExprKeyInfo partexprkeyinfo; PartitionTupleInfo() { @@ -189,10 +202,9 @@ struct PartitionTupleInfo { boundaries = (Datum)0; transitionPoint = (Datum)0; reloptions = (Datum)0; - partkeyexprIsNull = true; - partkeyIsFunc = false; partitionno = INVALID_PARTITION_NO; subpartitionno = INVALID_PARTITION_NO; + partexprkeyinfo = PartitionExprKeyInfo(); } }; diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index b352bb0dc..fdaa73c37 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -18,6 +18,7 @@ #include "access/htup.h" #include "catalog/dependency.h" #include "catalog/objectaddress.h" +#include "catalog/pg_partition_fn.h" #include "nodes/parsenodes.h" #include "nodes/plannodes.h" #include "rewrite/rewriteRlsPolicy.h" @@ -132,7 +133,7 @@ extern bool checkPartitionLocalIndexesUsable(Oid partitionOid); extern bool checkRelationLocalIndexesUsable(Relation relation); extern List* GetPartitionkeyPos(List* partitionkeys, List* schema, bool* partkeyIsFunc = NULL); -extern bool IsPartKeyFunc(Relation rel, bool isPartRel, bool forSubPartition); +extern bool IsPartKeyFunc(Relation rel, bool isPartRel, bool forSubPartition, PartitionExprKeyInfo* partExprKeyInfo = NULL); extern void ComparePartitionValue(List* pos, FormData_pg_attribute* attrs, List *partitionList, bool isPartition = true, bool partkeyIsFunc = false); extern void CompareListValue(const List* pos, FormData_pg_attribute* attrs, List *partitionList, bool partkeyIsFunc = false); extern void clearAttrInitDefVal(Oid relid); diff --git a/src/test/regress/input/partition_expr_key.source b/src/test/regress/input/partition_expr_key.source index c5d8ef0d4..5d081155a 100644 --- a/src/test/regress/input/partition_expr_key.source +++ b/src/test/regress/input/partition_expr_key.source @@ -216,6 +216,45 @@ select * from b_bug_2 partition(p1); select * from b_bug_2 partition(p2); select * from b_bug_2 partition(p3); +--test some bug fix +create table subpart_range_add (col1 int, col2 int) partition by range( abs(col2) ) +subpartition by hash( abs(col1) ) +( + partition p1 values less than (2000) + ( + SUBPARTITION p1sub1, + SUBPARTITION p1sub2 + ), + partition p2 values less than (3000) + ( + SUBPARTITION p2sub1, + SUBPARTITION p2sub2 + ) +); +select pg_get_tabledef('subpart_range_add'); +alter table subpart_range_add add partition p3 values less than(4000); +select pg_get_tabledef('subpart_range_add'); +select partkeyexpr from pg_partition where (parttype = 'p') and (parentid in (select oid from pg_class where relname = 'subpart_range_add')); + +create table subpart_list_add (col1 int, col2 int) partition by list( abs(col2) ) +subpartition by hash( abs(col1) ) +( + partition p1 values(2000) + ( + SUBPARTITION p1sub1, + SUBPARTITION p1sub2 + ), + partition p2 values(3000) + ( + SUBPARTITION p2sub1, + SUBPARTITION p2sub2 + ) +); +select pg_get_tabledef('subpart_list_add'); +alter table subpart_list_add add partition p3 values(4000); +select pg_get_tabledef('subpart_list_add'); +select partkeyexpr from pg_partition where (parttype = 'p') and (parentid in (select oid from pg_class where relname = 'subpart_list_add')); + --test pg_get_tabledef and pg_dump create table testnormalsubpart(a int, b int) partition by range(a) subpartition by range(b) diff --git a/src/test/regress/output/partition_expr_key.source b/src/test/regress/output/partition_expr_key.source index 3185072dd..8e1bf9536 100644 --- a/src/test/regress/output/partition_expr_key.source +++ b/src/test/regress/output/partition_expr_key.source @@ -604,6 +604,161 @@ select * from b_bug_2 partition(p3); 50 | 30 | 3 (1 row) +--test some bug fix +create table subpart_range_add (col1 int, col2 int) partition by range( abs(col2) ) +subpartition by hash( abs(col1) ) +( + partition p1 values less than (2000) + ( + SUBPARTITION p1sub1, + SUBPARTITION p1sub2 + ), + partition p2 values less than (3000) + ( + SUBPARTITION p2sub1, + SUBPARTITION p2sub2 + ) +); +select pg_get_tabledef('subpart_range_add'); + pg_get_tabledef +----------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE subpart_range_add ( + + col1 integer, + + col2 integer + + ) + + WITH (orientation=row, compression=no) + + PARTITION BY RANGE (abs(col2)) SUBPARTITION BY HASH (abs(col1))+ + ( + + PARTITION p1 VALUES LESS THAN (2000) TABLESPACE pg_default + + ( + + SUBPARTITION p1sub1 TABLESPACE pg_default, + + SUBPARTITION p1sub2 TABLESPACE pg_default + + ), + + PARTITION p2 VALUES LESS THAN (3000) TABLESPACE pg_default + + ( + + SUBPARTITION p2sub1 TABLESPACE pg_default, + + SUBPARTITION p2sub2 TABLESPACE pg_default + + ) + + ) + + ENABLE ROW MOVEMENT; +(1 row) + +alter table subpart_range_add add partition p3 values less than(4000); +select pg_get_tabledef('subpart_range_add'); + pg_get_tabledef +----------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE subpart_range_add ( + + col1 integer, + + col2 integer + + ) + + WITH (orientation=row, compression=no) + + PARTITION BY RANGE (abs(col2)) SUBPARTITION BY HASH (abs(col1))+ + ( + + PARTITION p1 VALUES LESS THAN (2000) TABLESPACE pg_default + + ( + + SUBPARTITION p1sub1 TABLESPACE pg_default, + + SUBPARTITION p1sub2 TABLESPACE pg_default + + ), + + PARTITION p2 VALUES LESS THAN (3000) TABLESPACE pg_default + + ( + + SUBPARTITION p2sub1 TABLESPACE pg_default, + + SUBPARTITION p2sub2 TABLESPACE pg_default + + ), + + PARTITION p3 VALUES LESS THAN (4000) TABLESPACE pg_default + + ( + + SUBPARTITION p3_subpartdefault1 TABLESPACE pg_default + + ) + + ) + + ENABLE ROW MOVEMENT; +(1 row) + +select partkeyexpr from pg_partition where (parttype = 'p') and (parentid in (select oid from pg_class where relname = 'subpart_range_add')); + partkeyexpr +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {FUNCEXPR :funcid 1397 :funcresulttype 23 :funcresulttype_orig -1 :funcretset false :funcformat 0 :funccollid 0 :inputcollid 0 :args ({VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 110}) :location 106 :refSynOid 0} + {FUNCEXPR :funcid 1397 :funcresulttype 23 :funcresulttype_orig -1 :funcretset false :funcformat 0 :funccollid 0 :inputcollid 0 :args ({VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 110}) :location 106 :refSynOid 0} + {FUNCEXPR :funcid 1397 :funcresulttype 23 :funcresulttype_orig -1 :funcretset false :funcformat 0 :funccollid 0 :inputcollid 0 :args ({VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 110}) :location 106 :refSynOid 0} +(3 rows) + +create table subpart_list_add (col1 int, col2 int) partition by list( abs(col2) ) +subpartition by hash( abs(col1) ) +( + partition p1 values(2000) + ( + SUBPARTITION p1sub1, + SUBPARTITION p1sub2 + ), + partition p2 values(3000) + ( + SUBPARTITION p2sub1, + SUBPARTITION p2sub2 + ) +); +select pg_get_tabledef('subpart_list_add'); + pg_get_tabledef +---------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE subpart_list_add ( + + col1 integer, + + col2 integer + + ) + + WITH (orientation=row, compression=no) + + PARTITION BY LIST (abs(col2)) SUBPARTITION BY HASH (abs(col1))+ + ( + + PARTITION p1 VALUES (2000) TABLESPACE pg_default + + ( + + SUBPARTITION p1sub1 TABLESPACE pg_default, + + SUBPARTITION p1sub2 TABLESPACE pg_default + + ), + + PARTITION p2 VALUES (3000) TABLESPACE pg_default + + ( + + SUBPARTITION p2sub1 TABLESPACE pg_default, + + SUBPARTITION p2sub2 TABLESPACE pg_default + + ) + + ) + + ENABLE ROW MOVEMENT; +(1 row) + +alter table subpart_list_add add partition p3 values(4000); +select pg_get_tabledef('subpart_list_add'); + pg_get_tabledef +---------------------------------------------------------------- + SET search_path = public; + + CREATE TABLE subpart_list_add ( + + col1 integer, + + col2 integer + + ) + + WITH (orientation=row, compression=no) + + PARTITION BY LIST (abs(col2)) SUBPARTITION BY HASH (abs(col1))+ + ( + + PARTITION p1 VALUES (2000) TABLESPACE pg_default + + ( + + SUBPARTITION p1sub1 TABLESPACE pg_default, + + SUBPARTITION p1sub2 TABLESPACE pg_default + + ), + + PARTITION p2 VALUES (3000) TABLESPACE pg_default + + ( + + SUBPARTITION p2sub1 TABLESPACE pg_default, + + SUBPARTITION p2sub2 TABLESPACE pg_default + + ), + + PARTITION p3 VALUES (4000) TABLESPACE pg_default + + ( + + SUBPARTITION p3_subpartdefault1 TABLESPACE pg_default + + ) + + ) + + ENABLE ROW MOVEMENT; +(1 row) + +select partkeyexpr from pg_partition where (parttype = 'p') and (parentid in (select oid from pg_class where relname = 'subpart_list_add')); + partkeyexpr +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {FUNCEXPR :funcid 1397 :funcresulttype 23 :funcresulttype_orig -1 :funcretset false :funcformat 0 :funccollid 0 :inputcollid 0 :args ({VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 108}) :location 104 :refSynOid 0} + {FUNCEXPR :funcid 1397 :funcresulttype 23 :funcresulttype_orig -1 :funcretset false :funcformat 0 :funccollid 0 :inputcollid 0 :args ({VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 108}) :location 104 :refSynOid 0} + {FUNCEXPR :funcid 1397 :funcresulttype 23 :funcresulttype_orig -1 :funcretset false :funcformat 0 :funccollid 0 :inputcollid 0 :args ({VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 108}) :location 104 :refSynOid 0} +(3 rows) + --test pg_get_tabledef and pg_dump create table testnormalsubpart(a int, b int) partition by range(a) subpartition by range(b) (