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

📄 execqual.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * execQual.c *	  Routines to evaluate qualification and targetlist expressions * * 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/execQual.c,v 1.183.2.3 2006/03/10 01:51:34 tgl Exp $ * *------------------------------------------------------------------------- *//* *	 INTERFACE ROUTINES *		ExecEvalExpr	- (now a macro) evaluate an expression, return a datum *		ExecEvalExprSwitchContext - same, but switch into eval memory context *		ExecQual		- return true/false if qualification is satisfied *		ExecProject		- form a new tuple by projecting the given tuple * *	 NOTES *		The more heavily used ExecEvalExpr routines, such as ExecEvalVar(), *		are hotspots. Making these faster will speed up the entire system. * *		ExecProject() is used to make tuple projections.  Rather then *		trying to speed it up, the execution plan should be pre-processed *		to facilitate attribute sharing between nodes wherever possible, *		instead of doing needless copying.	-cim 5/31/91 * *		During expression evaluation, we check_stack_depth only in *		ExecMakeFunctionResult rather than at every single node.  This *		is a compromise that trades off precision of the stack limit setting *		to gain speed. */#include "postgres.h"#include "access/heapam.h"#include "catalog/pg_type.h"#include "commands/typecmds.h"#include "executor/execdebug.h"#include "executor/functions.h"#include "executor/nodeSubplan.h"#include "funcapi.h"#include "miscadmin.h"#include "nodes/makefuncs.h"#include "optimizer/planmain.h"#include "parser/parse_expr.h"#include "utils/acl.h"#include "utils/array.h"#include "utils/builtins.h"#include "utils/lsyscache.h"#include "utils/memutils.h"#include "utils/typcache.h"/* static function decls */static Datum ExecEvalArrayRef(ArrayRefExprState *astate,				 ExprContext *econtext,				 bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalAggref(AggrefExprState *aggref,			   ExprContext *econtext,			   bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalVar(ExprState *exprstate, ExprContext *econtext,			bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext,					bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext,			  bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalParam(ExprState *exprstate, ExprContext *econtext,			  bool *isNull, ExprDoneCond *isDone);static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,				 List *argList, ExprContext *econtext);static Datum ExecMakeFunctionResultNoSets(FuncExprState *fcache,							 ExprContext *econtext,							 bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalFunc(FuncExprState *fcache, ExprContext *econtext,			 bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalOper(FuncExprState *fcache, ExprContext *econtext,			 bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalDistinct(FuncExprState *fcache, ExprContext *econtext,				 bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,					  ExprContext *econtext,					  bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,			bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,		   bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,			bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,					   ExprContext *econtext,					   bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,			 bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalCaseTestExpr(ExprState *exprstate,					 ExprContext *econtext,					 bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalArray(ArrayExprState *astate,			  ExprContext *econtext,			  bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalRow(RowExprState *rstate,			ExprContext *econtext,			bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,				 ExprContext *econtext,				 bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,			   ExprContext *econtext,			   bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,			   ExprContext *econtext,			   bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalNullTest(GenericExprState *nstate,				 ExprContext *econtext,				 bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalBooleanTest(GenericExprState *bstate,					ExprContext *econtext,					bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalCoerceToDomain(CoerceToDomainState *cstate,					   ExprContext *econtext,					   bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalCoerceToDomainValue(ExprState *exprstate,							ExprContext *econtext,							bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalFieldSelect(FieldSelectState *fstate,					ExprContext *econtext,					bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalFieldStore(FieldStoreState *fstate,				   ExprContext *econtext,				   bool *isNull, ExprDoneCond *isDone);static Datum ExecEvalRelabelType(GenericExprState *exprstate,					ExprContext *econtext,					bool *isNull, ExprDoneCond *isDone);/* ---------------------------------------------------------------- *		ExecEvalExpr routines * *		Recursively evaluate a targetlist or qualification expression. * * Each of the following routines having the signature *		Datum ExecEvalFoo(ExprState *expression, *						  ExprContext *econtext, *						  bool *isNull, *						  ExprDoneCond *isDone); * is responsible for evaluating one type or subtype of ExprState node. * They are normally called via the ExecEvalExpr macro, which makes use of * the function pointer set up when the ExprState node was built by * ExecInitExpr.  (In some cases, we change this pointer later to avoid * re-executing one-time overhead.) * * Note: for notational simplicity we declare these functions as taking the * specific type of ExprState that they work on.  This requires casting when * assigning the function pointer in ExecInitExpr.	Be careful that the * function signature is declared correctly, because the cast suppresses * automatic checking! * * * All these functions share this calling convention: * * Inputs: *		expression: the expression state tree to evaluate *		econtext: evaluation context information * * Outputs: *		return value: Datum value of result *		*isNull: set to TRUE if result is NULL (actual return value is *				 meaningless if so); set to FALSE if non-null result *		*isDone: set to indicator of set-result status * * A caller that can only accept a singleton (non-set) result should pass * NULL for isDone; if the expression computes a set result then an error * will be reported via ereport.  If the caller does pass an isDone pointer * then *isDone is set to one of these three states: *		ExprSingleResult		singleton result (not a set) *		ExprMultipleResult		return value is one element of a set *		ExprEndResult			there are no more elements in the set * When ExprMultipleResult is returned, the caller should invoke * ExecEvalExpr() repeatedly until ExprEndResult is returned.  ExprEndResult * is returned after the last real set element.  For convenience isNull will * always be set TRUE when ExprEndResult is returned, but this should not be * taken as indicating a NULL element of the set.  Note that these return * conventions allow us to distinguish among a singleton NULL, a NULL element * of a set, and an empty set. * * The caller should already have switched into the temporary memory * context econtext->ecxt_per_tuple_memory.  The convenience entry point * ExecEvalExprSwitchContext() is provided for callers who don't prefer to * do the switch in an outer loop.	We do not do the switch in these routines * because it'd be a waste of cycles during nested expression evaluation. * ---------------------------------------------------------------- *//*---------- *	  ExecEvalArrayRef * *	   This function takes an ArrayRef and returns the extracted Datum *	   if it's a simple reference, or the modified array value if it's *	   an array assignment (i.e., array element or slice insertion). * * NOTE: if we get a NULL result from a subexpression, we return NULL when * it's an array reference, or the unmodified source array when it's an * array assignment.  This may seem peculiar, but if we return NULL (as was * done in versions up through 7.0) then an assignment like *			UPDATE table SET arrayfield[4] = NULL * will result in setting the whole array to NULL, which is certainly not * very desirable.	By returning the source array we make the assignment * into a no-op, instead.  (Eventually we need to redesign arrays so that * individual elements can be NULL, but for now, let's try to protect users * from shooting themselves in the foot.) * * NOTE: we deliberately refrain from applying DatumGetArrayTypeP() here, * even though that might seem natural, because this code needs to support * both varlena arrays and fixed-length array types.  DatumGetArrayTypeP() * only works for the varlena kind.  The routines we call in arrayfuncs.c * have to know the difference (that's what they need refattrlength for). *---------- */static DatumExecEvalArrayRef(ArrayRefExprState *astate,				 ExprContext *econtext,				 bool *isNull,				 ExprDoneCond *isDone){	ArrayRef   *arrayRef = (ArrayRef *) astate->xprstate.expr;	ArrayType  *array_source;	ArrayType  *resultArray;	bool		isAssignment = (arrayRef->refassgnexpr != NULL);	bool		eisnull;	ListCell   *l;	int			i = 0,				j = 0;	IntArray	upper,				lower;	int		   *lIndex;	array_source = (ArrayType *)		DatumGetPointer(ExecEvalExpr(astate->refexpr,									 econtext,									 isNull,									 isDone));	/*	 * If refexpr yields NULL, and it's a fetch, then result is NULL. In the	 * assignment case, we'll cons up something below.	 */	if (*isNull)	{		if (isDone && *isDone == ExprEndResult)			return (Datum) NULL;	/* end of set result */		if (!isAssignment)			return (Datum) NULL;	}	foreach(l, astate->refupperindexpr)	{		ExprState  *eltstate = (ExprState *) lfirst(l);		if (i >= MAXDIM)			ereport(ERROR,					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),					 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",							i, MAXDIM)));		upper.indx[i++] = DatumGetInt32(ExecEvalExpr(eltstate,													 econtext,													 &eisnull,													 NULL));		/* If any index expr yields NULL, result is NULL or source array */		if (eisnull)		{			if (!isAssignment)			{				*isNull = true;				return (Datum) NULL;			}			return PointerGetDatum(array_source);		}	}	if (astate->reflowerindexpr != NIL)	{		foreach(l, astate->reflowerindexpr)		{			ExprState  *eltstate = (ExprState *) lfirst(l);			if (j >= MAXDIM)				ereport(ERROR,						(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),						 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",								i, MAXDIM)));			lower.indx[j++] = DatumGetInt32(ExecEvalExpr(eltstate,														 econtext,														 &eisnull,														 NULL));			/*			 * If any index expr yields NULL, result is NULL or source array			 */			if (eisnull)			{				if (!isAssignment)				{					*isNull = true;					return (Datum) NULL;				}				return PointerGetDatum(array_source);			}		}		/* this can't happen unless parser messed up */		if (i != j)			elog(ERROR, "upper and lower index lists are not same length");		lIndex = lower.indx;	}	else		lIndex = NULL;	if (isAssignment)	{		Datum		sourceData;		/*		 * Evaluate the value to be assigned into the array.		 *		 * XXX At some point we'll need to look into making the old value of		 * the array element available via CaseTestExpr, as is done by		 * ExecEvalFieldStore.	This is not needed now but will be needed to		 * support arrays of composite types; in an assignment to a field of		 * an array member, the parser would generate a FieldStore that		 * expects to fetch its input tuple via CaseTestExpr.		 */		sourceData = ExecEvalExpr(astate->refassgnexpr,								  econtext,								  &eisnull,								  NULL);		/*		 * For now, can't cope with inserting NULL into an array, so make it a		 * no-op per discussion above...		 */		if (eisnull)			return PointerGetDatum(array_source);		/*		 * For an assignment, if all the subscripts and the input expression		 * are non-null but the original array is null, then substitute an		 * empty (zero-dimensional) array and proceed with the assignment.		 * This only works for varlena arrays, though; for fixed-length array		 * types we punt and return the null input array.		 */		if (*isNull)		{			if (astate->refattrlength > 0)		/* fixed-length array? */				return PointerGetDatum(array_source);			array_source = construct_md_array(NULL, 0, NULL, NULL,											  arrayRef->refelemtype,											  astate->refelemlength,											  astate->refelembyval,											  astate->refelemalign);			*isNull = false;		}		if (lIndex == NULL)			resultArray = array_set(array_source, i,									upper.indx,									sourceData,									astate->refattrlength,									astate->refelemlength,									astate->refelembyval,									astate->refelemalign,									isNull);		else			resultArray = array_set_slice(array_source, i,										  upper.indx, lower.indx,								   (ArrayType *) DatumGetPointer(sourceData),										  astate->refattrlength,										  astate->refelemlength,										  astate->refelembyval,										  astate->refelemalign,										  isNull);		return PointerGetDatum(resultArray);	}	if (lIndex == NULL)		return array_ref(array_source, i, upper.indx,						 astate->refattrlength,						 astate->refelemlength,						 astate->refelembyval,						 astate->refelemalign,						 isNull);	else	{		resultArray = array_get_slice(array_source, i,									  upper.indx, lower.indx,									  astate->refattrlength,									  astate->refelemlength,									  astate->refelembyval,									  astate->refelemalign,									  isNull);		return PointerGetDatum(resultArray);	}}/* ---------------------------------------------------------------- *		ExecEvalAggref * *		Returns a Datum whose value is the value of the precomputed *		aggregate found in the given expression context. * ---------------------------------------------------------------- */static DatumExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext,			   bool *isNull, ExprDoneCond *isDone){	if (isDone)		*isDone = ExprSingleResult;	if (econtext->ecxt_aggvalues == NULL)		/* safety check */		elog(ERROR, "no aggregates in this expression context");	*isNull = econtext->ecxt_aggnulls[aggref->aggno];	return econtext->ecxt_aggvalues[aggref->aggno];}/* ---------------------------------------------------------------- *		ExecEvalVar * *		Returns a Datum whose value is the value of a range *		variable with respect to given expression context. * ---------------------------------------------------------------- */static DatumExecEvalVar(ExprState *exprstate, ExprContext *econtext,			bool *isNull, ExprDoneCond *isDone){	Var		   *variable = (Var *) exprstate->expr;	TupleTableSlot *slot;	AttrNumber	attnum;	if (isDone)		*isDone = ExprSingleResult;	/*	 * Get the slot and attribute number we want	 *	 * The asserts check that references to system attributes only appear at	 * the level of a relation scan; at higher levels, system attributes must	 * be treated as ordinary variables (since we no longer have access to the

⌨️ 快捷键说明

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