⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 executils.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
ExecBuildProjectionInfo(List *targetList,						ExprContext *econtext,						TupleTableSlot *slot){	ProjectionInfo *projInfo = makeNode(ProjectionInfo);	int			len;	len = ExecTargetListLength(targetList);	projInfo->pi_targetlist = targetList;	projInfo->pi_exprContext = econtext;	projInfo->pi_slot = slot;	if (len > 0)	{		projInfo->pi_tupValues = (Datum *) palloc(len * sizeof(Datum));		projInfo->pi_tupNulls = (char *) palloc(len * sizeof(char));		projInfo->pi_itemIsDone = (ExprDoneCond *) palloc(len * sizeof(ExprDoneCond));	}	return projInfo;}/* ---------------- *		ExecAssignProjectionInfo * * forms the projection information from the node's targetlist * ---------------- */voidExecAssignProjectionInfo(PlanState *planstate){	planstate->ps_ProjInfo =		ExecBuildProjectionInfo(planstate->targetlist,								planstate->ps_ExprContext,								planstate->ps_ResultTupleSlot);}/* ---------------- *		ExecFreeExprContext * * A plan node's ExprContext should be freed explicitly during ExecEndNode * because there may be shutdown callbacks to call.  (Other resources made * by the above routines, such as projection info, don't need to be freed * explicitly because they're just memory in the per-query memory context.) * ---------------- */voidExecFreeExprContext(PlanState *planstate){	ExprContext *econtext;	/*	 * get expression context.	if NULL then this node has none so we just	 * return.	 */	econtext = planstate->ps_ExprContext;	if (econtext == NULL)		return;	FreeExprContext(econtext);	planstate->ps_ExprContext = NULL;}/* ---------------------------------------------------------------- *		the following scan type support functions are for *		those nodes which are stubborn and return tuples in *		their Scan tuple slot instead of their Result tuple *		slot..	luck fur us, these nodes do not do projections *		so we don't have to worry about getting the ProjectionInfo *		right for them...  -cim 6/3/91 * ---------------------------------------------------------------- *//* ---------------- *		ExecGetScanType * ---------------- */TupleDescExecGetScanType(ScanState *scanstate){	TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;	return slot->ttc_tupleDescriptor;}/* ---------------- *		ExecAssignScanType * ---------------- */voidExecAssignScanType(ScanState *scanstate,				   TupleDesc tupDesc, bool shouldFree){	TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;	ExecSetSlotDescriptor(slot, tupDesc, shouldFree);}/* ---------------- *		ExecAssignScanTypeFromOuterPlan * ---------------- */voidExecAssignScanTypeFromOuterPlan(ScanState *scanstate){	PlanState  *outerPlan;	TupleDesc	tupDesc;	outerPlan = outerPlanState(scanstate);	tupDesc = ExecGetResultType(outerPlan);	ExecAssignScanType(scanstate, tupDesc, false);}/* ---------------------------------------------------------------- *				  ExecInsertIndexTuples support * ---------------------------------------------------------------- *//* ---------------------------------------------------------------- *		ExecOpenIndices * *		Find the indices associated with a result relation, open them, *		and save information about them in the result ResultRelInfo. * *		At entry, caller has already opened and locked *		resultRelInfo->ri_RelationDesc. * *		This used to be horribly ugly code, and slow too because it *		did a sequential scan of pg_index.	Now we rely on the relcache *		to cache a list of the OIDs of the indices associated with any *		specific relation, and we use the pg_index syscache to get the *		entries we need from pg_index. * ---------------------------------------------------------------- */voidExecOpenIndices(ResultRelInfo *resultRelInfo){	Relation	resultRelation = resultRelInfo->ri_RelationDesc;	List	   *indexoidlist,			   *indexoidscan;	int			len,				i;	RelationPtr relationDescs;	IndexInfo **indexInfoArray;	resultRelInfo->ri_NumIndices = 0;	/* fast path if no indexes */	if (!RelationGetForm(resultRelation)->relhasindex)		return;	/*	 * Get cached list of index OIDs	 */	indexoidlist = RelationGetIndexList(resultRelation);	len = length(indexoidlist);	if (len == 0)		return;	/*	 * allocate space for result arrays	 */	relationDescs = (RelationPtr) palloc(len * sizeof(Relation));	indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));	resultRelInfo->ri_NumIndices = len;	resultRelInfo->ri_IndexRelationDescs = relationDescs;	resultRelInfo->ri_IndexRelationInfo = indexInfoArray;	/*	 * For each index, open the index relation and save pg_index info.	 */	i = 0;	foreach(indexoidscan, indexoidlist)	{		Oid			indexOid = lfirsto(indexoidscan);		Relation	indexDesc;		IndexInfo  *ii;		/*		 * Open (and lock, if necessary) the index relation		 *		 * If the index AM is not safe for concurrent updates, obtain an		 * exclusive lock on the index to lock out other updaters as well		 * as readers (index_beginscan places AccessShareLock). We will		 * release this lock in ExecCloseIndices.		 *		 * If the index AM supports concurrent updates, we obtain no lock		 * here at all, which is a tad weird, but safe since any critical		 * operation on the index (like deleting it) will acquire		 * exclusive lock on the parent table.	Perhaps someday we should		 * acquire RowExclusiveLock on the index here?		 *		 * If there are multiple not-concurrent-safe indexes, all backends		 * must lock the indexes in the same order or we will get		 * deadlocks here during concurrent updates.  This is guaranteed		 * by RelationGetIndexList(), which promises to return the index		 * list in OID order.		 */		indexDesc = index_open(indexOid);		if (!indexDesc->rd_am->amconcurrent)			LockRelation(indexDesc, AccessExclusiveLock);		/* extract index key information from the index's pg_index info */		ii = BuildIndexInfo(indexDesc);		relationDescs[i] = indexDesc;		indexInfoArray[i] = ii;		i++;	}	freeList(indexoidlist);}/* ---------------------------------------------------------------- *		ExecCloseIndices * *		Close the index relations stored in resultRelInfo * ---------------------------------------------------------------- */voidExecCloseIndices(ResultRelInfo *resultRelInfo){	int			i;	int			numIndices;	RelationPtr indexDescs;	numIndices = resultRelInfo->ri_NumIndices;	indexDescs = resultRelInfo->ri_IndexRelationDescs;	for (i = 0; i < numIndices; i++)	{		if (indexDescs[i] == NULL)			continue;		/* Drop lock, if one was acquired by ExecOpenIndices */		if (!indexDescs[i]->rd_am->amconcurrent)			UnlockRelation(indexDescs[i], AccessExclusiveLock);		index_close(indexDescs[i]);	}	/*	 * XXX should free indexInfo array here too?  Currently we assume that	 * such stuff will be cleaned up automatically in FreeExecutorState.	 */}/* ---------------------------------------------------------------- *		ExecInsertIndexTuples * *		This routine takes care of inserting index tuples *		into all the relations indexing the result relation *		when a heap tuple is inserted into the result relation. *		Much of this code should be moved into the genam *		stuff as it only exists here because the genam stuff *		doesn't provide the functionality needed by the *		executor.. -cim 9/27/89 * ---------------------------------------------------------------- */voidExecInsertIndexTuples(TupleTableSlot *slot,					  ItemPointer tupleid,					  EState *estate,					  bool is_vacuum){	HeapTuple	heapTuple;	ResultRelInfo *resultRelInfo;	int			i;	int			numIndices;	RelationPtr relationDescs;	Relation	heapRelation;	TupleDesc	heapDescriptor;	IndexInfo **indexInfoArray;	ExprContext *econtext;	Datum		datum[INDEX_MAX_KEYS];	char		nullv[INDEX_MAX_KEYS];	heapTuple = slot->val;	/*	 * Get information from the result relation info structure.	 */	resultRelInfo = estate->es_result_relation_info;	numIndices = resultRelInfo->ri_NumIndices;	relationDescs = resultRelInfo->ri_IndexRelationDescs;	indexInfoArray = resultRelInfo->ri_IndexRelationInfo;	heapRelation = resultRelInfo->ri_RelationDesc;	heapDescriptor = RelationGetDescr(heapRelation);	/*	 * We will use the EState's per-tuple context for evaluating	 * predicates and index expressions (creating it if it's not already	 * there).	 */	econtext = GetPerTupleExprContext(estate);	/* Arrange for econtext's scan tuple to be the tuple under test */	econtext->ecxt_scantuple = slot;	/*	 * for each index, form and insert the index tuple	 */	for (i = 0; i < numIndices; i++)	{		IndexInfo  *indexInfo;		InsertIndexResult result;		if (relationDescs[i] == NULL)			continue;		indexInfo = indexInfoArray[i];		/* Check for partial index */		if (indexInfo->ii_Predicate != NIL)		{			List	   *predicate;			/*			 * If predicate state not set up yet, create it (in the			 * estate's per-query context)			 */			predicate = indexInfo->ii_PredicateState;			if (predicate == NIL)			{				predicate = (List *)					ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,									estate);				indexInfo->ii_PredicateState = predicate;			}			/* Skip this index-update if the predicate isn't satisfied */			if (!ExecQual(predicate, econtext, false))				continue;		}		/*		 * FormIndexDatum fills in its datum and null parameters with		 * attribute information taken from the given heap tuple. It also		 * computes any expressions needed.		 */		FormIndexDatum(indexInfo,					   heapTuple,					   heapDescriptor,					   estate,					   datum,					   nullv);		/*		 * The index AM does the rest.	Note we suppress unique-index		 * checks if we are being called from VACUUM, since VACUUM may		 * need to move dead tuples that have the same keys as live ones.		 */		result = index_insert(relationDescs[i], /* index relation */							  datum,	/* array of heaptuple Datums */							  nullv,	/* info on nulls */							  &(heapTuple->t_self),		/* tid of heap tuple */							  heapRelation,				  relationDescs[i]->rd_index->indisunique && !is_vacuum);		/*		 * keep track of index inserts for debugging		 */		IncrIndexInserted();		if (result)			pfree(result);	}}/* * UpdateChangedParamSet *		Add changed parameters to a plan node's chgParam set */voidUpdateChangedParamSet(PlanState *node, Bitmapset *newchg){	Bitmapset  *parmset;	/*	 * The plan node only depends on params listed in its allParam set.	 * Don't include anything else into its chgParam set.	 */	parmset = bms_intersect(node->plan->allParam, newchg);	/*	 * Keep node->chgParam == NULL if there's not actually any members;	 * this allows the simplest possible tests in executor node files.	 */	if (!bms_is_empty(parmset))		node->chgParam = bms_join(node->chgParam, parmset);	else		bms_free(parmset);}/* * Register a shutdown callback in an ExprContext. * * Shutdown callbacks will be called (in reverse order of registration) * when the ExprContext is deleted or rescanned.  This provides a hook * for functions called in the context to do any cleanup needed --- it's * particularly useful for functions returning sets.  Note that the * callback will *not* be called in the event that execution is aborted * by an error. */voidRegisterExprContextCallback(ExprContext *econtext,							ExprContextCallbackFunction function,							Datum arg){	ExprContext_CB *ecxt_callback;	/* Save the info in appropriate memory context */	ecxt_callback = (ExprContext_CB *)		MemoryContextAlloc(econtext->ecxt_per_query_memory,						   sizeof(ExprContext_CB));	ecxt_callback->function = function;	ecxt_callback->arg = arg;	/* link to front of list for appropriate execution order */	ecxt_callback->next = econtext->ecxt_callbacks;	econtext->ecxt_callbacks = ecxt_callback;}/* * Deregister a shutdown callback in an ExprContext. * * Any list entries matching the function and arg will be removed. * This can be used if it's no longer necessary to call the callback. */voidUnregisterExprContextCallback(ExprContext *econtext,							  ExprContextCallbackFunction function,							  Datum arg){	ExprContext_CB **prev_callback;	ExprContext_CB *ecxt_callback;	prev_callback = &econtext->ecxt_callbacks;	while ((ecxt_callback = *prev_callback) != NULL)	{		if (ecxt_callback->function == function && ecxt_callback->arg == arg)		{			*prev_callback = ecxt_callback->next;			pfree(ecxt_callback);		}		else			prev_callback = &ecxt_callback->next;	}}/* * Call all the shutdown callbacks registered in an ExprContext. * * The callback list is emptied (important in case this is only a rescan * reset, and not deletion of the ExprContext). */static voidShutdownExprContext(ExprContext *econtext){	ExprContext_CB *ecxt_callback;	MemoryContext oldcontext;	/* Fast path in normal case where there's nothing to do. */	if (econtext->ecxt_callbacks == NULL)		return;	/*	 * Call the callbacks in econtext's per-tuple context.  This ensures	 * that any memory they might leak will get cleaned up.	 */	oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);	/*	 * Call each callback function in reverse registration order.	 */	while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)	{		econtext->ecxt_callbacks = ecxt_callback->next;		(*ecxt_callback->function) (ecxt_callback->arg);		pfree(ecxt_callback);	}	MemoryContextSwitchTo(oldcontext);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -