/* ---------------------------------------------------------------- * MultiExecBitmapIndexScan(node) * ---------------------------------------------------------------- */ Node * MultiExecBitmapIndexScan(BitmapIndexScanState *node) { IndexScanState *scanState = (IndexScanState*)node; Node *bitmap = NULL; /* must provide our own instrumentation support */ if (scanState->ss.ps.instrument) { InstrStartNode(scanState->ss.ps.instrument); } bool partitionIsReady = DynamicScan_BeginIndexPartition(scanState, false /* initQual */, false /* initTargetList */, true /* supportsArrayKeys */, true /* isMultiScan */); Assert(partitionIsReady); if (!partitionIsReady) { DynamicScan_EndIndexPartition(scanState); return NULL; } bool doscan = node->indexScanState.iss_RuntimeKeysReady; IndexScanDesc scandesc = scanState->iss_ScanDesc; /* Get bitmap from index */ while (doscan) { bitmap = index_getmulti(scandesc, node->bitmap); if ((NULL != bitmap) && !(IsA(bitmap, HashBitmap) || IsA(bitmap, StreamBitmap))) { elog(ERROR, "unrecognized result from bitmap index scan"); } CHECK_FOR_INTERRUPTS(); /* CDB: If EXPLAIN ANALYZE, let bitmap share our Instrumentation. */ if (scanState->ss.ps.instrument) { tbm_bitmap_set_instrument(bitmap, scanState->ss.ps.instrument); } if(node->bitmap == NULL) { node->bitmap = (Node *)bitmap; } doscan = ExecIndexAdvanceArrayKeys(scanState->iss_ArrayKeys, scanState->iss_NumArrayKeys); if (doscan) { /* reset index scan */ index_rescan(scanState->iss_ScanDesc, scanState->iss_ScanKeys); } } DynamicScan_EndIndexPartition(scanState); /* must provide our own instrumentation support */ if (scanState->ss.ps.instrument) { InstrStopNode(scanState->ss.ps.instrument, 1 /* nTuples */); } return (Node *) bitmap; }
/* ---------------------------------------------------------------- * MultiExecBitmapIndexScan(node) * ---------------------------------------------------------------- */ Node * MultiExecBitmapIndexScan(BitmapIndexScanState *node) { #define MAX_TIDS 1024 TIDBitmap *tbm; IndexScanDesc scandesc; ItemPointerData tids[MAX_TIDS]; int32 ntids; double nTuples = 0; bool doscan; /* must provide our own instrumentation support */ if (node->ss.ps.instrument) InstrStartNode(node->ss.ps.instrument); /* * extract necessary information from index scan node */ scandesc = node->biss_ScanDesc; /* * If we have runtime keys and they've not already been set up, do it now. * Array keys are also treated as runtime keys; note that if ExecReScan * returns with biss_RuntimeKeysReady still false, then there is an empty * array key so we should do nothing. */ if (!node->biss_RuntimeKeysReady && (node->biss_NumRuntimeKeys != 0 || node->biss_NumArrayKeys != 0)) { ExecReScan((PlanState *) node, NULL); doscan = node->biss_RuntimeKeysReady; } else doscan = true; /* * Prepare the result bitmap. Normally we just create a new one to pass * back; however, our parent node is allowed to store a pre-made one into * node->biss_result, in which case we just OR our tuple IDs into the * existing bitmap. (This saves needing explicit UNION steps.) */ if (node->biss_result) { tbm = node->biss_result; node->biss_result = NULL; /* reset for next time */ } else { /* XXX should we use less than work_mem for this? */ tbm = tbm_create(work_mem * 1024L); } /* * Get TIDs from index and insert into bitmap */ while (doscan) { bool more = index_getmulti(scandesc, tids, MAX_TIDS, &ntids); if (ntids > 0) { tbm_add_tuples(tbm, tids, ntids); nTuples += ntids; } CHECK_FOR_INTERRUPTS(); if (!more) { doscan = ExecIndexAdvanceArrayKeys(node->biss_ArrayKeys, node->biss_NumArrayKeys); if (doscan) /* reset index scan */ index_rescan(node->biss_ScanDesc, node->biss_ScanKeys); } } /* must provide our own instrumentation support */ if (node->ss.ps.instrument) InstrStopNode(node->ss.ps.instrument, nTuples); return (Node *) tbm; }
/* ---------------------------------------------------------------- * MultiExecBitmapIndexScan(node) * ---------------------------------------------------------------- */ Node * MultiExecBitmapIndexScan(BitmapIndexScanState *node) { #define MAX_TIDS 1024 TIDBitmap *tbm = NULL; IndexScanDesc scandesc; IndexScanDesc odScanDesc; ItemPointerData tids[MAX_TIDS]; int32 ntids; double nTuples = 0; OnDiskBitmapWords *odbm = NULL; bool inmem = false; /* must provide our own instrumentation support */ if (node->ss.ps.instrument) InstrStartNode(node->ss.ps.instrument); /* * extract necessary information from index scan node */ scandesc = node->biss_ScanDesc; odScanDesc = node->odbiss_ScanDesc; /* * If we have runtime keys and they've not already been set up, do it * now. */ if (node->biss_RuntimeKeyInfo && !node->biss_RuntimeKeysReady) ExecReScan((PlanState *) node, NULL); inmem = ((BitmapIndexScan*)((PlanState*)node)->plan)->inmem; if (inmem) { node->odbiss_result = NULL; /* * Prepare the result bitmap. Normally we just create a new one to pass * back; however, our parent node is allowed to store a pre-made one * into node->biss_result, in which case we just OR our tuple IDs into * the existing bitmap. (This saves needing explicit UNION steps.) */ if (node->biss_result) { tbm = node->biss_result; node->biss_result = NULL; /* reset for next time */ } else { /* XXX should we use less than work_mem for this? */ tbm = tbm_create(work_mem * 1024L); } /* * Get TIDs from index and insert into bitmap */ for (;;) { bool more = index_getmulti(scandesc, tids, MAX_TIDS, &ntids); if (ntids > 0) { tbm_add_tuples(tbm, tids, ntids); nTuples += ntids; } if (!more) break; CHECK_FOR_INTERRUPTS(); } } else { node->biss_result = NULL; if (node->odbiss_result == NULL) node->odbiss_result = odbm_create(ODBM_MAX_WORDS); odbm = node->odbiss_result; index_getbitmapwords(odScanDesc, odbm->maxNumOfWords, &(odbm->numOfWords), odbm->bitmapHeaderWords, odbm->bitmapContentWords); } /* must provide our own instrumentation support */ if (node->ss.ps.instrument) InstrStopNodeMulti(node->ss.ps.instrument, nTuples); if (tbm != NULL) return (Node *) tbm; else return (Node *) odbm; }