!162 【gpi】 修复全局分区索引只支持31列的报错输出

Merge pull request !162 from xiliu/GPI_BUGFIX
This commit is contained in:
opengauss-bot 2020-09-01 10:00:33 +08:00 committed by Gitee
commit ea34abb507
20 changed files with 422 additions and 152 deletions

View File

@ -1268,6 +1268,7 @@ static bool _equalIndexStmt(const IndexStmt* a, const IndexStmt* b)
COMPARE_SCALAR_FIELD(oldNode);
COMPARE_NODE_FIELD(partClause);
COMPARE_SCALAR_FIELD(isPartitioned);
COMPARE_SCALAR_FIELD(isGlobal);
COMPARE_SCALAR_FIELD(unique);
COMPARE_SCALAR_FIELD(primary);
COMPARE_SCALAR_FIELD(isconstraint);

View File

@ -3293,6 +3293,7 @@ static void _outIndexStmt(StringInfo str, IndexStmt* node)
WRITE_OID_FIELD(oldNode);
WRITE_NODE_FIELD(partClause);
WRITE_BOOL_FIELD(isPartitioned);
WRITE_BOOL_FIELD(isGlobal);
WRITE_BOOL_FIELD(unique);
WRITE_BOOL_FIELD(primary);
WRITE_BOOL_FIELD(isconstraint);

View File

