[patch] support interval partition table

This commit is contained in:
yujiang 2020-07-28 09:28:46 +08:00
parent 0c06c55ea6
commit 8a87c14084
53 changed files with 4327 additions and 386 deletions

View File

@ -31,6 +31,7 @@
#include "postgres.h"
#include "knl/knl_variable.h"
#include "access/reloptions.h"
#include "access/sysattr.h"
#include "access/transam.h"
#include "access/xact.h"
@ -110,7 +111,7 @@
static void AddNewRelationTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid,
Oid reloftype, Oid relowner, char relkind, Datum relacl, Datum reloptions, int2vector* bucketcol, bool ispartrel);
static oidvector* buldIntervalTablespace(IntervalPartitionDefState* intervalPartDef);
static oidvector* BuildIntervalTablespace(const IntervalPartitionDefState* intervalPartDef);
static void deletePartitionTuple(Oid part_id);
static void addNewPartitionTuplesForPartition(Relation pg_partition_rel, Oid relid, List *filenodelist, Oid reltablespace,
Oid bucketOid, PartitionState* partTableState, Oid ownerid, Datum reloptions, const TupleDesc tupledesc);
@ -4087,7 +4088,6 @@ int2vector* buildPartitionKey(List* keys, TupleDesc tupledsc)
columName = ((Value*)linitial(col->fields))->val.str;
finded = false;
for (j = 0; j < attnum; j++) {
if (strcmp(columName, attrs[j]->attname.data) == 0) {
partkey->values[i] = attrs[j]->attnum;
finded = true;
@ -4106,16 +4106,44 @@ int2vector* buildPartitionKey(List* keys, TupleDesc tupledsc)
return partkey;
}
/*
* @@GaussDB@@
* Target : data partition
* Brief :
* Description :
* Notes :
*/
static oidvector* buldIntervalTablespace(IntervalPartitionDefState* intervalPartDef)
static oidvector* BuildIntervalTablespace(const IntervalPartitionDefState* intervalPartDef)
{
return (oidvector*)NULL;
if (intervalPartDef->intervalTablespaces == NULL || intervalPartDef->intervalTablespaces->length == 0) {
return NULL;
}
oidvector* tablespaceVec = buildoidvector(NULL, intervalPartDef->intervalTablespaces->length);
ListCell* cell = NULL;
int i = 0;
const char* tablespaceName;
Oid tableSpaceOid;
AclResult aclresult;
foreach (cell, intervalPartDef->intervalTablespaces) {
tablespaceName = ((Value*)lfirst(cell))->val.str;
tableSpaceOid = get_tablespace_oid(tablespaceName, false);
if (tableSpaceOid != u_sess->proc_cxt.MyDatabaseTableSpace) {
aclresult = pg_tablespace_aclcheck(tableSpaceOid, GetUserId(), ACL_CREATE);
if (aclresult != ACLCHECK_OK) {
aclcheck_error(aclresult, ACL_KIND_TABLESPACE, tablespaceName);
}
}
tablespaceVec->values[i] = tableSpaceOid;
i++;
}
return tablespaceVec;
}
static Datum BuildInterval(Node* partInterval)
{
Assert(IsA(partInterval, A_Const));
A_Const* constNode = (A_Const*)partInterval;
Assert(IsA(&constNode->val, String));
ArrayBuildState* astate = NULL;
astate = accumArrayResult(
astate, PointerGetDatum(cstring_to_text(constNode->val.val.str)), false, TEXTOID, CurrentMemoryContext);
return makeArrayResult(astate, CurrentMemoryContext);
}
/*
@ -4702,7 +4730,7 @@ Oid heapAddRangePartition(Relation pgPartRel, Oid partTableOid, Oid partrelfileO
}
}
/*create partition */
/* create partition */
if (!OidIsValid(partrelfileOid) && u_sess->proc_cxt.IsBinaryUpgrade
&& binary_upgrade_is_next_part_pg_partition_oid_valid()) {
newPartitionOid = binary_upgrade_get_next_part_pg_partition_oid();
@ -4710,7 +4738,7 @@ Oid heapAddRangePartition(Relation pgPartRel, Oid partTableOid, Oid partrelfileO
} else if (!OidIsValid(partrelfileOid)) {
newPartitionOid = GetNewRelFileNode(newPartitionTableSpaceOid,
pgPartRel,
RELPERSISTENCE_PERMANENT); /* partition's persistence only can be 'p'(permanent table)*/
RELPERSISTENCE_PERMANENT); /* partition's persistence only can be 'p'(permanent table) */
} else {
Assert(t_thrd.xact_cxt.inheritFileNode);
ereport(NOTICE,
@ -4742,14 +4770,14 @@ Oid heapAddRangePartition(Relation pgPartRel, Oid partTableOid, Oid partrelfileO
newPartition->pd_part->relcudescidx = InvalidOid;
newPartition->pd_part->indisusable = true;
/*step 3: insert into pg_partition tuple*/
/* step 3: insert into pg_partition tuple */
addNewPartitionTuple(pgPartRel, /* RelationData pointer for pg_partition */
newPartition, /* PartitionData pointer for partition */
NULL, /* */
NULL,
(Datum)0, /*interval*/
boundaryValue, /*max values */
(Datum)0, /*transition point*/
(Datum)0, /* interval*/
boundaryValue, /* max values */
(Datum)0, /* transition point */
reloptions);
relation = relation_open(partTableOid, NoLock);
@ -4760,6 +4788,353 @@ Oid heapAddRangePartition(Relation pgPartRel, Oid partTableOid, Oid partrelfileO
return newPartitionOid;
}
#define IsDigital(_ch) (((_ch) >= '0') && ((_ch) <= '9'))
static unsigned ExtractIntervalPartNameSuffix(const char* partName)
{
if (partName == NULL) {
return 0;
}
size_t len = strlen(partName);
size_t constPartLen = strlen(INTERVAL_PARTITION_NAME_PREFIX);
/* 5 is length of MAX_PARTITION_NUM */
if (len <= constPartLen || len > constPartLen + INTERVAL_PARTITION_NAME_SUFFIX_LEN) {
return 0;
}
if (strncmp(partName, INTERVAL_PARTITION_NAME_PREFIX, constPartLen) != 0) {
return 0;
}
for (size_t i = constPartLen; i < len; ++i) {
if (!IsDigital(partName[i])) {
return 0;
}
}
return (unsigned)atoi(partName + constPartLen);
}
int RangeElementOidCmp(const void* a, const void* b)
{
const RangeElement* rea = (const RangeElement*)a;
const RangeElement* reb = (const RangeElement*)b;
if (rea->partitionOid < reb->partitionOid) {
return 1;
}
if (rea->partitionOid == reb->partitionOid) {
return 0;
}
return -1;
}
char* GenIntervalPartitionName(Relation rel)
{
unsigned suffix = 0;
Oid existingPartOid;
RangePartitionMap* partMap = (RangePartitionMap*)rel->partMap;
RangeElement* eles = CopyRangeElementsWithoutBoundary(partMap->rangeElements, partMap->rangeElementsNum);
/* sort desc by oid */
qsort(eles, partMap->rangeElementsNum, sizeof(RangeElement), RangeElementOidCmp);
for (int i = 0; i < partMap->rangeElementsNum; ++i) {
/* merge or split may result in range oid bigger than interval range oid */
if (!eles[i].isInterval) {
continue;
}
char* name = PartitionOidGetName(eles[i].partitionOid);
if ((suffix = ExtractIntervalPartNameSuffix(name)) != 0) {
pfree(name);
break;
}
}
pfree(eles);
char* partName = (char*)palloc0(NAMEDATALEN);
error_t rc;
while (true) {
++suffix;
suffix = (suffix % MAX_PARTITION_NUM == 0 ? MAX_PARTITION_NUM : suffix % MAX_PARTITION_NUM);
rc = snprintf_s(partName, NAMEDATALEN, NAMEDATALEN - 1, INTERVAL_PARTITION_NAME_PREFIX_FMT, suffix);
securec_check_ss(rc, "\0", "\0");
existingPartOid = partitionNameGetPartitionOid(
rel->rd_id, partName, PART_OBJ_TYPE_TABLE_PARTITION, AccessExclusiveLock, true, false, NULL, NULL, NoLock);
if (!OidIsValid(existingPartOid)) {
return partName;
}
}
}
Oid GetRecentUsedTablespace(Relation rel)
{
RangePartitionMap* partMap = (RangePartitionMap*)rel->partMap;
Assert(partMap->rangeElementsNum >= 1);
RangeElement* maxOidEle = &partMap->rangeElements[0];
for (int i = 1; i < partMap->rangeElementsNum; ++i) {
if (partMap->rangeElements[i].partitionOid > maxOidEle->partitionOid) {
maxOidEle = &partMap->rangeElements[i];
}
}
/* no interval partition yet */
if (!maxOidEle->isInterval) {
return InvalidOid;
}
return PartitionOidGetTablespace(maxOidEle->partitionOid);
}
Oid ChooseIntervalTablespace(Relation rel)
{
const oidvector* tablespaceVec = ((RangePartitionMap*)rel->partMap)->intervalTablespace;
Assert(tablespaceVec->dim1 >= 1);
if (tablespaceVec->dim1 == 1) {
return tablespaceVec->values[0];
}
const Oid recentUsed = GetRecentUsedTablespace(rel);
if (!OidIsValid(recentUsed)) {
return tablespaceVec->values[0];
}
int i = 0;
for (; i < tablespaceVec->dim1; ++i) {
if (tablespaceVec->values[i] == recentUsed) {
break;
}
}
return tablespaceVec->values[(i + 1) % tablespaceVec->dim1];
}
Oid HeapAddIntervalPartition(Relation pgPartRel, Relation rel, Oid partTableOid, Oid partrelfileOid, Oid partTablespace,
Oid bucketOid, Datum boundaryValue, Oid ownerid, Datum reloptions)
{
Oid newPartitionOid = InvalidOid;
Oid newPartitionTableSpaceOid = InvalidOid;
Relation relation;
Partition newPartition;
if (((RangePartitionMap*)rel->partMap)->intervalTablespace != NULL) {
newPartitionTableSpaceOid = ChooseIntervalTablespace(rel);
}
if (!OidIsValid(newPartitionTableSpaceOid)) {
newPartitionTableSpaceOid = partTablespace;
}
/* Check permissions except when using database's default */
if (OidIsValid(newPartitionTableSpaceOid) && newPartitionTableSpaceOid != u_sess->proc_cxt.MyDatabaseTableSpace) {
AclResult aclresult = pg_tablespace_aclcheck(newPartitionTableSpaceOid, GetUserId(), ACL_CREATE);
if (aclresult != ACLCHECK_OK) {
aclcheck_error(aclresult, ACL_KIND_TABLESPACE, get_tablespace_name(newPartitionTableSpaceOid));
}
}
/* create partition */
if (!OidIsValid(partrelfileOid) && u_sess->proc_cxt.IsBinaryUpgrade &&
binary_upgrade_is_next_part_pg_partition_oid_valid()) {
newPartitionOid = binary_upgrade_get_next_part_pg_partition_oid();
partrelfileOid = binary_upgrade_get_next_part_pg_partition_rfoid();
} else if (!OidIsValid(partrelfileOid)) {
newPartitionOid = GetNewRelFileNode(newPartitionTableSpaceOid,
pgPartRel,
RELPERSISTENCE_PERMANENT); /* partition's persistence only can be 'p'(permanent table) */
} else {
Assert(t_thrd.xact_cxt.inheritFileNode);
ereport(NOTICE, (errmsg("Define inheritFileNode %u for new interval partition", partrelfileOid)));
}
LockPartitionOid(partTableOid, (uint32)newPartitionOid, AccessExclusiveLock);
char* partName = GenIntervalPartitionName(rel);
newPartition = heapCreatePartition(partName, /* partition's name */
false, /* false for partition */
newPartitionTableSpaceOid, /* partition's tablespace */
newPartitionOid, /* partition's oid */
partrelfileOid,
bucketOid,
ownerid);
pfree(partName);
Assert(newPartitionOid == PartitionGetPartid(newPartition));
newPartition->pd_part->parttype = PART_OBJ_TYPE_TABLE_PARTITION;
newPartition->pd_part->parentid = partTableOid;
newPartition->pd_part->rangenum = 0;
newPartition->pd_part->intervalnum = 0;
newPartition->pd_part->partstrategy = PART_STRATEGY_INTERVAL;
newPartition->pd_part->reltoastrelid = InvalidOid;
newPartition->pd_part->reltoastidxid = InvalidOid;
newPartition->pd_part->indextblid = InvalidOid;
newPartition->pd_part->reldeltarelid = InvalidOid;
newPartition->pd_part->reldeltaidx = InvalidOid;
newPartition->pd_part->relcudescrelid = InvalidOid;
newPartition->pd_part->relcudescidx = InvalidOid;
newPartition->pd_part->indisusable = true;
/* step 3: insert into pg_partition tuple*/
addNewPartitionTuple(pgPartRel, /* RelationData pointer for pg_partition */
newPartition, /* PartitionData pointer for partition */
NULL,
NULL,
(Datum)0, /* interval */
boundaryValue, /* max values */
(Datum)0, /* transition point */
reloptions);
relation = relation_open(partTableOid, NoLock);
PartitionCloseSmgr(newPartition);
partitionClose(relation, newPartition, NoLock);
relation_close(relation, NoLock);
return newPartitionOid;
}
Timestamp Align2UpBoundary(Timestamp value, Interval* intervalValue, Timestamp boundary)
{
Timestamp nearbyBoundary = boundary;
Interval* diff = DatumGetIntervalP(timestamp_mi(value, boundary));
/* approximate multiple */
int multiple = (int)(INTERVAL_TO_USEC(diff) / INTERVAL_TO_USEC(intervalValue));
pfree(diff);
if (multiple != 0) {
Interval* integerInterval = DatumGetIntervalP(interval_mul(intervalValue, (float8)multiple));
nearbyBoundary = DatumGetTimestamp(timestamp_pl_interval(boundary, integerInterval));
pfree(integerInterval);
}
if (nearbyBoundary <= value) {
while (true) {
nearbyBoundary = DatumGetTimestamp(timestamp_pl_interval(nearbyBoundary, intervalValue));
if (nearbyBoundary > value) {
return nearbyBoundary;
}
}
} else {
while (true) {
Timestamp res = DatumGetTimestamp(timestamp_mi_interval(nearbyBoundary, intervalValue));
if (res <= value) {
return nearbyBoundary;
}
nearbyBoundary = res;
}
}
}
Datum Timestamp2Boundarys(Relation rel, Timestamp ts)
{
Const consts;
RangePartitionMap* partMap = (RangePartitionMap*)rel->partMap;
bool isTimestamptz = partMap->rangeElements[partMap->rangeElementsNum - 1].boundary[0]->consttype == TIMESTAMPTZOID;
Datum columnRaw = TimestampGetDatum(ts);
int2vector* partKeyColumn = partMap->partitionKey;
Assert(partKeyColumn->dim1 == 1);
(void)transformDatum2Const(rel->rd_att, partKeyColumn->values[0], columnRaw, false, &consts);
List* bondary = list_make1(&consts);
Datum res = transformPartitionBoundary(bondary, &isTimestamptz);
list_free(bondary);
return res;
}
Datum GetPartBoundaryByTuple(Relation rel, HeapTuple tuple)
{
RangePartitionMap* partMap = (RangePartitionMap*)rel->partMap;
int2vector* partKeyColumn = partMap->partitionKey;
Assert(partKeyColumn->dim1 == 1);
Assert(partMap->type.type == PART_TYPE_INTERVAL);
Assert(partMap->rangeElementsNum >= 1);
Assert(partMap->rangeElements[partMap->rangeElementsNum - 1].boundary[0]->consttype == TIMESTAMPOID ||
partMap->rangeElements[partMap->rangeElementsNum - 1].boundary[0]->consttype == TIMESTAMPTZOID);
bool isNull = false;
Datum columnRaw = fastgetattr(tuple, partKeyColumn->values[0], rel->rd_att, &isNull);
Timestamp value = DatumGetTimestamp(columnRaw);
Timestamp boundaryTs =
DatumGetTimestamp(partMap->rangeElements[partMap->rangeElementsNum - 1].boundary[0]->constvalue);
return Timestamp2Boundarys(rel, Align2UpBoundary(value, partMap->intervalValue, boundaryTs));
}
Oid AddNewIntervalPartition(Relation rel, HeapTuple insertTuple)
{
Relation pgPartRel = NULL;
Oid newPartOid = InvalidOid;
Datum newRelOptions;
Datum relOptions;
HeapTuple tuple;
bool isNull = false;
List* oldRelOptions = NIL;
Oid bucketOid;
lockRelationForAddIntervalPartition(rel);
RelationInitPartitionMap(rel);
partitionRoutingForTuple(rel, insertTuple, u_sess->catalog_cxt.route);
/* if the partition exists, return partition's oid */
if (u_sess->catalog_cxt.route->fileExist) {
Assert(OidIsValid(u_sess->catalog_cxt.route->partitionId));
unLockRelationForAddIntervalPartition(rel);
return u_sess->catalog_cxt.route->partitionId;
}
/* check 1: can not add more partition, because more enough */
if ((getNumberOfPartitions(rel) + 1) > MAX_PARTITION_NUM) {
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("too many partitions for partitioned table"),
errhint("Number of partitions can not be more than %d", MAX_PARTITION_NUM)));
}
/* check 5: whether has the unusable local index */
if (!checkRelationLocalIndexesUsable(rel)) {
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("can't add partition bacause the relation %s has unusable local index",
NameStr(rel->rd_rel->relname)),
errhint("please reindex the unusable index first.")));
}
pgPartRel = relation_open(PartitionRelationId, RowExclusiveLock);
/* step 2: add new partition entry in pg_partition */
/* TRANSFORM into target first */
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(rel->rd_id));
relOptions = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions, &isNull);
oldRelOptions = untransformRelOptions(relOptions);
newRelOptions = transformRelOptions((Datum)0, oldRelOptions, NULL, NULL, false, false);
ReleaseSysCache(tuple);
if (oldRelOptions != NIL) {
list_free_ext(oldRelOptions);
}
bucketOid = RelationGetBucketOid(rel);
newPartOid = HeapAddIntervalPartition(pgPartRel,
rel,
rel->rd_id,
InvalidOid,
rel->rd_rel->reltablespace,
bucketOid,
GetPartBoundaryByTuple(rel, insertTuple),
rel->rd_rel->relowner,
(Datum)newRelOptions);
CommandCounterIncrement();
addIndexForPartition(rel, newPartOid);
addToastTableForNewPartition(rel, newPartOid);
/* step 4: invalidate relation */
CacheInvalidateRelcache(rel);
RelationInitPartitionMap(rel);
/* close relation, done */
relation_close(pgPartRel, NoLock);
return newPartOid;
}
static void addNewPartitionTupleForValuePartitionedTable(Relation pg_partition_rel, const char* relname,
const Oid reloid, const Oid reltablespaceid, const TupleDesc reltupledesc, const PartitionState* partTableState,
Datum reloptions)
@ -4872,10 +5247,10 @@ static void addNewPartitionTupleForTable(Relation pg_partition_rel, const char*
}
partition_key_attr_no = buildPartitionKey(partTableState->partitionKey, reltupledesc);
interval_talespace = buldIntervalTablespace(partTableState->intervalPartDef);
interval = (Datum)0;
transition_point = (Datum)0;
if (partTableState->intervalPartDef != NULL) {
interval_talespace = BuildIntervalTablespace(partTableState->intervalPartDef);
interval = BuildInterval(partTableState->intervalPartDef->partInterval);
}
/*step1: create partition relation, initialize and set tuple properties*/
if (u_sess->proc_cxt.IsBinaryUpgrade && OidIsValid(u_sess->upg_cxt.binary_upgrade_next_partrel_pg_partition_oid)) {
@ -4930,6 +5305,10 @@ static void addNewPartitionTupleForTable(Relation pg_partition_rel, const char*
if (interval_talespace != NULL) {
pfree(interval_talespace);
}
if (interval != 0) {
pfree(DatumGetPointer(interval));
}
}
/*
@ -5160,6 +5539,9 @@ Oid heapTupleGetPartitionId(Relation rel, HeapTuple tuple)
ereport(ERROR,
(errcode(ERRCODE_NO_DATA_FOUND), errmsg("inserted partition key does not map to any table partition")));
} break;
case PART_AREA_INTERVAL: {
return AddNewIntervalPartition(rel, tuple);
} break;
/* never happen; just to be self-contained */
default: {
ereport(ERROR,
@ -5302,18 +5684,6 @@ static Oid binary_upgrade_get_next_part_toast_pg_class_rfoid()
return old_part_toast_pg_class_rfoid;
}
/*
* @@GaussDB@@
* Target : data partition
* Brief : create a interval partition.
* Description :
* Notes :
*/
Oid createNewIntervalFile(Relation rel, int seqNum)
{
return InvalidOid;
}
static int TransformClusterColNameList(Oid relId, List* colList, int16* attnums)
{
ListCell* l = NULL;

13
src/common/backend/catalog/pg_partition.cpp Executable file → Normal file
View File

@ -41,7 +41,8 @@
#include "utils/snapmgr.h"
void insertPartitionEntry(Relation pg_partition_desc, Partition new_part_desc, Oid new_part_id, int2vector* pkey,
oidvector* intablespace, Datum interval, Datum maxValues, Datum transitionPoint, Datum reloptions, char parttype)
const oidvector* tablespaces, Datum interval, Datum maxValues, Datum transitionPoint, Datum reloptions,
char parttype)
{
Datum values[Natts_pg_partition];
bool nulls[Natts_pg_partition];
@ -88,7 +89,13 @@ void insertPartitionEntry(Relation pg_partition_desc, Partition new_part_desc, O
nulls[Anum_pg_partition_partkey - 1] = true;
}
nulls[Anum_pg_partition_intablespace - 1] = true;
/* interval tablespaces */
if (tablespaces != NULL) {
values[Anum_pg_partition_intablespace - 1] = PointerGetDatum(tablespaces);
} else {
nulls[Anum_pg_partition_intablespace - 1] = true;
}
nulls[Anum_pg_partition_intspnum - 1] = true;
/* interval */
@ -586,7 +593,7 @@ static Oid getPartitionIndexFormData(Oid indexid, Oid partitionid, Form_pg_parti
heap_close(pg_partition, AccessShareLock);
/* If drop index occur before this function and after pg_get_indexdef_partitions, */
/* the index has been deleted now. Ext. If drop patition occur, the partition might be deleted.
/* the index has been deleted now. Ext. If drop patition occur, the partition might be deleted.
* Drop partition just use RowExclusiveLock for parellel performance. */
if (!found) {
ereport(ERROR,

View File

@ -166,6 +166,7 @@ static void transformTableLikeClause(
CreateStmtContext* cxt, TableLikeClause* table_like_clause, bool preCheck, bool isFirstNode = false);
static void transformTableLikePartitionProperty(Relation relation, HeapTuple partitionTableTuple, List** partKeyColumns,
List* partitionList, List** partitionDefinitions);
static IntervalPartitionDefState* TransformTableLikeIntervalPartitionDef(HeapTuple partitionTableTuple);
static void transformTableLikePartitionKeys(
Relation relation, HeapTuple partitionTableTuple, List** partKeyColumns, List** partKeyPosList);
static void transformTableLikePartitionBoundaries(
@ -220,6 +221,7 @@ static List* divide_start_end_every_internal(ParseState* pstate, char* partName,
static List* DividePartitionStartEndInterval(ParseState* pstate, Form_pg_attribute attr, char* partName,
Const* startVal, Const* endVal, Const* everyVal, Node* everyExpr, int* numPart, int maxNum);
static void TryReuseFilenode(Relation rel, CreateStmtContext *ctx, bool clonepart);
extern Node* makeAConst(Value* v, int location);
/*
* transformCreateStmt -
@ -1537,14 +1539,12 @@ static void transformTableLikeClause(
n = makeNode(PartitionState);
n->partitionKey = partKeyColumns;
n->partitionList = partitionDefinitions;
#ifdef PGXC
// in mppdb, we do not support interval partition
n->intervalPartDef = NULL;
n->partitionStrategy = partitionForm->partstrategy;
#else
n->intervalPartDef = NULL;
n->partitionStrategy = partitionForm->partstrategy;
#endif
if (partitionForm->partstrategy == PART_STRATEGY_INTERVAL) {
n->intervalPartDef = TransformTableLikeIntervalPartitionDef(partitionTableTuple);
} else {
n->intervalPartDef = NULL;
}
n->rowMovement = relation->rd_rel->relrowmovement ? ROWMOVEMENT_ENABLE : ROWMOVEMENT_DISABLE;
// store the produced partition state in CreateStmtContext
@ -1683,6 +1683,32 @@ static void transformTableLikePartitionProperty(Relation relation, HeapTuple par
transformTableLikePartitionBoundaries(relation, partKeyPosList, partitionList, partitionDefinitions);
}
static IntervalPartitionDefState* TransformTableLikeIntervalPartitionDef(HeapTuple partitionTableTuple)
{
IntervalPartitionDefState* intervalPartDef = makeNode(IntervalPartitionDefState);
Relation partitionRel = relation_open(PartitionRelationId, RowExclusiveLock);
char* intervalStr = ReadIntervalStr(partitionTableTuple, RelationGetDescr(partitionRel));
Assert(intervalStr != NULL);
intervalPartDef->partInterval = makeAConst(makeString(intervalStr), -1);
oidvector* tablespaceIdVec = ReadIntervalTablespace(partitionTableTuple, RelationGetDescr(partitionRel));
intervalPartDef->intervalTablespaces = NULL;
if (tablespaceIdVec != NULL && tablespaceIdVec->dim1 > 0) {
for (int i = 0; i < tablespaceIdVec->dim1; ++i) {
char* tablespaceName = get_tablespace_name(tablespaceIdVec->values[i]);
if (tablespaceName == NULL) {
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("tablespace with OID %u does not exist", tablespaceIdVec->values[i])));
}
intervalPartDef->intervalTablespaces =
lappend(intervalPartDef->intervalTablespaces, makeString(tablespaceName));
}
}
relation_close(partitionRel, RowExclusiveLock);
return intervalPartDef;
}
static void transformTableLikePartitionKeys(
Relation relation, HeapTuple partitionTableTuple, List** partKeyColumns, List** partKeyPosList)
{
@ -1789,6 +1815,11 @@ static void transformTableLikePartitionBoundaries(
foreach (partitionCell, orderedPartitionList) {
HeapTuple partitionTuple = (HeapTuple)lfirst(partitionCell);
Form_pg_partition partitionForm = (Form_pg_partition)GETSTRUCT(partitionTuple);
/* no need to copy interval partition */
if (partitionForm->partstrategy == PART_STRATEGY_INTERVAL) {
continue;
}
bool attIsNull = false;
Datum tableSpace = (Datum)0;
Datum boundaries = (Datum)0;
@ -4161,19 +4192,24 @@ void checkPartitionSynax(CreateStmt* stmt)
/* check interval synax */
if (stmt->partTableState->intervalPartDef) {
#ifdef PGXC
/* in mpp version, we close interval partition feature */
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("Range partitioned table with INTERVAL was forbidden"),
errhint("Only support pure range partitioned table")));
#endif
if (stmt->partTableState->partitionKey->length > 1) {
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("Range partitioned table with INTERVAL clause has more than one column"),
errhint("Only support one partition key for interval partition")));
}
if (!IsA(stmt->partTableState->intervalPartDef->partInterval, A_Const) ||
((A_Const*)stmt->partTableState->intervalPartDef->partInterval)->val.type != T_String) {
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
// errmsg("invalid input syntax for type %s: \"%s\"", datatype, str)));
errmsg("invalid input syntax for type interval")));
}
int32 typmod = -1;
Interval* interval = NULL;
A_Const* node = (A_Const*)stmt->partTableState->intervalPartDef->partInterval;
interval = char_to_interval(node->val.val.str, typmod);
pfree(interval);
}
}

View File

@ -1391,6 +1391,7 @@ static int64 calculate_partition_indexes_size(Oid part_table_oid, Oid part_oid)
}
list_free_ext(indexOids);
relation_close(part_table_rel, AccessShareLock);
return size;
}

