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

📄 executils.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * execUtils.c *	  miscellaneous executor utility routines * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.126.2.3 2005/11/23 20:28:04 tgl Exp $ * *------------------------------------------------------------------------- *//* * INTERFACE ROUTINES *		CreateExecutorState		Create/delete executor working state *		FreeExecutorState *		CreateExprContext *		FreeExprContext *		ReScanExprContext * *		ExecAssignExprContext	Common code for plan node init routines. *		ExecAssignResultType *		etc * *		ExecOpenIndices			\ *		ExecCloseIndices		 | referenced by InitPlan, EndPlan, *		ExecInsertIndexTuples	/  ExecInsert, ExecUpdate * *		RegisterExprContextCallback    Register function shutdown callback *		UnregisterExprContextCallback  Deregister function shutdown callback * *	 NOTES *		This file has traditionally been the place to stick misc. *		executor support stuff that doesn't really go anyplace else. */#include "postgres.h"#include "access/genam.h"#include "access/heapam.h"#include "catalog/index.h"#include "catalog/catalog.h"#include "catalog/pg_index.h"#include "executor/execdebug.h"#include "miscadmin.h"#include "utils/builtins.h"#include "utils/fmgroids.h"#include "utils/memutils.h"#include "utils/relcache.h"#include "utils/syscache.h"/* ---------------------------------------------------------------- *		global counters for number of tuples processed, retrieved, *		appended, replaced, deleted. * ---------------------------------------------------------------- */int			NTupleProcessed;int			NTupleRetrieved;int			NTupleReplaced;int			NTupleAppended;int			NTupleDeleted;int			NIndexTupleInserted;extern int	NIndexTupleProcessed;		/* have to be defined in the access										 * method level so that the										 * cinterface.a will link ok. */static void ShutdownExprContext(ExprContext *econtext);/* ---------------------------------------------------------------- *						statistic functions * ---------------------------------------------------------------- *//* ---------------------------------------------------------------- *		ResetTupleCount * ---------------------------------------------------------------- */#ifdef NOT_USEDvoidResetTupleCount(void){	NTupleProcessed = 0;	NTupleRetrieved = 0;	NTupleAppended = 0;	NTupleDeleted = 0;	NTupleReplaced = 0;	NIndexTupleProcessed = 0;}#endif/* ---------------------------------------------------------------- *		PrintTupleCount * ---------------------------------------------------------------- */#ifdef NOT_USEDvoidDisplayTupleCount(FILE *statfp){	if (NTupleProcessed > 0)		fprintf(statfp, "!\t%d tuple%s processed, ", NTupleProcessed,				(NTupleProcessed == 1) ? "" : "s");	else	{		fprintf(statfp, "!\tno tuples processed.\n");		return;	}	if (NIndexTupleProcessed > 0)		fprintf(statfp, "%d indextuple%s processed, ", NIndexTupleProcessed,				(NIndexTupleProcessed == 1) ? "" : "s");	if (NIndexTupleInserted > 0)		fprintf(statfp, "%d indextuple%s inserted, ", NIndexTupleInserted,				(NIndexTupleInserted == 1) ? "" : "s");	if (NTupleRetrieved > 0)		fprintf(statfp, "%d tuple%s retrieved. ", NTupleRetrieved,				(NTupleRetrieved == 1) ? "" : "s");	if (NTupleAppended > 0)		fprintf(statfp, "%d tuple%s appended. ", NTupleAppended,				(NTupleAppended == 1) ? "" : "s");	if (NTupleDeleted > 0)		fprintf(statfp, "%d tuple%s deleted. ", NTupleDeleted,				(NTupleDeleted == 1) ? "" : "s");	if (NTupleReplaced > 0)		fprintf(statfp, "%d tuple%s replaced. ", NTupleReplaced,				(NTupleReplaced == 1) ? "" : "s");	fprintf(statfp, "\n");}#endif/* ---------------------------------------------------------------- *				 Executor state and memory management functions * ---------------------------------------------------------------- *//* ---------------- *		CreateExecutorState * *		Create and initialize an EState node, which is the root of *		working storage for an entire Executor invocation. * * Principally, this creates the per-query memory context that will be * used to hold all working data that lives till the end of the query. * Note that the per-query context will become a child of the caller's * CurrentMemoryContext. * ---------------- */EState *CreateExecutorState(void){	EState	   *estate;	MemoryContext qcontext;	MemoryContext oldcontext;	/*	 * Create the per-query context for this Executor run.	 */	qcontext = AllocSetContextCreate(CurrentMemoryContext,									 "ExecutorState",									 ALLOCSET_DEFAULT_MINSIZE,									 ALLOCSET_DEFAULT_INITSIZE,									 ALLOCSET_DEFAULT_MAXSIZE);	/*	 * Make the EState node within the per-query context.  This way, we don't	 * need a separate pfree() operation for it at shutdown.	 */	oldcontext = MemoryContextSwitchTo(qcontext);	estate = makeNode(EState);	/*	 * Initialize all fields of the Executor State structure	 */	estate->es_direction = ForwardScanDirection;	estate->es_snapshot = SnapshotNow;	estate->es_crosscheck_snapshot = InvalidSnapshot;	/* no crosscheck */	estate->es_range_table = NIL;	estate->es_result_relations = NULL;	estate->es_num_result_relations = 0;	estate->es_result_relation_info = NULL;	estate->es_junkFilter = NULL;	estate->es_trig_tuple_slot = NULL;	estate->es_into_relation_descriptor = NULL;	estate->es_into_relation_use_wal = false;	estate->es_param_list_info = NULL;	estate->es_param_exec_vals = NULL;	estate->es_query_cxt = qcontext;	estate->es_tupleTable = NULL;	estate->es_processed = 0;	estate->es_lastoid = InvalidOid;	estate->es_rowMarks = NIL;	estate->es_forUpdate = false;	estate->es_rowNoWait = false;	estate->es_instrument = false;	estate->es_select_into = false;	estate->es_into_oids = false;	estate->es_exprcontexts = NIL;	estate->es_per_tuple_exprcontext = NULL;	estate->es_topPlan = NULL;	estate->es_evalPlanQual = NULL;	estate->es_evTupleNull = NULL;	estate->es_evTuple = NULL;	estate->es_useEvalPlan = false;	/*	 * Return the executor state structure	 */	MemoryContextSwitchTo(oldcontext);	return estate;}/* ---------------- *		FreeExecutorState * *		Release an EState along with all remaining working storage. * * Note: this is not responsible for releasing non-memory resources, * such as open relations or buffer pins.  But it will shut down any * still-active ExprContexts within the EState.  That is sufficient * cleanup for situations where the EState has only been used for expression * evaluation, and not to run a complete Plan. * * This can be called in any memory context ... so long as it's not one * of the ones to be freed. * ---------------- */voidFreeExecutorState(EState *estate){	/*	 * Shut down and free any remaining ExprContexts.  We do this explicitly	 * to ensure that any remaining shutdown callbacks get called (since they	 * might need to release resources that aren't simply memory within the	 * per-query memory context).	 */	while (estate->es_exprcontexts)	{		/*		 * XXX: seems there ought to be a faster way to implement this than		 * repeated list_delete(), no?		 */		FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts));		/* FreeExprContext removed the list link for us */	}	/*	 * Free the per-query memory context, thereby releasing all working	 * memory, including the EState node itself.	 */	MemoryContextDelete(estate->es_query_cxt);}/* ---------------- *		CreateExprContext * *		Create a context for expression evaluation within an EState. * * An executor run may require multiple ExprContexts (we usually make one * for each Plan node, and a separate one for per-output-tuple processing * such as constraint checking).  Each ExprContext has its own "per-tuple" * memory context. * * Note we make no assumption about the caller's memory context. * ---------------- */ExprContext *CreateExprContext(EState *estate){	ExprContext *econtext;	MemoryContext oldcontext;	/* Create the ExprContext node within the per-query memory context */	oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);	econtext = makeNode(ExprContext);	/* Initialize fields of ExprContext */	econtext->ecxt_scantuple = NULL;	econtext->ecxt_innertuple = NULL;	econtext->ecxt_outertuple = NULL;	econtext->ecxt_per_query_memory = estate->es_query_cxt;	/*	 * Create working memory for expression evaluation in this context.	 */	econtext->ecxt_per_tuple_memory =		AllocSetContextCreate(estate->es_query_cxt,							  "ExprContext",							  ALLOCSET_DEFAULT_MINSIZE,							  ALLOCSET_DEFAULT_INITSIZE,							  ALLOCSET_DEFAULT_MAXSIZE);	econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;	econtext->ecxt_param_list_info = estate->es_param_list_info;	econtext->ecxt_aggvalues = NULL;	econtext->ecxt_aggnulls = NULL;	econtext->caseValue_datum = (Datum) 0;	econtext->caseValue_isNull = true;	econtext->domainValue_datum = (Datum) 0;	econtext->domainValue_isNull = true;	econtext->ecxt_estate = estate;	econtext->ecxt_callbacks = NULL;	/*	 * Link the ExprContext into the EState to ensure it is shut down when the	 * EState is freed.  Because we use lcons(), shutdowns will occur in	 * reverse order of creation, which may not be essential but can't hurt.	 */	estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);	MemoryContextSwitchTo(oldcontext);	return econtext;}/* ---------------- *		FreeExprContext * *		Free an expression context, including calling any remaining *		shutdown callbacks. * * Since we free the temporary context used for expression evaluation, * any previously computed pass-by-reference expression result will go away! * * Note we make no assumption about the caller's memory context. * ---------------- */voidFreeExprContext(ExprContext *econtext){	EState	   *estate;	/* Call any registered callbacks */	ShutdownExprContext(econtext);	/* And clean up the memory used */	MemoryContextDelete(econtext->ecxt_per_tuple_memory);	/* Unlink self from owning EState */	estate = econtext->ecxt_estate;	estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts, econtext);	/* And delete the ExprContext node */	pfree(econtext);}/* * ReScanExprContext * *		Reset an expression context in preparation for a rescan of its *		plan node.	This requires calling any registered shutdown callbacks, *		since any partially complete set-returning-functions must be canceled. * * Note we make no assumption about the caller's memory context. */voidReScanExprContext(ExprContext *econtext){	/* Call any registered callbacks */	ShutdownExprContext(econtext);	/* And clean up the memory used */	MemoryContextReset(econtext->ecxt_per_tuple_memory);}/* * Build a per-output-tuple ExprContext for an EState. * * This is normally invoked via GetPerTupleExprContext() macro, * not directly. */ExprContext *MakePerTupleExprContext(EState *estate){	if (estate->es_per_tuple_exprcontext == NULL)		estate->es_per_tuple_exprcontext = CreateExprContext(estate);	return estate->es_per_tuple_exprcontext;}/* ---------------------------------------------------------------- *				 miscellaneous node-init support functions * * Note: all of these are expected to be called with CurrentMemoryContext * equal to the per-query memory context. * ---------------------------------------------------------------- *//* ---------------- *		ExecAssignExprContext * *		This initializes the ps_ExprContext field.	It is only necessary *		to do this for nodes which use ExecQual or ExecProject *		because those routines require an econtext. Other nodes that *		don't have to evaluate expressions don't need to do this. * ---------------- */voidExecAssignExprContext(EState *estate, PlanState *planstate){	planstate->ps_ExprContext = CreateExprContext(estate);}/* ---------------- *		ExecAssignResultType * ---------------- */voidExecAssignResultType(PlanState *planstate,					 TupleDesc tupDesc, bool shouldFree){	TupleTableSlot *slot = planstate->ps_ResultTupleSlot;	ExecSetSlotDescriptor(slot, tupDesc, shouldFree);}/* ---------------- *		ExecAssignResultTypeFromTL * ---------------- */voidExecAssignResultTypeFromTL(PlanState *planstate){	bool		hasoid;	TupleDesc	tupDesc;	if (ExecContextForcesOids(planstate, &hasoid))	{		/* context forces OID choice; hasoid is now set correctly */	}	else	{		/* given free choice, don't leave space for OIDs in result tuples */		hasoid = false;	}	/*	 * ExecTypeFromTL needs the parse-time representation of the tlist, not a	 * list of ExprStates.	This is good because some plan nodes don't bother	 * to set up planstate->targetlist ...	 */	tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);	ExecAssignResultType(planstate, tupDesc, true);}/* ---------------- *		ExecGetResultType * ---------------- */TupleDescExecGetResultType(PlanState *planstate){	TupleTableSlot *slot = planstate->ps_ResultTupleSlot;	return slot->tts_tupleDescriptor;}/* ---------------- *		ExecBuildProjectionInfo * * Build a ProjectionInfo node for evaluating the given tlist in the given * econtext, and storing the result into the tuple slot.  (Caller must have * ensured that tuple slot has a descriptor matching the tlist!)  Note that * the given tlist should be a list of ExprState nodes, not Expr nodes. * ---------------- */ProjectionInfo *ExecBuildProjectionInfo(List *targetList,						ExprContext *econtext,						TupleTableSlot *slot){	ProjectionInfo *projInfo = makeNode(ProjectionInfo);	int			len;	bool		isVarList;	ListCell   *tl;	len = ExecTargetListLength(targetList);	projInfo->pi_targetlist = targetList;	projInfo->pi_exprContext = econtext;	projInfo->pi_slot = slot;	/*	 * Determine whether the target list consists entirely of simple Var	 * references (ie, references to non-system attributes).  If so, we can	 * use the simpler ExecVariableList instead of ExecTargetList.	 */	isVarList = true;	foreach(tl, targetList)	{		GenericExprState *gstate = (GenericExprState *) lfirst(tl);		Var		   *variable = (Var *) gstate->arg->expr;		if (variable == NULL ||			!IsA(variable, Var) ||			variable->varattno <= 0)		{			isVarList = false;			break;		}	}	projInfo->pi_isVarList = isVarList;	if (isVarList)	{		int		   *varSlotOffsets;

⌨️ 快捷键说明

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