Exemplo n.º 1
0
static bool
DynamicIndexScan_ReMapColumns(DynamicIndexScanState *scanState, Oid newOid)
{
	Assert(OidIsValid(newOid));

	IndexScan *indexScan = (IndexScan *) scanState->indexScanState.ss.ps.plan;

	if (!isDynamicScan(&indexScan->scan))
	{
		return false;
	}

	Oid oldOid = scanState->columnLayoutOid;

	if (!OidIsValid(oldOid))
	{
		/* Very first partition */

		oldOid = rel_partition_get_root(newOid);
	}

	Assert(OidIsValid(oldOid));

	if (oldOid == newOid)
	{
		/*
		 * If we have only one partition and we are rescanning
		 * then we can have this scenario.
		 */

		return false;
	}

	AttrNumber	*attMap = IndexScan_GetColumnMapping(oldOid, newOid);

	scanState->columnLayoutOid = newOid;

	if (attMap)
	{
		IndexScan_MapLogicalIndexInfo(indexScan->logicalIndexInfo, attMap, indexScan->scan.scanrelid);
		change_varattnos_of_a_varno((Node*)indexScan->scan.plan.targetlist, attMap, indexScan->scan.scanrelid);
		change_varattnos_of_a_varno((Node*)indexScan->scan.plan.qual, attMap, indexScan->scan.scanrelid);
		change_varattnos_of_a_varno((Node*)indexScan->indexqual, attMap, indexScan->scan.scanrelid);

		pfree(attMap);

		return true;
	}
	else
	{
		return false;
	}
}
Exemplo n.º 2
0
/*
 * DynamicScan_InitNextRelation
 *		Initializes states to process the next relation (if any).
 *		For partitioned scan we advance the iterator and prepare
 *		the next partition to scan. For non-partitioned case, we
 *		just start with the *only* relation, if we haven't
 *		already processed that relation.
 *
 *		Returns false if we don't have any more partition to iterate.
 */
static bool
DynamicScan_InitNextRelation(ScanState *scanState, PartitionInitMethod *partitionInitMethod, PartitionEndMethod *partitionEndMethod, PartitionReScanMethod *partitionReScanMethod)
{
	Assert(T_BitmapTableScanState == scanState->ps.type);

	Scan *scan = (Scan *)scanState->ps.plan;

	if (isDynamicScan(scan))
	{
		return DynamicScan_InitNextPartition(scanState, partitionInitMethod, partitionEndMethod, partitionReScanMethod);
	}

	return DynamicScan_InitSingleRelation(scanState, partitionInitMethod, partitionReScanMethod);
}
Exemplo n.º 3
0
/*
 * DynamicScan_Controller
 *		Controller function to transition from one scan status to another.
 *
 *		This function does not handle SCAN_END, which is exclusively controlled
 *		by the DynamicScan_End method
 */
static ScanStatus
DynamicScan_Controller(ScanState *scanState, ScanStatus desiredState, PartitionInitMethod *partitionInitMethod,
		PartitionEndMethod *partitionEndMethod, PartitionReScanMethod *partitionReScanMethod)
{
	ScanStatus startState = scanState->scan_state;

	/* Controller doesn't handle any state transition related to SCAN_END */
	if (SCAN_END == desiredState || SCAN_END == startState)
	{
		DynamicScan_StateTransitionError(startState, desiredState);
	}

	if (SCAN_SCAN == desiredState && (SCAN_INIT == startState || SCAN_NEXT == startState || SCAN_RESCAN == startState))
	{
		Assert(SCAN_DONE != startState || SCAN_END != startState);
		if (SCAN_INIT == startState || SCAN_RESCAN == startState)
		{
			DynamicScan_RewindIterator(scanState);
		}

		if (DynamicScan_InitNextRelation(scanState, partitionInitMethod, partitionEndMethod, partitionReScanMethod))
		{
			scanState->scan_state = SCAN_SCAN;
		}
		else
		{
			scanState->scan_state = SCAN_DONE;
		}
	}
	else if (SCAN_RESCAN == desiredState && SCAN_END != startState)
	{
		Assert(SCAN_END != startState);
		/* RESCAN shouldn't affect INIT, as nothing to rewind yet */
		if (SCAN_INIT != startState)
		{
			scanState->scan_state = SCAN_RESCAN;
		}
	}
	else if (SCAN_NEXT == desiredState && SCAN_SCAN == startState)
	{
		scanState->scan_state = isDynamicScan((Scan *)scanState->ps.plan) ? SCAN_NEXT : SCAN_DONE;
	}
	else
	{
		DynamicScan_StateTransitionError(scanState->scan_state, desiredState);
	}

	return scanState->scan_state;
}
Exemplo n.º 4
0
/*
 * DynamicScan_GetIterator
 * 		Returns the current iterator for the scanState's partIndex.
 */
