forked from huawei/openGauss-server
[patch] support interval partition table
This commit is contained in:
parent
0c06c55ea6
commit
8a87c14084
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
--
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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 ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
--
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
@ -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
|
||||
--
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
--
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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');
|
||||
|
|
@ -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');
|
||||
|
|
@ -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');
|
||||
|
|
@ -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 ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
Loading…
Reference in New Issue