/* * This function initializes a part and returns true if a new index has been prepared for scanning. */ static bool initNextIndexToScan(DynamicIndexScanState *node) { IndexScanState *indexState = &(node->indexScanState); DynamicIndexScan *dynamicIndexScan = (DynamicIndexScan *)node->indexScanState.ss.ps.plan; /* Load new index when the scanning of the previous index is done. */ if (indexState->ss.scan_state == SCAN_INIT || indexState->ss.scan_state == SCAN_DONE) { /* This is the oid of a partition of the table (*not* index) */ Oid *pid = hash_seq_search(&node->pidxStatus); if (pid == NULL) { /* Return if all parts have been scanned. */ node->shouldCallHashSeqTerm = false; return false; } /* Collect number of partitions scanned in EXPLAIN ANALYZE */ if(NULL != indexState->ss.ps.instrument) { Instrumentation *instr = indexState->ss.ps.instrument; instr->numPartScanned ++; } DynamicIndexScan_ReMapColumns(node, *pid); /* * The is the oid of the partition of an *index*. Note: a partitioned table * has a root and a set of partitions (may be multi-level). An index * on a partitioned table also has a root and a set of index partitions. * We started at table level, and now we are fetching the oid of an index * partition. */ Oid pindex = getPhysicalIndexRelid(dynamicIndexScan->logicalIndexInfo, *pid); Assert(OidIsValid(pindex)); Relation currentRelation = OpenScanRelationByOid(*pid); indexState->ss.ss_currentRelation = currentRelation; for (int i=0; i < DYNAMICINDEXSCAN_NSLOTS; i++) { indexState->ss.ss_ScanTupleSlot[i].tts_tableOid = *pid; } ExecAssignScanType(&indexState->ss, RelationGetDescr(currentRelation)); ScanState *scanState = (ScanState *)node; MemoryContextReset(node->partitionMemoryContext); MemoryContext oldCxt = MemoryContextSwitchTo(node->partitionMemoryContext); /* Initialize child expressions */ scanState->ps.qual = (List *)ExecInitExpr((Expr *)scanState->ps.plan->qual, (PlanState*)scanState); scanState->ps.targetlist = (List *)ExecInitExpr((Expr *)scanState->ps.plan->targetlist, (PlanState*)scanState); ExecAssignScanProjectionInfo(scanState); EState *estate = indexState->ss.ps.state; indexState->iss_RelationDesc = OpenIndexRelation(estate, pindex, *pid); /* * build the index scan keys from the index qualification */ ExecIndexBuildScanKeys((PlanState *) indexState, indexState->iss_RelationDesc, dynamicIndexScan->indexqual, dynamicIndexScan->indexstrategy, dynamicIndexScan->indexsubtype, &indexState->iss_ScanKeys, &indexState->iss_NumScanKeys, &indexState->iss_RuntimeKeys, &indexState->iss_NumRuntimeKeys, NULL, NULL); MemoryContextSwitchTo(oldCxt); ExprContext *econtext = indexState->iss_RuntimeContext; /* context for runtime keys */ if (indexState->iss_NumRuntimeKeys != 0) { ExecIndexEvalRuntimeKeys(econtext, indexState->iss_RuntimeKeys, indexState->iss_NumRuntimeKeys); } indexState->iss_RuntimeKeysReady = true; /* * Initialize result tuple type and projection info. */ TupleDesc td = indexState->ss.ps.ps_ResultTupleSlot->tts_tupleDescriptor; if (td) { pfree(td); td = NULL; } ExecAssignResultTypeFromTL(&indexState->ss.ps); ExecAssignScanProjectionInfo(&indexState->ss); indexState->iss_ScanDesc = index_beginscan(currentRelation, indexState->iss_RelationDesc, estate->es_snapshot, indexState->iss_NumScanKeys, indexState->iss_ScanKeys); indexState->ss.scan_state = SCAN_SCAN; } return true; }
Datum gp_get_physical_index_relid(PG_FUNCTION_ARGS) { Oid rootOid = PG_GETARG_OID(0); Oid partOid = PG_GETARG_OID(1); LogicalIndexInfo logicalIndexInfo; Oid resultOid; int2vector *indexKeys; text *inText; Relation rel; logicalIndexInfo.nColumns = 0; logicalIndexInfo.indexKeys = NULL; logicalIndexInfo.indPred = NIL; logicalIndexInfo.indExprs = NIL; if (!PG_ARGISNULL(2)) { indexKeys = (int2vector *)PG_GETARG_POINTER(2); logicalIndexInfo.nColumns = indexKeys->dim1; logicalIndexInfo.indexKeys = (AttrNumber *)palloc0(indexKeys->dim1 * sizeof(AttrNumber)); for (int i = 0; i < indexKeys->dim1; i++) logicalIndexInfo.indexKeys[i] = indexKeys->values[i]; } if (!PG_ARGISNULL(3)) { Node *indPred; inText = PG_GETARG_TEXT_P(3); indPred = stringToNode(text_to_cstring(inText)); /* Perform the same normalization as relcache.c does. */ indPred = eval_const_expressions(NULL, indPred); indPred = (Node *) canonicalize_qual((Expr *) indPred); set_coercionform_dontcare(indPred); indPred = (Node *) make_ands_implicit((Expr *) indPred); fix_opfuncids(indPred); logicalIndexInfo.indPred = (List *) indPred; } if (!PG_ARGISNULL(4)) { Node *indExprs; inText = PG_GETARG_TEXT_P(4); indExprs = stringToNode(text_to_cstring(inText)); /* Perform the same normalization as relcache.c does. */ indExprs = eval_const_expressions(NULL, indExprs); set_coercionform_dontcare(indExprs); fix_opfuncids(indExprs); logicalIndexInfo.indExprs = (List *) indExprs; } logicalIndexInfo.indIsUnique = PG_GETARG_BOOL(5); AttrNumber *attMap = IndexScan_GetColumnMapping(rootOid, partOid); rel = heap_open(partOid, AccessShareLock); /* * The varno is hard-coded to 1 as the original getPhysicalIndexRelid was * using a hard-coded 1 for varattno mapping of logicalIndexInfo. */ IndexScan_MapLogicalIndexInfo(&logicalIndexInfo, attMap, 1); /* do the actual work */ resultOid = getPhysicalIndexRelid(rel, &logicalIndexInfo); if (attMap) { pfree(attMap); } heap_close(rel, AccessShareLock); return ObjectIdGetDatum(resultOid); }