@ -4628,6 +4628,7 @@ static IndexStmt* _readIndexStmt()
READ_OID_FIELD(oldNode);
READ_NODE_FIELD(partClause);
READ_BOOL_FIELD(isPartitioned);
READ_BOOL_FIELD(isGlobal);
READ_BOOL_FIELD(unique);
READ_BOOL_FIELD(primary);
READ_BOOL_FIELD(isconstraint);
@ -4674,18 +4675,21 @@ static Constraint* _readConstraint()
} else if (MATCH_TYPE("PRIMARY_KEY")) {
local_node->contype = CONSTR_PRIMARY;
READ_NODE_FIELD(keys);
READ_NODE_FIELD(including);
READ_NODE_FIELD(options);
READ_STRING_FIELD(indexname);
READ_STRING_FIELD(indexspace);
} else if (MATCH_TYPE("UNIQUE")) {
local_node->contype = CONSTR_UNIQUE;
READ_NODE_FIELD(keys);
READ_NODE_FIELD(including);
READ_NODE_FIELD(options);
READ_STRING_FIELD(indexname);
READ_STRING_FIELD(indexspace);
} else if (MATCH_TYPE("EXCLUSION")) {
local_node->contype = CONSTR_EXCLUSION;
READ_NODE_FIELD(exclusions);
READ_NODE_FIELD(including);
READ_NODE_FIELD(options);
READ_STRING_FIELD(indexname);
READ_STRING_FIELD(indexspace);

View File

@ -322,9 +322,9 @@ void tbm_add_tuples(TIDBitmap* tbm, const ItemPointer tids, int ntids, bool rech
* This causes the whole page to be reported (with the recheck flag)
* when the TIDBitmap is scanned.
*/
void tbm_add_page(TIDBitmap* tbm, BlockNumber pageno)
void tbm_add_page(TIDBitmap* tbm, BlockNumber pageno, Oid partitionOid)
{
PagetableEntryNode pnode = {pageno, InvalidOid};
PagetableEntryNode pnode = {pageno, partitionOid};
/* Enter the page in the bitmap, or mark it lossy if already present */
tbm_mark_page_lossy(tbm, pnode);
/* If we went over the memory limit, lossify some more pages */

View File

@ -3159,6 +3159,12 @@ IndexStmt* transformIndexStmt(Oid relid, IndexStmt* stmt, const char* queryStrin
stmt->internal_flag = true;
}
/* default partition index is set to Global index */
if (RELATION_IS_PARTITIONED(rel) && !stmt->isPartitioned) {
stmt->isPartitioned = true;
stmt->isGlobal = true;
}
bool isColStore = RelationIsColStore(rel);
if (stmt->accessMethod == NULL) {
if (!isColStore) {

View File

@ -4703,9 +4703,10 @@ List* RelationGetSpecificKindIndexList(Relation relation, bool isGlobal)
{
ListCell* indList = NULL;
List* result = NULL;
List* indexOidList = RelationGetIndexList(relation);
/* Ask the relcache to produce a list of the indexes of the rel */
foreach (indList, RelationGetIndexList(relation)) {
foreach (indList, indexOidList) {
Oid indexId = lfirst_oid(indList);
Relation currentIndex;
@ -4723,6 +4724,7 @@ List* RelationGetSpecificKindIndexList(Relation relation, bool isGlobal)
index_close(currentIndex, AccessShareLock);
}
list_free_ext(indexOidList);
return result;
}

View File

@ -433,6 +433,12 @@ Oid DefineIndex(Oid relationId, IndexStmt* stmt, Oid indexRelationId, bool is_al
ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot create concurrent partitioned indexes ")));
}
if (stmt->isGlobal && (list_length(stmt->indexParams) > INDEX_MAX_KEYS - 1)) {
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_COLUMNS),
errmsg("cannot use more than %d columns in an global partition index", INDEX_MAX_KEYS - 1)));
}
/* Add special index columns tableoid to global partition index */
if (stmt->isGlobal) {
AddIndexColumnForGpi(stmt);
@ -3067,8 +3073,7 @@ static bool CheckGlobalIndexCompatible(Oid relOid, bool isGlobal, const IndexInf
/* only check index of different type(local and global) */
if (currIdxKind != tarIdxKind) {
if (!CheckIndexMethodConsistency(tarTuple, indexRelation, currMethodOid)) {
ret = false;
break;
continue;
}
heap_getattr(tarTuple, Anum_pg_index_indexprs, RelationGetDescr(indexRelation), &isNull);

View File

@ -8904,7 +8904,7 @@ static void ATExecAddIndex(AlteredTableInfo* tab, Relation rel, IndexStmt* stmt,
if (OidIsValid(stmt->oldNode)) {
Relation irel = index_open(new_index, NoLock);
if (!stmt->isPartitioned) {
if (!stmt->isPartitioned || stmt->isGlobal) {
RelationPreserveStorage(irel->rd_node, true);
} else {
List* partOids = NIL;
@ -11316,7 +11316,7 @@ static void ATCutOffPSortDependency(List* oldIndexPassList, LOCKMODE lockmode)
// if the index is a partition table, handle all the
// psort info for each partition.
if (istmt->isPartitioned) {
if (istmt->isPartitioned && !istmt->isGlobal) {
Relation hrel = relation_openrv(istmt->relation, lockmode);
Relation irel = index_open(istmt->indexOid, lockmode);
List* partHeapOids = relationGetPartitionOidList(hrel);
@ -11492,7 +11492,7 @@ static void ATPostAlterTypeParse(
AlterTableCmd* newcmd = NULL;
if (!rewrite) {
if (!stmt->isPartitioned) {
if (!stmt->isPartitioned || stmt->isGlobal) {
TryReuseIndex(oldId, stmt);
} else {
tryReusePartedIndex(oldId, stmt, rel);

View File

@ -57,6 +57,8 @@ static TupleTableSlot* BitmapHeapTblNext(BitmapHeapScanState* node);
static void bitgetpage(HeapScanDesc scan, TBMIterateResult* tbmres);
static void ExecInitPartitionForBitmapHeapScan(BitmapHeapScanState* scanstate, EState* estate);
static void ExecInitNextPartitionForBitmapHeapScan(BitmapHeapScanState* node);
static void BitmapHeapPrefetchNext(
BitmapHeapScanState* node, HeapScanDesc scan, const TIDBitmap* tbm, TBMIterator** prefetch_iterator);
/* This struct is used for partition switch while prefetch pages */
typedef struct PrefetchNode {
@ -182,18 +184,6 @@ 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;
}
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 */
@ -211,6 +201,21 @@ static TupleTableSlot* BitmapHeapTblNext(BitmapHeapScanState* node)
}
#endif /* USE_PREFETCH */
/* 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;
#ifdef USE_PREFETCH
BitmapHeapPrefetchNext(node, scan, tbm, &prefetch_iterator);
#endif /* USE_PREFETCH */
continue;
}
scan->rs_rd = node->gpi_scan->fakePartRelation;
scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_rd);
}
/*
* Ignore any claimed entries past what we think is the end of the
* relation. (This is probably not necessary given that we got at
@ -286,126 +291,7 @@ static TupleTableSlot* BitmapHeapTblNext(BitmapHeapScanState* node)
}
#ifdef USE_PREFETCH
/*
* We issue prefetch requests *after* fetching the current page to try
* to avoid having prefetching interfere with the main I/O. Also, this
* should happen only when we have determined there is still something
* to do on the current page, else we may uselessly prefetch the same
* page we are just about to request for real.
*/
if (prefetch_iterator != NULL) {
ADIO_RUN()
{
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;
}
while (node->prefetch_pages < node->prefetch_target) {
TBMIterateResult* tbmpre = tbm_iterate(prefetch_iterator);
if (tbmpre == NULL) {
/* No more pages to prefetch */
tbm_end_iterate(prefetch_iterator);
node->prefetch_iterator = prefetch_iterator = NULL;
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++;
}
/* Send the list we generated and free it */
if (prefetchNow) {
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);
node->prefetch_iterator = prefetch_iterator = NULL;
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(prefetchRel, MAIN_FORKNUM, tbmpre->blockno);
}
/* recover old oid after prefetch switch */
GPISetCurrPartOid(node->gpi_scan, oldOid);
}
ADIO_END();
}
BitmapHeapPrefetchNext(node, scan, tbm, &prefetch_iterator);
#endif /* USE_PREFETCH */
/*
@ -908,3 +794,127 @@ static void ExecInitPartitionForBitmapHeapScan(BitmapHeapScanState* scanstate, E
}
}
}
/*
* We issue prefetch requests *after* fetching the current page to try
* to avoid having prefetching interfere with the main I/O. Also, this
* should happen only when we have determined there is still something
* to do on the current page, else we may uselessly prefetch the same
* page we are just about to request for real.
*/
void BitmapHeapPrefetchNext(
BitmapHeapScanState* node, HeapScanDesc scan, const TIDBitmap* tbm, TBMIterator** prefetch_iterator)
{
if (*prefetch_iterator == NULL) {
return;
}
ADIO_RUN()
{
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;
}
while (node->prefetch_pages < node->prefetch_target) {
TBMIterateResult* tbmpre = tbm_iterate(*prefetch_iterator);
if (tbmpre == NULL) {
/* No more pages to prefetch */
tbm_end_iterate(*prefetch_iterator);
node->prefetch_iterator = *prefetch_iterator = NULL;
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++;
}
/* Send the list we generated and free it */
if (prefetchNow) {
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);
node->prefetch_iterator = *prefetch_iterator = NULL;
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(prefetchRel, MAIN_FORKNUM, tbmpre->blockno);
}
/* recover old oid after prefetch switch */
GPISetCurrPartOid(node->gpi_scan, oldOid);
}
ADIO_END();
}

View File

@ -1582,6 +1582,7 @@ static void scanPendingInsert(IndexScanDesc scan, TIDBitmap* tbm, int64* ntids)
pendingPosition pos;
Buffer metabuffer = ReadBuffer(scan->indexRelation, GIN_METAPAGE_BLKNO);
BlockNumber blkno;
Oid partHeapOid = IndexScanGetPartHeapOid(scan);
*ntids = 0;
@ -1640,7 +1641,7 @@ static void scanPendingInsert(IndexScanDesc scan, TIDBitmap* tbm, int64* ntids)
MemoryContextReset(so->tempCtx);
if (match) {
tbm_add_tuples(tbm, &pos.item, 1, recheck);
tbm_add_tuples(tbm, &pos.item, 1, recheck, partHeapOid);
(*ntids)++;
}
}
@ -1664,6 +1665,7 @@ Datum gingetbitmap(PG_FUNCTION_ARGS)
int64 ntids;
ItemPointerData iptr;
bool recheck = false;
Oid partHeapOid = IndexScanGetPartHeapOid(scan);
/*
* Set up the scan keys, and check for unsatisfiable query.
@ -1702,9 +1704,9 @@ Datum gingetbitmap(PG_FUNCTION_ARGS)
break;
if (ItemPointerIsLossyPage(&iptr))
tbm_add_page(tbm, ItemPointerGetBlockNumber(&iptr));
tbm_add_page(tbm, ItemPointerGetBlockNumber(&iptr), partHeapOid);
else
tbm_add_tuples(tbm, &iptr, 1, recheck);
tbm_add_tuples(tbm, &iptr, 1, recheck, partHeapOid);
ntids++;
}

View File

@ -215,6 +215,7 @@ static void gistScanPage(IndexScanDesc scan, const GISTSearchItem *pageItem, con
bool isNew = false;
MemoryContext oldcxt;
errno_t ret = EOK;
Oid partHeapOid = IndexScanGetPartHeapOid(scan);
Assert(!GISTSearchItemIsHeap(*pageItem));
@ -290,7 +291,7 @@ static void gistScanPage(IndexScanDesc scan, const GISTSearchItem *pageItem, con
* getbitmap scan, so just push heap tuple TIDs into the bitmap
* without worrying about ordering
*/
tbm_add_tuples(tbm, &it->t_tid, 1, recheck);
tbm_add_tuples(tbm, &it->t_tid, 1, recheck, partHeapOid);
(*ntids)++;
} else if (scan->numberOfOrderBys == 0 && GistPageIsLeaf(page)) {
/*

View File

@ -303,6 +303,7 @@ Datum hashgetbitmap(PG_FUNCTION_ARGS)
HashScanOpaque so = (HashScanOpaque)scan->opaque;
bool res = false;
int64 ntids = 0;
Oid partHeapOid = IndexScanGetPartHeapOid(scan);
res = _hash_first(scan, ForwardScanDirection);
@ -325,7 +326,7 @@ Datum hashgetbitmap(PG_FUNCTION_ARGS)
/* Save tuple ID, and continue scanning */
if (add_tuple) {
/* Note we mark the tuple ID as requiring recheck */
tbm_add_tuples(tbm, &(so->hashso_heappos), 1, true);
tbm_add_tuples(tbm, &(so->hashso_heappos), 1, true, partHeapOid);
ntids++;
}

View File

@ -664,6 +664,7 @@ bool GPIGetNextPartRelation(GPIScanDesc gpiScan, MemoryContext cxt, LOCKMODE lmo
if (bms_is_member(gpiScan->currPartOid, gpiScan->invisiblePartMap)) {
gpiScan->fakePartRelation = NULL;
gpiScan->partition = NULL;
gpiScan->currPartOid = InvalidOid;
return false;
}
@ -679,6 +680,7 @@ bool GPIGetNextPartRelation(GPIScanDesc gpiScan, MemoryContext cxt, LOCKMODE lmo
if (currStatus == PART_METADATA_INVISIBLE) {
/* If current partition metadata is invisible, add current partition oid into invisiblePartMap */
gpiScan->invisiblePartMap = bms_add_member(gpiScan->invisiblePartMap, gpiScan->currPartOid);
gpiScan->currPartOid = InvalidOid;
result = false;
} else {
/* If current partition metadata is invisible, add current partition oid into fakeRelationTable */

View File

@ -411,7 +411,6 @@ static TransactionId _bt_check_unique(Relation rel, IndexTuple itup, Relation he
* everyone, so we may as well mark the index entry
* killed.
*/
/* okay, we gotta fetch the heap tuple ... */
ItemIdMarkDead(curitemid);
opaque->btpo_flags |= BTP_HAS_GARBAGE;

View File

@ -497,7 +497,7 @@ static void spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex, st
/* storeRes subroutine for getbitmap case */
static void storeBitmap(SpGistScanOpaque so, ItemPointer heapPtr, Datum leafValue, bool isnull, bool recheck)
{
tbm_add_tuples(so->tbm, heapPtr, 1, recheck);
tbm_add_tuples(so->tbm, heapPtr, 1, recheck, so->partHeapOid);
so->ntids++;
}
@ -511,6 +511,7 @@ Datum spggetbitmap(PG_FUNCTION_ARGS)
so->want_itup = false;
so->tbm = tbm;
so->ntids = 0;
so->partHeapOid = IndexScanGetPartHeapOid(scan);
spgWalk(scan->indexRelation, so, true, storeBitmap);

View File

@ -136,8 +136,9 @@ typedef struct SpGistScanOpaqueData {
List* scanStack; /* List of ScanStackEntrys */
/* These fields are only used in amgetbitmap scans: */
TIDBitmap* tbm; /* bitmap being filled */
int64 ntids; /* number of TIDs passed to bitmap */
TIDBitmap* tbm; /* bitmap being filled */
int64 ntids; /* number of TIDs passed to bitmap */
Oid partHeapOid; /* partition oid passed to bitmap */
/* These fields are only used in amgettuple scans: */
bool want_itup; /* are we reconstructing tuples? */

View File

@ -49,7 +49,7 @@ extern void tbm_free(TIDBitmap* tbm);
extern void tbm_add_tuples(
TIDBitmap* tbm, const ItemPointer tids, int ntids, bool recheck, Oid partitionOid = InvalidOid);
extern void tbm_add_page(TIDBitmap* tbm, BlockNumber pageno);
extern void tbm_add_page(TIDBitmap* tbm, BlockNumber pageno, Oid partitionOid = InvalidOid);
extern void tbm_union(TIDBitmap* a, const TIDBitmap* b);
extern void tbm_intersect(TIDBitmap* a, const TIDBitmap* b);

View File

@ -227,3 +227,172 @@ ERROR: "idx1_gpi_bitmap_table2" is not a table
HINT: Use DROP INDEX to remove an global partition index.
SET enable_seqscan=on;
SET enable_indexscan=on;
drop table if exists test_part_bitmapand_ginst_btree;
NOTICE: table "test_part_bitmapand_ginst_btree" does not exist, skipping
CREATE TABLE test_part_bitmapand_ginst_btree (a int, txtkeyword TEXT, txtsample TEXT) partition by range(a) (partition p1 values less than (1001), partition p2 values less than (2001), partition p3 values less than (3001));
insert into test_part_bitmapand_ginst_btree values (10, $$'New York'$$, 'new & york | big & apple | nyc');
insert into test_part_bitmapand_ginst_btree values (1010, 'Moscow', 'moskva | moscow');
insert into test_part_bitmapand_ginst_btree values (1020, $$'Sanct Peter'$$, $$Peterburg | peter | 'Sanct Peterburg'$$);
insert into test_part_bitmapand_ginst_btree values (1030, $$'foo bar qq'$$, 'foo & (bar | qq) & city');
ALTER TABLE test_part_bitmapand_ginst_btree ADD COLUMN keyword tsquery;
UPDATE test_part_bitmapand_ginst_btree SET keyword = to_tsquery('english', txtkeyword);
ALTER TABLE test_part_bitmapand_ginst_btree ADD COLUMN sample tsquery;
UPDATE test_part_bitmapand_ginst_btree SET sample = to_tsquery('english', txtsample::text);
CREATE UNIQUE INDEX ON test_part_bitmapand_ginst_btree (a) local;
-- failed
CREATE INDEX qq ON test_part_bitmapand_ginst_btree USING gist (keyword tsquery_ops);
ERROR: Global partition index only support btree.
CREATE INDEX qq ON test_part_bitmapand_ginst_btree USING gist (keyword tsquery_ops) local;
CREATE INDEX ON test_part_bitmapand_ginst_btree USING gist (keyword tsquery_ops);
ERROR: Global partition index only support btree.
explain (costs off) SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
QUERY PLAN
--------------------------------------------------------------------------
Partition Iterator
Iterations: 1
-> Partitioned Index Scan using qq on test_part_bitmapand_ginst_btree
Index Cond: (keyword @> '''new'''::tsquery)
Filter: (a = 10)
Selected Partitions: 1
(6 rows)
SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
keyword
----------------
'new' & 'york'
(1 row)
set force_bitmapand = on;
set enable_seqscan = off;
set enable_indexscan = off;
--bitmapand scan
explain (costs off) SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
QUERY PLAN
------------------------------------------------------------------------------------------
Partition Iterator
Iterations: 1
-> Partitioned Bitmap Heap Scan on test_part_bitmapand_ginst_btree
Recheck Cond: ((keyword @> '''new'''::tsquery) AND (a = 10))
Selected Partitions: 1
-> BitmapAnd
-> Partitioned Bitmap Index Scan on qq
Index Cond: (keyword @> '''new'''::tsquery)
Selected Partitions: 1
-> Partitioned Bitmap Index Scan on test_part_bitmapand_ginst_btree_a_idx
Index Cond: (a = 10)
Selected Partitions: 1
(12 rows)
SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
keyword
----------------
'new' & 'york'
(1 row)
drop index test_part_bitmapand_ginst_btree_a_idx;
CREATE UNIQUE INDEX ON test_part_bitmapand_ginst_btree (a);
--bitmapand scan
explain (costs off) SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
QUERY PLAN
-----------------------------------------------------------------------
Partition Iterator
Iterations: 1
-> Partitioned Bitmap Heap Scan on test_part_bitmapand_ginst_btree
Recheck Cond: (keyword @> '''new'''::tsquery)
Filter: (a = 10)
Selected Partitions: 1
-> Partitioned Bitmap Index Scan on qq
Index Cond: (keyword @> '''new'''::tsquery)
Selected Partitions: 1
(9 rows)
SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
keyword
----------------
'new' & 'york'
(1 row)
drop table if exists test_part_bitmapand_gin_btree;
NOTICE: table "test_part_bitmapand_gin_btree" does not exist, skipping
create table test_part_bitmapand_gin_btree (a int, ts tsvector) partition by range(a) (partition p1 values less than (1001), partition p2 values less than (2001), partition p3 values less than (3001));
insert into test_part_bitmapand_gin_btree values (10, to_tsvector('Lore ipsam'));
insert into test_part_bitmapand_gin_btree values (1010, to_tsvector('Lore ipsum'));
create index test_part_bitmapand_gin_btree_idx on test_part_bitmapand_gin_btree using gin(ts) local;
create index test_part_bitmapand_gin_btree_idx_a on test_part_bitmapand_gin_btree using btree(a) local;
set force_bitmapand = on;
set enable_seqscan = off;
set enable_indexscan = off;
explain (costs off) select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 10;
QUERY PLAN
----------------------------------------------------------------------------------------
Partition Iterator
Iterations: 1
-> Partitioned Bitmap Heap Scan on test_part_bitmapand_gin_btree
Recheck Cond: ((a = 10) AND ('''ipsu'':*'::tsquery @@ ts))
Selected Partitions: 1
-> BitmapAnd
-> Partitioned Bitmap Index Scan on test_part_bitmapand_gin_btree_idx_a
Index Cond: (a = 10)
Selected Partitions: 1
-> Partitioned Bitmap Index Scan on test_part_bitmapand_gin_btree_idx
Index Cond: ('''ipsu'':*'::tsquery @@ ts)
Selected Partitions: 1
(12 rows)
select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 10;
a | ts
---+----
(0 rows)
explain (costs off) select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 1010;
QUERY PLAN
----------------------------------------------------------------------------------------
Partition Iterator
Iterations: 1
-> Partitioned Bitmap Heap Scan on test_part_bitmapand_gin_btree
Recheck Cond: ((a = 1010) AND ('''ipsu'':*'::tsquery @@ ts))
Selected Partitions: 2
-> BitmapAnd
-> Partitioned Bitmap Index Scan on test_part_bitmapand_gin_btree_idx_a
Index Cond: (a = 1010)
Selected Partitions: 2
-> Partitioned Bitmap Index Scan on test_part_bitmapand_gin_btree_idx
Index Cond: ('''ipsu'':*'::tsquery @@ ts)
Selected Partitions: 2
(12 rows)
select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 1010;
a | ts
------+--------------------
1010 | 'ipsum':2 'lore':1
(1 row)
drop index test_part_bitmapand_gin_btree_idx_a;
create index test_part_bitmapand_gin_btree_idx_a on test_part_bitmapand_gin_btree using btree(a) global;
explain (costs off) select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 1010;
QUERY PLAN
--------------------------------------------------------------------------------------
Partition Iterator
Iterations: 1
-> Partitioned Bitmap Heap Scan on test_part_bitmapand_gin_btree
Recheck Cond: ((a = 1010) AND ('''ipsu'':*'::tsquery @@ ts))
Selected Partitions: 2
-> BitmapAnd
-> Bitmap Index Scan on test_part_bitmapand_gin_btree_idx_a
Index Cond: (a = 1010)
-> Partitioned Bitmap Index Scan on test_part_bitmapand_gin_btree_idx
Index Cond: ('''ipsu'':*'::tsquery @@ ts)
Selected Partitions: 2
(11 rows)
select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 1010;
a | ts
------+--------------------
1010 | 'ipsum':2 'lore':1
(1 row)
reset force_bitmapand;
reset enable_seqscan;
reset enable_indexscan;
drop table test_part_bitmapand_gin_btree;
drop table test_part_bitmapand_ginst_btree;

View File

@ -249,7 +249,7 @@ create table gpi_multi_cols(a0 int,a1 int,a2 int,a3 int,a4 int,a5 int,a6 int,a7
create index gpi_multi_cols_index on gpi_multi_cols(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30) global;
--failed
create index gpi_multi_cols_index on gpi_multi_cols(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30, a31) global;
ERROR: cannot use more than 32 columns in an index
ERROR: cannot use more than 31 columns in an global partition index
--success
create index gpi_multi_cols_index_local on gpi_multi_cols(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30, a31) local;
insert into gpi_multi_cols select r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r,r from generate_series(1,3000) as r;

View File

@ -78,4 +78,69 @@ SELECT * FROM gpi_bitmap_table2 WHERE c1 = 10000 OR c2 = 30000;
DROP TABLE idx1_gpi_bitmap_table1;
DROP TABLE idx1_gpi_bitmap_table2;
SET enable_seqscan=on;
SET enable_indexscan=on;
SET enable_indexscan=on;
drop table if exists test_part_bitmapand_ginst_btree;
CREATE TABLE test_part_bitmapand_ginst_btree (a int, txtkeyword TEXT, txtsample TEXT) partition by range(a) (partition p1 values less than (1001), partition p2 values less than (2001), partition p3 values less than (3001));
insert into test_part_bitmapand_ginst_btree values (10, $$'New York'$$, 'new & york | big & apple | nyc');
insert into test_part_bitmapand_ginst_btree values (1010, 'Moscow', 'moskva | moscow');
insert into test_part_bitmapand_ginst_btree values (1020, $$'Sanct Peter'$$, $$Peterburg | peter | 'Sanct Peterburg'$$);
insert into test_part_bitmapand_ginst_btree values (1030, $$'foo bar qq'$$, 'foo & (bar | qq) & city');
ALTER TABLE test_part_bitmapand_ginst_btree ADD COLUMN keyword tsquery;
UPDATE test_part_bitmapand_ginst_btree SET keyword = to_tsquery('english', txtkeyword);
ALTER TABLE test_part_bitmapand_ginst_btree ADD COLUMN sample tsquery;
UPDATE test_part_bitmapand_ginst_btree SET sample = to_tsquery('english', txtsample::text);
CREATE UNIQUE INDEX ON test_part_bitmapand_ginst_btree (a) local;
-- failed
CREATE INDEX qq ON test_part_bitmapand_ginst_btree USING gist (keyword tsquery_ops);
CREATE INDEX qq ON test_part_bitmapand_ginst_btree USING gist (keyword tsquery_ops) local;
CREATE INDEX ON test_part_bitmapand_ginst_btree USING gist (keyword tsquery_ops);
explain (costs off) SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
set force_bitmapand = on;
set enable_seqscan = off;
set enable_indexscan = off;
--bitmapand scan
explain (costs off) SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
drop index test_part_bitmapand_ginst_btree_a_idx;
CREATE UNIQUE INDEX ON test_part_bitmapand_ginst_btree (a);
--bitmapand scan
explain (costs off) SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10;
drop table if exists test_part_bitmapand_gin_btree;
create table test_part_bitmapand_gin_btree (a int, ts tsvector) partition by range(a) (partition p1 values less than (1001), partition p2 values less than (2001), partition p3 values less than (3001));
insert into test_part_bitmapand_gin_btree values (10, to_tsvector('Lore ipsam'));
insert into test_part_bitmapand_gin_btree values (1010, to_tsvector('Lore ipsum'));
create index test_part_bitmapand_gin_btree_idx on test_part_bitmapand_gin_btree using gin(ts) local;
create index test_part_bitmapand_gin_btree_idx_a on test_part_bitmapand_gin_btree using btree(a) local;
set force_bitmapand = on;
set enable_seqscan = off;
set enable_indexscan = off;
explain (costs off) select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 10;
select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 10;
explain (costs off) select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 1010;
select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 1010;
drop index test_part_bitmapand_gin_btree_idx_a;
create index test_part_bitmapand_gin_btree_idx_a on test_part_bitmapand_gin_btree using btree(a) global;
explain (costs off) select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 1010;
select * from test_part_bitmapand_gin_btree where 'ipsu:*'::tsquery @@ ts and a = 1010;
reset force_bitmapand;
reset enable_seqscan;
reset enable_indexscan;
drop table test_part_bitmapand_gin_btree;
drop table test_part_bitmapand_ginst_btree;