View File

@ -2546,10 +2546,8 @@ Datum timestamp_larger(PG_FUNCTION_ARGS)
PG_RETURN_TIMESTAMP(result);
}
Datum timestamp_mi(PG_FUNCTION_ARGS)
Datum timestamp_mi(Timestamp dt1, Timestamp dt2)
{
Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
Interval* result = NULL;
result = (Interval*)palloc(sizeof(Interval));
@ -2593,6 +2591,13 @@ Datum timestamp_mi(PG_FUNCTION_ARGS)
PG_RETURN_INTERVAL_P(result);
}
Datum timestamp_mi(PG_FUNCTION_ARGS)
{
Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
return timestamp_mi(dt1, dt2);
}
/*
* interval_justify_interval()
*
@ -2732,20 +2737,8 @@ Datum interval_justify_days(PG_FUNCTION_ARGS)
PG_RETURN_INTERVAL_P(result);
}
/* timestamp_pl_interval()
* Add a interval to a timestamp data type.
* Note that interval has provisions for qualitative year/month and day
* units, so try to do the right thing with them.
* To add a month, increment the month, and use the same day of month.
* Then, if the next month has fewer days, set the day of month
* to the last day of month.
* To add a day, increment the mday, and use the same time of day.
* Lastly, add in the "quantitative time".
*/
Datum timestamp_pl_interval(PG_FUNCTION_ARGS)
Datum timestamp_pl_interval(Timestamp timestamp, Interval* span)
{
Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
Interval* span = PG_GETARG_INTERVAL_P(1);
Timestamp result;
if (TIMESTAMP_NOT_FINITE(timestamp)) {
@ -2803,10 +2796,25 @@ Datum timestamp_pl_interval(PG_FUNCTION_ARGS)
PG_RETURN_TIMESTAMP(result);
}
Datum timestamp_mi_interval(PG_FUNCTION_ARGS)
/* timestamp_pl_interval()
* Add a interval to a timestamp data type.
* Note that interval has provisions for qualitative year/month and day
* units, so try to do the right thing with them.
* To add a month, increment the month, and use the same day of month.
* Then, if the next month has fewer days, set the day of month
* to the last day of month.
* To add a day, increment the mday, and use the same time of day.
* Lastly, add in the "quantitative time".
*/
Datum timestamp_pl_interval(PG_FUNCTION_ARGS)
{
Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
Interval* span = PG_GETARG_INTERVAL_P(1);
return timestamp_pl_interval(timestamp, span);
}
Datum timestamp_mi_interval(Timestamp timestamp, Interval* span)
{
Interval tspan;
tspan.month = -span->month;
@ -2816,6 +2824,13 @@ Datum timestamp_mi_interval(PG_FUNCTION_ARGS)
return DirectFunctionCall2(timestamp_pl_interval, TimestampGetDatum(timestamp), PointerGetDatum(&tspan));
}
Datum timestamp_mi_interval(PG_FUNCTION_ARGS)
{
Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
Interval* span = PG_GETARG_INTERVAL_P(1);
return timestamp_mi_interval(timestamp, span);
}
/* timestamptz_pl_interval()
* Add a interval to a timestamp with time zone data type.
* Note that interval has provisions for qualitative year/month
@ -2981,15 +2996,8 @@ Datum interval_mi(PG_FUNCTION_ARGS)
PG_RETURN_INTERVAL_P(result);
}
/*
* There is no interval_abs(): it is unclear what value to return:
* http://archives.postgresql.org/pgsql-general/2009-10/msg01031.php
* http://archives.postgresql.org/pgsql-general/2009-11/msg00041.php
*/
Datum interval_mul(PG_FUNCTION_ARGS)
Datum interval_mul(Interval* span, float8 factor)
{
Interval* span = PG_GETARG_INTERVAL_P(0);
float8 factor = PG_GETARG_FLOAT8(1);
double month_remainder_days, sec_remainder;
int32 orig_month = span->month;
int32 orig_day = span->day;
@ -3051,6 +3059,18 @@ Datum interval_mul(PG_FUNCTION_ARGS)
PG_RETURN_INTERVAL_P(result);
}
/*
* There is no interval_abs(): it is unclear what value to return:
* http://archives.postgresql.org/pgsql-general/2009-10/msg01031.php
* http://archives.postgresql.org/pgsql-general/2009-11/msg00041.php
*/
Datum interval_mul(PG_FUNCTION_ARGS)
{
Interval* span = PG_GETARG_INTERVAL_P(0);
float8 factor = PG_GETARG_FLOAT8(1);
return interval_mul(span, factor);
}
Datum mul_d_interval(PG_FUNCTION_ARGS)
{
/* Args are float8 and Interval *, but leave them as generic Datum */

View File

@ -368,6 +368,36 @@ Partition PartitionIdGetPartition(Oid partitionId)
return pd;
}
char* PartitionOidGetName(Oid partOid)
{
HeapTuple tuple = ScanPgPartition(partOid, true);
if (!HeapTupleIsValid(tuple)) {
return NULL;
}
Form_pg_partition part = (Form_pg_partition)GETSTRUCT(tuple);
char* relName = (char*)palloc0(NAMEDATALEN);
error_t rc = strncpy_s(relName, NAMEDATALEN, part->relname.data, NAMEDATALEN - 1);
securec_check_ss(rc, "\0", "\0");
heap_freetuple_ext(tuple);
return relName;
}
Oid PartitionOidGetTablespace(Oid partOid)
{
HeapTuple tuple = ScanPgPartition(partOid, true);
if (!HeapTupleIsValid(tuple)) {
return InvalidOid;
}
Form_pg_partition part = (Form_pg_partition)GETSTRUCT(tuple);
Oid tablespaceOid = part->reltablespace;
heap_freetuple_ext(tuple);
return tablespaceOid;
}
void PartitionClose(Partition partition)
{
/* Note: no locking manipulations needed */

301
src/gausskernel/cbb/utils/partition/partitionmap.cpp Executable file → Normal file
View File

@ -20,7 +20,7 @@
*
* IDENTIFICATION
* src/gausskernel/cbb/utils/partition/partitionmap.cpp
*
*
* -------------------------------------------------------------------------
*/
#include "postgres.h"
@ -379,33 +379,32 @@ static inline void constCompare(Const* value1, Const* value2, int& compare)
} \
} while (0)
#define buildRangeElement(range, type, typelen, relid, attrno, tuple, desc) \
do { \
Assert(PointerIsValid(range)); \
Assert(PointerIsValid(type) && PointerIsValid(attrno)); \
Assert(PointerIsValid(tuple) && PointerIsValid(desc)); \
Assert((attrno)->dim1 <= RANGE_PARTKEYMAXNUM); \
Assert((attrno)->dim1 == (typelen)); \
unserializePartitionStringAttribute((range)->boundary, \
RANGE_PARTKEYMAXNUM, \
(type), \
(typelen), \
(relid), \
(attrno), \
(tuple), \
Anum_pg_partition_boundaries, \
(desc)); \
(range)->partitionOid = HeapTupleGetOid(tuple); \
(range)->len = (typelen); \
#define BuildRangeElement(range, type, typelen, relid, attrno, tuple, desc, isInter) \
do { \
Assert(PointerIsValid(range)); \
Assert(PointerIsValid(type) && PointerIsValid(attrno)); \
Assert(PointerIsValid(tuple) && PointerIsValid(desc)); \
Assert((attrno)->dim1 <= RANGE_PARTKEYMAXNUM); \
Assert((attrno)->dim1 == (typelen)); \
unserializePartitionStringAttribute((range)->boundary, \
RANGE_PARTKEYMAXNUM, \
(type), \
(typelen), \
(relid), \
(attrno), \
(tuple), \
Anum_pg_partition_boundaries, \
(desc)); \
(range)->partitionOid = HeapTupleGetOid(tuple); \
(range)->len = (typelen); \
(range)->isInterval = (isInter); \
} while (0)
static void RebuildRangePartitionMap(RangePartitionMap* oldMap, RangePartitionMap* newMap);
static void RebuildIntervalPartitionMap(IntervalPartitionMap* oldMap, IntervalPartitionMap* newMap);
/* these routines are partition map related */
static void buildRangePartitionMap(Relation relation, Form_pg_partition partitioned_form, HeapTuple partitioned_tuple,
Relation pg_partition, List* partition_list);
Relation pg_partition, const List* partition_list);
static RangeElement* copyRangeElements(RangeElement* src, int elementNum, int partkeyNum);
@ -635,7 +634,6 @@ void RelationInitPartitionMap(Relation relation)
}
partitioned_form = (Form_pg_partition)GETSTRUCT(partitioned_tuple);
/*
* For value based partition-table, we only have to retrieve partkeys
*/
@ -694,6 +692,7 @@ void RelationInitPartitionMap(Relation relation)
switch (partitioned_form->partstrategy) {
case PART_STRATEGY_RANGE:
case PART_STRATEGY_INTERVAL:
buildRangePartitionMap(relation, partitioned_form, partitioned_tuple, pg_partition, partition_list);
break;
default:
@ -765,11 +764,7 @@ void RebuildPartitonMap(PartitionMap* oldMap, PartitionMap* newMap)
// when the map is referenced, don't rebuild the partitionmap
if (oldMap->refcount == 0) {
if (PartitionMapIsRange(oldMap)) {
RebuildRangePartitionMap((RangePartitionMap*)oldMap, (RangePartitionMap*)newMap);
} else {
RebuildIntervalPartitionMap((IntervalPartitionMap*)oldMap, (IntervalPartitionMap*)newMap);
}
RebuildRangePartitionMap((RangePartitionMap*)oldMap, (RangePartitionMap*)newMap);
} else {
oldMap->isDirty = true;
elog(LOG, "map refcount is not zero when RebuildPartitonMap ");
@ -799,9 +794,6 @@ static void RebuildRangePartitionMap(RangePartitionMap* oldMap, RangePartitionMa
PARTITIONMAP_SWAPFIELD(Oid*, partitionKeyDataType);
}
static void RebuildIntervalPartitionMap(IntervalPartitionMap* oldMap, IntervalPartitionMap* newMap)
{}
/*
* copy the rangeElement
*/
@ -826,6 +818,79 @@ static RangeElement* copyRangeElements(RangeElement* src, int elementNum, int pa
return ret;
}
RangeElement* CopyRangeElementsWithoutBoundary(const RangeElement* src, int elementNum)
{
Size size_ret = sizeof(RangeElement) * elementNum;
RangeElement* ret = (RangeElement*)palloc0(size_ret);
errno_t rc = memcpy_s(ret, size_ret, src, size_ret);
securec_check(rc, "\0", "\0");
return ret;
}
char* ReadIntervalStr(HeapTuple tuple, TupleDesc tupleDesc)
{
bool isNull = true;
Oid elemType;
int16 elemLen;
bool elemByval = false;
char elemAlign;
int numElems;
Datum* elemValues = NULL;
bool* elemNulls = NULL;
Datum attrRawValue = heap_getattr(tuple, (uint32)Anum_pg_partition_interval, tupleDesc, &isNull);
ArrayType* array = DatumGetArrayTypeP(attrRawValue);
elemType = ARR_ELEMTYPE(array);
Assert(elemType == TEXTOID);
get_typlenbyvalalign(elemType, &elemLen, &elemByval, &elemAlign);
deconstruct_array(array, elemType, elemLen, elemByval, elemAlign, &elemValues, &elemNulls, &numElems);
Assert(numElems == 1);
Assert(!elemNulls[0]);
char* intervalStr = text_to_cstring(DatumGetTextP(*elemValues));
pfree(elemValues);
pfree(elemNulls);
return intervalStr;
}
static Interval* ReadInterval(HeapTuple tuple, TupleDesc tupleDesc)
{
int32 typmod = -1;
char* intervalStr = ReadIntervalStr(tuple, tupleDesc);
Interval* res = char_to_interval(intervalStr, typmod);
pfree(intervalStr);
return res;
}
oidvector* ReadIntervalTablespace(HeapTuple tuple, TupleDesc tupleDesc)
{
Datum tablespaceRaw;
ArrayType* tablespaceArray = NULL;
bool isNull = false;
Oid* values = NULL;
int arraySize;
/* Get the raw data which contain interval tablespace's columns */
tablespaceRaw = heap_getattr(tuple, Anum_pg_partition_intablespace, tupleDesc, &isNull);
if (isNull) {
return NULL;
}
/* convert Datum to ArrayType */
tablespaceArray = DatumGetArrayTypeP(tablespaceRaw);
arraySize = ARR_DIMS(tablespaceArray)[0];
/* CHECK: the ArrayType of interval tablespace is valid */
if (ARR_NDIM(tablespaceArray) != 1 || arraySize <= 0 || ARR_HASNULL(tablespaceArray) ||
ARR_ELEMTYPE(tablespaceArray) != OIDOID) {
ereport(ERROR,
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR), errmsg("interval tablespace column's number is not a oid array")));
}
values = (Oid*)ARR_DATA_PTR(tablespaceArray);
return buildoidvector(values, arraySize);
}
/*
* @@GaussDB@@
* Target : data partition
@ -834,7 +899,7 @@ static RangeElement* copyRangeElements(RangeElement* src, int elementNum, int pa
* Notes :
*/
static void buildRangePartitionMap(Relation relation, Form_pg_partition partitioned_form, HeapTuple partitioned_tuple,
Relation pg_partition, List* partition_list)
Relation pg_partition, const List* partition_list)
{
int range_itr = 0;
RangePartitionMap* range_map = NULL;
@ -870,6 +935,14 @@ static void buildRangePartitionMap(Relation relation, Form_pg_partition partitio
partitionKeyDataType,
sizeof(Oid) * partitionKey->dim1);
securec_check(rc, "\0", "\0");
if (partitioned_form->partstrategy == PART_STRATEGY_INTERVAL) {
range_map->type.type = PART_TYPE_INTERVAL;
/* the interval partition only supports one partition key */
Assert(partitionKey->dim1 == 1);
range_map->intervalValue = ReadInterval(partitioned_tuple, RelationGetDescr(pg_partition));
range_map->intervalTablespace = ReadIntervalTablespace(partitioned_tuple, RelationGetDescr(pg_partition));
}
(void)MemoryContextSwitchTo(old_context);
/* allocate range element array */
@ -881,7 +954,8 @@ static void buildRangePartitionMap(Relation relation, Form_pg_partition partitio
partition_tuple = (HeapTuple)lfirst(tuple_cell);
partition_form = (Form_pg_partition)GETSTRUCT(partition_tuple);
if (PART_STRATEGY_RANGE != partition_form->partstrategy) {
if (partition_form->partstrategy != PART_STRATEGY_RANGE &&
partition_form->partstrategy != PART_STRATEGY_INTERVAL) {
pfree_ext(range_eles);
pfree_ext(range_map);
@ -891,14 +965,14 @@ static void buildRangePartitionMap(Relation relation, Form_pg_partition partitio
errdetail("Incorrect partition strategy for partition %u", HeapTupleGetOid(partition_tuple))));
}
buildRangeElement(&(range_eles[range_itr]),
BuildRangeElement(&(range_eles[range_itr]),
range_map->partitionKeyDataType,
range_map->partitionKey->dim1,
RelationGetRelid(relation),
range_map->partitionKey,
partition_tuple,
RelationGetDescr(pg_partition));
RelationGetDescr(pg_partition),
partition_form->partstrategy == PART_STRATEGY_INTERVAL);
range_itr++;
}
@ -1017,7 +1091,7 @@ Oid getRangePartitionOid(Relation relation, Const** partKeyValue, int32* partSeq
RangeElement* rangeElementIterator = NULL;
RangePartitionMap* rangePartMap = NULL;
Oid result = InvalidOid;
int keyNums = 0;
int keyNums;
int hit = -1;
int min_part_id = 0;
int max_part_id = 0;
@ -1084,13 +1158,39 @@ Oid getRangePartitionOid(Relation relation, Const** partKeyValue, int32* partSeq
return result;
}
/*
* return value: InvalidOid---when requested partition not created yet
*/
Oid getIntervalPartitionOid(IntervalPartitionMap* intervalPartMap, Const** partKeyValue, int32* partIndex,
PartitionArea* partArea, bool topClosed, bool missIsOk)
inline Const* CalcLowBoundary(const Const* upBoundary, Interval* intervalValue)
{
return InvalidOid;
Assert(upBoundary->consttype == TIMESTAMPOID || upBoundary->consttype == TIMESTAMPTZOID);
Timestamp lowTs = timestamp_mi_interval(DatumGetTimestamp(upBoundary->constvalue), intervalValue);
return makeConst(upBoundary->consttype,
upBoundary->consttypmod,
upBoundary->constcollid,
upBoundary->constlen,
TimestampGetDatum(lowTs),
upBoundary->constisnull,
upBoundary->constbyval);
}
inline int ValueCmpLowBoudary(Const** partKeyValue, const RangeElement* partition, Interval* intervalValue)
{
Assert(partition->isInterval);
Assert(partition->len == 1);
int compare = 0;
Const* lowBoundary = CalcLowBoundary(partition->boundary[0], intervalValue);
partitonKeyCompareForRouting(partKeyValue, &lowBoundary, partition->len, compare);
pfree(lowBoundary);
return compare;
}
/* the low boundary is close */
bool ValueSatisfyLowBoudary(Const** partKeyValue, RangeElement* partition, Interval* intervalValue, bool topClosed)
{
int compare = ValueCmpLowBoudary(partKeyValue, partition, intervalValue);
if (compare > 0 || (compare == 0 && topClosed)) {
return true;
}
return false;
}
/*
@ -1110,7 +1210,7 @@ int getNumberOfRangePartitions(Relation rel)
errmsg("CAN NOT get number of partition against NON-PARTITIONED relation")));
}
if (rel->partMap->type == PART_TYPE_RANGE) {
if (rel->partMap->type == PART_TYPE_RANGE || rel->partMap->type == PART_TYPE_INTERVAL) {
RangePartitionMap* rangeMap = NULL;
rangeMap = (RangePartitionMap*)(rel->partMap);
@ -1121,33 +1221,9 @@ int getNumberOfRangePartitions(Relation rel)
return ret;
}
/*
* @@GaussDB@@
* Target : data partition
* Brief :
* Description :
* Notes :
*/
int getNumberOfIntervalPartitions(Relation rel)
{
return 0;
}
int getNumberOfPartitions(Relation rel)
{
int ranges = 0;
int intervals = 0;
if (!RELATION_IS_PARTITIONED(rel)) {
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("CAN NOT get number of partition against NON-PARTITIONED relation")));
}
ranges = getNumberOfRangePartitions(rel);
intervals = getNumberOfIntervalPartitions(rel);
return (ranges + intervals);
return getNumberOfRangePartitions(rel);
}
Oid partIDGetPartOid(Relation relation, PartitionIdentifier* partID)
@ -1164,9 +1240,7 @@ Oid partIDGetPartOid(Relation relation, PartitionIdentifier* partID)
return InvalidOid;
}
if (relation->partMap->type == PART_TYPE_RANGE) {
Assert(partID->partArea == PART_AREA_RANGE);
if (relation->partMap->type == PART_TYPE_RANGE || relation->partMap->type == PART_TYPE_INTERVAL) {
rang_map = (RangePartitionMap*)(relation->partMap);
if (partID->partSeq <= rang_map->rangeElementsNum) {
@ -1201,13 +1275,17 @@ PartitionIdentifier* partOidGetPartID(Relation rel, Oid partOid)
}
result = (PartitionIdentifier*)palloc0(sizeof(PartitionIdentifier));
if (PART_TYPE_RANGE == rel->partMap->type) {
if (rel->partMap->type == PART_TYPE_RANGE || rel->partMap->type == PART_TYPE_INTERVAL) {
int i;
RangePartitionMap* rangeMap = (RangePartitionMap*)rel->partMap;
for (i = 0; i < rangeMap->rangeElementsNum; i++) {
if (partOid == rangeMap->rangeElements[i].partitionOid) {
result->partArea = PART_AREA_RANGE;
if (rangeMap->rangeElements[i].isInterval) {
result->partArea = PART_AREA_INTERVAL;
} else {
result->partArea = PART_AREA_RANGE;
}
result->partSeq = i;
result->fileExist = true;
result->partitionId = partOid;
@ -1237,9 +1315,7 @@ int partOidGetPartSequence(Relation rel, Oid partOid)
} else if (false == resultPartID->fileExist || PART_AREA_NONE == resultPartID->partArea) {
resultPartSequence = -1;
} else {
if (resultPartID->partArea == PART_AREA_RANGE) {
resultPartSequence = resultPartID->partSeq + 1;
}
resultPartSequence = resultPartID->partSeq + 1;
}
pfree_ext(resultPartID);
@ -1346,34 +1422,19 @@ void releasePartitionList(Relation relation, List** partList, LOCKMODE lockmode)
List* relationGetPartitionOidList(Relation rel)
{
List* result = NIL;
int conuter = 0;
int sumtotal = -1;
int rangeNumber = -1;
Bitmapset* mapset = NULL;
PartitionMap* map = NULL;
Oid partitionid = InvalidOid;
Oid partitionId = InvalidOid;
if (rel == NULL || rel->partMap == NULL) {
return NIL;
}
map = rel->partMap;
sumtotal = getPartitionNumber(map);
rangeNumber = ((RangePartitionMap*)map)->rangeElementsNum;
if (sumtotal > rangeNumber) {
mapset = bms_copy(((IntervalPartitionMap*)map)->sequenceMap);
PartitionMap* map = rel->partMap;
int sumTotal = getPartitionNumber(map);
for (int conuter = 0; conuter < sumTotal; ++conuter) {
partitionId = ((RangePartitionMap*)map)->rangeElements[conuter].partitionOid;
result = lappend_oid(result, partitionId);
}
for (conuter = 0; conuter < sumtotal; ++conuter) {
if (conuter < rangeNumber) { /* range partition */
partitionid = ((RangePartitionMap*)map)->rangeElements[conuter].partitionOid;
}
result = lappend_oid(result, partitionid);
}
bms_free_ext(mapset);
return result;
}
@ -1533,7 +1594,7 @@ int getPartitionNumber(PartitionMap* map)
{
int result = -1;
if (map->type == PART_TYPE_RANGE) {
if (map->type == PART_TYPE_RANGE || map->type == PART_TYPE_INTERVAL) {
result = ((RangePartitionMap*)map)->rangeElementsNum;
} else {
ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("unsupported partitioned strategy")));
@ -1708,3 +1769,45 @@ void decre_partmap_refcount(PartitionMap* map)
if (!IsBootstrapProcessingMode())
ResourceOwnerForgetPartitionMapRef(t_thrd.utils_cxt.CurrentResourceOwner, map);
}
/*
* Get the oid of the partition which is a interval partition and next to the droped range partition which is
* specificed by partOid. If the droped partition is a interval partition, the next partition no need to
* be changed to range partition, return InvalidOid. If the next partition is a range partition, nothing need
* to do, return InvalidOid.
*/
Oid GetNeedDegradToRangePartOid(Relation rel, Oid partOid)
{
/* never happen */
if (!PointerIsValid(rel) || !OidIsValid(partOid)) {
ereport(ERROR,
(errcode(ERRCODE_FETCH_DATA_FAILED), errmsg("invalid partitioned table relaiton or partition table oid")));
}
Assert(rel->partMap->type == PART_TYPE_RANGE || rel->partMap->type == PART_TYPE_INTERVAL);
/* In normal range partitioned tabel, there has no interval ranges. */
if (rel->partMap->type == PART_TYPE_RANGE) {
return InvalidOid;
}
RangePartitionMap* rangeMap = (RangePartitionMap*)rel->partMap;
for (int i = 0; i < rangeMap->rangeElementsNum; i++) {
if (rangeMap->rangeElements[i].partitionOid == partOid) {
/*
* 1. the droped range is interval range
* 2. there is no more ranges
* 3. the next partition is a range partition
*/
if (rangeMap->rangeElements[i].isInterval || (i == rangeMap->rangeElementsNum - 1) ||
!rangeMap->rangeElements[i + 1].isInterval) {
return InvalidOid;
}
return rangeMap->rangeElements[i + 1].partitionOid;
}
}
/* It must never happened. */
ereport(ERROR, (errcode(ERRCODE_CASE_NOT_FOUND), errmsg("Not find the target partiton %u", partOid)));
return InvalidOid;
}

View File

@ -522,18 +522,19 @@ static void RangeVarCallbackForAlterRelation(
const RangeVar* rv, Oid relid, Oid oldrelid, bool target_is_partition, void* arg);
static bool CheckRangePartitionKeyType(Oid typoid);
static void CheckRangePartitionKeyType(Form_pg_attribute* attrs, List* pos);
static void CheckIntervalPartitionKeyType(Form_pg_attribute* attrs, List* pos);
static void CheckPartitionTablespace(const char* spcname, Oid owner);
static void ComparePartitionValue(List* pos, Form_pg_attribute* attrs, PartitionState* partTableState);
static bool ConfirmTypeInfo(Oid* target_oid, int* target_mod, Const* src, Form_pg_attribute attrs, bool isinterval);
static void addToastTableForNewPartition(Relation relation, Oid newPartId);
void addToastTableForNewPartition(Relation relation, Oid newPartId);
static void ATPrepAddPartition(Relation rel);
static void ATPrepDropPartition(Relation rel);
static void ATPrepUnusableIndexPartition(Relation rel);
static void ATPrepUnusableAllIndexOnPartition(Relation rel);
static void ATExecAddPartition(Relation rel, AddPartitionState* partState);
static void ATExecDropPartition(Relation rel, AlterTableCmd* cmd);
void fastDropPartition(Relation rel, Oid partOid, const char* stmt);
static void ATExecUnusableIndexPartition(Relation rel, const char* partition_name);
static void ATExecUnusableIndex(Relation rel);
static void ATExecUnusableAllIndexOnPartition(Relation rel, const char* partition_name);
@ -1722,16 +1723,18 @@ Oid DefineRelation(CreateStmt* stmt, char relkind, Oid ownerId)
if (stmt->partTableState) {
List* pos = NIL;
bool is_interval = false;
/* get partitionkey's position */
pos = GetPartitionkeyPos(stmt->partTableState->partitionKey, schema);
/* check partitionkey's datatype */
if (stmt->partTableState->partitionStrategy == PART_STRATEGY_VALUE)
if (stmt->partTableState->partitionStrategy == PART_STRATEGY_VALUE) {
CheckValuePartitionKeyType(descriptor->attrs, pos);
else
CheckPartitionKeyType(descriptor->attrs, pos, is_interval);
} else if (stmt->partTableState->partitionStrategy == PART_STRATEGY_INTERVAL) {
CheckIntervalPartitionKeyType(descriptor->attrs, pos);
} else {
CheckRangePartitionKeyType(descriptor->attrs, pos);
}
/*
* Check partitionkey's value for none value-partition table as for value
@ -12465,7 +12468,7 @@ static void ATExecSetTableSpaceForPartitionP2(AlteredTableInfo* tab, Relation re
rangePartDef = (RangePartitionDefState*)partition;
transformRangePartitionValue(make_parsestate(NULL), (Node*)rangePartDef, false);
rangePartDef->boundary = transformConstIntoTargetType(rel->rd_att->attrs,
((IntervalPartitionMap*)rel->partMap)->rangePartitionMap.partitionKey,
((RangePartitionMap*)rel->partMap)->partitionKey,
rangePartDef->boundary);
partOid =
partitionValuesGetPartitionOid(rel, rangePartDef->boundary, AccessExclusiveLock, true, false, false);
@ -15549,17 +15552,11 @@ List* GetPartitionkeyPos(List* partitionkeys, List* schema)
* Description :
* Notes :
*/
void CheckPartitionKeyType(Form_pg_attribute* attrs, List* pos, bool is_interval)
static void CheckRangePartitionKeyType(Form_pg_attribute* attrs, List* pos)
{
int location = 0;
ListCell* cell = NULL;
Oid typoid = InvalidOid;
/* must be one partitionkey for interval partition */
if (is_interval && pos->length != 1) {
list_free_ext(pos);
ereport(
ERROR, (errcode(ERRCODE_INVALID_OPERATION), errmsg("must be one partition key for interval partition")));
}
foreach (cell, pos) {
bool result = false;
location = lfirst_int(cell);
@ -15577,6 +15574,23 @@ void CheckPartitionKeyType(Form_pg_attribute* attrs, List* pos, bool is_interval
}
}
static void CheckIntervalPartitionKeyType(Form_pg_attribute* attrs, List* pos)
{
/* must be one partitionkey for interval partition, have checked before */
Assert(pos->length == 1);
ListCell* cell = list_head(pos);
int location = lfirst_int(cell);
Oid typoid = attrs[location]->atttypid;
if (typoid != TIMESTAMPOID && typoid != TIMESTAMPTZOID) {
list_free_ext(pos);
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("column %s cannot serve as a interval partitioning column because of its datatype",
NameStr(attrs[location]->attname))));
}
}
/*
* @@GaussDB@@
* Target : value-partition type check
@ -15953,6 +15967,11 @@ static void ATPrepAddPartition(Relation rel)
ereport(
ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("can not add partition against NON-PARTITIONED table")));
}
if (rel->partMap->type == PART_TYPE_INTERVAL) {
ereport(ERROR, (errcode(ERRCODE_OPERATE_NOT_SUPPORTED),
errmsg("can not add partition against interval partitioned table")));
}
}
/*
@ -16063,6 +16082,11 @@ static void ATPrepMergePartition(Relation rel)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("can not merge partition against NON-PARTITIONED table")));
}
if (rel->partMap->type == PART_TYPE_INTERVAL) {
ereport(ERROR, (errcode(ERRCODE_OPERATE_NOT_SUPPORTED),
errmsg("can not merge partition against interval partitioned table")));
}
}
static void ATPrepSplitPartition(Relation rel)
@ -16071,6 +16095,11 @@ static void ATPrepSplitPartition(Relation rel)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("can not split partition against NON-PARTITIONED table")));
}
if (rel->partMap->type == PART_TYPE_INTERVAL) {
ereport(ERROR, (errcode(ERRCODE_OPERATE_NOT_SUPPORTED),
errmsg("can not split partition against interval partitioned table")));
}
}
/*
@ -16224,8 +16253,43 @@ static void ATExecAddPartition(Relation rel, AddPartitionState* partState)
pfree_ext(isTimestamptz);
}
// assume caller already hold AccessExclusiveLock on the partition being dropped
void fastDropPartition(Relation rel, Oid partOid, const char* stmt)
/* Assume the caller has already hold RowExclusiveLock on the pg_partition. */
static void UpdateIntervalPartToRange(Relation relPartition, Oid partOid, const char* stmt)
{
bool dirty = false;
/* Fetch a copy of the tuple to scribble on */
HeapTuple parttup = SearchSysCacheCopy1(PARTRELID, ObjectIdGetDatum(partOid));
if (!HeapTupleIsValid(parttup)) {
ereport(ERROR,
(errcode(ERRCODE_SQL_ROUTINE_EXCEPTION),
errmsg("pg_partition entry for partid %u vanished during %s.", partOid, stmt)));
}
Form_pg_partition partform = (Form_pg_partition)GETSTRUCT(parttup);
/* Apply required updates, if any, to copied tuple */
if (partform->partstrategy == PART_STRATEGY_INTERVAL) {
partform->partstrategy = PART_STRATEGY_RANGE;
dirty = true;
} else {
ereport(LOG,
(errcode(ERRCODE_SQL_ROUTINE_EXCEPTION),
errmsg("pg_partition entry for partid %u is not a interval "
"partition when execute %s .",
partOid,
stmt)));
}
/* If anything changed, write out the tuple. */
if (dirty) {
heap_inplace_update(relPartition, parttup);
}
}
/* assume caller already hold AccessExclusiveLock on the partition being dropped
* if the intervalPartOid is not InvalidOid, the interval partition which is specificed by it
* need to be changed to normal range partition.
*/
void fastDropPartition(Relation rel, Oid partOid, const char* stmt, Oid intervalPartOid)
{
Partition part = NULL;
Relation pg_partition = NULL;
@ -16240,6 +16304,7 @@ void fastDropPartition(Relation rel, Oid partOid, const char* stmt)
getPartitionName(partOid, false),
stmt)));
}
/* drop toast table, index, and finally the partition iteselt */
dropIndexForPartition(partOid);
dropToastTableOnPartition(partOid);
@ -16249,6 +16314,10 @@ void fastDropPartition(Relation rel, Oid partOid, const char* stmt)
}
heapDropPartition(rel, part);
if (intervalPartOid) {
UpdateIntervalPartToRange(pg_partition, intervalPartOid, stmt);
}
/* step 3: no need to update number of partitions in pg_partition */
/* step 4: invalidate relation */
CacheInvalidateRelcache(rel);
@ -16291,8 +16360,7 @@ static void ATExecDropPartition(Relation rel, AlterTableCmd* cmd)
/* next IS the DROP PARTITION FOR (MAXVALUELIST) branch */
rangePartDef = (RangePartitionDefState*)cmd->def;
rangePartDef->boundary = transformConstIntoTargetType(rel->rd_att->attrs,
((IntervalPartitionMap*)rel->partMap)->rangePartitionMap.partitionKey,
rangePartDef->boundary);
((RangePartitionMap*)rel->partMap)->partitionKey, rangePartDef->boundary);
partOid = partitionValuesGetPartitionOid(rel,
rangePartDef->boundary,
AccessExclusiveLock,
@ -16311,7 +16379,9 @@ static void ATExecDropPartition(Relation rel, AlterTableCmd* cmd)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OPERATION), errmsg("Cannot drop the only partition of a partitioned table")));
}
fastDropPartition(rel, partOid, "DROP PARTITION");
Oid changeToRangePartOid = GetNeedDegradToRangePartOid(rel, partOid);
fastDropPartition(rel, partOid, "DROP PARTITION", changeToRangePartOid);
}
/*
@ -16565,7 +16635,6 @@ static void ATExecModifyRowMovement(Relation rel, bool rowMovement)
/* get the tuple of partitioned table */
tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
if (!HeapTupleIsValid(tuple)) {
ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), errmsg("could not find tuple for relation %u", relid)));
}
@ -16671,7 +16740,7 @@ static void ATExecTruncatePartition(Relation rel, AlterTableCmd* cmd)
} else {
rangePartDef = (RangePartitionDefState*)cmd->def;
rangePartDef->boundary = transformConstIntoTargetType(rel->rd_att->attrs,
((IntervalPartitionMap*)rel->partMap)->rangePartitionMap.partitionKey,
((RangePartitionMap*)rel->partMap)->partitionKey,
rangePartDef->boundary);
partOid = partitionValuesGetPartitionOid(rel,
rangePartDef->boundary,
@ -19298,7 +19367,7 @@ List* transformConstIntoTargetType(Form_pg_attribute* attrs, int2vector* partiti
* Return :
* Notes :
*/
static void addToastTableForNewPartition(Relation relation, Oid newPartId)
void addToastTableForNewPartition(Relation relation, Oid newPartId)
{
Oid firstPartitionId = InvalidOid;
Oid firstPartitionToastId = InvalidOid;

View File

@ -1610,7 +1610,7 @@ static bool vacuum_rel(Oid relid, VacuumStmt* vacstmt, bool do_toast)
if (onepartrel) {
if (onepartrel->rd_rel->relkind == RELKIND_RELATION) {
partID = partOidGetPartID(onepartrel, relid);
if (partID->partArea == PART_AREA_RANGE) {
if (partID->partArea == PART_AREA_RANGE || partID->partArea == PART_AREA_INTERVAL) {
if (ConditionalLockPartition(onepartrel->rd_id, relid, lmode, PARTITION_LOCK)) {
GetLock = true;
}

View File

@ -73,9 +73,7 @@ static void acquireSamplesForPartitionedRelation(
if (RelationIsPartitioned(relation)) {
if (relation->rd_rel->relkind == RELKIND_RELATION) {
RangePartitionMap* partMap = (RangePartitionMap*)(relation->partMap);
int totalRangePartitionNumber = getNumberOfRangePartitions(relation);
int totalInervalPartitionNumber = getNumberOfIntervalPartitions(relation);
int totalPartitionNumber = totalRangePartitionNumber + totalInervalPartitionNumber;
int totalPartitionNumber = getNumberOfRangePartitions(relation);
int partitionNumber = 0;
int nonzeroPartitionNumber = 0;
BlockNumber partPages = 0;
@ -83,24 +81,7 @@ static void acquireSamplesForPartitionedRelation(
Partition part = NULL;
for (partitionNumber = 0; partitionNumber < totalPartitionNumber; partitionNumber++) {
Oid partitionOid = InvalidOid;
#ifdef PGXC // open range partition
partitionOid = partMap->rangeElements[partitionNumber].partitionOid;
#else // open range partition or interval partition
if (partitionNumber < totalRangePartitionNumber) {
partitionOid = partMap->rangeElements[partitionNumber].partitionOid;
} else {
IntervalPartitionMap* intervalPartMap = NULL;
int intervalPartitionIndex = partitionNumber - totalRangePartitionNumber;
AssertEreport(relation->partMap->type == PART_TYPE_INTERVAL,
MOD_OPT,
"Expected interval partition type but exception occurred.");
intervalPartMap = (IntervalPartitionMap*)(relation->partMap);
partitionOid = intervalPartMap->intervalElements[intervalPartitionIndex].partitionOid;
}
#endif
Oid partitionOid = partMap->rangeElements[partitionNumber].partitionOid;
if (!OidIsValid(partitionOid))
continue;

View File

@ -140,7 +140,7 @@ bool checkPartitionIndexUnusable(Oid indexOid, int partItrs, PruningResult* prun
heapRel = relation_open(heapRelOid, NoLock);
indexRel = relation_open(indexOid, NoLock);
if (!RelationIsPartitioned(heapRel) || !RelationIsPartitioned(indexRel) ||
heapRel->partMap->type != PART_TYPE_RANGE) {
(heapRel->partMap->type != PART_TYPE_RANGE && heapRel->partMap->type != PART_TYPE_INTERVAL)) {
ereport(ERROR,
(errmodule(MOD_OPT),
errcode(ERRCODE_OPTIMIZER_INCONSISTENT_STATE),
@ -226,8 +226,7 @@ IndexesUsableType eliminate_partition_index_unusable(Oid indexOid, PruningResult
heapRel = relation_open(heapRelOid, NoLock);
indexRel = relation_open(indexOid, NoLock);
if (!RelationIsPartitioned(heapRel) || !RelationIsPartitioned(indexRel) ||
heapRel->partMap->type != PART_TYPE_RANGE) {
if (!RelationIsPartitioned(heapRel) || !RelationIsPartitioned(indexRel)) {
ereport(ERROR,
(errmodule(MOD_OPT),
(errcode(ERRCODE_OPTIMIZER_INCONSISTENT_STATE),
@ -438,7 +437,7 @@ PruningResult* singlePartitionPruningForRestrictInfo(Oid partitionOid, Relation
pruningRes->state = PRUNING_RESULT_SUBSET;
/* it's a pattitioned table without interval */
if (rel->partMap->type == PART_TYPE_RANGE) {
if (rel->partMap->type == PART_TYPE_RANGE || rel->partMap->type == PART_TYPE_INTERVAL) {
rangePartMap = (RangePartitionMap*)rel->partMap;
for (counter = 0; counter < rangePartMap->rangeElementsNum; counter++) {
@ -1152,13 +1151,13 @@ int varIsInPartitionKey(int attrNo, int2vector* partKeyAttrs, int partKeyNum)
(PruningResultIsFull(pruningResult) || PruningResultIsEmpty(pruningResult) || \
!PointerIsValid((pruningResult)->boundary))
#define IsCleanPruningBottom(bottomSeqPtr, pruningResult, bottomValue) \
((bottomSeqPtr)->partArea == PART_AREA_RANGE && (pruningResult)->boundary->partitionKeyNum > 1 && \
PointerIsValid((bottomValue)[0]) && !(pruningResult)->boundary->minClose[0])
#define IsCleanPruningBottom(bottomSeqPtr, pruningResult, bottomValue) \
((pruningResult)->boundary->partitionKeyNum > 1 && PointerIsValid((bottomValue)[0]) && \
!(pruningResult)->boundary->minClose[0])
#define IsCleanPruningTop(topSeqPtr, pruningResult, topValue) \
((topSeqPtr)->partArea == PART_AREA_RANGE && (pruningResult)->boundary->partitionKeyNum > 1 && (topValue) && \
PointerIsValid((topValue)[0]) && !(pruningResult)->boundary->maxClose[0])
#define IsCleanPruningTop(topSeqPtr, pruningResult, topValue) \
((pruningResult)->boundary->partitionKeyNum > 1 && (topValue) && PointerIsValid((topValue)[0]) && \
!(pruningResult)->boundary->maxClose[0])
/*
* @@GaussDB@@
@ -1209,13 +1208,14 @@ static void partitionPruningFromBoundary(Relation relation, PruningResult* pruni
// compare the bottom and the intervalMax, if the bottom is large than or equal than intervalMax, pruning result is
// empty.
partitionRoutingForValue(
partitionRoutingForValueRange(
relation, bottomValue, pruningResult->boundary->partitionKeyNum, true, true, u_sess->opt_cxt.bottom_seq);
if (IsCleanPruningBottom(u_sess->opt_cxt.bottom_seq, pruningResult, bottomValue)) {
cleanPruningBottom(relation, u_sess->opt_cxt.bottom_seq, bottomValue[0]);
}
partitionRoutingForValue(
relation, topValue, pruningResult->boundary->partitionKeyNum, isTopClosed, true, u_sess->opt_cxt.top_seq);
partitionRoutingForValueRange(
relation, topValue, pruningResult->boundary->partitionKeyNum, isTopClosed, false, u_sess->opt_cxt.top_seq);
if (IsCleanPruningTop(u_sess->opt_cxt.top_seq, pruningResult, topValue)) {
cleanPruningTop(relation, u_sess->opt_cxt.top_seq, topValue[0]);
}
@ -1226,22 +1226,14 @@ static void partitionPruningFromBoundary(Relation relation, PruningResult* pruni
if (!PartitionLogicalExist(u_sess->opt_cxt.bottom_seq) && !PartitionLogicalExist(u_sess->opt_cxt.top_seq)) {
/* pruning failed or result contains all partition */
pruningResult->state = PRUNING_RESULT_EMPTY;
} else if (!PartitionLogicalExist(u_sess->opt_cxt.bottom_seq) &&
u_sess->opt_cxt.top_seq->partArea == PART_AREA_RANGE) {
} else if (!PartitionLogicalExist(u_sess->opt_cxt.bottom_seq)) {
rangeStart = 0;
rangeEnd = u_sess->opt_cxt.top_seq->partSeq;
} else if (u_sess->opt_cxt.bottom_seq->partArea == PART_AREA_RANGE &&
!PartitionLogicalExist(u_sess->opt_cxt.top_seq)) {
} else if (!PartitionLogicalExist(u_sess->opt_cxt.top_seq)) {
rangeStart = u_sess->opt_cxt.bottom_seq->partSeq;
} else if (u_sess->opt_cxt.bottom_seq->partArea == PART_AREA_RANGE &&
u_sess->opt_cxt.top_seq->partArea == PART_AREA_RANGE) {
} else {
rangeStart = u_sess->opt_cxt.bottom_seq->partSeq;
rangeEnd = u_sess->opt_cxt.top_seq->partSeq;
} else {
ereport(ERROR,
(errmodule(MOD_OPT),
errcode(ERRCODE_OPTIMIZER_INCONSISTENT_STATE),
errmsg("pruning result(PartitionIdentifier) is invalid")));
}
if (0 <= rangeStart) {
@ -1655,8 +1647,8 @@ static void cleanPruningBottom(Relation relation, PartitionIdentifier* bottomSeq
int i = 0;
RangePartitionMap* partMap = NULL;
if (bottomSeq->partArea != PART_AREA_RANGE || bottomSeq->partSeq < 0 ||
bottomSeq->partSeq >= ((RangePartitionMap*)relation->partMap)->rangeElementsNum || value == NULL) {
if (bottomSeq->partSeq < 0 || bottomSeq->partSeq >= ((RangePartitionMap*)relation->partMap)->rangeElementsNum ||
value == NULL) {
return;
}
@ -1688,8 +1680,8 @@ static void cleanPruningTop(Relation relation, PartitionIdentifier* topSeq, Cons
int i = 0;
RangePartitionMap* partMap = NULL;
if (topSeq->partArea != PART_AREA_RANGE || topSeq->partSeq < 0 ||
topSeq->partSeq >= ((RangePartitionMap*)relation->partMap)->rangeElementsNum || value == NULL) {
if (topSeq->partSeq < 0 || topSeq->partSeq >= ((RangePartitionMap*)relation->partMap)->rangeElementsNum ||
value == NULL) {
return;
}
@ -1853,7 +1845,7 @@ Oid getPartitionOidFromSequence(Relation relation, int partSeq)
AssertEreport(PointerIsValid(relation), MOD_OPT, "Unexpected NULL pointer for relation.");
AssertEreport(PointerIsValid(relation->partMap), MOD_OPT, "Unexpected NULL pointer for relation->partMap.");
if (relation->partMap->type == PART_TYPE_RANGE) {
if (relation->partMap->type == PART_TYPE_RANGE || relation->partMap->type == PART_TYPE_INTERVAL) {
int rangeElementsNum = ((RangePartitionMap*)(relation->partMap))->rangeElementsNum;
if (partSeq < rangeElementsNum) {
result = ((RangePartitionMap*)(relation->partMap))->rangeElements[partSeq].partitionOid;

View File

@ -1216,7 +1216,6 @@ TupleTableSlot* ExecUpdate(ItemPointer tupleid,
/* for partitioned table */
bool row_movement = false;
bool need_create_file = false;
int seq_num = -1;
if (!partKeyUpdate) {
row_movement = false;
@ -1257,7 +1256,6 @@ TupleTableSlot* ExecUpdate(ItemPointer tupleid,
if (result_relation_desc->rd_rel->relrowmovement) {
row_movement = true;
need_create_file = true;
seq_num = u_sess->exec_cxt.route->partSeq;
} else {
ereport(ERROR,
(errmodule(MOD_EXECUTOR),
@ -1519,7 +1517,7 @@ TupleTableSlot* ExecUpdate(ItemPointer tupleid,
Relation fake_insert_relation = NULL;
if (need_create_file) {
new_partId = createNewIntervalFile(result_relation_desc, seq_num);
new_partId = AddNewIntervalPartition(result_relation_desc, tuple);
}
searchFakeReationForPartitionOid(estate->esfRelations,

View File

@ -7362,10 +7362,6 @@ Partition partitionOpen(Relation relation, Oid partition_id, LOCKMODE lockmode,
/* Get the lock before trying to open the relcache entry */
if (lockmode != NoLock) {
if (relation->rd_rel->relkind == RELKIND_RELATION) {
/*
* assume the partition is in PART_AREA_RANGE, if we support interval partition,
* we have to find a quick way to find the area it belongs to.
*/
LockPartition(relation->rd_id, partition_id, lockmode, PARTITION_LOCK);
} else if (relation->rd_rel->relkind == RELKIND_INDEX) {
LockPartition(relation->rd_id, partition_id, lockmode, PARTITION_LOCK);
@ -7427,6 +7423,9 @@ Partition tryPartitionOpen(Relation relation, Oid partition_id, LOCKMODE lockmod
case PART_AREA_RANGE:
LockPartition(relation->rd_id, partition_id, lockmode, PARTITION_LOCK);
break;
case PART_AREA_INTERVAL:
LockPartition(relation->rd_id, partition_id, lockmode, PARTITION_LOCK);
break;
default:
break;
}
@ -7456,6 +7455,9 @@ Partition tryPartitionOpen(Relation relation, Oid partition_id, LOCKMODE lockmod
case PART_AREA_RANGE:
UnlockPartition(relation->rd_id, partition_id, lockmode, PARTITION_LOCK);
break;
case PART_AREA_INTERVAL:
UnlockPartition(relation->rd_id, partition_id, lockmode, PARTITION_LOCK);
break;
default:
break;
}
@ -7524,6 +7526,9 @@ void partitionClose(Relation relation, Partition partition, LOCKMODE lockmode)
case PART_AREA_RANGE:
UnlockPartition(relation->rd_id, part->pd_id, lockmode, PARTITION_LOCK);
break;
case PART_AREA_INTERVAL:
UnlockPartition(relation->rd_id, part->pd_id, lockmode, PARTITION_LOCK);
break;
default:
break;
}

View File

@ -37,8 +37,6 @@
#include "catalog/index.h"
#include "storage/remote_read.h"
extern void fastDropPartition(Relation rel, Oid partOid, const char* stmt);
#define IsBitmapSet(_bitmap, _i) (((_bitmap)[(_i) >> 3] & (1 << ((_i) % 8))) != 0)
#define ARRAY_2_LEN 2

View File

@ -941,7 +941,7 @@ void LockPartitionVacuum(Relation prel, Oid partId, LOCKMODE lockmode)
Assert(PointerIsValid(prel) && prel->rd_rel->relkind == RELKIND_RELATION);
partIdentifier = partOidGetPartID(prel, partId);
if (partIdentifier->partArea == PART_AREA_RANGE) {
if (partIdentifier->partArea == PART_AREA_RANGE || partIdentifier->partArea == PART_AREA_INTERVAL) {
LockPartition(prel->rd_id, partId, lockmode, PARTITION_LOCK);
}
@ -951,29 +951,16 @@ void LockPartitionVacuum(Relation prel, Oid partId, LOCKMODE lockmode)
bool ConditionalLockPartitionWithRetry(Relation relation, Oid partitionId, LOCKMODE lockmode)
{
Oid relationId = relation->rd_id;
char relkind = relation->rd_rel->relkind;
PartitionIdentifier *partIdentifier = NULL;
int lock_retry = 0;
int lock_retry_limit = u_sess->attr.attr_storage.partition_lock_upgrade_timeout *
(1000000 / PARTITION_RETRY_LOCK_WAIT_INTERVAL);
if (relkind == RELKIND_RELATION)
partIdentifier = partOidGetPartID(relation, partitionId);
while (true) {
/* step 1.1: try to lock partition */
if (relkind == RELKIND_RELATION) {
if (partIdentifier->partArea == PART_AREA_RANGE) {
if (ConditionalLockPartition(relationId, partitionId, lockmode, PARTITION_LOCK))
break;
} else if (partIdentifier->partArea == PART_AREA_INTERVAL) {
if (ConditionalLockPartition(relationId, partIdentifier->partSeq, lockmode, PARTITION_SEQUENCE_LOCK))
break;
}
} else if (relkind == RELKIND_INDEX) {
if (ConditionalLockPartition(relationId, partitionId, lockmode, PARTITION_LOCK))
break;
if (ConditionalLockPartition(relationId, partitionId, lockmode, PARTITION_LOCK)) {
break;
}
/* step 1.2: examine the try count */
if (lock_retry_limit < 0) {
/* do nothing, infinite loop */
@ -982,15 +969,12 @@ bool ConditionalLockPartitionWithRetry(Relation relation, Oid partitionId, LOCKM
* We failed to establish the lock in the specified timeout
* . This means we give up.
*/
pfree(partIdentifier);
return false;
}
/* step 1.3: just sleep for a while, then re-enter this loop */
pg_usleep(PARTITION_RETRY_LOCK_WAIT_INTERVAL);
}
if (partIdentifier != NULL)
pfree(partIdentifier);
return true;
}
@ -1003,7 +987,7 @@ bool ConditionalLockPartitionVacuum(Relation prel, Oid partId, LOCKMODE lockmode
Assert(PointerIsValid(prel) && prel->rd_rel->relkind == RELKIND_RELATION);
partIdentifier = partOidGetPartID(prel, partId);
if (partIdentifier->partArea == PART_AREA_RANGE) {
if (partIdentifier->partArea == PART_AREA_RANGE || partIdentifier->partArea == PART_AREA_INTERVAL) {
if (ConditionalLockPartition(prel->rd_id, partId, lockmode, PARTITION_LOCK)) {
getLock = true;
}
@ -1022,6 +1006,9 @@ void UnLockPartitionVacuum(Relation prel, Oid partId, LOCKMODE lockmode)
case PART_AREA_RANGE:
UnlockPartition(prel->rd_id, partId, lockmode, PARTITION_LOCK);
break;
case PART_AREA_INTERVAL:
UnlockPartition(prel->rd_id, partId, lockmode, PARTITION_LOCK);
break;
default:
Assert(0);
break;
@ -1046,7 +1033,7 @@ void LockPartitionVacuumForSession(PartitionIdentifier *partIdtf, Oid partrelid,
{
LOCKTAG tag;
if (partIdtf->partArea == PART_AREA_RANGE) {
if (partIdtf->partArea == PART_AREA_RANGE || partIdtf->partArea == PART_AREA_INTERVAL) {
SetLocktagPartitionOid(&tag, partrelid, partid);
}
@ -1059,7 +1046,7 @@ void UnLockPartitionVacuumForSession(PartitionIdentifier *partIdtf, Oid partreli
{
LOCKTAG tag;
if (partIdtf->partArea == PART_AREA_RANGE) {
if (partIdtf->partArea == PART_AREA_RANGE || partIdtf->partArea == PART_AREA_INTERVAL) {
SetLocktagPartitionOid(&tag, partrelid, partid);
}

View File

@ -76,7 +76,6 @@ extern void addNewPartitionTuple(Relation pg_part_desc, Partition new_part_desc,
extern void heap_truncate_one_part(Relation rel , Oid partOid);
extern Oid heapTupleGetPartitionId(Relation rel, HeapTuple tuple);
extern Oid createNewIntervalFile(Relation rel, int seqNum);
extern void heap_truncate(List *relids);
extern void heap_truncate_one_rel(Relation rel);
extern void heap_truncate_check_FKs(List *relations, bool tempTables);
@ -144,4 +143,6 @@ extern char* make_column_map(TupleDesc tuple_desc);
*/
extern bool* check_partkey_has_timestampwithzone(Relation partTableRel);
extern Oid AddNewIntervalPartition(Relation rel, HeapTuple insertTuple);
#endif /* HEAP_H */

View File

@ -42,7 +42,10 @@
#define MAX_PARTITIONKEY_NUM 4
#define MAX_PARTITION_NUM 32767 /* update LEN_PARTITION_PREFIX as well ! */
#define INTERVAL_PARTITION_NAME_PREFIX "sys_p"
#define INTERVAL_PARTITION_NAME_PREFIX_FMT "sys_p%u"
#define INTERVAL_PARTITION_NAME_SUFFIX_LEN 5 /* max length of partitio num */
/*
* In start/end syntax, partition name is of form:
* PARTITION_PREFIX_NUM,
@ -72,7 +75,7 @@
typedef void (*PartitionNameGetPartidCallback) (Oid partitioned_relation, const char *partition_name, Oid partId,
Oid oldPartId, char partition_type, void *callback_arg, LOCKMODE callbackobj_lockMode);
extern void insertPartitionEntry(Relation pg_partition_desc, Partition new_part_desc, Oid new_part_id,
int2vector *pkey, oidvector *inttablespace, Datum interval,
int2vector *pkey, const oidvector *inttablespace, Datum interval,
Datum maxValues, Datum transitionPoint, Datum reloptions, char parttype);
extern bool isPartitionedObject(Oid relid, char relkind, bool missing_ok);
extern bool isPartitionObject(Oid partid, char partkind, bool missing_ok);

View File

@ -123,7 +123,6 @@ extern void ATExecSetIndexUsableState(Oid objclassOid, Oid objOid, bool newState
extern bool checkPartitionLocalIndexesUsable(Oid partitionOid);
extern bool checkRelationLocalIndexesUsable(Relation relation);
extern List* GetPartitionkeyPos(List* partitionkeys, List* schema);
extern void CheckPartitionKeyType(Form_pg_attribute* attrs, List* pos, bool is_interval);
extern void clearAttrInitDefVal(Oid relid);
@ -140,5 +139,7 @@ extern Node* GetTargetValue(Form_pg_attribute attrs, Const* src, bool isinterval
extern void ATExecEnableDisableRls(Relation rel, RelationRlsStatus changeType, LOCKMODE lockmode);
extern void create_part_policy_if_needed(CreateStmt *stmt, char relkind);
extern void addToastTableForNewPartition(Relation relation, Oid newPartId);
extern void fastDropPartition(Relation rel, Oid partOid, const char* stmt, Oid intervalPartOid = InvalidOid);
#endif /* TABLECMDS_H */

View File

@ -47,6 +47,9 @@
extern Partition PartitionIdGetPartition(Oid partitionId);
extern void PartitionClose(Partition partition);
extern char* PartitionOidGetName(Oid partOid);
extern Oid PartitionOidGetTablespace(Oid partOid);
/*
* Routines for flushing/rebuilding relcache entries in various scenarios
*/

View File

@ -56,8 +56,7 @@ typedef struct PartitionMap {
#define VALUE_PARTKEYMAXNUM 4
#define INTERVAL_PARTKEYMAXNUM 1
#define PartitionLogicalExist(partitionIdentifier) \
((partitionIdentifier)->partSeq >= 0 && (partitionIdentifier)->partArea != PART_AREA_NONE)
#define PartitionLogicalExist(partitionIdentifier) ((partitionIdentifier)->partSeq >= 0)
#define PartitionPhysicalExist(partitionIdentifier) \
((partitionIdentifier)->partArea != PART_AREA_NONE && ((partitionIdentifier)->fileExist)
@ -98,7 +97,6 @@ extern Oid getRangePartitionOid(Relation relation, Const** partKeyValue, int* pa
extern List* getPartitionBoundaryList(Relation rel, int sequence);
extern Oid partitionKeyValueListGetPartitionOid(Relation rel, List* partKeyValueList, bool topClosed);
extern int getNumberOfRangePartitions(Relation rel);
extern int getNumberOfIntervalPartitions(Relation rel);
extern int getNumberOfPartitions(Relation rel);
extern Const* transformDatum2Const(TupleDesc tupledesc, int16 attnum, Datum datumValue, bool isnull, Const* cnst);

View File

@ -69,6 +69,7 @@ typedef struct RangeElement {
Oid partitionOid; /*the oid of partition*/
int len; /*the length of partition key number*/
Const* boundary[RANGE_PARTKEYMAXNUM]; /*upper bond of partition */
bool isInterval; /* is interval partition */
} RangeElement;
typedef struct IntervalElement {
@ -90,29 +91,13 @@ typedef struct RangePartitionMap {
int2vector* partitionKey; /*partition key*/
Oid* partitionKeyDataType; /*the data type of partition key*/
/*section 1: range partition specific*/
int rangeElementsNum; /*the number of range partition*/
RangeElement* rangeElements; /*array of RangeElement*/
int rangeElementsNum; /*the number of range partition*/
RangeElement* rangeElements; /*array of RangeElement*/
Interval* intervalValue; /* valid for interval partition */
oidvector* intervalTablespace; /* valid for interval partition */
} RangePartitionMap;
/*
* describe partition info of Interval Partitioned-Table
* intervalElements: starting from min existing interval partition, to max existing interval partition.
and holes for un-created between them
* sequenceMap: bitmap representation of intervalElements
*/
typedef struct IntervalPartitionMap {
RangePartitionMap rangePartitionMap;
/*section 2: interval partition specific*/
int intervalElementsNum;
IntervalElement* intervalElements; /*array of IntervalElement, it's bitmap represetation is sequenceMap belowing*/
Datum transitionPoint; /*the low boundary of interval part*/
Datum intervalValue;
int intervalMaxSeq; /*sequence number of last interval element in intervalElements*/
int intervalMinSeq; /*sequence number of first interval element in intervalElements*/
Bitmapset* sequenceMap; /*a bit map represent which interval partition is created*/
bool transitionPointByVal;
bool intervalValuePointByVal;
} IntervalPartitionMap;
bool ValueSatisfyLowBoudary(Const** partKeyValue, RangeElement* partition, Interval* intervalValue, bool topClosed);
#define PartitionkeyTypeGetIntervalType(type) \
do { \
@ -153,29 +138,57 @@ typedef struct IntervalPartitionMap {
do { \
if ((rel)->partMap->type == PART_TYPE_RANGE) { \
(result)->partArea = PART_AREA_RANGE; \
(result)->partitionId = getRangePartitionOid((rel), (keyValue), &((result)->partSeq), topClosed); \
if ((result)->partSeq < 0) { \
(result)->fileExist = false; \
} else { \
(result)->fileExist = true; \
} \
} else if (rel->partMap->type == PART_TYPE_INTERVAL) { \
Assert((valueLen) == 1); \
(result)->partitionId = getIntervalPartitionOid((IntervalPartitionMap*)((rel)->partMap), \
(keyValue), \
&((result)->partSeq), \
&((result)->partArea), \
topClosed, \
missIsOk); \
if (OidIsValid((result)->partitionId)) { \
(result)->fileExist = true; \
} else { \
(result)->fileExist = false; \
} \
(result)->partArea = PART_AREA_INTERVAL; \
} else { \
ereport(ERROR, \
(errcode(ERRCODE_INTERNAL_ERROR), errmsg("Unsupported partition strategy:%d", (rel)->partMap->type))); \
} \
(result)->partitionId = getRangePartitionOid((rel), (keyValue), &((result)->partSeq), topClosed); \
if ((result)->partSeq < 0) { \
(result)->fileExist = false; \
} else { \
(result)->fileExist = true; \
RangePartitionMap* partMap = (RangePartitionMap*)((rel)->partMap); \
if (partMap->rangeElements[(result)->partSeq].isInterval && \
!ValueSatisfyLowBoudary( \
keyValue, &partMap->rangeElements[(result)->partSeq], partMap->intervalValue, topClosed)) { \
(result)->partSeq = -1; \
(result)->partitionId = InvalidOid; \
(result)->fileExist = false; \
} \
} \
} while (0)
/*
* search >/>= keyValue partition if direction is true
* search </<= keyValue partition if direction is false
*/
#define partitionRoutingForValueRange(rel, keyValue, valueLen, topClosed, direction, result) \
do { \
if ((rel)->partMap->type == PART_TYPE_RANGE) { \
(result)->partArea = PART_AREA_RANGE; \
} else if (rel->partMap->type == PART_TYPE_INTERVAL) { \
Assert((valueLen) == 1); \
(result)->partArea = PART_AREA_INTERVAL; \
} else { \
ereport(ERROR, \
(errcode(ERRCODE_INTERNAL_ERROR), errmsg("Unsupported partition strategy:%d", (rel)->partMap->type))); \
} \
(result)->partitionId = getRangePartitionOid((rel), (keyValue), &((result)->partSeq), topClosed); \
if ((result)->partSeq < 0) { \
(result)->fileExist = false; \
} else { \
(result)->fileExist = true; \
RangePartitionMap* partMap = (RangePartitionMap*)((rel)->partMap); \
if (partMap->rangeElements[(result)->partSeq].isInterval && !direction && \
!ValueSatisfyLowBoudary( \
keyValue, &partMap->rangeElements[(result)->partSeq], partMap->intervalValue, topClosed)) { \
--((result)->partSeq); \
(result)->partitionId = partMap->rangeElements[(result)->partSeq].partitionOid; \
} \
} \
} while (0)
typedef enum PruningResultState { PRUNING_RESULT_EMPTY, PRUNING_RESULT_SUBSET, PRUNING_RESULT_FULL } PruningResultState;
@ -338,8 +351,6 @@ extern Oid partIDGetPartOid(Relation relation, PartitionIdentifier* partID);
extern PartitionIdentifier* partOidGetPartID(Relation rel, Oid partOid);
extern void RebuildPartitonMap(PartitionMap* oldMap, PartitionMap* newMap);
extern Oid getIntervalPartitionOid(IntervalPartitionMap* intervalPartMap, Const** partKeyValue, int32* partIndex,
PartitionArea* partArea, bool topClosed, bool missIsOk);
bool isPartKeyValuesInPartition(RangePartitionMap* partMap, Const** partKeyValues, int partkeyColumnNum, int partSeq);
extern int comparePartitionKey(RangePartitionMap* partMap, Const** values1, Const** values2, int partKeyNum);
@ -347,5 +358,10 @@ extern int comparePartitionKey(RangePartitionMap* partMap, Const** values1, Cons
extern int lookupHBucketid(oidvector *buckets, int low, int2 bucket_id);
extern int2 computeTupleBucketId(Relation rel, HeapTuple tuple);
extern Oid GetNeedDegradToRangePartOid(Relation rel, Oid partOid);
extern RangeElement* CopyRangeElementsWithoutBoundary(const RangeElement* src, int elementNum);
extern char* ReadIntervalStr(HeapTuple tuple, TupleDesc tupleDesc);
extern oidvector* ReadIntervalTablespace(HeapTuple tuple, TupleDesc tupleDesc);
#endif /* PARTITIONMAP_GS_H_ */

View File

@ -189,6 +189,7 @@ extern Datum timestamptz_timestamptz(PG_FUNCTION_ARGS);
extern Datum interval_um(PG_FUNCTION_ARGS);
extern Datum interval_pl(PG_FUNCTION_ARGS);
extern Datum interval_mi(PG_FUNCTION_ARGS);
extern Datum interval_mul(Interval* span, float8 factor);
extern Datum interval_mul(PG_FUNCTION_ARGS);
extern Datum mul_d_interval(PG_FUNCTION_ARGS);
extern Datum interval_div(PG_FUNCTION_ARGS);
@ -198,8 +199,11 @@ extern Datum interval_collect(PG_FUNCTION_ARGS);
#endif
extern Datum interval_avg(PG_FUNCTION_ARGS);
extern Datum timestamp_mi(Timestamp dt1, Timestamp dt2);
extern Datum timestamp_mi(PG_FUNCTION_ARGS);
extern Datum timestamp_pl_interval(Timestamp timestamp, Interval* span);
extern Datum timestamp_pl_interval(PG_FUNCTION_ARGS);
extern Datum timestamp_mi_interval(Timestamp timestamp, Interval* span);
extern Datum timestamp_mi_interval(PG_FUNCTION_ARGS);
extern Datum timestamp_age(PG_FUNCTION_ARGS);
extern Datum timestamp_diff(PG_FUNCTION_ARGS);

View File

@ -140,7 +140,7 @@ create index cross_test_table_index on cross_test_table(c1) local;
delete from cross_test_table where c1 = 149;
rollback;
select * from cross_test_table order by 1;
ERROR: relation "cross_test_table" does not exist
ERROR: relation "cross_test_table" does not exist on datanode1
LINE 1: select * from cross_test_table order by 1;
^
--table not exist

View File

@ -0,0 +1,217 @@
--
-- Test exchange operator for interval partitioned table
--
--
---- create interval partitioned table
--
CREATE TABLE interval_normal_exchange (logdate date not null)
PARTITION BY RANGE (logdate)
INTERVAL ('1 month')
(
PARTITION interval_normal_exchange_p1 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_normal_exchange_p2 VALUES LESS THAN ('2020-04-01'),
PARTITION interval_normal_exchange_p3 VALUES LESS THAN ('2020-05-01')
);
-- see about the info of the partitioned table in pg_partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_exchange')
order by relname;
relname | parttype | partstrategy | boundaries
-----------------------------+----------+--------------+--------------
interval_normal_exchange | r | i |
interval_normal_exchange_p1 | p | r | {2020-03-01}
interval_normal_exchange_p2 | p | r | {2020-04-01}
interval_normal_exchange_p3 | p | r | {2020-05-01}
(4 rows)
-- insert the record that is smaller than the lower boundary
insert into interval_normal_exchange values ('2020-02-21');
insert into interval_normal_exchange values ('2020-02-22');
insert into interval_normal_exchange values ('2020-02-23');
insert into interval_normal_exchange values ('2020-5-01');
insert into interval_normal_exchange values ('2020-5-02');
insert into interval_normal_exchange values ('2020-5-03');
-- see about the info of the partitioned table in pg_partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_exchange')
order by relname;
relname | parttype | partstrategy | boundaries
-----------------------------+----------+--------------+------------------------------
interval_normal_exchange | r | i |
interval_normal_exchange_p1 | p | r | {2020-03-01}
interval_normal_exchange_p2 | p | r | {2020-04-01}
interval_normal_exchange_p3 | p | r | {2020-05-01}
sys_p1 | p | i | {"Mon Jun 01 00:00:00 2020"}
(5 rows)
--
---- create to be exchanged table and test range partition exchange
--
CREATE TABLE interval_exchange_test (logdate date not null);
insert into interval_exchange_test values ('2020-02-24');
insert into interval_exchange_test values ('2020-02-25');
insert into interval_exchange_test values ('2020-02-26');
-- do exchange partition interval_normal_exchange_p1 and interval_exchange_test
-- The data they have belongs to the same range.
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test;
select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate;
logdate
--------------------------
Mon Feb 24 00:00:00 2020
Tue Feb 25 00:00:00 2020
Wed Feb 26 00:00:00 2020
(3 rows)
select * from interval_exchange_test order by logdate;
logdate
--------------------------
Fri Feb 21 00:00:00 2020
Sat Feb 22 00:00:00 2020
Sun Feb 23 00:00:00 2020
(3 rows)
-- exchange back
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test;
select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate;
logdate
--------------------------
Fri Feb 21 00:00:00 2020
Sat Feb 22 00:00:00 2020
Sun Feb 23 00:00:00 2020
(3 rows)
select * from interval_exchange_test order by logdate;
logdate
--------------------------
Mon Feb 24 00:00:00 2020
Tue Feb 25 00:00:00 2020
Wed Feb 26 00:00:00 2020
(3 rows)
-- Insert a new record not belongs to interval_normal_exchange_p1
insert into interval_exchange_test values ('2020-3-05');
-- defaut is WITH VALIDATION, and the exchange will be failed
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test;
ERROR: some rows in table do not qualify for specified partition
-- WITHOUT VALIDATION and the exchange will be success, but some date will in the wrong range;
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test WITHOUT VALIDATION;
select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate;
logdate
--------------------------
Mon Feb 24 00:00:00 2020
Tue Feb 25 00:00:00 2020
Wed Feb 26 00:00:00 2020
Thu Mar 05 00:00:00 2020
(4 rows)
select * from interval_exchange_test order by logdate;
logdate
--------------------------
Fri Feb 21 00:00:00 2020
Sat Feb 22 00:00:00 2020
Sun Feb 23 00:00:00 2020
(3 rows)
-- not include '2020-3-05'
select * from interval_normal_exchange where logdate > '2020-03-01' order by logdate;
logdate
--------------------------
Fri May 01 00:00:00 2020
Sat May 02 00:00:00 2020
Sun May 03 00:00:00 2020
(3 rows)
--
---- clean the data and test interval partition exchange
--
truncate table interval_exchange_test;
insert into interval_exchange_test values ('2020-5-04');
insert into interval_exchange_test values ('2020-5-05');
insert into interval_exchange_test values ('2020-5-06');
-- exchange table
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (sys_p1)
WITH TABLE interval_exchange_test;
select * from interval_normal_exchange partition (sys_p1)order by logdate;
logdate
--------------------------
Mon May 04 00:00:00 2020
Tue May 05 00:00:00 2020
Wed May 06 00:00:00 2020
(3 rows)
select * from interval_exchange_test order by logdate;
logdate
--------------------------
Fri May 01 00:00:00 2020
Sat May 02 00:00:00 2020
Sun May 03 00:00:00 2020
(3 rows)
-- exchange back
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (sys_p1)
WITH TABLE interval_exchange_test;
select * from interval_normal_exchange partition (sys_p1)order by logdate;
logdate
--------------------------
Fri May 01 00:00:00 2020
Sat May 02 00:00:00 2020
Sun May 03 00:00:00 2020
(3 rows)
select * from interval_exchange_test order by logdate;
logdate
--------------------------
Mon May 04 00:00:00 2020
Tue May 05 00:00:00 2020
Wed May 06 00:00:00 2020
(3 rows)
insert into interval_exchange_test values ('2020-6-05');
-- defaut is WITH VALIDATION, and the exchange will be failed
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test;
ERROR: some rows in table do not qualify for specified partition
-- WITHOUT VALIDATION and the exchange will be success, but some date will in the wrong range;
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test WITHOUT VALIDATION;
select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate;
logdate
--------------------------
Mon May 04 00:00:00 2020
Tue May 05 00:00:00 2020
Wed May 06 00:00:00 2020
Fri Jun 05 00:00:00 2020
(4 rows)
select * from interval_exchange_test order by logdate;
logdate
--------------------------
Mon Feb 24 00:00:00 2020
Tue Feb 25 00:00:00 2020
Wed Feb 26 00:00:00 2020
Thu Mar 05 00:00:00 2020
(4 rows)
-- not include '2020-6-05'
select * from interval_normal_exchange order by logdate;
logdate
--------------------------
Fri May 01 00:00:00 2020
Sat May 02 00:00:00 2020
Sun May 03 00:00:00 2020
Mon May 04 00:00:00 2020
Tue May 05 00:00:00 2020
Wed May 06 00:00:00 2020
Fri Jun 05 00:00:00 2020
(7 rows)
select * from interval_normal_exchange where logdate > '2020-06-01' order by logdate;
logdate
---------
(0 rows)
drop table interval_normal_exchange;

View File

@ -0,0 +1,426 @@
--
---- test interval partitioned index
--
drop table if exists hw_partition_index_ip;
NOTICE: table "hw_partition_index_ip" does not exist, skipping
create table hw_partition_index_ip
(
c1 int,
c2 int,
logdate date not null
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION hw_partition_index_ip_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION hw_partition_index_ip_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION hw_partition_index_ip_p2 VALUES LESS THAN ('2020-05-01')
);
--succeed
create index ip_index_local1 on hw_partition_index_ip (c1) local;
--succeed
create index ip_index_local2 on hw_partition_index_ip (logdate) local
(
partition,
partition,
partition
);
ERROR: syntax error at or near ","
LINE 3: partition,
^
--fail , the gram.y is not support opt_index_name
create index ip_index_local3 on hw_partition_index_ip (logdate) local
(
partition sip1_index_local,
partition sip2_index_local,
partition sip3_index_local
);
--succeed
create index ip_index_local4 on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--succeed
create index ip_index_local6 on hw_partition_index_ip (logdate) local
(
partition sip1_index_local,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--succeed
create unique index ip_index_local7 on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--succeed
create unique index on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
-- fail same partition name
create unique index on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT
);
ERROR: index partition with name "sip2_index_local" already exists
--
---- expression, only test sample expression for inter1, more info see hw_partition_index.sql
--
create index on hw_partition_index_ip ((c1+c2)) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--succeed
create index on hw_partition_index_ip ((c1-c2)) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--succeed
--not support CONCURRENTLY
create unique index CONCURRENTLY on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
ERROR: PGXC does not support concurrent INDEX yet
DETAIL: The feature is not currently supported
-- Not enough index partition defined
create unique index on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT
);
ERROR: Not enough index partition defined
-- number of partitions of LOCAL index must equal that of the underlying table
create unique index on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT,
partition sip4_index_local tablespace PG_DEFAULT
);
ERROR: number of partitions of LOCAL index must equal that of the underlying table
create unique index on hw_partition_index_ip (logdate);
ERROR: partitioned table does not support global index
--fail wrong syntax
drop table hw_partition_index_ip;
--unique index , index para must contain partition key
create table hw_partition_index_ip
(
c1 int,
c2 int,
logdate date not null
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION hw_partition_index_ip_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION hw_partition_index_ip_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION hw_partition_index_ip_p2 VALUES LESS THAN ('2020-05-01')
);
-- succeed
create unique index ip_index_local on hw_partition_index_ip (c1,logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
-- fail without logdate
create unique index ip_index_local2 on hw_partition_index_ip (c1) local
(
partition sip1_index_local tablespace PG_DEFAULT ,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
ERROR: unique index columns must contain the partition key and collation must be default collation
create unique index ip_index_local3 on hw_partition_index_ip (c2, c1) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
ERROR: unique index columns must contain the partition key and collation must be default collation
--insert into table
insert into hw_partition_index_ip values(7,2,'2020-03-01');
insert into hw_partition_index_ip values(3,1,'2020-04-01');
insert into hw_partition_index_ip values(5,3,'2020-05-01');
insert into hw_partition_index_ip values(7,5,'2020-06-01');
insert into hw_partition_index_ip values(1,4,'2020-07-01');
--succeed
select * from hw_partition_index_ip order by 1, 2;
c1 | c2 | logdate
----+----+--------------------------
1 | 4 | Wed Jul 01 00:00:00 2020
3 | 1 | Wed Apr 01 00:00:00 2020
5 | 3 | Fri May 01 00:00:00 2020
7 | 2 | Sun Mar 01 00:00:00 2020
7 | 5 | Mon Jun 01 00:00:00 2020
(5 rows)
--to select all index object
select part.relname, part.parttype, part.rangenum,
part.intervalnum,
part.partstrategy,
part.relallvisible,
part.reltoastrelid,
part.partkey,
part.interval,
part.boundaries
from pg_class class , pg_partition part , pg_index ind where class.relname = 'hw_partition_index_ip' and ind.indrelid = class.oid and part.parentid = ind.indexrelid order by 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
relname | parttype | rangenum | intervalnum | partstrategy | relallvisible | reltoastrelid | partkey | interval | boundaries
-----------------------+----------+----------+-------------+--------------+---------------+---------------+---------+----------+------------
sip1_index_local | x | 0 | 0 | n | 0 | 0 | | |
sip2_index_local | x | 0 | 0 | n | 0 | 0 | | |
sip3_index_local | x | 0 | 0 | n | 0 | 0 | | |
sys_p1_c1_logdate_idx | x | 0 | 0 | n | 0 | 0 | | |
sys_p2_c1_logdate_idx | x | 0 | 0 | n | 0 | 0 | | |
sys_p3_c1_logdate_idx | x | 0 | 0 | n | 0 | 0 | | |
(6 rows)
drop index ip_index_local;
drop table if exists hw_partition_index_ip;
select count(*) from pg_class class , pg_partition part , pg_index ind where class.relname = 'hw_partition_index_ip' and ind.indrelid = class.oid and part.parentid = ind.indexrelid;
count
-------
0
(1 row)
--
---- test input for unique index
--
create table interval_partition_table_001
(
c1 int,
logdate date not null
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION interval_partition_table_001_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_partition_table_001_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION interval_partition_table_001_p2 VALUES LESS THAN ('2020-05-01')
);
create unique index index_interval_partition_table_001 on interval_partition_table_001(logdate) local;
--fail: unique index
insert into interval_partition_table_001 values(10, '2020-06-01');
insert into interval_partition_table_001 values(10, '2020-06-01');
ERROR: duplicate key value violates unique constraint "index_interval_partition_table_001"
DETAIL: Key (logdate)=(Mon Jun 01 00:00:00 2020) already exists.
analyze interval_partition_table_001;
drop table interval_partition_table_001;
--
---- test with primary key
--
create table interval_partition_table_002(
c1 int,
c2 int,
logdate date not null,
CONSTRAINT interval_partition_table_CONSTRAINT PRIMARY KEY(c2,logdate)
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION interval_partition_table_002_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_partition_table_002_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION interval_partition_table_002_p2 VALUES LESS THAN ('2020-05-01')
);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "interval_partition_table_constraint" for table "interval_partition_table_002"
insert into interval_partition_table_002 values(10, 10, '2020-06-01');
insert into interval_partition_table_002 values(10, 10, '2020-06-01');
ERROR: duplicate key value violates unique constraint "interval_partition_table_constraint"
DETAIL: Key (c2, logdate)=(10, Mon Jun 01 00:00:00 2020) already exists.
analyze interval_partition_table_002;
drop table interval_partition_table_002;
--
---- test with hash index, not support hash index yet;
--
create table interval_partition_table_003(
c1 int,
c2 int,
logdate date not null,
PRIMARY KEY(c2,logdate)
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION interval_partition_table_003_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_partition_table_003_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION interval_partition_table_003_p2 VALUES LESS THAN ('2020-05-01')
);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "interval_partition_table_003_pkey" for table "interval_partition_table_003"
create index interval_partition_table_003_1 ON interval_partition_table_003 USING HASH (logdate) LOCAL;
ERROR: access method "hash" does not support row store
create index interval_partition_table_003_2 ON interval_partition_table_003 USING HASH (c2) LOCAL;
ERROR: access method "hash" does not support row store
create index interval_partition_table_003_3 ON interval_partition_table_003 USING HASH (c1) LOCAL;
ERROR: access method "hash" does not support row store
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_1') order by 1;
relname
---------
(0 rows)
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_2') order by 1;
relname
---------
(0 rows)
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_3') order by 1;
relname
---------
(0 rows)
insert into interval_partition_table_003 values(1,2,'2020-03-01');
insert into interval_partition_table_003 values(1,2,'2020-04-01');
insert into interval_partition_table_003 values(1,2,'2020-05-01');
insert into interval_partition_table_003 values(1,2,'2020-06-01');
insert into interval_partition_table_003 values(1,2,'2020-07-01');
alter table interval_partition_table_003 drop column C2;
insert into interval_partition_table_003 values(1,2,'2020-07-01');
ERROR: INSERT has more expressions than target columns
LINE 1: ...sert into interval_partition_table_003 values(1,2,'2020-07-0...
^
insert into interval_partition_table_003 values(1,'2020-07-01');
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_1') order by 1;
relname
---------
(0 rows)
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_2') order by 1;
relname
---------
(0 rows)
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_3') order by 1;
relname
---------
(0 rows)
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_partition_table_003')
order by relname;
relname | parttype | partstrategy | boundaries
---------------------------------+----------+--------------+------------------------------
interval_partition_table_003 | r | i |
interval_partition_table_003_p0 | p | r | {2020-03-01}
interval_partition_table_003_p1 | p | r | {2020-04-01}
interval_partition_table_003_p2 | p | r | {2020-05-01}
sys_p1 | p | i | {"Mon Jun 01 00:00:00 2020"}
sys_p2 | p | i | {"Wed Jul 01 00:00:00 2020"}
sys_p3 | p | i | {"Sat Aug 01 00:00:00 2020"}
(7 rows)
analyze interval_partition_table_003;
drop table interval_partition_table_003;
--
---- test partition BTREE index
--
create table interval_partition_table_004(
c1 int,
c2 int,
logdate date not null,
PRIMARY KEY(c2,logdate)
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION interval_partition_table_004_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_partition_table_004_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION interval_partition_table_004_p2 VALUES LESS THAN ('2020-05-01')
);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "interval_partition_table_004_pkey" for table "interval_partition_table_004"
-- expression index
CREATE INDEX interval_partition_table_004_index_01 on interval_partition_table_004 using btree(c2) local;
CREATE INDEX interval_partition_table_004_index_02 on interval_partition_table_004 using btree(logdate) local;
CREATE INDEX interval_partition_table_004_index_03 on interval_partition_table_004 using btree(c1) local;
insert into interval_partition_table_004 values(7,2,'2020-03-01');
insert into interval_partition_table_004 values(3,1,'2020-04-01');
insert into interval_partition_table_004 values(5,3,'2020-05-01');
insert into interval_partition_table_004 values(7,5,'2020-06-01');
insert into interval_partition_table_004 values(1,4,'2020-07-01');
SELECT * FROM interval_partition_table_004 ORDER BY logdate;
c1 | c2 | logdate
----+----+--------------------------
7 | 2 | Sun Mar 01 00:00:00 2020
3 | 1 | Wed Apr 01 00:00:00 2020
5 | 3 | Fri May 01 00:00:00 2020
7 | 5 | Mon Jun 01 00:00:00 2020
1 | 4 | Wed Jul 01 00:00:00 2020
(5 rows)
SELECT * FROM interval_partition_table_004 ORDER BY 1;
c1 | c2 | logdate
----+----+--------------------------
1 | 4 | Wed Jul 01 00:00:00 2020
3 | 1 | Wed Apr 01 00:00:00 2020
5 | 3 | Fri May 01 00:00:00 2020
7 | 2 | Sun Mar 01 00:00:00 2020
7 | 5 | Mon Jun 01 00:00:00 2020
(5 rows)
SELECT * FROM interval_partition_table_004 ORDER BY 2;
c1 | c2 | logdate
----+----+--------------------------
3 | 1 | Wed Apr 01 00:00:00 2020
7 | 2 | Sun Mar 01 00:00:00 2020
5 | 3 | Fri May 01 00:00:00 2020
1 | 4 | Wed Jul 01 00:00:00 2020
7 | 5 | Mon Jun 01 00:00:00 2020
(5 rows)
DROP TABLE interval_partition_table_004;
-- test interval table with toast table and index
CREATE TABLE interval_sales
(prod_id NUMBER(6),
cust_id NUMBER,
time_id DATE,
channel_id CHAR(1),
promo_id NUMBER(6),
quantity_sold NUMBER(3),
amount_sold NUMBER(10,2)
)
PARTITION BY RANGE (time_id)
INTERVAL('1 MONTH')
( PARTITION p0 VALUES LESS THAN (TO_DATE('1-1-2008', 'DD-MM-YYYY')),
PARTITION p1 VALUES LESS THAN (TO_DATE('6-5-2008', 'DD-MM-YYYY'))
);
select relname, parentid, reltoastrelid, boundaries from pg_partition;
relname | parentid | reltoastrelid | boundaries
----------------+----------+---------------+------------------------------
interval_sales | 19348 | 0 |
p0 | 19348 | 19354 | {"Tue Jan 01 00:00:00 2008"}
p1 | 19348 | 19357 | {"Tue May 06 00:00:00 2008"}
(3 rows)
insert into interval_sales values (generate_series(1,10), generate_series(1,10), generate_series(TO_DATE('2020-01-01', 'YYYY-MM-DD'),TO_DATE('2020-07-01', 'YYYY-MM-DD'),'1 day'), 1, 1, 1, 1);
select relname, parentid, reltoastrelid, boundaries from pg_partition;
relname | parentid | reltoastrelid | boundaries
----------------+----------+---------------+------------------------------
interval_sales | 19348 | 0 |
p0 | 19348 | 19354 | {"Tue Jan 01 00:00:00 2008"}
p1 | 19348 | 19357 | {"Tue May 06 00:00:00 2008"}
sys_p1 | 19348 | 19361 | {"Mon Jan 06 00:00:00 2020"}
sys_p2 | 19348 | 19365 | {"Thu Feb 06 00:00:00 2020"}
sys_p3 | 19348 | 19369 | {"Fri Mar 06 00:00:00 2020"}
sys_p4 | 19348 | 19373 | {"Mon Apr 06 00:00:00 2020"}
sys_p5 | 19348 | 19377 | {"Wed May 06 00:00:00 2020"}
sys_p6 | 19348 | 19381 | {"Sat Jun 06 00:00:00 2020"}
sys_p7 | 19348 | 19385 | {"Mon Jul 06 00:00:00 2020"}
(10 rows)
drop table interval_sales;
--
---- test exchange table whit index
--

View File

@ -0,0 +1,106 @@
--
---- test row movement
--
drop table if exists hw_partition_interval_movement;
NOTICE: table "hw_partition_interval_movement" does not exist, skipping
create table hw_partition_interval_movement
(
c1 int,
c2 int,
C3 date not null
)
partition by range (C3)
INTERVAL ('1 month')
(
PARTITION hw_partition_interval_movement_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION hw_partition_interval_movement_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION hw_partition_interval_movement_p2 VALUES LESS THAN ('2020-05-01')
) DISABLE ROW MOVEMENT;
create index hw_partition_interval_movement_ind1 on hw_partition_interval_movement(c1) local;
create index hw_partition_interval_movement_ind2 on hw_partition_interval_movement(c2) local;
create index hw_partition_interval_movement_ind3 on hw_partition_interval_movement(c3) local;
--insert into table
insert into hw_partition_interval_movement values(7,2,'2020-02-01');
insert into hw_partition_interval_movement values(3,1,'2020-03-01');
insert into hw_partition_interval_movement values(5,3,'2020-04-01');
insert into hw_partition_interval_movement values(7,5,'2020-05-01');
insert into hw_partition_interval_movement values(1,4,'2020-06-01');
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'hw_partition_interval_movement')
order by 1;
relname | parttype | partstrategy | boundaries
-----------------------------------+----------+--------------+------------------------------
hw_partition_interval_movement | r | i |
hw_partition_interval_movement_p0 | p | r | {2020-03-01}
hw_partition_interval_movement_p1 | p | r | {2020-04-01}
hw_partition_interval_movement_p2 | p | r | {2020-05-01}
sys_p1 | p | i | {"Mon Jun 01 00:00:00 2020"}
sys_p2 | p | i | {"Wed Jul 01 00:00:00 2020"}
(6 rows)
-- fail: update record belongs to a range partition which will be move to other range partition
update hw_partition_interval_movement set C3 = '2020-04-22' where C3 = '2020-03-01';
ERROR: fail to update partitioned table "hw_partition_interval_movement"
DETAIL: disable row movement
-- fail: update record belongs to a range partition which will be move to an existed interval partition
update hw_partition_interval_movement set C3 = '2020-05-22' where C3 = '2020-03-01';
ERROR: fail to update partitioned table "hw_partition_interval_movement"
DETAIL: disable row movement
-- fail: update record belongs to a range partition which will be move to a not existed interval partition
update hw_partition_interval_movement set C3 = '2020-07-22' where C3 = '2020-03-01';
ERROR: fail to update partitioned table "hw_partition_interval_movement"
DETAIL: disable row movement
-- fail: update record belongs to a interval partition which will be move to a range partition
update hw_partition_interval_movement set C3 = '2020-03-22' where C3 = '2020-05-01';
ERROR: fail to update partitioned table "hw_partition_interval_movement"
DETAIL: disable row movement
-- fail: update record belongs to a interval partition which will be move to a not existed interval partition
update hw_partition_interval_movement set C3 = '2020-07-22' where C3 = '2020-05-01';
ERROR: fail to update partitioned table "hw_partition_interval_movement"
DETAIL: disable row movement
-- enable row movement
alter table hw_partition_interval_movement ENABLE ROW MOVEMENT;
-- succeed: update record belongs to a range partition which will be move to other range partition
update hw_partition_interval_movement set C3 = '2020-04-22' where C3 = '2020-03-01';
-- succeed: update record belongs to a range partition which will be move to an existed interval partition
update hw_partition_interval_movement set C3 = '2020-05-22' where C3 = '2020-04-22';
-- succeed: update record belongs to a range partition which will be move to a not existed interval partition
update hw_partition_interval_movement set C3 = '2020-07-22' where C3 = '2020-04-01';
-- succeed: update record belongs to a interval partition which will be move to a range partition
update hw_partition_interval_movement set C3 = '2020-03-22' where C3 = '2020-05-01';
-- succeed: update record belongs to a interval partition which will be move to a not existed interval partition
update hw_partition_interval_movement set C3 = '2020-08-22' where C3 = '2020-06-01';
select * from hw_partition_interval_movement;
c1 | c2 | c3
----+----+--------------------------
7 | 2 | Sat Feb 01 00:00:00 2020
7 | 5 | Sun Mar 22 00:00:00 2020
3 | 1 | Fri May 22 00:00:00 2020
5 | 3 | Wed Jul 22 00:00:00 2020
1 | 4 | Sat Aug 22 00:00:00 2020
(5 rows)
-- add two new interval ranges
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'hw_partition_interval_movement')
order by 1;
relname | parttype | partstrategy | boundaries
-----------------------------------+----------+--------------+------------------------------
hw_partition_interval_movement | r | i |
hw_partition_interval_movement_p0 | p | r | {2020-03-01}
hw_partition_interval_movement_p1 | p | r | {2020-04-01}
hw_partition_interval_movement_p2 | p | r | {2020-05-01}
sys_p1 | p | i | {"Mon Jun 01 00:00:00 2020"}
sys_p2 | p | i | {"Wed Jul 01 00:00:00 2020"}
sys_p3 | p | i | {"Sat Aug 01 00:00:00 2020"}
sys_p4 | p | i | {"Tue Sep 01 00:00:00 2020"}
(8 rows)
drop table hw_partition_interval_movement;

View File

@ -0,0 +1,25 @@
-- check results and clean
select count(*) from partition_interval_parallel;
count
-------
10500
(1 row)
select relname, parttype, partstrategy, boundaries, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'partition_interval_parallel')
order by 1;
relname | parttype | partstrategy | boundaries | indisusable
--------------------------------+----------+--------------+------------------------------+-------------
partition_interval_parallel | r | i | | t
partition_interval_parallel_p1 | p | r | {2020-05-01} | t
partition_interval_parallel_p2 | p | r | {2020-06-01} | t
sys_p1 | p | i | {"Wed Jul 01 00:00:00 2020"} | t
sys_p2 | p | i | {"Sat Aug 01 00:00:00 2020"} | t
sys_p3 | p | i | {"Tue Sep 01 00:00:00 2020"} | t
sys_p4 | p | i | {"Thu Oct 01 00:00:00 2020"} | t
sys_p5 | p | i | {"Sun Nov 01 00:00:00 2020"} | t
sys_p6 | p | i | {"Tue Dec 01 00:00:00 2020"} | t
(9 rows)
--cleanup
DROP TABLE partition_interval_parallel;

View File

@ -0,0 +1,58 @@
--insert data
create or replace function insert_mm(dat text) returns void as $$
declare
times integer :=1;
begin
loop
insert into partition_interval_parallel values(1, 1, dat);
times = times + 1;
if times > 500 then
exit;
end if;
end loop;
end;
$$ language plpgsql;
select insert_mm('2020-05-1');
insert_mm
-----------
(1 row)
select insert_mm('2020-06-1');
insert_mm
-----------
(1 row)
select insert_mm('2020-07-1');
insert_mm
-----------
(1 row)
select insert_mm('2020-08-1');
insert_mm
-----------
(1 row)
select insert_mm('2020-09-1');
insert_mm
-----------
(1 row)
select insert_mm('2020-10-1');
insert_mm
-----------
(1 row)
select insert_mm('2020-11-1');
insert_mm
-----------
(1 row)

View File

@ -0,0 +1,56 @@
--insert data
create or replace function insert_mm_01(dat text) returns void as $$
declare
times integer :=1;
begin
loop
insert into partition_interval_parallel values(1, 1, dat);
times = times + 1;
if times > 500 then
exit;
end if;
end loop;
end;
$$ language plpgsql;
select insert_mm_01('2020-05-1');
insert_mm_01
--------------
(1 row)
select insert_mm_01('2020-06-1');
insert_mm_01
--------------
(1 row)
select insert_mm_01('2020-07-1');
insert_mm_01
--------------
(1 row)
select insert_mm_01('2020-08-1');
insert_mm_01
--------------
(1 row)
select insert_mm_01('2020-09-1');
insert_mm_01
--------------
(1 row)
select insert_mm_01('2020-10-1');
insert_mm_01
--------------
(1 row)
select insert_mm_01('2020-11-1');
insert_mm_01
--------------
(1 row)

View File

@ -0,0 +1,56 @@
--insert data
create or replace function insert_mm_02(dat text) returns void as $$
declare
times integer :=1;
begin
loop
insert into partition_interval_parallel values(1, 1, dat);
times = times + 1;
if times > 500 then
exit;
end if;
end loop;
end;
$$ language plpgsql;
select insert_mm_02('2020-05-1');
insert_mm_02
--------------
(1 row)
select insert_mm_02('2020-06-1');
insert_mm_02
--------------
(1 row)
select insert_mm_02('2020-07-1');
insert_mm_02
--------------
(1 row)
select insert_mm_02('2020-08-1');
insert_mm_02
--------------
(1 row)
select insert_mm_02('2020-09-1');
insert_mm_02
--------------
(1 row)
select insert_mm_02('2020-10-1');
insert_mm_02
--------------
(1 row)
select insert_mm_02('2020-11-1');
insert_mm_02
--------------
(1 row)

View File

@ -0,0 +1,21 @@
-- prepare the parrallel modifed table;
DROP TABLE IF EXISTS partition_interval_parallel;
NOTICE: table "partition_interval_parallel" does not exist, skipping
create table partition_interval_parallel
(
c1 int,
c2 int,
c3 date not null
)
partition by range (c3)
INTERVAL ('1 month')
(
PARTITION partition_interval_parallel_p1 VALUES LESS THAN ('2020-05-01'),
PARTITION partition_interval_parallel_p2 VALUES LESS THAN ('2020-06-01')
);
CREATE INDEX idx1_partition_interval_parallel on partition_interval_parallel(c3) local ;

View File

@ -0,0 +1,168 @@
--01--------------------------------------------------------------------
--prepare table , index
drop table if exists partition_reindex_table3;
NOTICE: table "partition_reindex_table3" does not exist, skipping
create table partition_reindex_table3
(
c1 int,
c2 int,
C3 date not null
)
partition by range (C3)
INTERVAL ('1 month')
(
PARTITION partition_reindex_table3_p0 VALUES LESS THAN ('2020-02-01'),
PARTITION partition_reindex_table3_p1 VALUES LESS THAN ('2020-05-01'),
PARTITION partition_reindex_table3_p2 VALUES LESS THAN ('2020-06-01')
)
enable row movement;
create index partition_reindex_table3_ind1 on partition_reindex_table3(c1) local;
create index partition_reindex_table3_ind2 on partition_reindex_table3(c2) local;
create index partition_reindex_table3_ind3 on partition_reindex_table3(c3) local;
--02--------------------------------------------------------------------
--reindex index, cross test with insert
insert into partition_reindex_table3 values (generate_series(1,10), generate_series(1,10), generate_series(TO_DATE('2020-01-01', 'YYYY-MM-DD'),TO_DATE('2020-07-01', 'YYYY-MM-DD'),'1, day'));
select count(*) from partition_reindex_table3;
count
-------
1830
(1 row)
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'partition_reindex_table3')
order by 1;
relname | parttype | partstrategy | boundaries
-----------------------------+----------+--------------+------------------------------
partition_reindex_table3 | r | i |
partition_reindex_table3_p0 | p | r | {2020-02-01}
partition_reindex_table3_p1 | p | r | {2020-05-01}
partition_reindex_table3_p2 | p | r | {2020-06-01}
sys_p1 | p | i | {"Wed Jul 01 00:00:00 2020"}
sys_p2 | p | i | {"Sat Aug 01 00:00:00 2020"}
(6 rows)
truncate table partition_reindex_table3;
insert into partition_reindex_table3 values (generate_series(1,10), generate_series(1,10), generate_series(TO_DATE('2020-01-01', 'YYYY-MM-DD'),TO_DATE('2020-07-01', 'YYYY-MM-DD'),'1, day'));
select count(*) from partition_reindex_table3;
count
-------
1830
(1 row)
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'partition_reindex_table3')
order by 1;
relname | parttype | partstrategy | boundaries
-----------------------------+----------+--------------+------------------------------
partition_reindex_table3 | r | i |
partition_reindex_table3_p0 | p | r | {2020-02-01}
partition_reindex_table3_p1 | p | r | {2020-05-01}
partition_reindex_table3_p2 | p | r | {2020-06-01}
sys_p1 | p | i | {"Wed Jul 01 00:00:00 2020"}
sys_p2 | p | i | {"Sat Aug 01 00:00:00 2020"}
(6 rows)
analyze partition_reindex_table3;
select c.relname,c.relpages > 0 as relpagesgtzero, c.reltuples > 0 as reltuplesgtzero,i.indisunique, i.indisvalid, i.indcheckxmin, i.indisready from pg_index i, pg_class c where c.relname = 'partition_reindex_table3_ind1' and c.oid = i.indexrelid;
relname | relpagesgtzero | reltuplesgtzero | indisunique | indisvalid | indcheckxmin | indisready
-------------------------------+----------------+-----------------+-------------+------------+--------------+------------
partition_reindex_table3_ind1 | t | t | f | t | f | t
(1 row)
explain (costs off, nodes off) select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
QUERY PLAN
----------------------------------------------------------------------------------------------
Partition Iterator
Iterations: 1
-> Partitioned Index Scan using partition_reindex_table3_ind3 on partition_reindex_table3
Index Cond: (c3 = to_date('2020-04-21'::text, 'YYYY-MM-DD'::text))
Filter: (c2 = 8)
Selected Partitions: 2
(6 rows)
select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
c1 | c2 | c3
----+----+--------------------------
8 | 8 | Tue Apr 21 00:00:00 2020
(1 row)
reindex index partition_reindex_table3_ind1;
select c.relname,c.relpages > 0 as relpagesgtzero, c.reltuples > 0 as reltuplesgtzero,i.indisunique, i.indisvalid, i.indcheckxmin, i.indisready from pg_index i, pg_class c where c.relname = 'partition_reindex_table3_ind1' and c.oid = i.indexrelid;
relname | relpagesgtzero | reltuplesgtzero | indisunique | indisvalid | indcheckxmin | indisready
-------------------------------+----------------+-----------------+-------------+------------+--------------+------------
partition_reindex_table3_ind1 | t | t | f | t | f | t
(1 row)
explain (costs off, nodes off) select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
QUERY PLAN
----------------------------------------------------------------------------------------------
Partition Iterator
Iterations: 1
-> Partitioned Index Scan using partition_reindex_table3_ind3 on partition_reindex_table3
Index Cond: (c3 = to_date('2020-04-21'::text, 'YYYY-MM-DD'::text))
Filter: (c2 = 8)
Selected Partitions: 2
(6 rows)
--the plan before reindex and after reindex should be same
select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
c1 | c2 | c3
----+----+--------------------------
8 | 8 | Tue Apr 21 00:00:00 2020
(1 row)
--03--------------------------------------------------------------------
--reindex table cross test with truncate
truncate table partition_reindex_table3;
insert into partition_reindex_table3 values (generate_series(1,10), generate_series(1,10), generate_series(TO_DATE('2020-01-01', 'YYYY-MM-DD'),TO_DATE('2020-07-01', 'YYYY-MM-DD'),'1, day'));
analyze partition_reindex_table3;
select c.relname,c.relpages > 0 as relpagesgtzero, c.reltuples > 0 as reltuplesgtzero,i.indisunique, i.indisvalid, i.indcheckxmin, i.indisready from pg_index i, pg_class c where c.relname = 'partition_reindex_table3_ind1' and c.oid = i.indexrelid;
relname | relpagesgtzero | reltuplesgtzero | indisunique | indisvalid | indcheckxmin | indisready
-------------------------------+----------------+-----------------+-------------+------------+--------------+------------
partition_reindex_table3_ind1 | t | t | f | t | f | t
(1 row)
explain (costs off, nodes off) select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
QUERY PLAN
----------------------------------------------------------------------------------------------
Partition Iterator
Iterations: 1
-> Partitioned Index Scan using partition_reindex_table3_ind3 on partition_reindex_table3
Index Cond: (c3 = to_date('2020-04-21'::text, 'YYYY-MM-DD'::text))
Filter: (c2 = 8)
Selected Partitions: 2
(6 rows)
select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
c1 | c2 | c3
----+----+--------------------------
8 | 8 | Tue Apr 21 00:00:00 2020
(1 row)
reindex index partition_reindex_table3_ind1;
select c.relname,c.relpages > 0 as relpagesgtzero, c.reltuples > 0 as reltuplesgtzero,i.indisunique, i.indisvalid, i.indcheckxmin, i.indisready from pg_index i, pg_class c where c.relname = 'partition_reindex_table3_ind1' and c.oid = i.indexrelid;
relname | relpagesgtzero | reltuplesgtzero | indisunique | indisvalid | indcheckxmin | indisready
-------------------------------+----------------+-----------------+-------------+------------+--------------+------------
partition_reindex_table3_ind1 | t | t | f | t | f | t
(1 row)
explain (costs off, nodes off) select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
QUERY PLAN
----------------------------------------------------------------------------------------------
Partition Iterator
Iterations: 1
-> Partitioned Index Scan using partition_reindex_table3_ind3 on partition_reindex_table3
Index Cond: (c3 = to_date('2020-04-21'::text, 'YYYY-MM-DD'::text))
Filter: (c2 = 8)
Selected Partitions: 2
(6 rows)
--the plan before reindex and after reindex should be same
select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
c1 | c2 | c3
----+----+--------------------------
8 | 8 | Tue Apr 21 00:00:00 2020
(1 row)
--clean
drop table partition_reindex_table3;

View File

@ -0,0 +1,145 @@
CREATE TABLE interval_tab1 (
city_id int not null,
logdate date not null,
peaktemp int,
unitsales int
)
PARTITION BY RANGE (logdate)
INTERVAL ('1 day')
(
PARTITION p1 VALUES LESS THAN (('2020-03-01'))
);
insert into interval_tab1 values(1,'2020-4-7 2:0:0', 1, 1);
insert into interval_tab1 values(1,'2020-4-8 2:0:0', 1, 1);
select relname, boundaries from pg_partition;
relname | boundaries
---------------+------------------------------
interval_tab1 |
p1 | {2020-03-01}
sys_p1 | {"Wed Apr 08 00:00:00 2020"}
sys_p2 | {"Thu Apr 09 00:00:00 2020"}
(4 rows)
select * from interval_tab1 where logdate < '2020-4-7 0:0:0';
city_id | logdate | peaktemp | unitsales
---------+---------+----------+-----------
(0 rows)
explain (costs off, verbose on, nodes off) select * from interval_tab1 where logdate < '2020-4-7 0:0:0';
QUERY PLAN
---------------------------------------------------------------------------------------------------
Partition Iterator
Output: city_id, logdate, peaktemp, unitsales
Iterations: 1
-> Partitioned Seq Scan on public.interval_tab1
Output: city_id, logdate, peaktemp, unitsales
Filter: (interval_tab1.logdate < 'Tue Apr 07 00:00:00 2020'::timestamp without time zone)
Selected Partitions: 1
(7 rows)
select * from interval_tab1 where logdate > '2020-4-6';
city_id | logdate | peaktemp | unitsales
---------+--------------------------+----------+-----------
1 | Tue Apr 07 02:00:00 2020 | 1 | 1
1 | Wed Apr 08 02:00:00 2020 | 1 | 1
(2 rows)
explain (costs off, verbose on, nodes off) select * from interval_tab1 where logdate > '2020-4-6';
QUERY PLAN
---------------------------------------------------------------------------------------------------
Partition Iterator
Output: city_id, logdate, peaktemp, unitsales
Iterations: 2
-> Partitioned Seq Scan on public.interval_tab1
Output: city_id, logdate, peaktemp, unitsales
Filter: (interval_tab1.logdate > 'Mon Apr 06 00:00:00 2020'::timestamp without time zone)
Selected Partitions: 2..3
(7 rows)
select * from interval_tab1 where logdate = '2020-4-7 2:0:0';
city_id | logdate | peaktemp | unitsales
---------+--------------------------+----------+-----------
1 | Tue Apr 07 02:00:00 2020 | 1 | 1
(1 row)
insert into interval_tab1 values(1,'2020-4-7 0:0:0', 1, 1);
select * from interval_tab1 where logdate = '2020-4-7 0:0:0';
city_id | logdate | peaktemp | unitsales
---------+--------------------------+----------+-----------
1 | Tue Apr 07 00:00:00 2020 | 1 | 1
(1 row)
select * from interval_tab1 where logdate != '2020-4-7 0:0:0';
city_id | logdate | peaktemp | unitsales
---------+--------------------------+----------+-----------
1 | Tue Apr 07 02:00:00 2020 | 1 | 1
1 | Wed Apr 08 02:00:00 2020 | 1 | 1
(2 rows)
select * from interval_tab1 where logdate >= '2020-4-7 0:0:0';
city_id | logdate | peaktemp | unitsales
---------+--------------------------+----------+-----------
1 | Tue Apr 07 02:00:00 2020 | 1 | 1
1 | Tue Apr 07 00:00:00 2020 | 1 | 1
1 | Wed Apr 08 02:00:00 2020 | 1 | 1
(3 rows)
insert into interval_tab1 values(1,'2020-4-5 2:0:0', 1, 1);
select relname, boundaries from pg_partition;
relname | boundaries
---------------+------------------------------
interval_tab1 |
p1 | {2020-03-01}
sys_p1 | {"Wed Apr 08 00:00:00 2020"}
sys_p2 | {"Thu Apr 09 00:00:00 2020"}
sys_p3 | {"Mon Apr 06 00:00:00 2020"}
(5 rows)
insert into interval_tab1 values(1,'2020-4-9 0:0:0', 1, 1);
select * from interval_tab1 where logdate >= '2020-4-7 0:0:0' and logdate < '2020-4-9 0:0:0';
city_id | logdate | peaktemp | unitsales
---------+--------------------------+----------+-----------
1 | Tue Apr 07 02:00:00 2020 | 1 | 1
1 | Tue Apr 07 00:00:00 2020 | 1 | 1
1 | Wed Apr 08 02:00:00 2020 | 1 | 1
(3 rows)
select * from interval_tab1 where logdate > '2020-4-7 0:0:0' and logdate <= '2020-4-9 0:0:0';
city_id | logdate | peaktemp | unitsales
---------+--------------------------+----------+-----------
1 | Tue Apr 07 02:00:00 2020 | 1 | 1
1 | Wed Apr 08 02:00:00 2020 | 1 | 1
1 | Thu Apr 09 00:00:00 2020 | 1 | 1
(3 rows)
select * from interval_tab1 where logdate >= '2020-4-7 0:0:0' and logdate <= '2020-4-9 0:0:0';
city_id | logdate | peaktemp | unitsales
---------+--------------------------+----------+-----------
1 | Tue Apr 07 02:00:00 2020 | 1 | 1
1 | Tue Apr 07 00:00:00 2020 | 1 | 1
1 | Wed Apr 08 02:00:00 2020 | 1 | 1
1 | Thu Apr 09 00:00:00 2020 | 1 | 1
(4 rows)
select * from interval_tab1 where logdate > '2020-4-6 0:0:0' and logdate <= '2020-4-9 0:0:0';
city_id | logdate | peaktemp | unitsales
---------+--------------------------+----------+-----------
1 | Tue Apr 07 02:00:00 2020 | 1 | 1
1 | Tue Apr 07 00:00:00 2020 | 1 | 1
1 | Wed Apr 08 02:00:00 2020 | 1 | 1
1 | Thu Apr 09 00:00:00 2020 | 1 | 1
(4 rows)
explain (costs off, verbose on, nodes off) select * from interval_tab1 where logdate >= '2020-4-10 0:0:0';
QUERY PLAN
----------------------------------------------------------------------------------------------------
Partition Iterator
Output: city_id, logdate, peaktemp, unitsales
Iterations: 0
-> Partitioned Seq Scan on public.interval_tab1
Output: city_id, logdate, peaktemp, unitsales
Filter: (interval_tab1.logdate >= 'Fri Apr 10 00:00:00 2020'::timestamp without time zone)
Selected Partitions: NONE
(7 rows)
drop table interval_tab1;

View File

@ -0,0 +1,409 @@
--create table
DROP TABLE IF EXISTS partition_unsable_index_1;
NOTICE: table "partition_unsable_index_1" does not exist, skipping
create table partition_unsable_index_1
(
c1 int,
c2 int,
c3 date not null
)
partition by range (c3)
INTERVAL ('1 month')
(
PARTITION partition_unsable_index_1_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION partition_unsable_index_1_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION partition_unsable_index_1_p2 VALUES LESS THAN ('2020-05-01')
);
-- create 3 indexes, and specify it's partition name
CREATE INDEX idx1_partition_unsable_index_1 on partition_unsable_index_1(c3) local
(
partition idx1_partition_unsable_index_1_p1,
partition idx1_partition_unsable_index_1_p2,
partition idx1_partition_unsable_index_1_p3
);
CREATE INDEX idx2_partition_unsable_index_1 on partition_unsable_index_1(c2, c3) local
(
partition idx2_partition_unsable_index_1_p1,
partition idx2_partition_unsable_index_1_p2,
partition idx2_partition_unsable_index_1_p3
);
CREATE INDEX idx3_partition_unsable_index_1 on partition_unsable_index_1(c1, c2, c3) local
(
partition idx3_partition_unsable_index_1_p1,
partition idx3_partition_unsable_index_1_p2,
partition idx3_partition_unsable_index_1_p3
);
--insert data
insert into partition_unsable_index_1 values(7,2,'2020-03-01');
insert into partition_unsable_index_1 values(3,1,'2020-04-01');
insert into partition_unsable_index_1 values(5,3,'2020-05-01');
insert into partition_unsable_index_1 values(7,5,'2020-06-01');
insert into partition_unsable_index_1 values(1,4,'2020-07-01');
-- query all index partitions
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by relname;
relname | parttype | partstrategy | indisusable
-----------------------------------+----------+--------------+-------------
idx1_partition_unsable_index_1_p1 | x | n | t
idx1_partition_unsable_index_1_p2 | x | n | t
idx1_partition_unsable_index_1_p3 | x | n | t
sys_p1_c3_idx | x | n | t
sys_p2_c3_idx | x | n | t
sys_p3_c3_idx | x | n | t
(6 rows)
-- 1. alter index, modify one of it's partition to unusable state
ALTER INDEX idx1_partition_unsable_index_1 MODIFY PARTITION idx1_partition_unsable_index_1_p1 UNUSABLE;
-- check indunusable info
select relname, parttype, partstrategy, boundaries, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
relname | parttype | partstrategy | boundaries | indisusable
-----------------------------------+----------+--------------+------------+-------------
idx1_partition_unsable_index_1_p1 | x | n | | f
idx1_partition_unsable_index_1_p2 | x | n | | t
idx1_partition_unsable_index_1_p3 | x | n | | t
sys_p1_c3_idx | x | n | | t
sys_p2_c3_idx | x | n | | t
sys_p3_c3_idx | x | n | | t
(6 rows)
-- rebuild index partition
ALTER INDEX idx1_partition_unsable_index_1 REBUILD PARTITION idx1_partition_unsable_index_1_p1;
-- check indunusable info
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
relname | parttype | partstrategy | indisusable
-----------------------------------+----------+--------------+-------------
idx1_partition_unsable_index_1_p1 | x | n | t
idx1_partition_unsable_index_1_p2 | x | n | t
idx1_partition_unsable_index_1_p3 | x | n | t
sys_p1_c3_idx | x | n | t
sys_p2_c3_idx | x | n | t
sys_p3_c3_idx | x | n | t
(6 rows)
--2.ALTER INDEX unusable
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
relname | parttype | partstrategy | indisusable
-----------------------------------+----------+--------------+-------------
idx1_partition_unsable_index_1_p1 | x | n | t
idx1_partition_unsable_index_1_p2 | x | n | t
idx1_partition_unsable_index_1_p3 | x | n | t
sys_p1_c3_idx | x | n | t
sys_p2_c3_idx | x | n | t
sys_p3_c3_idx | x | n | t
(6 rows)
ALTER INDEX idx1_partition_unsable_index_1 UNUSABLE;
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
relname | parttype | partstrategy | indisusable
-----------------------------------+----------+--------------+-------------
idx1_partition_unsable_index_1_p1 | x | n | f
idx1_partition_unsable_index_1_p2 | x | n | f
idx1_partition_unsable_index_1_p3 | x | n | f
sys_p1_c3_idx | x | n | f
sys_p2_c3_idx | x | n | f
sys_p3_c3_idx | x | n | f
(6 rows)
ALTER INDEX idx1_partition_unsable_index_1 REBUILD;
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
relname | parttype | partstrategy | indisusable
-----------------------------------+----------+--------------+-------------
idx1_partition_unsable_index_1_p1 | x | n | t
idx1_partition_unsable_index_1_p2 | x | n | t
idx1_partition_unsable_index_1_p3 | x | n | t
sys_p1_c3_idx | x | n | t
sys_p2_c3_idx | x | n | t
sys_p3_c3_idx | x | n | t
(6 rows)
--test for reindex partition
ALTER INDEX idx1_partition_unsable_index_1 UNUSABLE;
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
relname | parttype | partstrategy | indisusable
-----------------------------------+----------+--------------+-------------
idx1_partition_unsable_index_1_p1 | x | n | f
idx1_partition_unsable_index_1_p2 | x | n | f
idx1_partition_unsable_index_1_p3 | x | n | f
sys_p1_c3_idx | x | n | f
sys_p2_c3_idx | x | n | f
sys_p3_c3_idx | x | n | f
(6 rows)
REINDEX INDEX idx1_partition_unsable_index_1 PARTITION idx1_partition_unsable_index_1_p1;
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
relname | parttype | partstrategy | indisusable
-----------------------------------+----------+--------------+-------------
idx1_partition_unsable_index_1_p1 | x | n | t
idx1_partition_unsable_index_1_p2 | x | n | f
idx1_partition_unsable_index_1_p3 | x | n | f
sys_p1_c3_idx | x | n | f
sys_p2_c3_idx | x | n | f
sys_p3_c3_idx | x | n | f
(6 rows)
ALTER INDEX idx1_partition_unsable_index_1 REBUILD;
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
relname | parttype | partstrategy | indisusable
-----------------------------------+----------+--------------+-------------
idx1_partition_unsable_index_1_p1 | x | n | t
idx1_partition_unsable_index_1_p2 | x | n | t
idx1_partition_unsable_index_1_p3 | x | n | t
sys_p1_c3_idx | x | n | t
sys_p2_c3_idx | x | n | t
sys_p3_c3_idx | x | n | t
(6 rows)
-- 3. alter table, modify one of it's partition's all indexes to unusable state
ALTER TABLE partition_unsable_index_1 MODIFY PARTITION partition_unsable_index_1_p0 UNUSABLE LOCAL INDEXES;
-- check indunusable info
select relname, indisusable from pg_partition
where relname = 'idx1_partition_unsable_index_1_p1'
or relname = 'idx2_partition_unsable_index_1_p1'
or relname = 'idx3_partition_unsable_index_1_p1'
or relname = 'p1_partition_unsable_index_1'
order by 1;
relname | indisusable
-----------------------------------+-------------
idx1_partition_unsable_index_1_p1 | f
idx2_partition_unsable_index_1_p1 | f
idx3_partition_unsable_index_1_p1 | f
(3 rows)
-- rebuild
ALTER TABLE partition_unsable_index_1 MODIFY PARTITION partition_unsable_index_1_p0 REBUILD UNUSABLE LOCAL INDEXES;
-- check again
select relname, indisusable from pg_partition
where relname = 'idx1_partition_unsable_index_1_p1'
or relname = 'idx2_partition_unsable_index_1_p1'
or relname = 'idx3_partition_unsable_index_1_p1'
or relname = 'p1_partition_unsable_index_1'
order by 1;
relname | indisusable
-----------------------------------+-------------
idx1_partition_unsable_index_1_p1 | t
idx2_partition_unsable_index_1_p1 | t
idx3_partition_unsable_index_1_p1 | t
(3 rows)
ALTER INDEX idx1_partition_unsable_index_1 MODIFY PARTITION idx1_partition_unsable_index_1_p1 UNUSABLE;
-- idx1_partition_unsable_index_1_p1 is unusable
select part.relname, part.indisusable
from pg_class class , pg_partition part , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
and part.parentid = ind.indexrelid
order by 1;
relname | indisusable
-----------------------------------+-------------
idx1_partition_unsable_index_1_p1 | f
idx1_partition_unsable_index_1_p2 | t
idx1_partition_unsable_index_1_p3 | t
idx2_partition_unsable_index_1_p1 | t
idx2_partition_unsable_index_1_p2 | t
idx2_partition_unsable_index_1_p3 | t
idx3_partition_unsable_index_1_p1 | t
idx3_partition_unsable_index_1_p2 | t
idx3_partition_unsable_index_1_p3 | t
sys_p1_c1_c2_c3_idx | t
sys_p1_c2_c3_idx | t
sys_p1_c3_idx | t
sys_p2_c1_c2_c3_idx | t
sys_p2_c2_c3_idx | t
sys_p2_c3_idx | t
sys_p3_c1_c2_c3_idx | t
sys_p3_c2_c3_idx | t
sys_p3_c3_idx | t
(18 rows)
-- can not cluster partition bacause of unusable local index
CLUSTER partition_unsable_index_1 PARTITION (partition_unsable_index_1_p0) USING idx1_partition_unsable_index_1;
ERROR: can not cluster partition partition_unsable_index_1_p0 using idx1_partition_unsable_index_1 bacause of unusable local index
CLUSTER partition_unsable_index_1 USING idx1_partition_unsable_index_1;
ERROR: can not cluster partition partition_unsable_index_1_p0 using idx1_partition_unsable_index_1 bacause of unusable local index
-- indisclustered is false
select class.relname, ind.indisclustered
from pg_class class , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
order by 2;
relname | indisclustered
---------------------------+----------------
partition_unsable_index_1 | f
partition_unsable_index_1 | f
partition_unsable_index_1 | f
(3 rows)
-- cluster ok
ALTER INDEX idx1_partition_unsable_index_1 REBUILD;
CLUSTER partition_unsable_index_1 USING idx1_partition_unsable_index_1;
-- idx1_partition_unsable_index_1_p1 is usable
select part.relname, part.indisusable
from pg_class class , pg_partition part , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
and part.parentid = ind.indexrelid
order by 1;
relname | indisusable
-----------------------------------+-------------
idx1_partition_unsable_index_1_p1 | t
idx1_partition_unsable_index_1_p2 | t
idx1_partition_unsable_index_1_p3 | t
idx2_partition_unsable_index_1_p1 | t
idx2_partition_unsable_index_1_p2 | t
idx2_partition_unsable_index_1_p3 | t
idx3_partition_unsable_index_1_p1 | t
idx3_partition_unsable_index_1_p2 | t
idx3_partition_unsable_index_1_p3 | t
sys_p1_c1_c2_c3_idx | t
sys_p1_c2_c3_idx | t
sys_p1_c3_idx | t
sys_p2_c1_c2_c3_idx | t
sys_p2_c2_c3_idx | t
sys_p2_c3_idx | t
sys_p3_c1_c2_c3_idx | t
sys_p3_c2_c3_idx | t
sys_p3_c3_idx | t
(18 rows)
-- indisclustered is true
select class.relname, ind.indisclustered
from pg_class class , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
order by 2;
relname | indisclustered
---------------------------+----------------
partition_unsable_index_1 | f
partition_unsable_index_1 | f
partition_unsable_index_1 | t
(3 rows)
-- cluster other index
ALTER INDEX idx2_partition_unsable_index_1 MODIFY PARTITION idx2_partition_unsable_index_1_p1 UNUSABLE;
ALTER INDEX idx2_partition_unsable_index_1 REBUILD;
CLUSTER partition_unsable_index_1 USING idx2_partition_unsable_index_1;
select class.relname, ind.indisclustered
from pg_class class , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
order by 2;
relname | indisclustered
---------------------------+----------------
partition_unsable_index_1 | f
partition_unsable_index_1 | f
partition_unsable_index_1 | t
(3 rows)
-- cluster a partition
ALTER INDEX idx1_partition_unsable_index_1 MODIFY PARTITION idx1_partition_unsable_index_1_p1 UNUSABLE;
ALTER INDEX idx1_partition_unsable_index_1 REBUILD PARTITION idx1_partition_unsable_index_1_p1;
CLUSTER partition_unsable_index_1 PARTITION (partition_unsable_index_1_p0) USING idx1_partition_unsable_index_1;
CLUSTER partition_unsable_index_1 USING idx1_partition_unsable_index_1;
select class.relname, ind.indisclustered
from pg_class class , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
order by 2;
relname | indisclustered
---------------------------+----------------
partition_unsable_index_1 | f
partition_unsable_index_1 | f
partition_unsable_index_1 | t
(3 rows)
--5.2 merge (not support yet, keep the case hear for support in the future)
-- merge failed due to unusable index partition
ALTER INDEX idx1_partition_unsable_index_1 MODIFY PARTITION idx1_partition_unsable_index_1_p1 UNUSABLE;
ALTER TABLE partition_unsable_index_1 MERGE PARTITIONS partition_unsable_index_1_p0, p2_partition_unsable_index_3
INTO PARTITION px_partition_unsable_index_3;
ERROR: can not merge partition against interval partitioned table
--rebuild unusable index partition
ALTER INDEX idx1_partition_unsable_index_1 REBUILD PARTITION idx1_partition_unsable_index_1_p1;
--5.3 exchange
-- create plain table and index
CREATE TABLE table_unusable_index_exchange (c1 int, c2 int, c3 date not null);
CREATE INDEX idx1_table_unusable_index_exchange on table_unusable_index_exchange(c3);
CREATE INDEX idx2_table_unusable_index_exchange on table_unusable_index_exchange(c2, c3);
CREATE INDEX idx3_table_unusable_index_exchange on table_unusable_index_exchange(c1, c2, c3);
--- unusable non-partitioned-index
ALTER INDEX idx1_table_unusable_index_exchange UNUSABLE;
ALTER TABLE partition_unsable_index_1 EXCHANGE PARTITION (partition_unsable_index_1_p0)
WITH TABLE table_unusable_index_exchange;
ERROR: tables in ALTER TABLE EXCHANGE PARTITION must have the same number of indexs
ALTER INDEX idx1_table_unusable_index_exchange REBUILD;
-- unusable partitioned-index
ALTER INDEX idx1_partition_unsable_index_1 UNUSABLE;
ALTER TABLE partition_unsable_index_1 EXCHANGE PARTITION (partition_unsable_index_1_p0)
WITH TABLE table_unusable_index_exchange;
ERROR: index mismatch for tables in ALTER TABLE EXCHANGE PARTITION
ALTER INDEX idx1_partition_unsable_index_1 REBUILD;
-- modify one index partition unusable
-- exchange failed due to unusable index partition
ALTER INDEX idx1_partition_unsable_index_1 MODIFY PARTITION idx1_partition_unsable_index_1_p1 UNUSABLE;
ALTER TABLE partition_unsable_index_1 EXCHANGE PARTITION (partition_unsable_index_1_p0)
WITH TABLE table_unusable_index_exchange;
ERROR: index mismatch for tables in ALTER TABLE EXCHANGE PARTITION
-- exchange ok
ALTER INDEX idx1_partition_unsable_index_1 REBUILD PARTITION idx1_partition_unsable_index_1_p1;
ALTER TABLE partition_unsable_index_1 EXCHANGE PARTITION (partition_unsable_index_1_p0)
WITH TABLE table_unusable_index_exchange;
-- clean table_unusable_index_exchange
DROP TABLE table_unusable_index_exchange;
DROP TABLE partition_unsable_index_1;
--6. index and unique index check
create table partition_unsable_index_1
(
c1 int,
c2 int,
c3 date not null
)
partition by range (c3)
INTERVAL ('1 month')
(
PARTITION partition_unsable_index_1_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION partition_unsable_index_1_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION partition_unsable_index_1_p2 VALUES LESS THAN ('2020-05-01')
);
-- create a unique index
CREATE UNIQUE INDEX idx_unique_partition_unsable_index_1 on partition_unsable_index_1(c2, c3) LOCAL
(
partition idx_unique_partition_unsable_index_1_p1,
partition idx_unique_partition_unsable_index_1_p2,
partition idx_unique_partition_unsable_index_1_p3
);
--insert duplicated rows should report error
insert into partition_unsable_index_1 values(3,3,'2020-02-01');
insert into partition_unsable_index_1 values(5,3,'2020-02-01'); -- fail
ERROR: duplicate key value violates unique constraint "idx_unique_partition_unsable_index_1"
DETAIL: Key (c2, c3)=(3, Sat Feb 01 00:00:00 2020) already exists.
-- set local index unusable
ALTER INDEX idx_unique_partition_unsable_index_1 MODIFY PARTITION idx_unique_partition_unsable_index_1_p1 UNUSABLE;
-- bypass the unique index check
insert into partition_unsable_index_1 values(5,3,'2020-02-01'); -- success
--but report unique check error here
ALTER INDEX idx_unique_partition_unsable_index_1 REBUILD PARTITION idx_unique_partition_unsable_index_1_p1;
ERROR: could not create unique index "idx_unique_partition_unsable_index_1"
DETAIL: Key (c2, c3)=(3, Sat Feb 01 00:00:00 2020) is duplicated.
-- cleanup
DROP INDEX idx_unique_partition_unsable_index_1;
insert into partition_unsable_index_1 values(5,3,'2020-02-01'); -- success
--cleanup
DROP TABLE partition_unsable_index_1;

View File

@ -27,14 +27,13 @@ SET ENABLE_SEQSCAN = FALSE;
SET ENABLE_BITMAPSCAN = FALSE;
EXPLAIN (COSTS off, NODES off) SELECT * FROM TEST1_P WHERE TEST1_F1 > 5000;
QUERY PLAN
---------------------------------------------------------------------------
Streaming (type: GATHER)
-> Partition Iterator
Iterations: 0
-> Partitioned Index Only Scan using index_on_test1_p on test1_p
Index Cond: (test1_f1 > 5000)
Selected Partitions: NONE
(6 rows)
---------------------------------------------------------------------
Partition Iterator
Iterations: 0
-> Partitioned Index Only Scan using index_on_test1_p on test1_p
Index Cond: (test1_f1 > 5000)
Selected Partitions: NONE
(5 rows)
RESET ENABLE_SEQSCAN;
RESET ENABLE_BITMAPSCAN;

View File

@ -96,16 +96,6 @@ drop table insert_without_index_without_interval_with_maxvalue_tz;
--
---- MAX_PARTITION_NUM(32767)
--
--date
create table insert_max_partition_num_date(col_date date)
partition by range(col_date)
interval (interval '1' day) store in (hw_partition_insert_tsp4, hw_partition_insert_tsp5, hw_partition_insert_tsp6)
(
partition insert_max_partition_num_date_p1 values less than ('2012-1-25') tablespace hw_partition_insert_tsp4,
partition insert_max_partition_num_date_p2 values less than ('2012-2-25') tablespace hw_partition_insert_tsp5,
partition insert_max_partition_num_date_p3 values less than ('2012-3-25') tablespace hw_partition_insert_tsp6
);
--
---- test for null, int2
--

View File

@ -0,0 +1,229 @@
--
-- prepare: create tablespace dir
--
\! mkdir '@testtablespace@/hw_partition_interval_tsp4'
\! mkdir '@testtablespace@/hw_partition_interval_tsp5'
\! mkdir '@testtablespace@/hw_partition_interval_tsp6'
set timezone = 'PRC';
create tablespace hw_partition_interval_tsp4 location '@testtablespace@/hw_partition_interval_tsp4';
create tablespace hw_partition_interval_tsp5 location '@testtablespace@/hw_partition_interval_tsp5';
create tablespace hw_partition_interval_tsp6 location '@testtablespace@/hw_partition_interval_tsp6';
--
---- normal operates : create, insert, auto create and drop without table space
--
CREATE TABLE interval_normal_date (logdate date not null)
PARTITION BY RANGE (logdate)
INTERVAL ('1 day')
(
PARTITION interval_normal_date_p1 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_normal_date_p2 VALUES LESS THAN ('2020-05-01'),
PARTITION interval_normal_date_p3 VALUES LESS THAN ('2020-06-01')
);
-- see about the info of the partitioned table in pg_partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
-- insert the record that is smaller than the lower boundary
insert into interval_normal_date values ('2020-02-20');
insert into interval_normal_date values ('2020-3-01');
insert into interval_normal_date values ('2020-3-02');
insert into interval_normal_date values ('2020-5-02');
-- no new interval range created
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
-- insert the record that is smaller than the lower boundary
insert into interval_normal_date values ('2020-6-01');
insert into interval_normal_date values ('2020-6-02');
insert into interval_normal_date values ('2020-6-03');
-- created two new interval ranges
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
-- inquire about data of the partition and the partitioned table
select * from interval_normal_date order by logdate;
select * from interval_normal_date partition (interval_normal_date_p1) order by logdate;
select * from interval_normal_date partition (interval_normal_date_p2) order by logdate;
select * from interval_normal_date partition (interval_normal_date_p3) order by logdate;
-- first created interval range
select * from interval_normal_date partition (sys_p1) order by logdate;
-- second created interval range
select * from interval_normal_date partition (sys_p2) order by logdate;
-- third created interval range
select * from interval_normal_date partition (sys_p3) order by logdate;
-- drop range partition which is not next to interval range.
ALTER TABLE interval_normal_date DROP PARTITION interval_normal_date_p2;
-- see about the info of the partitioned table in pg_partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
-- drop interval range partition
ALTER TABLE interval_normal_date DROP PARTITION sys_p2;
-- see the info of the partitioned table in pg_partition, only reduce a interval range partition instance.
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
-- drop range partition which is next to interval range.
ALTER TABLE interval_normal_date DROP PARTITION interval_normal_date_p3;
-- the interval parttition will changed to range partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
-- insert the record to create droped range sys_p2, which will have a new relname.
insert into interval_normal_date values ('2020-6-02');
-- will add the new created interval partition.
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
-- insert the record that is smaller than the lower boundary
insert into interval_normal_date values ('2020-3-02');
insert into interval_normal_date values ('2020-5-02');
-- inquire about data of the partition and the partitioned table
select * from interval_normal_date order by logdate;
select * from interval_normal_date partition (interval_normal_date_p1) order by logdate;
-- first created interval range
select * from interval_normal_date partition (sys_p1) order by logdate;
-- third created interval range
select * from interval_normal_date partition (sys_p3) order by logdate;
-- fourth created interval range
select * from interval_normal_date partition (sys_p4) order by logdate;
-- Insert a future data
insert into interval_normal_date values ('2030-3-01');
insert into interval_normal_date values ('2040-06-20');
-- see about the info of the partitioned table in pg_partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
-- inquire about data of the partition and the partitioned table
select * from interval_normal_date order by logdate;
select * from interval_normal_date partition (sys_p5) order by logdate;
select * from interval_normal_date partition (sys_p6) order by logdate;
--
---- test truncate partitions without index
--
-- truncate a range partition
ALTER TABLE interval_normal_date truncate PARTITION interval_normal_date_p1;
select * from interval_normal_date partition (interval_normal_date_p1) order by logdate;
-- truncate a interval partition
ALTER TABLE interval_normal_date truncate PARTITION sys_p4;
select * from interval_normal_date partition (sys_p4) order by logdate;
-- truncate the partitioned table
truncate table interval_normal_date;
select * from interval_normal_date order by logdate;
--
---- merge and split partition are not supported yet;
--
-- split partition
ALTER TABLE interval_normal_date SPLIT PARTITION sys_p1 AT ('2020-04-01 00:00:00') INTO
(
PARTITION sys_p6,
PARTITION sys_p7
);
-- mgerge partition
ALTER TABLE interval_normal_date MERGE PARTITIONS interval_normal_date_p1, sys_p1 into PARTITION sys_p8;
ALTER TABLE interval_normal_date MERGE PARTITIONS sys_p1, sys_p4 into PARTITION sys_p9;
--
---- add partition is not supported;
--
ALTER TABLE interval_normal_date ADD PARTITION sys_10 VALUES LESS THAN ('2020-07-01');
--
---- alter partition name
--
ALTER TABLE interval_normal_date RENAME PARTITION sys_p5 To my_sys_p5;
ALTER TABLE interval_normal_date RENAME PARTITION FOR ('2020-06-02') To my_sys_p4;
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
ALTER TABLE interval_normal_date RENAME PARTITION sys_p6 To my_sys_p6;
insert into interval_normal_date values ('2040-06-21');
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
ALTER TABLE interval_normal_date RENAME PARTITION sys_p4 To sys_p32767;
insert into interval_normal_date values ('2040-06-22');
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
ALTER TABLE interval_normal_date RENAME PARTITION sys_p2 To sys_p32780;
insert into interval_normal_date values ('2040-06-24');
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
--clean up
drop table interval_normal_date;
--
---- tablespace
--
--date
--create table insert_max_partition_num_date(col_date date)
--partition by range(col_date)
--interval ('1' day) store in (hw_partition_insert_tsp4, hw_partition_insert_tsp5, hw_partition_insert_tsp6)
--(
-- partition insert_max_partition_num_date_p1 values less than ('2012-1-25') tablespace hw_partition_insert_tsp4,
-- partition insert_max_partition_num_date_p2 values less than ('2012-2-25') tablespace hw_partition_insert_tsp5,
-- partition insert_max_partition_num_date_p3 values less than ('2012-3-25') tablespace hw_partition_insert_tsp6
--);
--
---- test with where conditions
--
--select * from interval_normal_date where logdate < '2020-06-01';
--ERROR: pruning result(PartitionIdentifier) is invalid
--
---- test with maxvalue
--
--
---- test with null
--
--
---- test support interval type maxvalue
-- Hour, Day, month, timestamp, timestamptz, date
--
--
---- test month interval increase, specific Feb
--
--
-- clean up
--
drop tablespace hw_partition_interval_tsp4;
drop tablespace hw_partition_interval_tsp5;
drop tablespace hw_partition_interval_tsp6;
\! rm -fr '@testtablespace@/hw_partition_interval_tsp4'
\! rm -fr '@testtablespace@/hw_partition_interval_tsp5'
\! rm -fr '@testtablespace@/hw_partition_interval_tsp6'

View File

@ -60,29 +60,29 @@ select p.relname, p.boundaries, t.spcname from pg_partition p left join pg_table
select * from insert_without_index_without_interval_without_maxvalue_tz order by col_timestamptz;
col_timestamptz
------------------------------
Sat Feb 26 14:00:00 2011 CST
Wed Jan 25 14:00:00 2012 CST
Mon Feb 20 14:00:00 2012 CST
Sat Feb 25 14:00:00 2012 CST
Sat Feb 26 00:00:00 2011 CST
Wed Jan 25 00:00:00 2012 CST
Mon Feb 20 00:00:00 2012 CST
Sat Feb 25 00:00:00 2012 CST
(4 rows)
select * from insert_without_index_without_interval_without_maxvalue_tz partition (insert_without_index_without_interval_without_maxvalue_tz_p1) order by 1;
col_timestamptz
------------------------------
Sat Feb 26 14:00:00 2011 CST
Sat Feb 26 00:00:00 2011 CST
(1 row)
select * from insert_without_index_without_interval_without_maxvalue_tz partition (insert_without_index_without_interval_without_maxvalue_tz_p2) order by 1;
col_timestamptz
------------------------------
Wed Jan 25 14:00:00 2012 CST
Mon Feb 20 14:00:00 2012 CST
Wed Jan 25 00:00:00 2012 CST
Mon Feb 20 00:00:00 2012 CST
(2 rows)
select * from insert_without_index_without_interval_without_maxvalue_tz partition (insert_without_index_without_interval_without_maxvalue_tz_p3) order by 1;
col_timestamptz
------------------------------
Sat Feb 25 14:00:00 2012 CST
Sat Feb 25 00:00:00 2012 CST
(1 row)
--clean up
@ -137,33 +137,33 @@ select p.relname, p.boundaries, t.spcname from pg_partition p left join pg_table
select * from insert_without_index_without_interval_with_maxvalue_tz order by col_timestamptz;
col_timestamptz
------------------------------
Sat Feb 26 14:00:00 2011 CST
Wed Jan 25 14:00:00 2012 CST
Mon Feb 20 14:00:00 2012 CST
Sat Feb 25 14:00:00 2012 CST
Sun Mar 25 14:00:00 2012 CST
Mon Mar 25 14:00:00 2013 CST
Sat Feb 26 00:00:00 2011 CST
Wed Jan 25 00:00:00 2012 CST
Mon Feb 20 00:00:00 2012 CST
Sat Feb 25 00:00:00 2012 CST
Sun Mar 25 00:00:00 2012 CST
Mon Mar 25 00:00:00 2013 CST
(6 rows)
select * from insert_without_index_without_interval_with_maxvalue_tz partition (insert_without_index_without_interval_with_maxvalue_tz_p1) order by 1;
col_timestamptz
------------------------------
Sat Feb 26 14:00:00 2011 CST
Sat Feb 26 00:00:00 2011 CST
(1 row)
select * from insert_without_index_without_interval_with_maxvalue_tz partition (insert_without_index_without_interval_with_maxvalue_tz_p2) order by 1;
col_timestamptz
------------------------------
Wed Jan 25 14:00:00 2012 CST
Mon Feb 20 14:00:00 2012 CST
Wed Jan 25 00:00:00 2012 CST
Mon Feb 20 00:00:00 2012 CST
(2 rows)
select * from insert_without_index_without_interval_with_maxvalue_tz partition (insert_without_index_without_interval_with_maxvalue_tz_p3) order by 1;
col_timestamptz
------------------------------
Sat Feb 25 14:00:00 2012 CST
Sun Mar 25 14:00:00 2012 CST
Mon Mar 25 14:00:00 2013 CST
Sat Feb 25 00:00:00 2012 CST
Sun Mar 25 00:00:00 2012 CST
Mon Mar 25 00:00:00 2013 CST
(3 rows)
--clean up
@ -171,17 +171,6 @@ drop table insert_without_index_without_interval_with_maxvalue_tz;
--
---- MAX_PARTITION_NUM(32767)
--
--date
create table insert_max_partition_num_date(col_date date)
partition by range(col_date)
interval (interval '1' day) store in (hw_partition_insert_tsp4, hw_partition_insert_tsp5, hw_partition_insert_tsp6)
(
partition insert_max_partition_num_date_p1 values less than ('2012-1-25') tablespace hw_partition_insert_tsp4,
partition insert_max_partition_num_date_p2 values less than ('2012-2-25') tablespace hw_partition_insert_tsp5,
partition insert_max_partition_num_date_p3 values less than ('2012-3-25') tablespace hw_partition_insert_tsp6
);
ERROR: Range partitioned table with INTERVAL was forbidden
HINT: Only support pure range partitioned table
--
---- test for null, int2
--

View File

@ -0,0 +1,428 @@
--
-- prepare: create tablespace dir
--
\! mkdir '@testtablespace@/hw_partition_interval_tsp4'
\! mkdir '@testtablespace@/hw_partition_interval_tsp5'
\! mkdir '@testtablespace@/hw_partition_interval_tsp6'
set timezone = 'PRC';
create tablespace hw_partition_interval_tsp4 location '@testtablespace@/hw_partition_interval_tsp4';
create tablespace hw_partition_interval_tsp5 location '@testtablespace@/hw_partition_interval_tsp5';
create tablespace hw_partition_interval_tsp6 location '@testtablespace@/hw_partition_interval_tsp6';
--
---- normal operates : create, insert, auto create and drop without table space
--
CREATE TABLE interval_normal_date (logdate date not null)
PARTITION BY RANGE (logdate)
INTERVAL ('1 day')
(
PARTITION interval_normal_date_p1 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_normal_date_p2 VALUES LESS THAN ('2020-05-01'),
PARTITION interval_normal_date_p3 VALUES LESS THAN ('2020-06-01')
);
-- see about the info of the partitioned table in pg_partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+--------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
interval_normal_date_p2 | p | r | {2020-05-01}
interval_normal_date_p3 | p | r | {2020-06-01}
(4 rows)
-- insert the record that is smaller than the lower boundary
insert into interval_normal_date values ('2020-02-20');
insert into interval_normal_date values ('2020-3-01');
insert into interval_normal_date values ('2020-3-02');
insert into interval_normal_date values ('2020-5-02');
-- no new interval range created
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+--------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
interval_normal_date_p2 | p | r | {2020-05-01}
interval_normal_date_p3 | p | r | {2020-06-01}
(4 rows)
-- insert the record that is smaller than the lower boundary
insert into interval_normal_date values ('2020-6-01');
insert into interval_normal_date values ('2020-6-02');
insert into interval_normal_date values ('2020-6-03');
-- created two new interval ranges
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+------------------------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
interval_normal_date_p2 | p | r | {2020-05-01}
interval_normal_date_p3 | p | r | {2020-06-01}
sys_p1 | p | i | {"Tue Jun 02 00:00:00 2020"}
sys_p2 | p | i | {"Wed Jun 03 00:00:00 2020"}
sys_p3 | p | i | {"Thu Jun 04 00:00:00 2020"}
(7 rows)
-- inquire about data of the partition and the partitioned table
select * from interval_normal_date order by logdate;
logdate
--------------------------
Thu Feb 20 00:00:00 2020
Sun Mar 01 00:00:00 2020
Mon Mar 02 00:00:00 2020
Sat May 02 00:00:00 2020
Mon Jun 01 00:00:00 2020
Tue Jun 02 00:00:00 2020
Wed Jun 03 00:00:00 2020
(7 rows)
select * from interval_normal_date partition (interval_normal_date_p1) order by logdate;
logdate
--------------------------
Thu Feb 20 00:00:00 2020
(1 row)
select * from interval_normal_date partition (interval_normal_date_p2) order by logdate;
logdate
--------------------------
Sun Mar 01 00:00:00 2020
Mon Mar 02 00:00:00 2020
(2 rows)
select * from interval_normal_date partition (interval_normal_date_p3) order by logdate;
logdate
--------------------------
Sat May 02 00:00:00 2020
(1 row)
-- first created interval range
select * from interval_normal_date partition (sys_p1) order by logdate;
logdate
--------------------------
Mon Jun 01 00:00:00 2020
(1 row)
-- second created interval range
select * from interval_normal_date partition (sys_p2) order by logdate;
logdate
--------------------------
Tue Jun 02 00:00:00 2020
(1 row)
-- third created interval range
select * from interval_normal_date partition (sys_p3) order by logdate;
logdate
--------------------------
Wed Jun 03 00:00:00 2020
(1 row)
-- drop range partition which is not next to interval range.
ALTER TABLE interval_normal_date DROP PARTITION interval_normal_date_p2;
-- see about the info of the partitioned table in pg_partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+------------------------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
interval_normal_date_p3 | p | r | {2020-06-01}
sys_p1 | p | i | {"Tue Jun 02 00:00:00 2020"}
sys_p2 | p | i | {"Wed Jun 03 00:00:00 2020"}
sys_p3 | p | i | {"Thu Jun 04 00:00:00 2020"}
(6 rows)
-- drop interval range partition
ALTER TABLE interval_normal_date DROP PARTITION sys_p2;
-- see the info of the partitioned table in pg_partition, only reduce a interval range partition instance.
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+------------------------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
interval_normal_date_p3 | p | r | {2020-06-01}
sys_p1 | p | i | {"Tue Jun 02 00:00:00 2020"}
sys_p3 | p | i | {"Thu Jun 04 00:00:00 2020"}
(5 rows)
-- drop range partition which is next to interval range.
ALTER TABLE interval_normal_date DROP PARTITION interval_normal_date_p3;
-- the interval parttition will changed to range partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+------------------------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
sys_p1 | p | r | {"Tue Jun 02 00:00:00 2020"}
sys_p3 | p | i | {"Thu Jun 04 00:00:00 2020"}
(4 rows)
-- insert the record to create droped range sys_p2, which will have a new relname.
insert into interval_normal_date values ('2020-6-02');
-- will add the new created interval partition.
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+------------------------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
sys_p1 | p | r | {"Tue Jun 02 00:00:00 2020"}
sys_p3 | p | i | {"Thu Jun 04 00:00:00 2020"}
sys_p4 | p | i | {"Wed Jun 03 00:00:00 2020"}
(5 rows)
-- insert the record that is smaller than the lower boundary
insert into interval_normal_date values ('2020-3-02');
insert into interval_normal_date values ('2020-5-02');
-- inquire about data of the partition and the partitioned table
select * from interval_normal_date order by logdate;
logdate
--------------------------
Thu Feb 20 00:00:00 2020
Mon Mar 02 00:00:00 2020
Sat May 02 00:00:00 2020
Mon Jun 01 00:00:00 2020
Tue Jun 02 00:00:00 2020
Wed Jun 03 00:00:00 2020
(6 rows)
select * from interval_normal_date partition (interval_normal_date_p1) order by logdate;
logdate
--------------------------
Thu Feb 20 00:00:00 2020
(1 row)
-- first created interval range
select * from interval_normal_date partition (sys_p1) order by logdate;
logdate
--------------------------
Mon Mar 02 00:00:00 2020
Sat May 02 00:00:00 2020
Mon Jun 01 00:00:00 2020
(3 rows)
-- third created interval range
select * from interval_normal_date partition (sys_p3) order by logdate;
logdate
--------------------------
Wed Jun 03 00:00:00 2020
(1 row)
-- fourth created interval range
select * from interval_normal_date partition (sys_p4) order by logdate;
logdate
--------------------------
Tue Jun 02 00:00:00 2020
(1 row)
-- Insert a future data
insert into interval_normal_date values ('2030-3-01');
insert into interval_normal_date values ('2040-06-20');
-- see about the info of the partitioned table in pg_partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+------------------------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
sys_p1 | p | r | {"Tue Jun 02 00:00:00 2020"}
sys_p3 | p | i | {"Thu Jun 04 00:00:00 2020"}
sys_p4 | p | i | {"Wed Jun 03 00:00:00 2020"}
sys_p5 | p | i | {"Sat Mar 02 00:00:00 2030"}
sys_p6 | p | i | {"Thu Jun 21 00:00:00 2040"}
(7 rows)
-- inquire about data of the partition and the partitioned table
select * from interval_normal_date order by logdate;
logdate
--------------------------
Thu Feb 20 00:00:00 2020
Mon Mar 02 00:00:00 2020
Sat May 02 00:00:00 2020
Mon Jun 01 00:00:00 2020
Tue Jun 02 00:00:00 2020
Wed Jun 03 00:00:00 2020
Fri Mar 01 00:00:00 2030
Wed Jun 20 00:00:00 2040
(8 rows)
select * from interval_normal_date partition (sys_p5) order by logdate;
logdate
--------------------------
Fri Mar 01 00:00:00 2030
(1 row)
select * from interval_normal_date partition (sys_p6) order by logdate;
logdate
--------------------------
Wed Jun 20 00:00:00 2040
(1 row)
--
---- test truncate partitions without index
--
-- truncate a range partition
ALTER TABLE interval_normal_date truncate PARTITION interval_normal_date_p1;
select * from interval_normal_date partition (interval_normal_date_p1) order by logdate;
logdate
---------
(0 rows)
-- truncate a interval partition
ALTER TABLE interval_normal_date truncate PARTITION sys_p4;
select * from interval_normal_date partition (sys_p4) order by logdate;
logdate
---------
(0 rows)
-- truncate the partitioned table
truncate table interval_normal_date;
select * from interval_normal_date order by logdate;
logdate
---------
(0 rows)
--
---- merge and split partition are not supported yet;
--
-- split partition
ALTER TABLE interval_normal_date SPLIT PARTITION sys_p1 AT ('2020-04-01 00:00:00') INTO
(
PARTITION sys_p6,
PARTITION sys_p7
);
ERROR: can not split partition against interval partitioned table
-- mgerge partition
ALTER TABLE interval_normal_date MERGE PARTITIONS interval_normal_date_p1, sys_p1 into PARTITION sys_p8;
ERROR: can not merge partition against interval partitioned table
ALTER TABLE interval_normal_date MERGE PARTITIONS sys_p1, sys_p4 into PARTITION sys_p9;
ERROR: can not merge partition against interval partitioned table
--
---- add partition is not supported;
--
ALTER TABLE interval_normal_date ADD PARTITION sys_10 VALUES LESS THAN ('2020-07-01');
ERROR: can not add partition against interval partitioned table
--
---- alter partition name
--
ALTER TABLE interval_normal_date RENAME PARTITION sys_p5 To my_sys_p5;
ALTER TABLE interval_normal_date RENAME PARTITION FOR ('2020-06-02') To my_sys_p4;
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+------------------------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
my_sys_p4 | p | i | {"Wed Jun 03 00:00:00 2020"}
my_sys_p5 | p | i | {"Sat Mar 02 00:00:00 2030"}
sys_p1 | p | r | {"Tue Jun 02 00:00:00 2020"}
sys_p3 | p | i | {"Thu Jun 04 00:00:00 2020"}
sys_p6 | p | i | {"Thu Jun 21 00:00:00 2040"}
(7 rows)
ALTER TABLE interval_normal_date RENAME PARTITION sys_p6 To my_sys_p6;
insert into interval_normal_date values ('2040-06-21');
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+------------------------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
my_sys_p4 | p | i | {"Wed Jun 03 00:00:00 2020"}
my_sys_p5 | p | i | {"Sat Mar 02 00:00:00 2030"}
my_sys_p6 | p | i | {"Thu Jun 21 00:00:00 2040"}
sys_p1 | p | r | {"Tue Jun 02 00:00:00 2020"}
sys_p3 | p | i | {"Thu Jun 04 00:00:00 2020"}
sys_p4 | p | i | {"Fri Jun 22 00:00:00 2040"}
(8 rows)
ALTER TABLE interval_normal_date RENAME PARTITION sys_p4 To sys_p32767;
insert into interval_normal_date values ('2040-06-22');
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+------------------------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
my_sys_p4 | p | i | {"Wed Jun 03 00:00:00 2020"}
my_sys_p5 | p | i | {"Sat Mar 02 00:00:00 2030"}
my_sys_p6 | p | i | {"Thu Jun 21 00:00:00 2040"}
sys_p1 | p | r | {"Tue Jun 02 00:00:00 2020"}
sys_p2 | p | i | {"Sat Jun 23 00:00:00 2040"}
sys_p3 | p | i | {"Thu Jun 04 00:00:00 2020"}
sys_p32767 | p | i | {"Fri Jun 22 00:00:00 2040"}
(9 rows)
ALTER TABLE interval_normal_date RENAME PARTITION sys_p2 To sys_p32780;
insert into interval_normal_date values ('2040-06-24');
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_date')
order by relname;
relname | parttype | partstrategy | boundaries
-------------------------+----------+--------------+------------------------------
interval_normal_date | r | i |
interval_normal_date_p1 | p | r | {2020-03-01}
my_sys_p4 | p | i | {"Wed Jun 03 00:00:00 2020"}
my_sys_p5 | p | i | {"Sat Mar 02 00:00:00 2030"}
my_sys_p6 | p | i | {"Thu Jun 21 00:00:00 2040"}
sys_p1 | p | r | {"Tue Jun 02 00:00:00 2020"}
sys_p14 | p | i | {"Mon Jun 25 00:00:00 2040"}
sys_p3 | p | i | {"Thu Jun 04 00:00:00 2020"}
sys_p32767 | p | i | {"Fri Jun 22 00:00:00 2040"}
sys_p32780 | p | i | {"Sat Jun 23 00:00:00 2040"}
(10 rows)
--clean up
drop table interval_normal_date;
--
---- tablespace
--
--date
--create table insert_max_partition_num_date(col_date date)
--partition by range(col_date)
--interval ('1' day) store in (hw_partition_insert_tsp4, hw_partition_insert_tsp5, hw_partition_insert_tsp6)
--(
-- partition insert_max_partition_num_date_p1 values less than ('2012-1-25') tablespace hw_partition_insert_tsp4,
-- partition insert_max_partition_num_date_p2 values less than ('2012-2-25') tablespace hw_partition_insert_tsp5,
-- partition insert_max_partition_num_date_p3 values less than ('2012-3-25') tablespace hw_partition_insert_tsp6
--);
--
---- test with where conditions
--
--select * from interval_normal_date where logdate < '2020-06-01';
--ERROR: pruning result(PartitionIdentifier) is invalid
--
---- test with maxvalue
--
--
---- test with null
--
--
---- test support interval type maxvalue
-- Hour, Day, month, timestamp, timestamptz, date
--
--
---- test month interval increase, specific Feb
--
--
-- clean up
--
drop tablespace hw_partition_interval_tsp4;
drop tablespace hw_partition_interval_tsp5;
drop tablespace hw_partition_interval_tsp6;
\! rm -fr '@testtablespace@/hw_partition_interval_tsp4'
\! rm -fr '@testtablespace@/hw_partition_interval_tsp5'
\! rm -fr '@testtablespace@/hw_partition_interval_tsp6'

View File

@ -279,8 +279,8 @@ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for t
insert into test values (0);
-- failed
alter table test_add_column_constraint add foreign key (a) references test(a) ;
ERROR: FOREIGN KEY ... REFERENCES constraint is not yet supported.
drop table test cascade;
NOTICE: drop cascades to constraint test_add_column_constraint_a_fkey on table test_add_column_constraint
-- d.deferrable
-- failed
alter table test_add_column_constraint add column c4 int deferrable;
@ -827,7 +827,7 @@ select * from test_drop_column_view order by 1,2;
-- failed
select * from temp_view order by 1,2;
ERROR: relation "temp_view" does not exist
ERROR: relation "temp_view" does not exist on datanode1
LINE 1: select * from temp_view order by 1,2;
^
-- failed

View File

@ -964,8 +964,6 @@ Indexes:
Range partition by(a)
Number of partition: 3 (View pg_partition to check each partition range.)
Has OIDs: no
Distribute By: HASH(a)
Location Nodes: ALL DATANODES
Options: orientation=row, compression=no
-- clean
@ -1031,18 +1029,25 @@ partition by range (a, b)
partition test_partition_foreign_key_p2 values less than (4, 'e'),
partition test_partition_foreign_key_p3 values less than (7, 'h')
);
ERROR: FOREIGN KEY ... REFERENCES constraint is not yet supported.
-- failed
drop user temp_user;
ERROR: cannot drop schema temp_user because other objects depend on it
DETAIL: table temp_user.test_ordinary_reftable depends on schema temp_user
constraint test_partition_foreign_key_a_fkey on table test_partition_foreign_key depends on table temp_user.test_ordinary_reftable
HINT: Use DROP ... CASCADE to drop the dependent objects too.
-- failed
drop owned by temp_user;
ERROR: cannot drop desired object(s) because other objects depend on them
DETAIL: constraint test_partition_foreign_key_a_fkey on table test_partition_foreign_key depends on table temp_user.test_ordinary_reftable
HINT: Use DROP ... CASCADE to drop the dependent objects too.
-- failed
drop owned by temp_user restrict;
ERROR: cannot drop desired object(s) because other objects depend on them
DETAIL: constraint test_partition_foreign_key_a_fkey on table test_partition_foreign_key depends on table temp_user.test_ordinary_reftable
HINT: Use DROP ... CASCADE to drop the dependent objects too.
-- success
drop owned by temp_user cascade;
NOTICE: drop cascades to constraint test_partition_foreign_key_a_fkey on table test_partition_foreign_key
select relname, rolname from pg_class, pg_roles where relname='test_ordinary_reftable' and pg_class.relowner=pg_roles.oid;
relname | rolname
---------+---------
@ -1050,14 +1055,10 @@ select relname, rolname from pg_class, pg_roles where relname='test_ordinary_ref
-- success
insert into test_partition_foreign_key values (0, 'a', 0, 'a');
ERROR: relation "test_partition_foreign_key" does not exist
LINE 1: insert into test_partition_foreign_key values (0, 'a', 0, 'a...
^
-- success
drop user temp_user;
-- clean
drop table test_partition_foreign_key;
ERROR: table "test_partition_foreign_key" does not exist
----------------------
-- test alter table set tablespace on ordinary table
\! rm -fr '@testtablespace@/hw_partition_sql_adapt_ts1'

View File

@ -0,0 +1,25 @@
test: hw_partition_index
test: hw_partition_unusable_index_1 hw_partition_unusable_index_3
test: hw_partition_insert hw_partition_insert_01 hw_partition_dml
test: hw_partition_grant hw_partition_of_type
test: hw_partition_nodes hw_partition_size hw_partition_compare hw_partition_storage_parameters hw_partition_storage_parameters_index hw_partition_toast hw_partition_cross hw_partition_maxvalue
test: hw_partition_sql_adapt1 hw_partition_update1
test: hw_partition_sql_adapt0 hw_partition_update0
test: hw_partition_sql_adapt2
test: hw_partition_interval
test: hw_partition_interval_exchange
test: hw_partition_interval_index
test: hw_partition_interval_unusable_index
test: hw_partition_interval_reindex
test: hw_partition_interval_movement
# To check create interval partition parallel
test: hw_partition_interval_parallel_prepare
test: hw_partition_interval_parallel_insert hw_partition_interval_parallel_insert_01 hw_partition_interval_parallel_insert_02
test: hw_partition_interval_parallel_end
test: hw_partition_interval_select
#test: hw_partition_lock
#test: hw_partition_llt
# FIXME: move me back to the parallel test when the refcnt issue is fixed
# Below two teste are unstable, temporarily ignoring. This is same to distribute_dattistic, relallvisible, Dongwang will solve the problem.
#test: hw_partition_vacuum_full
#test: hw_partition_vacuum

View File

@ -0,0 +1,99 @@
--
-- Test exchange operator for interval partitioned table
--
--
---- create interval partitioned table
--
CREATE TABLE interval_normal_exchange (logdate date not null)
PARTITION BY RANGE (logdate)
INTERVAL ('1 month')
(
PARTITION interval_normal_exchange_p1 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_normal_exchange_p2 VALUES LESS THAN ('2020-04-01'),
PARTITION interval_normal_exchange_p3 VALUES LESS THAN ('2020-05-01')
);
-- see about the info of the partitioned table in pg_partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_exchange')
order by relname;
-- insert the record that is smaller than the lower boundary
insert into interval_normal_exchange values ('2020-02-21');
insert into interval_normal_exchange values ('2020-02-22');
insert into interval_normal_exchange values ('2020-02-23');
insert into interval_normal_exchange values ('2020-5-01');
insert into interval_normal_exchange values ('2020-5-02');
insert into interval_normal_exchange values ('2020-5-03');
-- see about the info of the partitioned table in pg_partition
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_normal_exchange')
order by relname;
--
---- create to be exchanged table and test range partition exchange
--
CREATE TABLE interval_exchange_test (logdate date not null);
insert into interval_exchange_test values ('2020-02-24');
insert into interval_exchange_test values ('2020-02-25');
insert into interval_exchange_test values ('2020-02-26');
-- do exchange partition interval_normal_exchange_p1 and interval_exchange_test
-- The data they have belongs to the same range.
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test;
select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate;
select * from interval_exchange_test order by logdate;
-- exchange back
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test;
select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate;
select * from interval_exchange_test order by logdate;
-- Insert a new record not belongs to interval_normal_exchange_p1
insert into interval_exchange_test values ('2020-3-05');
-- defaut is WITH VALIDATION, and the exchange will be failed
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test;
-- WITHOUT VALIDATION and the exchange will be success, but some date will in the wrong range;
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test WITHOUT VALIDATION;
select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate;
select * from interval_exchange_test order by logdate;
-- not include '2020-3-05'
select * from interval_normal_exchange where logdate > '2020-03-01' order by logdate;
--
---- clean the data and test interval partition exchange
--
truncate table interval_exchange_test;
insert into interval_exchange_test values ('2020-5-04');
insert into interval_exchange_test values ('2020-5-05');
insert into interval_exchange_test values ('2020-5-06');
-- exchange table
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (sys_p1)
WITH TABLE interval_exchange_test;
select * from interval_normal_exchange partition (sys_p1)order by logdate;
select * from interval_exchange_test order by logdate;
-- exchange back
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (sys_p1)
WITH TABLE interval_exchange_test;
select * from interval_normal_exchange partition (sys_p1)order by logdate;
select * from interval_exchange_test order by logdate;
insert into interval_exchange_test values ('2020-6-05');
-- defaut is WITH VALIDATION, and the exchange will be failed
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test;
-- WITHOUT VALIDATION and the exchange will be success, but some date will in the wrong range;
ALTER TABLE interval_normal_exchange EXCHANGE PARTITION (interval_normal_exchange_p1)
WITH TABLE interval_exchange_test WITHOUT VALIDATION;
select * from interval_normal_exchange partition (interval_normal_exchange_p1)order by logdate;
select * from interval_exchange_test order by logdate;
-- not include '2020-6-05'
select * from interval_normal_exchange order by logdate;
select * from interval_normal_exchange where logdate > '2020-06-01' order by logdate;
drop table interval_normal_exchange;

View File

@ -0,0 +1,336 @@
--
---- test interval partitioned index
--
drop table if exists hw_partition_index_ip;
create table hw_partition_index_ip
(
c1 int,
c2 int,
logdate date not null
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION hw_partition_index_ip_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION hw_partition_index_ip_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION hw_partition_index_ip_p2 VALUES LESS THAN ('2020-05-01')
);
--succeed
create index ip_index_local1 on hw_partition_index_ip (c1) local;
--succeed
create index ip_index_local2 on hw_partition_index_ip (logdate) local
(
partition,
partition,
partition
);
--fail , the gram.y is not support opt_index_name
create index ip_index_local3 on hw_partition_index_ip (logdate) local
(
partition sip1_index_local,
partition sip2_index_local,
partition sip3_index_local
);
--succeed
create index ip_index_local4 on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--succeed
create index ip_index_local6 on hw_partition_index_ip (logdate) local
(
partition sip1_index_local,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--succeed
create unique index ip_index_local7 on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--succeed
create unique index on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
-- fail same partition name
create unique index on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT
);
--
---- expression, only test sample expression for inter1, more info see hw_partition_index.sql
--
create index on hw_partition_index_ip ((c1+c2)) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--succeed
create index on hw_partition_index_ip ((c1-c2)) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--succeed
--not support CONCURRENTLY
create unique index CONCURRENTLY on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
-- Not enough index partition defined
create unique index on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT
);
-- number of partitions of LOCAL index must equal that of the underlying table
create unique index on hw_partition_index_ip (logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT,
partition sip4_index_local tablespace PG_DEFAULT
);
create unique index on hw_partition_index_ip (logdate);
--fail wrong syntax
drop table hw_partition_index_ip;
--unique index , index para must contain partition key
create table hw_partition_index_ip
(
c1 int,
c2 int,
logdate date not null
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION hw_partition_index_ip_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION hw_partition_index_ip_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION hw_partition_index_ip_p2 VALUES LESS THAN ('2020-05-01')
);
-- succeed
create unique index ip_index_local on hw_partition_index_ip (c1,logdate) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
-- fail without logdate
create unique index ip_index_local2 on hw_partition_index_ip (c1) local
(
partition sip1_index_local tablespace PG_DEFAULT ,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
create unique index ip_index_local3 on hw_partition_index_ip (c2, c1) local
(
partition sip1_index_local tablespace PG_DEFAULT,
partition sip2_index_local tablespace PG_DEFAULT,
partition sip3_index_local tablespace PG_DEFAULT
);
--insert into table
insert into hw_partition_index_ip values(7,2,'2020-03-01');
insert into hw_partition_index_ip values(3,1,'2020-04-01');
insert into hw_partition_index_ip values(5,3,'2020-05-01');
insert into hw_partition_index_ip values(7,5,'2020-06-01');
insert into hw_partition_index_ip values(1,4,'2020-07-01');
--succeed
select * from hw_partition_index_ip order by 1, 2;
--to select all index object
select part.relname, part.parttype, part.rangenum,
part.intervalnum,
part.partstrategy,
part.relallvisible,
part.reltoastrelid,
part.partkey,
part.interval,
part.boundaries
from pg_class class , pg_partition part , pg_index ind where class.relname = 'hw_partition_index_ip' and ind.indrelid = class.oid and part.parentid = ind.indexrelid order by 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
drop index ip_index_local;
drop table if exists hw_partition_index_ip;
select count(*) from pg_class class , pg_partition part , pg_index ind where class.relname = 'hw_partition_index_ip' and ind.indrelid = class.oid and part.parentid = ind.indexrelid;
--
---- test input for unique index
--
create table interval_partition_table_001
(
c1 int,
logdate date not null
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION interval_partition_table_001_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_partition_table_001_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION interval_partition_table_001_p2 VALUES LESS THAN ('2020-05-01')
);
create unique index index_interval_partition_table_001 on interval_partition_table_001(logdate) local;
--fail: unique index
insert into interval_partition_table_001 values(10, '2020-06-01');
insert into interval_partition_table_001 values(10, '2020-06-01');
analyze interval_partition_table_001;
drop table interval_partition_table_001;
--
---- test with primary key
--
create table interval_partition_table_002(
c1 int,
c2 int,
logdate date not null,
CONSTRAINT interval_partition_table_CONSTRAINT PRIMARY KEY(c2,logdate)
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION interval_partition_table_002_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_partition_table_002_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION interval_partition_table_002_p2 VALUES LESS THAN ('2020-05-01')
);
insert into interval_partition_table_002 values(10, 10, '2020-06-01');
insert into interval_partition_table_002 values(10, 10, '2020-06-01');
analyze interval_partition_table_002;
drop table interval_partition_table_002;
--
---- test with hash index, not support hash index yet;
--
create table interval_partition_table_003(
c1 int,
c2 int,
logdate date not null,
PRIMARY KEY(c2,logdate)
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION interval_partition_table_003_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_partition_table_003_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION interval_partition_table_003_p2 VALUES LESS THAN ('2020-05-01')
);
create index interval_partition_table_003_1 ON interval_partition_table_003 USING HASH (logdate) LOCAL;
create index interval_partition_table_003_2 ON interval_partition_table_003 USING HASH (c2) LOCAL;
create index interval_partition_table_003_3 ON interval_partition_table_003 USING HASH (c1) LOCAL;
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_1') order by 1;
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_2') order by 1;
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_3') order by 1;
insert into interval_partition_table_003 values(1,2,'2020-03-01');
insert into interval_partition_table_003 values(1,2,'2020-04-01');
insert into interval_partition_table_003 values(1,2,'2020-05-01');
insert into interval_partition_table_003 values(1,2,'2020-06-01');
insert into interval_partition_table_003 values(1,2,'2020-07-01');
alter table interval_partition_table_003 drop column C2;
insert into interval_partition_table_003 values(1,2,'2020-07-01');
insert into interval_partition_table_003 values(1,'2020-07-01');
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_1') order by 1;
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_2') order by 1;
select relname from pg_partition where INDEXTBLID=(select RELFILENODE from pg_partition where relname='interval_partition_table_003_3') order by 1;
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'interval_partition_table_003')
order by relname;
analyze interval_partition_table_003;
drop table interval_partition_table_003;
--
---- test partition BTREE index
--
create table interval_partition_table_004(
c1 int,
c2 int,
logdate date not null,
PRIMARY KEY(c2,logdate)
)
partition by range (logdate)
INTERVAL ('1 month')
(
PARTITION interval_partition_table_004_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION interval_partition_table_004_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION interval_partition_table_004_p2 VALUES LESS THAN ('2020-05-01')
);
-- expression index
CREATE INDEX interval_partition_table_004_index_01 on interval_partition_table_004 using btree(c2) local;
CREATE INDEX interval_partition_table_004_index_02 on interval_partition_table_004 using btree(logdate) local;
CREATE INDEX interval_partition_table_004_index_03 on interval_partition_table_004 using btree(c1) local;
insert into interval_partition_table_004 values(7,2,'2020-03-01');
insert into interval_partition_table_004 values(3,1,'2020-04-01');
insert into interval_partition_table_004 values(5,3,'2020-05-01');
insert into interval_partition_table_004 values(7,5,'2020-06-01');
insert into interval_partition_table_004 values(1,4,'2020-07-01');
SELECT * FROM interval_partition_table_004 ORDER BY logdate;
SELECT * FROM interval_partition_table_004 ORDER BY 1;
SELECT * FROM interval_partition_table_004 ORDER BY 2;
DROP TABLE interval_partition_table_004;
-- test interval table with toast table and index
CREATE TABLE interval_sales
(prod_id NUMBER(6),
cust_id NUMBER,
time_id DATE,
channel_id CHAR(1),
promo_id NUMBER(6),
quantity_sold NUMBER(3),
amount_sold NUMBER(10,2)
)
PARTITION BY RANGE (time_id)
INTERVAL('1 MONTH')
( PARTITION p0 VALUES LESS THAN (TO_DATE('1-1-2008', 'DD-MM-YYYY')),
PARTITION p1 VALUES LESS THAN (TO_DATE('6-5-2008', 'DD-MM-YYYY'))
);
select relname, parentid, reltoastrelid, boundaries from pg_partition;
insert into interval_sales values (generate_series(1,10), generate_series(1,10), generate_series(TO_DATE('2020-01-01', 'YYYY-MM-DD'),TO_DATE('2020-07-01', 'YYYY-MM-DD'),'1 day'), 1, 1, 1, 1);
select relname, parentid, reltoastrelid, boundaries from pg_partition;
drop table interval_sales;
--
---- test exchange table whit index
--

View File

@ -0,0 +1,64 @@
--
---- test row movement
--
drop table if exists hw_partition_interval_movement;
create table hw_partition_interval_movement
(
c1 int,
c2 int,
C3 date not null
)
partition by range (C3)
INTERVAL ('1 month')
(
PARTITION hw_partition_interval_movement_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION hw_partition_interval_movement_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION hw_partition_interval_movement_p2 VALUES LESS THAN ('2020-05-01')
) DISABLE ROW MOVEMENT;
create index hw_partition_interval_movement_ind1 on hw_partition_interval_movement(c1) local;
create index hw_partition_interval_movement_ind2 on hw_partition_interval_movement(c2) local;
create index hw_partition_interval_movement_ind3 on hw_partition_interval_movement(c3) local;
--insert into table
insert into hw_partition_interval_movement values(7,2,'2020-02-01');
insert into hw_partition_interval_movement values(3,1,'2020-03-01');
insert into hw_partition_interval_movement values(5,3,'2020-04-01');
insert into hw_partition_interval_movement values(7,5,'2020-05-01');
insert into hw_partition_interval_movement values(1,4,'2020-06-01');
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'hw_partition_interval_movement')
order by 1;
-- fail: update record belongs to a range partition which will be move to other range partition
update hw_partition_interval_movement set C3 = '2020-04-22' where C3 = '2020-03-01';
-- fail: update record belongs to a range partition which will be move to an existed interval partition
update hw_partition_interval_movement set C3 = '2020-05-22' where C3 = '2020-03-01';
-- fail: update record belongs to a range partition which will be move to a not existed interval partition
update hw_partition_interval_movement set C3 = '2020-07-22' where C3 = '2020-03-01';
-- fail: update record belongs to a interval partition which will be move to a range partition
update hw_partition_interval_movement set C3 = '2020-03-22' where C3 = '2020-05-01';
-- fail: update record belongs to a interval partition which will be move to a not existed interval partition
update hw_partition_interval_movement set C3 = '2020-07-22' where C3 = '2020-05-01';
-- enable row movement
alter table hw_partition_interval_movement ENABLE ROW MOVEMENT;
-- succeed: update record belongs to a range partition which will be move to other range partition
update hw_partition_interval_movement set C3 = '2020-04-22' where C3 = '2020-03-01';
-- succeed: update record belongs to a range partition which will be move to an existed interval partition
update hw_partition_interval_movement set C3 = '2020-05-22' where C3 = '2020-04-22';
-- succeed: update record belongs to a range partition which will be move to a not existed interval partition
update hw_partition_interval_movement set C3 = '2020-07-22' where C3 = '2020-04-01';
-- succeed: update record belongs to a interval partition which will be move to a range partition
update hw_partition_interval_movement set C3 = '2020-03-22' where C3 = '2020-05-01';
-- succeed: update record belongs to a interval partition which will be move to a not existed interval partition
update hw_partition_interval_movement set C3 = '2020-08-22' where C3 = '2020-06-01';
select * from hw_partition_interval_movement;
-- add two new interval ranges
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'hw_partition_interval_movement')
order by 1;
drop table hw_partition_interval_movement;

View File

@ -0,0 +1,7 @@
-- check results and clean
select count(*) from partition_interval_parallel;
select relname, parttype, partstrategy, boundaries, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'partition_interval_parallel')
order by 1;
--cleanup
DROP TABLE partition_interval_parallel;

View File

@ -0,0 +1,23 @@
--insert data
create or replace function insert_mm(dat text) returns void as $$
declare
times integer :=1;
begin
loop
insert into partition_interval_parallel values(1, 1, dat);
times = times + 1;
if times > 500 then
exit;
end if;
end loop;
end;
$$ language plpgsql;
select insert_mm('2020-05-1');
select insert_mm('2020-06-1');
select insert_mm('2020-07-1');
select insert_mm('2020-08-1');
select insert_mm('2020-09-1');
select insert_mm('2020-10-1');
select insert_mm('2020-11-1');

View File

@ -0,0 +1,23 @@
--insert data
create or replace function insert_mm_01(dat text) returns void as $$
declare
times integer :=1;
begin
loop
insert into partition_interval_parallel values(1, 1, dat);
times = times + 1;
if times > 500 then
exit;
end if;
end loop;
end;
$$ language plpgsql;
select insert_mm_01('2020-05-1');
select insert_mm_01('2020-06-1');
select insert_mm_01('2020-07-1');
select insert_mm_01('2020-08-1');
select insert_mm_01('2020-09-1');
select insert_mm_01('2020-10-1');
select insert_mm_01('2020-11-1');

View File

@ -0,0 +1,23 @@
--insert data
create or replace function insert_mm_02(dat text) returns void as $$
declare
times integer :=1;
begin
loop
insert into partition_interval_parallel values(1, 1, dat);
times = times + 1;
if times > 500 then
exit;
end if;
end loop;
end;
$$ language plpgsql;
select insert_mm_02('2020-05-1');
select insert_mm_02('2020-06-1');
select insert_mm_02('2020-07-1');
select insert_mm_02('2020-08-1');
select insert_mm_02('2020-09-1');
select insert_mm_02('2020-10-1');
select insert_mm_02('2020-11-1');

View File

@ -0,0 +1,20 @@
-- prepare the parrallel modifed table;
DROP TABLE IF EXISTS partition_interval_parallel;
create table partition_interval_parallel
(
c1 int,
c2 int,
c3 date not null
)
partition by range (c3)
INTERVAL ('1 month')
(
PARTITION partition_interval_parallel_p1 VALUES LESS THAN ('2020-05-01'),
PARTITION partition_interval_parallel_p2 VALUES LESS THAN ('2020-06-01')
);
CREATE INDEX idx1_partition_interval_parallel on partition_interval_parallel(c3) local ;

View File

@ -0,0 +1,65 @@
--01--------------------------------------------------------------------
--prepare table , index
drop table if exists partition_reindex_table3;
create table partition_reindex_table3
(
c1 int,
c2 int,
C3 date not null
)
partition by range (C3)
INTERVAL ('1 month')
(
PARTITION partition_reindex_table3_p0 VALUES LESS THAN ('2020-02-01'),
PARTITION partition_reindex_table3_p1 VALUES LESS THAN ('2020-05-01'),
PARTITION partition_reindex_table3_p2 VALUES LESS THAN ('2020-06-01')
)
enable row movement;
create index partition_reindex_table3_ind1 on partition_reindex_table3(c1) local;
create index partition_reindex_table3_ind2 on partition_reindex_table3(c2) local;
create index partition_reindex_table3_ind3 on partition_reindex_table3(c3) local;
--02--------------------------------------------------------------------
--reindex index, cross test with insert
insert into partition_reindex_table3 values (generate_series(1,10), generate_series(1,10), generate_series(TO_DATE('2020-01-01', 'YYYY-MM-DD'),TO_DATE('2020-07-01', 'YYYY-MM-DD'),'1, day'));
select count(*) from partition_reindex_table3;
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'partition_reindex_table3')
order by 1;
truncate table partition_reindex_table3;
insert into partition_reindex_table3 values (generate_series(1,10), generate_series(1,10), generate_series(TO_DATE('2020-01-01', 'YYYY-MM-DD'),TO_DATE('2020-07-01', 'YYYY-MM-DD'),'1, day'));
select count(*) from partition_reindex_table3;
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'partition_reindex_table3')
order by 1;
analyze partition_reindex_table3;
select c.relname,c.relpages > 0 as relpagesgtzero, c.reltuples > 0 as reltuplesgtzero,i.indisunique, i.indisvalid, i.indcheckxmin, i.indisready from pg_index i, pg_class c where c.relname = 'partition_reindex_table3_ind1' and c.oid = i.indexrelid;
explain (costs off, nodes off) select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
reindex index partition_reindex_table3_ind1;
select c.relname,c.relpages > 0 as relpagesgtzero, c.reltuples > 0 as reltuplesgtzero,i.indisunique, i.indisvalid, i.indcheckxmin, i.indisready from pg_index i, pg_class c where c.relname = 'partition_reindex_table3_ind1' and c.oid = i.indexrelid;
explain (costs off, nodes off) select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
--the plan before reindex and after reindex should be same
select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
--03--------------------------------------------------------------------
--reindex table cross test with truncate
truncate table partition_reindex_table3;
insert into partition_reindex_table3 values (generate_series(1,10), generate_series(1,10), generate_series(TO_DATE('2020-01-01', 'YYYY-MM-DD'),TO_DATE('2020-07-01', 'YYYY-MM-DD'),'1, day'));
analyze partition_reindex_table3;
select c.relname,c.relpages > 0 as relpagesgtzero, c.reltuples > 0 as reltuplesgtzero,i.indisunique, i.indisvalid, i.indcheckxmin, i.indisready from pg_index i, pg_class c where c.relname = 'partition_reindex_table3_ind1' and c.oid = i.indexrelid;
explain (costs off, nodes off) select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
reindex index partition_reindex_table3_ind1;
select c.relname,c.relpages > 0 as relpagesgtzero, c.reltuples > 0 as reltuplesgtzero,i.indisunique, i.indisvalid, i.indcheckxmin, i.indisready from pg_index i, pg_class c where c.relname = 'partition_reindex_table3_ind1' and c.oid = i.indexrelid;
explain (costs off, nodes off) select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
--the plan before reindex and after reindex should be same
select * from partition_reindex_table3 where c3 = TO_DATE('2020-04-21', 'YYYY-MM-DD') and c2 = 8;
--clean
drop table partition_reindex_table3;

View File

@ -0,0 +1,54 @@
CREATE TABLE interval_tab1 (
city_id int not null,
logdate date not null,
peaktemp int,
unitsales int
)
PARTITION BY RANGE (logdate)
INTERVAL ('1 day')
(
PARTITION p1 VALUES LESS THAN (('2020-03-01'))
);
insert into interval_tab1 values(1,'2020-4-7 2:0:0', 1, 1);
insert into interval_tab1 values(1,'2020-4-8 2:0:0', 1, 1);
select relname, boundaries from pg_partition;
select * from interval_tab1 where logdate < '2020-4-7 0:0:0';
explain (costs off, verbose on, nodes off) select * from interval_tab1 where logdate < '2020-4-7 0:0:0';
select * from interval_tab1 where logdate > '2020-4-6';
explain (costs off, verbose on, nodes off) select * from interval_tab1 where logdate > '2020-4-6';
select * from interval_tab1 where logdate = '2020-4-7 2:0:0';
insert into interval_tab1 values(1,'2020-4-7 0:0:0', 1, 1);
select * from interval_tab1 where logdate = '2020-4-7 0:0:0';
select * from interval_tab1 where logdate != '2020-4-7 0:0:0';
select * from interval_tab1 where logdate >= '2020-4-7 0:0:0';
insert into interval_tab1 values(1,'2020-4-5 2:0:0', 1, 1);
select relname, boundaries from pg_partition;
insert into interval_tab1 values(1,'2020-4-9 0:0:0', 1, 1);
select * from interval_tab1 where logdate >= '2020-4-7 0:0:0' and logdate < '2020-4-9 0:0:0';
select * from interval_tab1 where logdate > '2020-4-7 0:0:0' and logdate <= '2020-4-9 0:0:0';
select * from interval_tab1 where logdate >= '2020-4-7 0:0:0' and logdate <= '2020-4-9 0:0:0';
select * from interval_tab1 where logdate > '2020-4-6 0:0:0' and logdate <= '2020-4-9 0:0:0';
explain (costs off, verbose on, nodes off) select * from interval_tab1 where logdate >= '2020-4-10 0:0:0';
drop table interval_tab1;

View File

@ -0,0 +1,256 @@
--create table
DROP TABLE IF EXISTS partition_unsable_index_1;
create table partition_unsable_index_1
(
c1 int,
c2 int,
c3 date not null
)
partition by range (c3)
INTERVAL ('1 month')
(
PARTITION partition_unsable_index_1_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION partition_unsable_index_1_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION partition_unsable_index_1_p2 VALUES LESS THAN ('2020-05-01')
);
-- create 3 indexes, and specify it's partition name
CREATE INDEX idx1_partition_unsable_index_1 on partition_unsable_index_1(c3) local
(
partition idx1_partition_unsable_index_1_p1,
partition idx1_partition_unsable_index_1_p2,
partition idx1_partition_unsable_index_1_p3
);
CREATE INDEX idx2_partition_unsable_index_1 on partition_unsable_index_1(c2, c3) local
(
partition idx2_partition_unsable_index_1_p1,
partition idx2_partition_unsable_index_1_p2,
partition idx2_partition_unsable_index_1_p3
);
CREATE INDEX idx3_partition_unsable_index_1 on partition_unsable_index_1(c1, c2, c3) local
(
partition idx3_partition_unsable_index_1_p1,
partition idx3_partition_unsable_index_1_p2,
partition idx3_partition_unsable_index_1_p3
);
--insert data
insert into partition_unsable_index_1 values(7,2,'2020-03-01');
insert into partition_unsable_index_1 values(3,1,'2020-04-01');
insert into partition_unsable_index_1 values(5,3,'2020-05-01');
insert into partition_unsable_index_1 values(7,5,'2020-06-01');
insert into partition_unsable_index_1 values(1,4,'2020-07-01');
-- query all index partitions
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by relname;
-- 1. alter index, modify one of it's partition to unusable state
ALTER INDEX idx1_partition_unsable_index_1 MODIFY PARTITION idx1_partition_unsable_index_1_p1 UNUSABLE;
-- check indunusable info
select relname, parttype, partstrategy, boundaries, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
-- rebuild index partition
ALTER INDEX idx1_partition_unsable_index_1 REBUILD PARTITION idx1_partition_unsable_index_1_p1;
-- check indunusable info
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
--2.ALTER INDEX unusable
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
ALTER INDEX idx1_partition_unsable_index_1 UNUSABLE;
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
ALTER INDEX idx1_partition_unsable_index_1 REBUILD;
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
--test for reindex partition
ALTER INDEX idx1_partition_unsable_index_1 UNUSABLE;
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
REINDEX INDEX idx1_partition_unsable_index_1 PARTITION idx1_partition_unsable_index_1_p1;
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
ALTER INDEX idx1_partition_unsable_index_1 REBUILD;
select relname, parttype, partstrategy, indisusable from pg_partition
where parentid = (select oid from pg_class where relname = 'idx1_partition_unsable_index_1')
order by 1;
-- 3. alter table, modify one of it's partition's all indexes to unusable state
ALTER TABLE partition_unsable_index_1 MODIFY PARTITION partition_unsable_index_1_p0 UNUSABLE LOCAL INDEXES;
-- check indunusable info
select relname, indisusable from pg_partition
where relname = 'idx1_partition_unsable_index_1_p1'
or relname = 'idx2_partition_unsable_index_1_p1'
or relname = 'idx3_partition_unsable_index_1_p1'
or relname = 'p1_partition_unsable_index_1'
order by 1;
-- rebuild
ALTER TABLE partition_unsable_index_1 MODIFY PARTITION partition_unsable_index_1_p0 REBUILD UNUSABLE LOCAL INDEXES;
-- check again
select relname, indisusable from pg_partition
where relname = 'idx1_partition_unsable_index_1_p1'
or relname = 'idx2_partition_unsable_index_1_p1'
or relname = 'idx3_partition_unsable_index_1_p1'
or relname = 'p1_partition_unsable_index_1'
order by 1;
ALTER INDEX idx1_partition_unsable_index_1 MODIFY PARTITION idx1_partition_unsable_index_1_p1 UNUSABLE;
-- idx1_partition_unsable_index_1_p1 is unusable
select part.relname, part.indisusable
from pg_class class , pg_partition part , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
and part.parentid = ind.indexrelid
order by 1;
-- can not cluster partition bacause of unusable local index
CLUSTER partition_unsable_index_1 PARTITION (partition_unsable_index_1_p0) USING idx1_partition_unsable_index_1;
CLUSTER partition_unsable_index_1 USING idx1_partition_unsable_index_1;
-- indisclustered is false
select class.relname, ind.indisclustered
from pg_class class , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
order by 2;
-- cluster ok
ALTER INDEX idx1_partition_unsable_index_1 REBUILD;
CLUSTER partition_unsable_index_1 USING idx1_partition_unsable_index_1;
-- idx1_partition_unsable_index_1_p1 is usable
select part.relname, part.indisusable
from pg_class class , pg_partition part , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
and part.parentid = ind.indexrelid
order by 1;
-- indisclustered is true
select class.relname, ind.indisclustered
from pg_class class , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
order by 2;
-- cluster other index
ALTER INDEX idx2_partition_unsable_index_1 MODIFY PARTITION idx2_partition_unsable_index_1_p1 UNUSABLE;
ALTER INDEX idx2_partition_unsable_index_1 REBUILD;
CLUSTER partition_unsable_index_1 USING idx2_partition_unsable_index_1;
select class.relname, ind.indisclustered
from pg_class class , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
order by 2;
-- cluster a partition
ALTER INDEX idx1_partition_unsable_index_1 MODIFY PARTITION idx1_partition_unsable_index_1_p1 UNUSABLE;
ALTER INDEX idx1_partition_unsable_index_1 REBUILD PARTITION idx1_partition_unsable_index_1_p1;
CLUSTER partition_unsable_index_1 PARTITION (partition_unsable_index_1_p0) USING idx1_partition_unsable_index_1;
CLUSTER partition_unsable_index_1 USING idx1_partition_unsable_index_1;
select class.relname, ind.indisclustered
from pg_class class , pg_index ind
where class.relname = 'partition_unsable_index_1'
and ind.indrelid = class.oid
order by 2;
--5.2 merge (not support yet, keep the case hear for support in the future)
-- merge failed due to unusable index partition
ALTER INDEX idx1_partition_unsable_index_1 MODIFY PARTITION idx1_partition_unsable_index_1_p1 UNUSABLE;
ALTER TABLE partition_unsable_index_1 MERGE PARTITIONS partition_unsable_index_1_p0, p2_partition_unsable_index_3
INTO PARTITION px_partition_unsable_index_3;
--rebuild unusable index partition
ALTER INDEX idx1_partition_unsable_index_1 REBUILD PARTITION idx1_partition_unsable_index_1_p1;
--5.3 exchange
-- create plain table and index
CREATE TABLE table_unusable_index_exchange (c1 int, c2 int, c3 date not null);
CREATE INDEX idx1_table_unusable_index_exchange on table_unusable_index_exchange(c3);
CREATE INDEX idx2_table_unusable_index_exchange on table_unusable_index_exchange(c2, c3);
CREATE INDEX idx3_table_unusable_index_exchange on table_unusable_index_exchange(c1, c2, c3);
--- unusable non-partitioned-index
ALTER INDEX idx1_table_unusable_index_exchange UNUSABLE;
ALTER TABLE partition_unsable_index_1 EXCHANGE PARTITION (partition_unsable_index_1_p0)
WITH TABLE table_unusable_index_exchange;
ALTER INDEX idx1_table_unusable_index_exchange REBUILD;
-- unusable partitioned-index
ALTER INDEX idx1_partition_unsable_index_1 UNUSABLE;
ALTER TABLE partition_unsable_index_1 EXCHANGE PARTITION (partition_unsable_index_1_p0)
WITH TABLE table_unusable_index_exchange;
ALTER INDEX idx1_partition_unsable_index_1 REBUILD;
-- modify one index partition unusable
-- exchange failed due to unusable index partition
ALTER INDEX idx1_partition_unsable_index_1 MODIFY PARTITION idx1_partition_unsable_index_1_p1 UNUSABLE;
ALTER TABLE partition_unsable_index_1 EXCHANGE PARTITION (partition_unsable_index_1_p0)
WITH TABLE table_unusable_index_exchange;
-- exchange ok
ALTER INDEX idx1_partition_unsable_index_1 REBUILD PARTITION idx1_partition_unsable_index_1_p1;
ALTER TABLE partition_unsable_index_1 EXCHANGE PARTITION (partition_unsable_index_1_p0)
WITH TABLE table_unusable_index_exchange;
-- clean table_unusable_index_exchange
DROP TABLE table_unusable_index_exchange;
DROP TABLE partition_unsable_index_1;
--6. index and unique index check
create table partition_unsable_index_1
(
c1 int,
c2 int,
c3 date not null
)
partition by range (c3)
INTERVAL ('1 month')
(
PARTITION partition_unsable_index_1_p0 VALUES LESS THAN ('2020-03-01'),
PARTITION partition_unsable_index_1_p1 VALUES LESS THAN ('2020-04-01'),
PARTITION partition_unsable_index_1_p2 VALUES LESS THAN ('2020-05-01')
);
-- create a unique index
CREATE UNIQUE INDEX idx_unique_partition_unsable_index_1 on partition_unsable_index_1(c2, c3) LOCAL
(
partition idx_unique_partition_unsable_index_1_p1,
partition idx_unique_partition_unsable_index_1_p2,
partition idx_unique_partition_unsable_index_1_p3
);
--insert duplicated rows should report error
insert into partition_unsable_index_1 values(3,3,'2020-02-01');
insert into partition_unsable_index_1 values(5,3,'2020-02-01'); -- fail
-- set local index unusable
ALTER INDEX idx_unique_partition_unsable_index_1 MODIFY PARTITION idx_unique_partition_unsable_index_1_p1 UNUSABLE;
-- bypass the unique index check
insert into partition_unsable_index_1 values(5,3,'2020-02-01'); -- success
--but report unique check error here
ALTER INDEX idx_unique_partition_unsable_index_1 REBUILD PARTITION idx_unique_partition_unsable_index_1_p1;
-- cleanup
DROP INDEX idx_unique_partition_unsable_index_1;
insert into partition_unsable_index_1 values(5,3,'2020-02-01'); -- success
--cleanup
DROP TABLE partition_unsable_index_1;