DynamicPartitionIterator*
DynamicScan_GetIterator(ScanState *scanState)
{
	Assert(isDynamicScan((Scan *)scanState->ps.plan));
	Assert(NULL != scanState->ps.state->dynamicTableScanInfo);

	int partIndex = ((Scan*)scanState->ps.plan)->partIndex;
	Assert(partIndex <= scanState->ps.state->dynamicTableScanInfo->numScans);

	DynamicPartitionIterator *iterator = scanState->ps.state->dynamicTableScanInfo->iterators[partIndex - 1];

	Assert(NULL != iterator);

	return iterator;
}
Exemplo n.º 5
0
/*
 * DynamicScan_MapRelationColumns
 * 		Returns dropped column mapping between two relations. Returns NULL if
 * 		no mapping is necessary.
 */
static AttrNumber*
DynamicScan_MapRelationColumns(ScanState *scanState, Relation oldRelation, Relation newRelation)
{
	AttrNumber *attMap = NULL;

	if (isDynamicScan((Scan *)scanState->ps.plan) && (oldRelation != newRelation))
	{
		TupleDesc oldTupDesc = RelationGetDescr(oldRelation);
		TupleDesc newTupDesc = RelationGetDescr(newRelation);

		attMap = varattnos_map(oldTupDesc, newTupDesc);
	}

	return attMap;
}
Exemplo n.º 6
0
/*
 * DynamicScan_RemapExpression
 * 		Re-maps the expression using the provided attMap.
 */
bool
DynamicScan_RemapExpression(ScanState *scanState, AttrNumber *attMap, Node *expr)
{
	if (!isDynamicScan((Scan *)scanState->ps.plan))
	{
		return false;
	}

	if (NULL != attMap)
	{
		change_varattnos_of_a_varno((Node*)expr, attMap, ((Scan *)scanState->ps.plan)->scanrelid);
		return true;
	}

	return false;
}
Exemplo n.º 7
0
/*
 * DynamicScan_RewindIterator
 *		Rewinds the iterator for a new scan of all the parts
 */
static void
DynamicScan_RewindIterator(ScanState *scanState)
{
	if (!isDynamicScan((Scan *)scanState->ps.plan))
	{
		return;
	}

	/*
	 * For EXPLAIN of a plan, we may never finish the initialization,
	 * and end up calling the End method directly.In such cases, we
	 * don't have any iterator to end.
	 */
	if (SCAN_INIT == scanState->scan_state)
	{
		DynamicScan_CreateIterator(scanState, (Scan *)scanState->ps.plan);
		return;
	}

	Scan *scan = (Scan *)scanState->ps.plan;

	DynamicTableScanInfo *partitionInfo = scanState->ps.state->dynamicTableScanInfo;

	Assert(partitionInfo->numScans >= scan->partIndex);
	DynamicPartitionIterator *iterator = partitionInfo->iterators[scan->partIndex - 1];

	Assert(NULL != iterator);

	if (iterator->shouldCallHashSeqTerm)
	{
		hash_seq_term(iterator->partitionIterator);
	}

	pfree(iterator->partitionIterator);

	iterator->partitionOids = partitionInfo->pidIndexes[scan->partIndex - 1];
	Assert(iterator->partitionOids != NULL);
	iterator->shouldCallHashSeqTerm = true;

	HASH_SEQ_STATUS *partitionIterator = palloc(sizeof(HASH_SEQ_STATUS));
	hash_seq_init(partitionIterator, iterator->partitionOids);

	iterator->partitionIterator = partitionIterator;

	Assert(iterator == partitionInfo->iterators[scan->partIndex - 1]);
}
Exemplo n.º 8
0
/*
 * DynamicScan_InitSingleRelation
 *		Prepares a single relation for scanning by calling various
 *		helper methods to open relation, initialize expressions etc.
 *
 *		Note: this is for the non-partitioned relations.
 *
 *		Returns true upon success.
 */
static bool
DynamicScan_InitSingleRelation(ScanState *scanState, PartitionInitMethod *partitionInitMethod, PartitionReScanMethod *partitionReScanMethod)
{
	Assert(!isDynamicScan((Scan *)scanState->ps.plan));

	if (NULL == scanState->ss_currentRelation)
	{
		/* Open the relation and initalize the expressions (targetlist, qual etc.) */
		InitScanStateRelationDetails(scanState, scanState->ps.plan, scanState->ps.state);
		partitionInitMethod(scanState, NULL /* No dropped column mapping */);
	}
	else
	{
		Insist(scanState->scan_state == SCAN_RESCAN);
		partitionReScanMethod(scanState);
	}

	return true;
}
Exemplo n.º 9
0
/*
 * DynamicScan_GetTableOid
 * 		Returns the Oid of the table/partition to scan.
 *
 *		For partitioned case this method returns InvalidOid
 *		if the partition iterator hasn't been initialized yet.
 */
