/*
 * 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;
}
Example #2
0
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);
}