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

📄 execqual.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
					/*					 * Scalar type, so make a single-column descriptor					 */					tupdesc = CreateTemplateTupleDesc(1, false);					TupleDescInitEntry(tupdesc,									   (AttrNumber) 1,									   "column",									   funcrettype,									   -1,									   0);				}				tupstore = tuplestore_begin_heap(true, false, work_mem);				MemoryContextSwitchTo(oldcontext);				rsinfo.setResult = tupstore;				rsinfo.setDesc = tupdesc;			}			/*			 * Store current resultset item.			 */			if (returnsTuple)			{				HeapTupleHeader td;				td = DatumGetHeapTupleHeader(result);				/*				 * tuplestore_puttuple needs a HeapTuple not a bare				 * HeapTupleHeader, but it doesn't need all the fields.				 */				tmptup.t_len = HeapTupleHeaderGetDatumLength(td);				tmptup.t_data = td;				tuple = &tmptup;			}			else			{				tuple = heap_form_tuple(tupdesc, &result, &fcinfo.isnull);			}			oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);			tuplestore_puttuple(tupstore, tuple);			MemoryContextSwitchTo(oldcontext);			/*			 * Are we done?			 */			if (rsinfo.isDone != ExprMultipleResult)				break;		}		else if (rsinfo.returnMode == SFRM_Materialize)		{			/* check we're on the same page as the function author */			if (!first_time || rsinfo.isDone != ExprSingleResult)				ereport(ERROR,						(errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),						 errmsg("table-function protocol for materialize mode was not followed")));			/* Done evaluating the set result */			break;		}		else			ereport(ERROR,					(errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),					 errmsg("unrecognized table-function returnMode: %d",							(int) rsinfo.returnMode)));		first_time = false;	}no_function_result:	/*	 * If we got nothing from the function (ie, an empty-set or NULL result),	 * we have to create the tuplestore to return, and if it's a	 * non-set-returning function then insert a single all-nulls row.	 */	if (rsinfo.setResult == NULL)	{		MemoryContextSwitchTo(econtext->ecxt_per_query_memory);		tupstore = tuplestore_begin_heap(true, false, work_mem);		rsinfo.setResult = tupstore;		if (!returnsSet)		{			int			natts = expectedDesc->natts;			Datum	   *nulldatums;			bool	   *nullflags;			HeapTuple	tuple;			MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);			nulldatums = (Datum *) palloc0(natts * sizeof(Datum));			nullflags = (bool *) palloc(natts * sizeof(bool));			memset(nullflags, true, natts * sizeof(bool));			tuple = heap_form_tuple(expectedDesc, nulldatums, nullflags);			MemoryContextSwitchTo(econtext->ecxt_per_query_memory);			tuplestore_puttuple(tupstore, tuple);		}	}	MemoryContextSwitchTo(callerContext);	/* The returned pointers are those in rsinfo */	*returnDesc = rsinfo.setDesc;	return rsinfo.setResult;}/* ---------------------------------------------------------------- *		ExecEvalFunc *		ExecEvalOper * *		Evaluate the functional result of a list of arguments by calling the *		function manager. * ---------------------------------------------------------------- *//* ---------------------------------------------------------------- *		ExecEvalFunc * ---------------------------------------------------------------- */static DatumExecEvalFunc(FuncExprState *fcache,			 ExprContext *econtext,			 bool *isNull,			 ExprDoneCond *isDone){	/* This is called only the first time through */	FuncExpr   *func = (FuncExpr *) fcache->xprstate.expr;	/* Initialize function lookup info */	init_fcache(func->funcid, fcache, econtext->ecxt_per_query_memory);	/* Go directly to ExecMakeFunctionResult on subsequent uses */	fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResult;	return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);}/* ---------------------------------------------------------------- *		ExecEvalOper * ---------------------------------------------------------------- */static DatumExecEvalOper(FuncExprState *fcache,			 ExprContext *econtext,			 bool *isNull,			 ExprDoneCond *isDone){	/* This is called only the first time through */	OpExpr	   *op = (OpExpr *) fcache->xprstate.expr;	/* Initialize function lookup info */	init_fcache(op->opfuncid, fcache, econtext->ecxt_per_query_memory);	/* Go directly to ExecMakeFunctionResult on subsequent uses */	fcache->xprstate.evalfunc = (ExprStateEvalFunc) ExecMakeFunctionResult;	return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);}/* ---------------------------------------------------------------- *		ExecEvalDistinct * * IS DISTINCT FROM must evaluate arguments to determine whether * they are NULL; if either is NULL then the result is already * known. If neither is NULL, then proceed to evaluate the * function. Note that this is *always* derived from the equals * operator, but since we need special processing of the arguments * we can not simply reuse ExecEvalOper() or ExecEvalFunc(). * ---------------------------------------------------------------- */static DatumExecEvalDistinct(FuncExprState *fcache,				 ExprContext *econtext,				 bool *isNull,				 ExprDoneCond *isDone){	Datum		result;	FunctionCallInfoData fcinfo;	ExprDoneCond argDone;	List	   *argList;	/* Set default values for result flags: non-null, not a set result */	*isNull = false;	if (isDone)		*isDone = ExprSingleResult;	/*	 * Initialize function cache if first time through	 */	if (fcache->func.fn_oid == InvalidOid)	{		DistinctExpr *op = (DistinctExpr *) fcache->xprstate.expr;		init_fcache(op->opfuncid, fcache, econtext->ecxt_per_query_memory);		Assert(!fcache->func.fn_retset);	}	/*	 * extract info from fcache	 */	argList = fcache->args;	/* Need to prep callinfo structure */	InitFunctionCallInfoData(fcinfo, &(fcache->func), 0, NULL, NULL);	argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);	if (argDone != ExprSingleResult)		ereport(ERROR,				(errcode(ERRCODE_DATATYPE_MISMATCH),				 errmsg("IS DISTINCT FROM does not support set arguments")));	Assert(fcinfo.nargs == 2);	if (fcinfo.argnull[0] && fcinfo.argnull[1])	{		/* Both NULL? Then is not distinct... */		result = BoolGetDatum(FALSE);	}	else if (fcinfo.argnull[0] || fcinfo.argnull[1])	{		/* Only one is NULL? Then is distinct... */		result = BoolGetDatum(TRUE);	}	else	{		fcinfo.isnull = false;		result = FunctionCallInvoke(&fcinfo);		*isNull = fcinfo.isnull;		/* Must invert result of "=" */		result = BoolGetDatum(!DatumGetBool(result));	}	return result;}/* * ExecEvalScalarArrayOp * * Evaluate "scalar op ANY/ALL (array)".  The operator always yields boolean, * and we combine the results across all array elements using OR and AND * (for ANY and ALL respectively).	Of course we short-circuit as soon as * the result is known. */static DatumExecEvalScalarArrayOp(ScalarArrayOpExprState *sstate,					  ExprContext *econtext,					  bool *isNull, ExprDoneCond *isDone){	ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) sstate->fxprstate.xprstate.expr;	bool		useOr = opexpr->useOr;	ArrayType  *arr;	int			nitems;	Datum		result;	bool		resultnull;	FunctionCallInfoData fcinfo;	ExprDoneCond argDone;	int			i;	int16		typlen;	bool		typbyval;	char		typalign;	char	   *s;	/* Set default values for result flags: non-null, not a set result */	*isNull = false;	if (isDone)		*isDone = ExprSingleResult;	/*	 * Initialize function cache if first time through	 */	if (sstate->fxprstate.func.fn_oid == InvalidOid)	{		init_fcache(opexpr->opfuncid, &sstate->fxprstate,					econtext->ecxt_per_query_memory);		Assert(!sstate->fxprstate.func.fn_retset);	}	/* Need to prep callinfo structure */	InitFunctionCallInfoData(fcinfo, &(sstate->fxprstate.func), 0, NULL, NULL);	argDone = ExecEvalFuncArgs(&fcinfo, sstate->fxprstate.args, econtext);	if (argDone != ExprSingleResult)		ereport(ERROR,				(errcode(ERRCODE_DATATYPE_MISMATCH),			   errmsg("op ANY/ALL (array) does not support set arguments")));	Assert(fcinfo.nargs == 2);	/*	 * If the array is NULL then we return NULL --- it's not very meaningful	 * to do anything else, even if the operator isn't strict.	 */	if (fcinfo.argnull[1])	{		*isNull = true;		return (Datum) 0;	}	/* Else okay to fetch and detoast the array */	arr = DatumGetArrayTypeP(fcinfo.arg[1]);	/*	 * If the array is empty, we return either FALSE or TRUE per the useOr	 * flag.  This is correct even if the scalar is NULL; since we would	 * evaluate the operator zero times, it matters not whether it would want	 * to return NULL.	 */	nitems = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));	if (nitems <= 0)		return BoolGetDatum(!useOr);	/*	 * If the scalar is NULL, and the function is strict, return NULL. This is	 * just to avoid having to test for strictness inside the loop.  (XXX but	 * if arrays could have null elements, we'd need a test anyway.)	 */	if (fcinfo.argnull[0] && sstate->fxprstate.func.fn_strict)	{		*isNull = true;		return (Datum) 0;	}	/*	 * We arrange to look up info about the element type only once per series	 * of calls, assuming the element type doesn't change underneath us.	 */	if (sstate->element_type != ARR_ELEMTYPE(arr))	{		get_typlenbyvalalign(ARR_ELEMTYPE(arr),							 &sstate->typlen,							 &sstate->typbyval,							 &sstate->typalign);		sstate->element_type = ARR_ELEMTYPE(arr);	}	typlen = sstate->typlen;	typbyval = sstate->typbyval;	typalign = sstate->typalign;	result = BoolGetDatum(!useOr);	resultnull = false;	/* Loop over the array elements */	s = (char *) ARR_DATA_PTR(arr);	for (i = 0; i < nitems; i++)	{		Datum		elt;		Datum		thisresult;		/* Get array element */		elt = fetch_att(s, typbyval, typlen);		s = att_addlength(s, typlen, PointerGetDatum(s));		s = (char *) att_align(s, typalign);		/* Call comparison function */		fcinfo.arg[1] = elt;		fcinfo.argnull[1] = false;		fcinfo.isnull = false;		thisresult = FunctionCallInvoke(&fcinfo);		/* Combine results per OR or AND semantics */		if (fcinfo.isnull)			resultnull = true;		else if (useOr)		{			if (DatumGetBool(thisresult))			{				result = BoolGetDatum(true);				resultnull = false;				break;			/* needn't look at any more elements */			}		}		else		{			if (!DatumGetBool(thisresult))			{				result = BoolGetDatum(false);				resultnull = false;				break;			/* needn't look at any more elements */			}		}	}	*isNull = resultnull;	return result;}/* ---------------------------------------------------------------- *		ExecEvalNot *		ExecEvalOr *		ExecEvalAnd * *		Evaluate boolean expressions, with appropriate short-circuiting. * *		The query planner reformulates clause expressions in the *		qualification to conjunctive normal form.  If we ever get *		an AND to evaluate, we can be sure that it's not a top-level *		clause in the qualification, but appears lower (as a function *		argument, for example), or in the target list.	Not that you *		need to know this, mind you... * ---------------------------------------------------------------- */static DatumExecEvalNot(BoolExprState *notclause, ExprContext *econtext,			bool *isNull, ExprDoneCond *isDone){	ExprState  *clause = linitial(notclause->args);	Datum		expr_value;	if (isDone)		*isDone = ExprSingleResult;	expr_value = ExecEvalExpr(clause, econtext, isNull, NULL);	/*	 * if the expression evaluates to null, then we just cascade the null back	 * to whoever called us.	 */	if (*isNull)		return expr_value;	/*	 * evaluation of 'not' is simple.. expr is false, then return 'true' and	 * vice versa.	 */	return BoolGetDatum(!DatumGetBool(expr_value));}/* ---------------------------------------------------------------- *		ExecEvalOr * ---------------------------------------------------------------- */static DatumExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,		   bool *isNull, ExprDoneCond *isDone){	List	   *clauses = orExpr->args;	ListCell   *clause;	bool		AnyNull;	if (isDone)		*isDone = ExprSingleResult;	AnyNull = false;	/*	 * If any of the clauses is TRUE, the OR result is TRUE regardless of the	 * states of the rest of the clauses, so we can stop evaluating and return	 * TRUE immediately.  If none are TRUE and one or more is NULL, we return	 * NULL; otherwise we return FALSE.  This makes sense when you interpret	 * NULL as "don't know": if we have a TRUE then the OR is TRUE even if we	 * aren't sure about some of the other inputs. If all the known inputs are	 * FALSE, but we have one or more "don't knows", then we have to report	 * that we "don't know" what the OR's result should be --- perhaps one of	 * the "don't knows" would have been TRUE if we'd known its value.  Only	 * when all the inputs are known to be FALSE can we state confidently that	 * the OR's result is FALSE.	 */	foreach(clause, clauses)	{		ExprState  *clausestate = (ExprState *) lfirst(clause);

⌨️ 快捷键说明

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