code for Global-Partition-Index feature
Signed-off-by: xiliu <xiliu_h@163.com>
This commit is contained in:
@ -1582,6 +1582,7 @@ void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc
|
||||
resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
|
||||
resultRelInfo->ri_RelationDesc = resultRelationDesc;
|
||||
resultRelInfo->ri_NumIndices = 0;
|
||||
resultRelInfo->ri_ContainGPI = false;
|
||||
resultRelInfo->ri_IndexRelationDescs = NULL;
|
||||
resultRelInfo->ri_IndexRelationInfo = NULL;
|
||||
/* make a copy so as not to depend on relcache info not changing... */
|
||||
|
||||
@ -1112,6 +1112,7 @@ void ExecOpenIndices(ResultRelInfo* resultRelInfo, bool speculative)
|
||||
IndexInfo** indexInfoArray;
|
||||
|
||||
resultRelInfo->ri_NumIndices = 0;
|
||||
resultRelInfo->ri_ContainGPI = false;
|
||||
|
||||
/* fast path if no indexes */
|
||||
if (!RelationGetForm(resultRelation)->relhasindex)
|
||||
@ -1155,6 +1156,12 @@ void ExecOpenIndices(ResultRelInfo* resultRelInfo, bool speculative)
|
||||
index_close(indexDesc, RowExclusiveLock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check index whether is global parition index, and save */
|
||||
if (RelationIsGlobalIndex(indexDesc)) {
|
||||
resultRelInfo->ri_ContainGPI = true;
|
||||
}
|
||||
|
||||
/* extract index key information from the index's pg_index info */
|
||||
ii = BuildIndexInfo(indexDesc);
|
||||
|
||||
@ -1397,6 +1404,7 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e
|
||||
bool isnull[INDEX_MAX_KEYS];
|
||||
Relation actualheap;
|
||||
bool ispartitionedtable = false;
|
||||
bool containGPI;
|
||||
List* partitionIndexOidList = NIL;
|
||||
|
||||
/*
|
||||
@ -1407,6 +1415,7 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e
|
||||
relationDescs = resultRelInfo->ri_IndexRelationDescs;
|
||||
indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
|
||||
heapRelation = resultRelInfo->ri_RelationDesc;
|
||||
containGPI = resultRelInfo->ri_ContainGPI;
|
||||
|
||||
/*
|
||||
* We will use the EState's per-tuple context for evaluating predicates
|
||||
@ -1427,7 +1436,8 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e
|
||||
if (p == NULL || p->pd_part == NULL) {
|
||||
return NIL;
|
||||
}
|
||||
if (!p->pd_part->indisusable) {
|
||||
/* If the global partition index is included, the index insertion process needs to continue */
|
||||
if (!p->pd_part->indisusable && !containGPI) {
|
||||
numIndices = 0;
|
||||
}
|
||||
} else {
|
||||
@ -1437,6 +1447,15 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e
|
||||
if (bucketId != InvalidBktId) {
|
||||
searchHBucketFakeRelation(estate->esfRelations, estate->es_query_cxt, actualheap, bucketId, actualheap);
|
||||
}
|
||||
|
||||
/* Partition create in current transaction, set partition and rel reloption wait_clean_gpi */
|
||||
if (RelationCreateInCurrXact(actualheap) && containGPI && !PartitionEnableWaitCleanGpi(p)) {
|
||||
/* partition create not set wait_clean_gpi, must use update, and we ensure no concurrency */
|
||||
PartitionSetWaitCleanGpi(RelationGetRelid(actualheap), true, false);
|
||||
/* Partitioned create set wait_clean_gpi=n, and we want save it, so just use inplace */
|
||||
PartitionedSetWaitCleanGpi(RelationGetRelationName(heapRelation), RelationGetRelid(heapRelation), true, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* for each index, form and insert the index tuple
|
||||
*/
|
||||
@ -1461,28 +1480,36 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ispartitionedtable) {
|
||||
partitionedindexid = RelationGetRelid(indexRelation);
|
||||
if (!PointerIsValid(partitionIndexOidList)) {
|
||||
partitionIndexOidList = PartitionGetPartIndexList(p);
|
||||
// no local indexes available
|
||||
if (!PointerIsValid(partitionIndexOidList)) {
|
||||
return NIL;
|
||||
if (ispartitionedtable && !RelationIsGlobalIndex(indexRelation)) {
|
||||
/* The GPI index insertion is the same as that of a common table */
|
||||
if (RelationIsGlobalIndex(indexRelation)) {
|
||||
if (indexRelation->rd_index->indisusable == false) {
|
||||
continue;
|
||||
}
|
||||
actualindex = indexRelation;
|
||||
} else {
|
||||
partitionedindexid = RelationGetRelid(indexRelation);
|
||||
if (!PointerIsValid(partitionIndexOidList)) {
|
||||
partitionIndexOidList = PartitionGetPartIndexList(p);
|
||||
// no local indexes available
|
||||
if (!PointerIsValid(partitionIndexOidList)) {
|
||||
return NIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indexpartitionid = searchPartitionIndexOid(partitionedindexid, partitionIndexOidList);
|
||||
indexpartitionid = searchPartitionIndexOid(partitionedindexid, partitionIndexOidList);
|
||||
|
||||
searchFakeReationForPartitionOid(estate->esfRelations,
|
||||
estate->es_query_cxt,
|
||||
indexRelation,
|
||||
indexpartitionid,
|
||||
actualindex,
|
||||
indexpartition,
|
||||
RowExclusiveLock);
|
||||
// skip unusable index
|
||||
if (false == indexpartition->pd_part->indisusable) {
|
||||
continue;
|
||||
searchFakeReationForPartitionOid(estate->esfRelations,
|
||||
estate->es_query_cxt,
|
||||
indexRelation,
|
||||
indexpartitionid,
|
||||
actualindex,
|
||||
indexpartition,
|
||||
RowExclusiveLock);
|
||||
// skip unusable index
|
||||
if (false == indexpartition->pd_part->indisusable) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
actualindex = indexRelation;
|
||||
@ -1617,7 +1644,7 @@ bool check_violation(Relation heap, Relation index, IndexInfo* indexInfo, ItemPo
|
||||
Oid* constr_procs = indexInfo->ii_ExclusionProcs;
|
||||
uint16* constr_strats = indexInfo->ii_ExclusionStrats;
|
||||
Oid* index_collations = index->rd_indcollation;
|
||||
int index_natts = index->rd_index->indnatts;
|
||||
int indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index);
|
||||
IndexScanDesc index_scan;
|
||||
HeapTuple tup;
|
||||
ScanKeyData scankeys[INDEX_MAX_KEYS];
|
||||
@ -1633,7 +1660,7 @@ bool check_violation(Relation heap, Relation index, IndexInfo* indexInfo, ItemPo
|
||||
* If any of the input values are NULL, the constraint check is assumed to
|
||||
* pass (i.e., we assume the operators are strict).
|
||||
*/
|
||||
for (i = 0; i < index_natts; i++) {
|
||||
for (i = 0; i < indnkeyatts; i++) {
|
||||
if (isnull[i]) {
|
||||
return true;
|
||||
}
|
||||
@ -1652,7 +1679,7 @@ bool check_violation(Relation heap, Relation index, IndexInfo* indexInfo, ItemPo
|
||||
*/
|
||||
InitDirtySnapshot(DirtySnapshot);
|
||||
|
||||
for (i = 0; i < index_natts; i++) {
|
||||
for (i = 0; i < indnkeyatts; i++) {
|
||||
ScanKeyEntryInitialize(
|
||||
&scankeys[i], 0, i + 1, constr_strats[i], InvalidOid, index_collations[i], constr_procs[i], values[i]);
|
||||
}
|
||||
@ -1677,8 +1704,8 @@ bool check_violation(Relation heap, Relation index, IndexInfo* indexInfo, ItemPo
|
||||
retry:
|
||||
conflict = false;
|
||||
found_self = false;
|
||||
index_scan = index_beginscan(heap, index, &DirtySnapshot, index_natts, 0);
|
||||
index_rescan(index_scan, scankeys, index_natts, NULL, 0);
|
||||
index_scan = index_beginscan(heap, index, &DirtySnapshot, indnkeyatts, 0);
|
||||
index_rescan(index_scan, scankeys, indnkeyatts, NULL, 0);
|
||||
|
||||
while ((tup = index_getnext(index_scan, ForwardScanDirection)) != NULL) {
|
||||
TransactionId xwait;
|
||||
@ -1795,10 +1822,10 @@ retry:
|
||||
static bool index_recheck_constraint(
|
||||
Relation index, Oid* constr_procs, Datum* existing_values, const bool* existing_isnull, Datum* new_values)
|
||||
{
|
||||
int index_natts = index->rd_index->indnatts;
|
||||
int indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < index_natts; i++) {
|
||||
for (i = 0; i < indnkeyatts; i++) {
|
||||
/* Assume the exclusion operators are strict */
|
||||
if (existing_isnull[i]) {
|
||||
return false;
|
||||
|
||||
@ -125,6 +125,18 @@ Node* MultiExecBitmapAnd(BitmapAndState* node)
|
||||
if (result == NULL) {
|
||||
result = subresult; /* first subplan */
|
||||
} else {
|
||||
/*
|
||||
* If the global tbm intersect with non-global tbm,
|
||||
* set the final result to non-global tbm.
|
||||
*
|
||||
* Notes: This scenario means that the two filter criteria used in the where
|
||||
* condition of the sql statement, one uses the local partitioned index and
|
||||
* the other uses the global partitioned index
|
||||
*/
|
||||
if (tbm_is_global(result) != tbm_is_global(subresult)) {
|
||||
tbm_set_global(result, false);
|
||||
}
|
||||
|
||||
tbm_intersect(result, subresult);
|
||||
tbm_free(subresult);
|
||||
}
|
||||
|
||||
@ -58,6 +58,12 @@ static void bitgetpage(HeapScanDesc scan, TBMIterateResult* tbmres);
|
||||
static void ExecInitPartitionForBitmapHeapScan(BitmapHeapScanState* scanstate, EState* estate);
|
||||
static void ExecInitNextPartitionForBitmapHeapScan(BitmapHeapScanState* node);
|
||||
|
||||
/* This struct is used for partition switch while prefetch pages */
|
||||
typedef struct PrefetchNode {
|
||||
BlockNumber blockNum;
|
||||
Oid partOid;
|
||||
} PrefetchNode;
|
||||
|
||||
void BitmapHeapFree(BitmapHeapScanState* node)
|
||||
{
|
||||
if (node->tbmiterator != NULL) {
|
||||
@ -176,6 +182,19 @@ static TupleTableSlot* BitmapHeapTblNext(BitmapHeapScanState* node)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check whether switch partition-fake-rel, use rd_rel save */
|
||||
if (BitmapNodeNeedSwitchPartRel(node)) {
|
||||
GPISetCurrPartOid(node->gpi_scan, node->tbmres->partitionOid);
|
||||
if (!GPIGetNextPartRelation(node->gpi_scan, CurrentMemoryContext, AccessShareLock)) {
|
||||
/* If the current partition is invalid, the next page is directly processed */
|
||||
tbmres = NULL;
|
||||
continue;
|
||||
} else {
|
||||
scan->rs_rd = node->gpi_scan->fakePartRelation;
|
||||
scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_rd);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_PREFETCH
|
||||
if (node->prefetch_pages > 0) {
|
||||
/* The main iterator has closed the distance by one page */
|
||||
@ -281,11 +300,17 @@ static TupleTableSlot* BitmapHeapTblNext(BitmapHeapScanState* node)
|
||||
{
|
||||
BlockNumber* blockList = NULL;
|
||||
BlockNumber* blockListPtr = NULL;
|
||||
PrefetchNode* prefetchNode = NULL;
|
||||
PrefetchNode* prefetchNodePtr = NULL;
|
||||
int prefetchNow = 0;
|
||||
int prefetchWindow = node->prefetch_target - node->prefetch_pages;
|
||||
|
||||
/* We expect to prefetch at most prefetchWindow pages */
|
||||
if (prefetchWindow > 0) {
|
||||
if (tbm_is_global(tbm)) {
|
||||
prefetchNode = (PrefetchNode*)malloc(sizeof(PrefetchNode) * prefetchWindow);
|
||||
prefetchNodePtr = prefetchNode;
|
||||
}
|
||||
blockList = (BlockNumber*)palloc(sizeof(BlockNumber) * prefetchWindow);
|
||||
blockListPtr = blockList;
|
||||
}
|
||||
@ -299,7 +324,12 @@ static TupleTableSlot* BitmapHeapTblNext(BitmapHeapScanState* node)
|
||||
break;
|
||||
}
|
||||
node->prefetch_pages++;
|
||||
|
||||
/* we use PrefetchNode here to store relations between blockno and partition Oid */
|
||||
if (tbm_is_global(tbm)) {
|
||||
prefetchNodePtr->blockNum = tbmpre->blockno;
|
||||
prefetchNodePtr->partOid = tbmpre->partitionOid;
|
||||
prefetchNodePtr++;
|
||||
}
|
||||
/* For Async Direct I/O we accumulate a list and send it */
|
||||
*blockListPtr++ = tbmpre->blockno;
|
||||
prefetchNow++;
|
||||
@ -307,17 +337,51 @@ static TupleTableSlot* BitmapHeapTblNext(BitmapHeapScanState* node)
|
||||
|
||||
/* Send the list we generated and free it */
|
||||
if (prefetchNow) {
|
||||
PageListPrefetch(scan->rs_rd, MAIN_FORKNUM, blockList, prefetchNow, 0, 0);
|
||||
if (tbm_is_global(tbm)) {
|
||||
/*
|
||||
* we must save part Oid before switch relation, and recover it after prefetch.
|
||||
* The reason for this is to assure correctness while getting a new tbmres.
|
||||
*/
|
||||
Oid oldOid = GPIGetCurrPartOid(node->gpi_scan);
|
||||
int blkCount = 0;
|
||||
Oid prevOid = prefetchNode[0].partOid;
|
||||
for (int i = 0; i < prefetchNow; i++) {
|
||||
if (prefetchNode[i].partOid == prevOid) {
|
||||
blockList[blkCount++] = prefetchNode[i].blockNum;
|
||||
} else {
|
||||
GPISetCurrPartOid(node->gpi_scan, prevOid);
|
||||
if (GPIGetNextPartRelation(node->gpi_scan, CurrentMemoryContext, AccessShareLock)) {
|
||||
PageListPrefetch(
|
||||
node->gpi_scan->fakePartRelation, MAIN_FORKNUM, blockList, blkCount, 0, 0);
|
||||
}
|
||||
blkCount = 0;
|
||||
prevOid = prefetchNode[i].partOid;
|
||||
blockList[blkCount++] = prefetchNode[i].blockNum;
|
||||
}
|
||||
}
|
||||
GPISetCurrPartOid(node->gpi_scan, prevOid);
|
||||
if (GPIGetNextPartRelation(node->gpi_scan, CurrentMemoryContext, AccessShareLock)) {
|
||||
PageListPrefetch(node->gpi_scan->fakePartRelation, MAIN_FORKNUM, blockList, blkCount, 0, 0);
|
||||
}
|
||||
/* recover old oid after prefetch switch */
|
||||
GPISetCurrPartOid(node->gpi_scan, oldOid);
|
||||
} else {
|
||||
PageListPrefetch(scan->rs_rd, MAIN_FORKNUM, blockList, prefetchNow, 0, 0);
|
||||
}
|
||||
}
|
||||
if (prefetchWindow > 0) {
|
||||
pfree_ext(blockList);
|
||||
if (tbm_is_global(tbm)) {
|
||||
pfree_ext(prefetchNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
ADIO_ELSE()
|
||||
{
|
||||
Oid oldOid = GPIGetCurrPartOid(node->gpi_scan);
|
||||
while (node->prefetch_pages < node->prefetch_target) {
|
||||
TBMIterateResult* tbmpre = tbm_iterate(prefetch_iterator);
|
||||
|
||||
Relation prefetchRel = scan->rs_rd;
|
||||
if (tbmpre == NULL) {
|
||||
/* No more pages to prefetch */
|
||||
tbm_end_iterate(prefetch_iterator);
|
||||
@ -325,10 +389,21 @@ static TupleTableSlot* BitmapHeapTblNext(BitmapHeapScanState* node)
|
||||
break;
|
||||
}
|
||||
node->prefetch_pages++;
|
||||
|
||||
if (tbm_is_global(node->tbm) && GPIScanCheckPartOid(node->gpi_scan, tbmpre->partitionOid)) {
|
||||
GPISetCurrPartOid(node->gpi_scan, tbmpre->partitionOid);
|
||||
if (!GPIGetNextPartRelation(node->gpi_scan, CurrentMemoryContext, AccessShareLock)) {
|
||||
/* If the current partition is invalid, the next page is directly processed */
|
||||
tbmpre = NULL;
|
||||
continue;
|
||||
} else {
|
||||
prefetchRel = node->gpi_scan->fakePartRelation;
|
||||
}
|
||||
}
|
||||
/* For posix_fadvise() we just send the one request */
|
||||
PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
|
||||
PrefetchBuffer(prefetchRel, MAIN_FORKNUM, tbmpre->blockno);
|
||||
}
|
||||
/* recover old oid after prefetch switch */
|
||||
GPISetCurrPartOid(node->gpi_scan, oldOid);
|
||||
}
|
||||
ADIO_END();
|
||||
}
|
||||
@ -542,9 +617,9 @@ void ExecReScanBitmapHeapScan(BitmapHeapScanState* node)
|
||||
*/
|
||||
abs_tbl_endscan(node->ss.ss_currentScanDesc);
|
||||
|
||||
/* switch to next partition for scan */
|
||||
ExecInitNextPartitionForBitmapHeapScan(node);
|
||||
} else {
|
||||
/* switch to next partition for scan */
|
||||
ExecInitNextPartitionForBitmapHeapScan(node);
|
||||
} else {
|
||||
/* rescan to release any page pin */
|
||||
abs_tbl_rescan(node->ss.ss_currentScanDesc, NULL);
|
||||
}
|
||||
@ -598,20 +673,26 @@ void ExecEndBitmapHeapScan(BitmapHeapScanState* node)
|
||||
if (node->ss.ss_currentScanDesc != NULL) {
|
||||
abs_tbl_endscan(node->ss.ss_currentScanDesc);
|
||||
}
|
||||
|
||||
if (node->gpi_scan != NULL) {
|
||||
GPIScanEnd(node->gpi_scan);
|
||||
}
|
||||
|
||||
/* close heap scan */
|
||||
if (node->ss.isPartTbl && PointerIsValid(node->ss.partitions)) {
|
||||
/* close table partition */
|
||||
|
||||
Assert(node->ss.ss_currentPartition);
|
||||
releaseDummyRelation(&(node->ss.ss_currentPartition));
|
||||
Assert(node->ss.ss_currentPartition);
|
||||
releaseDummyRelation(&(node->ss.ss_currentPartition));
|
||||
|
||||
releasePartitionList(node->ss.ss_currentRelation, &(node->ss.partitions), NoLock);
|
||||
releasePartitionList(node->ss.ss_currentRelation, &(node->ss.partitions), NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* close the heap relation.
|
||||
*/
|
||||
ExecCloseScanRelation(relation);
|
||||
|
||||
}
|
||||
static inline void InitBitmapHeapScanNextMtd(BitmapHeapScanState* bmstate)
|
||||
{
|
||||
@ -659,6 +740,9 @@ BitmapHeapScanState* ExecInitBitmapHeapScan(BitmapHeapScan* node, EState* estate
|
||||
scanstate->ss.currentSlot = 0;
|
||||
scanstate->ss.partScanDirection = node->scan.partScanDirection;
|
||||
|
||||
/* initilize Global partition index scan information */
|
||||
GPIScanInit(&scanstate->gpi_scan);
|
||||
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
@ -687,6 +771,7 @@ BitmapHeapScanState* ExecInitBitmapHeapScan(BitmapHeapScan* node, EState* estate
|
||||
currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid);
|
||||
|
||||
scanstate->ss.ss_currentRelation = currentRelation;
|
||||
scanstate->gpi_scan->parentRelation = currentRelation;
|
||||
|
||||
InitBitmapHeapScanNextMtd(scanstate);
|
||||
/*
|
||||
|
||||
@ -92,6 +92,11 @@ Node* MultiExecBitmapIndexScan(BitmapIndexScanState* node)
|
||||
} else {
|
||||
/* XXX should we use less than u_sess->attr.attr_memory.work_mem for this? */
|
||||
tbm = tbm_create(u_sess->attr.attr_memory.work_mem * 1024L);
|
||||
|
||||
/* If bitmapscan uses global partition index, set tbm to global */
|
||||
if (RelationIsGlobalIndex(node->biss_RelationDesc)) {
|
||||
tbm_set_global(tbm, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (hbkt_idx_need_switch_bkt(scandesc, node->ss.ps.hbktScanSlot.currSlot)) {
|
||||
|
||||
@ -126,6 +126,10 @@ Node* MultiExecBitmapOr(BitmapOrState* node)
|
||||
if (result == NULL) {
|
||||
/* XXX should we use less than u_sess->attr.attr_memory.work_mem for this? */
|
||||
result = tbm_create(u_sess->attr.attr_memory.work_mem * 1024L);
|
||||
/* If bitmapscan uses global partition index, set tbm to global */
|
||||
if (RelationIsGlobalIndex(((BitmapIndexScanState*)subnode)->biss_RelationDesc)) {
|
||||
tbm_set_global(result, true);
|
||||
}
|
||||
}
|
||||
|
||||
((BitmapIndexScanState*)subnode)->biss_result = result;
|
||||
@ -148,6 +152,12 @@ Node* MultiExecBitmapOr(BitmapOrState* node)
|
||||
if (result == NULL) {
|
||||
result = subresult; /* first subplan */
|
||||
} else {
|
||||
if (tbm_is_global(result) != tbm_is_global(subresult)) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE),
|
||||
errmsg(
|
||||
"do not support bitmap index scan for global index and local index simultaneously.")));
|
||||
}
|
||||
tbm_union(result, subresult);
|
||||
tbm_free(subresult);
|
||||
}
|
||||
|
||||
@ -97,6 +97,15 @@ static TupleTableSlot* IndexOnlyNext(IndexOnlyScanState* node)
|
||||
* reading the TID; and (2) is satisfied by the acquisition of the
|
||||
* buffer content lock in order to insert the TID.
|
||||
*/
|
||||
if (IndexScanNeedSwitchPartRel(indexScan)) {
|
||||
/*
|
||||
* Change the heapRelation in indexScanDesc to Partition Relation of current index
|
||||
*/
|
||||
if (!GPIGetNextPartRelation(indexScan->xs_gpi_scan, CurrentMemoryContext, AccessShareLock)) {
|
||||
continue;
|
||||
}
|
||||
indexScan->heapRelation = indexScan->xs_gpi_scan->fakePartRelation;
|
||||
}
|
||||
if (!visibilitymap_test(indexScan->heapRelation, ItemPointerGetBlockNumber(tid), &node->ioss_VMBuffer)) {
|
||||
/*
|
||||
* Rats, we have to visit the heap to check visibility.
|
||||
@ -286,16 +295,16 @@ void ExecReScanIndexOnlyScan(IndexOnlyScanState* node)
|
||||
if (!PointerIsValid(node->ss.partitions)) {
|
||||
return;
|
||||
}
|
||||
Assert(PointerIsValid(node->ioss_ScanDesc));
|
||||
Assert(PointerIsValid(node->ioss_ScanDesc));
|
||||
abs_idx_endscan(node->ioss_ScanDesc);
|
||||
|
||||
/* initialize to scan the next partition */
|
||||
ExecInitNextIndexPartitionForIndexScanOnly(node);
|
||||
/* initialize to scan the next partition */
|
||||
ExecInitNextIndexPartitionForIndexScanOnly(node);
|
||||
ExecScanReScan(&node->ss);
|
||||
/*
|
||||
* give up rescaning the index if there is no partition to scan
|
||||
*/
|
||||
return;
|
||||
/*
|
||||
* give up rescaning the index if there is no partition to scan
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -41,7 +41,6 @@
|
||||
#include "gstrace/executer_gstrace.h"
|
||||
|
||||
static TupleTableSlot* IndexNext(IndexScanState* node);
|
||||
|
||||
static void ExecInitNextPartitionForIndexScan(IndexScanState* node);
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
@ -818,7 +817,9 @@ void ExecIndexBuildScanKeys(PlanState* plan_state, Relation index, List* quals,
|
||||
Expr* leftop = NULL; /* expr on lhs of operator */
|
||||
Expr* rightop = NULL; /* expr on rhs ... */
|
||||
AttrNumber varattno; /* att number used in scan */
|
||||
int indnkeyatts;
|
||||
|
||||
indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index);
|
||||
if (IsA(clause, OpExpr)) {
|
||||
/* indexkey op const or indexkey op expression */
|
||||
uint32 flags = 0;
|
||||
@ -839,7 +840,7 @@ void ExecIndexBuildScanKeys(PlanState* plan_state, Relation index, List* quals,
|
||||
(errcode(ERRCODE_INDEX_CORRUPTED), errmsg("indexqual for OpExpr doesn't have key on left side")));
|
||||
|
||||
varattno = ((Var*)leftop)->varattno;
|
||||
if (varattno < 1 || varattno > index->rd_index->indnatts)
|
||||
if (varattno < 1 || varattno > indnkeyatts)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INDEX_CORRUPTED),
|
||||
errmsg("bogus index qualification for OpExpr, attribute number is %d.", varattno)));
|
||||
@ -1050,7 +1051,7 @@ void ExecIndexBuildScanKeys(PlanState* plan_state, Relation index, List* quals,
|
||||
errmsg("indexqual for ScalarArray doesn't have key on left side")));
|
||||
|
||||
varattno = ((Var*)leftop)->varattno;
|
||||
if (varattno < 1 || varattno > index->rd_index->indnatts)
|
||||
if (varattno < 1 || varattno > indnkeyatts)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INDEX_CORRUPTED),
|
||||
errmsg("bogus index qualification for ScalarArray, attribute number is %d.", varattno)));
|
||||
|
||||
@ -1405,6 +1405,10 @@ bool UpdateFusion::execute(long max_rows, char* completionTag)
|
||||
|
||||
|
||||
while ((oldtup = m_scan->getTuple()) != NULL) {
|
||||
if (RelationIsPartitioned(m_scan->m_rel)) {
|
||||
rel = m_scan->getCurrentRel();
|
||||
}
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
HTSU_Result result;
|
||||
ItemPointerData update_ctid;
|
||||
@ -1589,6 +1593,10 @@ bool DeleteFusion::execute(long max_rows, char* completionTag)
|
||||
m_tupDesc = RelationGetDescr(rel);
|
||||
|
||||
while ((oldtup = m_scan->getTuple()) != NULL) {
|
||||
if (RelationIsPartitioned(m_scan->m_rel)) {
|
||||
rel = m_scan->getCurrentRel();
|
||||
}
|
||||
|
||||
HTSU_Result result;
|
||||
ItemPointerData update_ctid;
|
||||
TransactionId update_xmax;
|
||||
@ -1806,6 +1814,10 @@ bool SelectForUpdateFusion::execute(long max_rows, char* completionTag)
|
||||
}
|
||||
|
||||
while (nprocessed < (unsigned long)get_rows && (tuple = m_scan->getTuple()) != NULL) {
|
||||
if (RelationIsPartitioned(m_scan->m_rel)) {
|
||||
rel = m_scan->getCurrentRel();
|
||||
}
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
heap_deform_tuple(tuple, RelationGetDescr(rel), m_values, m_isnull);
|
||||
|
||||
|
||||
@ -295,6 +295,19 @@ bool IndexFusion::EpqCheck(Datum* values, const bool* isnull)
|
||||
return true;
|
||||
}
|
||||
|
||||
Relation IndexFusion::getCurrentRel()
|
||||
{
|
||||
IndexScanDesc indexScan = GetIndexScanDesc(m_scandesc);
|
||||
if (indexScan->xs_gpi_scan) {
|
||||
return indexScan->xs_gpi_scan->fakePartRelation;
|
||||
} else {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE),
|
||||
errmsg("partitioned relation dose not use global partition index")));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void IndexFusion::setAttrNo()
|
||||
{
|
||||
ListCell* lc = NULL;
|
||||
@ -326,7 +339,6 @@ IndexScanFusion::IndexScanFusion(IndexScan* node, PlannedStmt* planstmt, ParamLi
|
||||
m_node = node;
|
||||
m_keyInit = false;
|
||||
m_keyNum = list_length(node->indexqual);
|
||||
;
|
||||
m_scanKeys = (ScanKey)palloc0(m_keyNum * sizeof(ScanKeyData));
|
||||
|
||||
/* init params */
|
||||
@ -594,6 +606,15 @@ TupleTableSlot* IndexOnlyScanFusion::getTupleSlot()
|
||||
while ((tid = abs_idx_getnext_tid(m_scandesc, *m_direction)) != NULL) {
|
||||
HeapTuple tuple = NULL;
|
||||
IndexScanDesc indexdesc = GetIndexScanDesc(m_scandesc);
|
||||
if (IndexScanNeedSwitchPartRel(indexdesc)) {
|
||||
/*
|
||||
* Change the heapRelation in indexScanDesc to Partition Relation of current index
|
||||
*/
|
||||
if (!GPIGetNextPartRelation(indexdesc->xs_gpi_scan, CurrentMemoryContext, AccessShareLock)) {
|
||||
continue;
|
||||
}
|
||||
indexdesc->heapRelation = indexdesc->xs_gpi_scan->fakePartRelation;
|
||||
}
|
||||
if (!visibilitymap_test(indexdesc->heapRelation, ItemPointerGetBlockNumber(tid), &m_VMBuffer)) {
|
||||
tuple = index_fetch_heap(indexdesc);
|
||||
if (tuple == NULL) {
|
||||
|
||||
Reference in New Issue
Block a user