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

📄 executils.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
		int		   *varNumbers;		AttrNumber	lastInnerVar = 0;		AttrNumber	lastOuterVar = 0;		AttrNumber	lastScanVar = 0;		projInfo->pi_itemIsDone = NULL; /* not needed */		projInfo->pi_varSlotOffsets = varSlotOffsets = (int *)			palloc0(len * sizeof(int));		projInfo->pi_varNumbers = varNumbers = (int *)			palloc0(len * sizeof(int));		/*		 * Set up the data needed by ExecVariableList.	The slots in which the		 * variables can be found at runtime are denoted by the offsets of		 * their slot pointers within the econtext.  This rather grotty		 * representation is needed because the caller may not have given us		 * the real econtext yet (see hacks in nodeSubplan.c).		 */		foreach(tl, targetList)		{			GenericExprState *gstate = (GenericExprState *) lfirst(tl);			Var		   *variable = (Var *) gstate->arg->expr;			AttrNumber	attnum = variable->varattno;			TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;			AttrNumber	resind = tle->resno - 1;			Assert(resind >= 0 && resind < len);			varNumbers[resind] = attnum;			switch (variable->varno)			{				case INNER:					varSlotOffsets[resind] = offsetof(ExprContext,													  ecxt_innertuple);					lastInnerVar = Max(lastInnerVar, attnum);					break;				case OUTER:					varSlotOffsets[resind] = offsetof(ExprContext,													  ecxt_outertuple);					lastOuterVar = Max(lastOuterVar, attnum);					break;				default:					varSlotOffsets[resind] = offsetof(ExprContext,													  ecxt_scantuple);					lastScanVar = Max(lastScanVar, attnum);					break;			}		}		projInfo->pi_lastInnerVar = lastInnerVar;		projInfo->pi_lastOuterVar = lastOuterVar;		projInfo->pi_lastScanVar = lastScanVar;	}	else	{		projInfo->pi_itemIsDone = (ExprDoneCond *)			palloc(len * sizeof(ExprDoneCond));		projInfo->pi_varSlotOffsets = NULL;		projInfo->pi_varNumbers = NULL;	}	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 executor * shutdown 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.) * * However ... there is no particular need to do it during ExecEndNode, * because FreeExecutorState will free any remaining ExprContexts within * the EState.	Letting FreeExecutorState do it allows the ExprContexts to * be freed in reverse order of creation, rather than order of creation as * will happen if we delete them here, which saves O(N^2) work in the list * cleanup inside FreeExprContext. * ---------------- */voidExecFreeExprContext(PlanState *planstate){	/*	 * Per above discussion, don't actually delete the ExprContext. We do	 * unlink it from the plan node, though.	 */	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->tts_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;	ListCell   *l;	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 = list_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(l, indexoidlist)	{		Oid			indexOid = lfirst_oid(l);		Relation	indexDesc;		IndexInfo  *ii;		/*		 * Open and lock the index relation		 *		 * If the index AM supports concurrent updates, obtain		 * RowExclusiveLock to signify that we are updating the index.	This		 * locks out only operations that need exclusive access, such as		 * relocating the index to a new tablespace.		 *		 * 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).		 *		 * If there are multiple not-concurrent-safe indexes, all backends		 * must lock the indexes in the same order or we will get deadlocks		 * here. This is guaranteed by RelationGetIndexList(), which promises		 * to return the index list in OID order.		 *		 * The locks will be released in ExecCloseIndices.		 */		indexDesc = index_open(indexOid);		if (indexDesc->rd_am->amconcurrent)			LockRelation(indexDesc, RowExclusiveLock);		else			LockRelation(indexDesc, AccessExclusiveLock);		/* extract index key information from the index's pg_index info */		ii = BuildIndexInfo(indexDesc);		relationDescs[i] = indexDesc;		indexInfoArray[i] = ii;		i++;	}	list_free(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;			/* shouldn't happen? */		/* Drop lock acquired by ExecOpenIndices */		if (indexDescs[i]->rd_am->amconcurrent)			UnlockRelation(indexDescs[i], RowExclusiveLock);		else			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){	ResultRelInfo *resultRelInfo;	int			i;	int			numIndices;	RelationPtr relationDescs;	Relation	heapRelation;	IndexInfo **indexInfoArray;	ExprContext *econtext;	Datum		values[INDEX_MAX_KEYS];	bool		isnull[INDEX_MAX_KEYS];	/*	 * 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;	/*	 * 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;		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 values and isnull parameters with the		 * appropriate values for the column(s) of the index.		 */		FormIndexDatum(indexInfo,					   slot,					   estate,					   values,					   isnull);		/*		 * 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.		 */		index_insert(relationDescs[i],	/* index relation */					 values,	/* array of index Datums */					 isnull,	/* null flags */					 tupleid,	/* tid of heap tuple */					 heapRelation,					 relationDescs[i]->rd_index->indisunique && !is_vacuum);		/*		 * keep track of index inserts for debugging		 */		IncrIndexInserted();	}}/* * 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 + -