Oid
DynamicScan_GetTableOid(ScanState *scanState)
{
	/* For non-partitioned scan, just lookup the RTE */
	if (!isDynamicScan((Scan *)scanState->ps.plan))
	{
		return getrelid(((Scan *)scanState->ps.plan)->scanrelid, scanState->ps.state->es_range_table);
	}

	/* We are yet to initialize the iterator, so return InvalidOid */
	if (SCAN_INIT == scanState->scan_state)
	{
		return InvalidOid;
	}

	/* Get the iterator and look up the oid of the current relation */
	DynamicPartitionIterator *iterator = DynamicScan_GetIterator(scanState);
	Assert(NULL != iterator);
	Assert(OidIsValid(iterator->curRelOid));

	return iterator->curRelOid;
}
Exemplo n.º 10
0
/*
 * DynamicScan_GetPartitionMemoryContext
 * 		Returns the current partition's (if any) memory context.
 */
MemoryContext
DynamicScan_GetPartitionMemoryContext(ScanState *scanState)
{
	Assert(T_BitmapTableScanState == scanState->ps.type
			|| T_BitmapIndexScanState == scanState->ps.type);

	Scan *scan = (Scan *)scanState->ps.plan;

	/*
	 * TODO rahmaf2 05/08/2014 [JIRA: MPP-23513] We currently
	 * return NULL memory context during initialization. So,
	 * for partitioned case, we will leak memory for all the
	 * expression initialization allocations during ExecInit.
	 */
	if (!isDynamicScan(scan) || SCAN_INIT == scanState->scan_state)
	{
		return NULL;
	}

	DynamicPartitionIterator *iterator = DynamicScan_GetIterator(scanState);

	Assert(NULL != iterator);
	return iterator->partitionMemoryContext;
}
Exemplo n.º 11
0
/*
 * DynamicScan_End
 *		Ends partition/relation iteration/scanning and cleans up everything.
 */
void
DynamicScan_End(ScanState *scanState, PartitionEndMethod *partitionEndMethod)
{
	Assert(NULL != scanState);
	Assert(T_BitmapTableScanState == scanState->ps.type);

	if (SCAN_END == scanState->scan_state)
	{
		return;
	}

	Scan *scan = (Scan *)scanState->ps.plan;

	DynamicScan_CleanupOneRelation(scanState, scanState->ss_currentRelation, partitionEndMethod);

	if (isDynamicScan(scan))
	{
		DynamicScan_EndIterator(scanState);
	}

	FreeScanRelationInternal(scanState, false /* Do not close the relation. We closed it in DynamicScan_CleanupOneRelation */);

	scanState->scan_state = SCAN_END;
}
Exemplo n.º 12
0
/*
 * DynamicScan_InitNextPartition
 *		Prepares the next partition for scanning by calling various
 *		helper methods to open relation, map dropped attributes,
 *		initialize expressions etc.
 */
static bool
DynamicScan_InitNextPartition(ScanState *scanState, PartitionInitMethod *partitionInitMethod, PartitionEndMethod *partitionEndMethod, PartitionReScanMethod *partitionReScanMethod)
{
	Assert(isDynamicScan((Scan *)scanState->ps.plan));
	AssertImply(scanState->scan_state != SCAN_INIT, NULL != scanState->ss_currentRelation);

	Scan *scan = (Scan *)scanState->ps.plan;
	DynamicTableScanInfo *partitionInfo = scanState->ps.state->dynamicTableScanInfo;
	Assert(partitionInfo->numScans >= scan->partIndex);
	int32 numSelectors = list_nth_int(partitionInfo->numSelectorsPerScanId, scan->partIndex);

	Oid newOid = DynamicScan_AdvanceIterator(scanState, numSelectors);

	if (!OidIsValid(newOid))
	{
		return false;
	}

	Relation oldRelation = NULL;
	Relation newRelation = NULL;

	DynamicScan_ObtainRelations(scanState, newOid, &oldRelation, &newRelation);
	/* Either we have a new relation or this is the first relation */
	if (oldRelation != newRelation || NULL == scanState->ss_currentRelation)
	{
		AttrNumber *attMap = DynamicScan_MapRelationColumns(scanState, oldRelation, newRelation);

		DynamicScan_RemapExpression(scanState, attMap, (Node*)scanState->ps.plan->qual);
		DynamicScan_RemapExpression(scanState, attMap, (Node*)scanState->ps.plan->targetlist);

		/*
		 * We only initialize expression if this is the first partition
		 * or if the column mapping changes between two partitions.
		 * Otherwise, we reuse the previously initialized expression.
		 */
		bool initExpressions = (NULL != attMap || SCAN_INIT == scanState->scan_state);

		if (newRelation != oldRelation)
		{
			/* Close the old relation */
			DynamicScan_CleanupOneRelation(scanState, oldRelation, partitionEndMethod);
		}

		DynamicScan_UpdateScanStateForNewPart(scanState, newRelation);

		if (initExpressions)
		{
			DynamicScan_InitExpr(scanState);
		}

		partitionInitMethod(scanState, attMap);

		if (NULL != attMap)
		{
			pfree(attMap);
			attMap = NULL;
		}
	}
	else
	{
		/* Rescan of the same part */
		partitionReScanMethod(scanState);
	}

	/* Collect number of partitions scanned in EXPLAIN ANALYZE */
	if(NULL != scanState->ps.instrument)
	{
		Instrumentation *instr = scanState->ps.instrument;
		instr->numPartScanned ++;
	}

	return true;
}