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

📄 execqual.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
		{			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){	ExprState  *clause;	Datum		expr_value;	clause = lfirst(notclause->args);	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){	List	   *clauses;	List	   *clause;	bool		AnyNull;	Datum		clause_value;	clauses = orExpr->args;	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)	{		clause_value = ExecEvalExpr((ExprState *) lfirst(clause),									econtext, isNull, NULL);		/*		 * if we have a non-null true result, then return it.		 */		if (*isNull)			AnyNull = true;		/* remember we got a null */		else if (DatumGetBool(clause_value))			return clause_value;	}	/* AnyNull is true if at least one clause evaluated to NULL */	*isNull = AnyNull;	return BoolGetDatum(false);}/* ---------------------------------------------------------------- *		ExecEvalAnd * ---------------------------------------------------------------- */static DatumExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext, bool *isNull){	List	   *clauses;	List	   *clause;	bool		AnyNull;	Datum		clause_value;	clauses = andExpr->args;	AnyNull = false;	/*	 * If any of the clauses is FALSE, the AND result is FALSE regardless	 * of the states of the rest of the clauses, so we can stop evaluating	 * and return FALSE immediately.  If none are FALSE and one or more is	 * NULL, we return NULL; otherwise we return TRUE.	This makes sense	 * when you interpret NULL as "don't know", using the same sort of	 * reasoning as for OR, above.	 */	foreach(clause, clauses)	{		clause_value = ExecEvalExpr((ExprState *) lfirst(clause),									econtext, isNull, NULL);		/*		 * if we have a non-null false result, then return it.		 */		if (*isNull)			AnyNull = true;		/* remember we got a null */		else if (!DatumGetBool(clause_value))			return clause_value;	}	/* AnyNull is true if at least one clause evaluated to NULL */	*isNull = AnyNull;	return BoolGetDatum(!AnyNull);}/* ---------------------------------------------------------------- *		ExecEvalCase * *		Evaluate a CASE clause. Will have boolean expressions *		inside the WHEN clauses, and will have expressions *		for results. *		- thomas 1998-11-09 * ---------------------------------------------------------------- */static DatumExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,			 bool *isNull, ExprDoneCond *isDone){	List	   *clauses;	List	   *clause;	Datum		clause_value;	clauses = caseExpr->args;	/*	 * we evaluate each of the WHEN clauses in turn, as soon as one is	 * true we return the corresponding result. If none are true then we	 * return the value of the default clause, or NULL if there is none.	 */	foreach(clause, clauses)	{		CaseWhenState *wclause = lfirst(clause);		clause_value = ExecEvalExpr(wclause->expr,									econtext,									isNull,									NULL);		/*		 * if we have a true test, then we return the result, since the		 * case statement is satisfied.  A NULL result from the test is		 * not considered true.		 */		if (DatumGetBool(clause_value) && !*isNull)		{			return ExecEvalExpr(wclause->result,								econtext,								isNull,								isDone);		}	}	if (caseExpr->defresult)	{		return ExecEvalExpr(caseExpr->defresult,							econtext,							isNull,							isDone);	}	*isNull = true;	return (Datum) 0;}/* ---------------------------------------------------------------- *		ExecEvalArray - ARRAY[] expressions * * NOTE: currently, if any input value is NULL then we return a NULL array, * so the ARRAY[] construct can be considered strict.  Eventually this will * change; when it does, be sure to fix contain_nonstrict_functions(). * ---------------------------------------------------------------- */static DatumExecEvalArray(ArrayExprState *astate, ExprContext *econtext,			  bool *isNull){	ArrayExpr  *arrayExpr = (ArrayExpr *) astate->xprstate.expr;	ArrayType  *result;	List	   *element;	Oid			element_type = arrayExpr->element_typeid;	int			ndims = 0;	int			dims[MAXDIM];	int			lbs[MAXDIM];	if (!arrayExpr->multidims)	{		/* Elements are presumably of scalar type */		int			nelems;		Datum	   *dvalues;		int			i = 0;		ndims = 1;		nelems = length(astate->elements);		/* Shouldn't happen here, but if length is 0, return NULL */		if (nelems == 0)		{			*isNull = true;			return (Datum) 0;		}		dvalues = (Datum *) palloc(nelems * sizeof(Datum));		/* loop through and build array of datums */		foreach(element, astate->elements)		{			ExprState  *e = (ExprState *) lfirst(element);			bool		eisnull;			dvalues[i++] = ExecEvalExpr(e, econtext, &eisnull, NULL);			if (eisnull)			{				*isNull = true;				return (Datum) 0;			}		}		/* setup for 1-D array of the given length */		dims[0] = nelems;		lbs[0] = 1;		result = construct_md_array(dvalues, ndims, dims, lbs,									element_type,									astate->elemlength,									astate->elembyval,									astate->elemalign);	}	else	{		/* Must be nested array expressions */		char	   *dat = NULL;		Size		ndatabytes = 0;		int			nbytes;		int			outer_nelems = length(astate->elements);		int			elem_ndims = 0;		int		   *elem_dims = NULL;		int		   *elem_lbs = NULL;		bool		firstone = true;		int			i;		/* loop through and get data area from each element */		foreach(element, astate->elements)		{			ExprState  *e = (ExprState *) lfirst(element);			bool		eisnull;			Datum		arraydatum;			ArrayType  *array;			int			elem_ndatabytes;			arraydatum = ExecEvalExpr(e, econtext, &eisnull, NULL);			if (eisnull)			{				*isNull = true;				return (Datum) 0;			}			array = DatumGetArrayTypeP(arraydatum);			/* run-time double-check on element type */			if (element_type != ARR_ELEMTYPE(array))				ereport(ERROR,						(errcode(ERRCODE_DATATYPE_MISMATCH),						 errmsg("cannot merge incompatible arrays"),						 errdetail("Array with element type %s cannot be "								   "included in ARRAY construct with element type %s.",								   format_type_be(ARR_ELEMTYPE(array)),								   format_type_be(element_type))));			if (firstone)			{				/* Get sub-array details from first member */				elem_ndims = ARR_NDIM(array);				ndims = elem_ndims + 1;				if (ndims <= 0 || ndims > MAXDIM)					ereport(ERROR,							(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),							 errmsg("number of array dimensions (%d) exceeds " \									"the maximum allowed (%d)", ndims, MAXDIM)));				elem_dims = (int *) palloc(elem_ndims * sizeof(int));				memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int));				elem_lbs = (int *) palloc(elem_ndims * sizeof(int));				memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int));				firstone = false;			}			else			{				/* Check other sub-arrays are compatible */				if (elem_ndims != ARR_NDIM(array) ||					memcmp(elem_dims, ARR_DIMS(array),						   elem_ndims * sizeof(int)) != 0 ||					memcmp(elem_lbs, ARR_LBOUND(array),						   elem_ndims * sizeof(int)) != 0)					ereport(ERROR,							(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),						errmsg("multidimensional arrays must have array "							   "expressions with matching dimensions")));			}			elem_ndatabytes = ARR_SIZE(array) - ARR_OVERHEAD(elem_ndims);			ndatabytes += elem_ndatabytes;			if (dat == NULL)				dat = (char *) palloc(ndatabytes);			else				dat = (char *) repalloc(dat, ndatabytes);			memcpy(dat + (ndatabytes - elem_ndatabytes),				   ARR_DATA_PTR(array),				   elem_ndatabytes);		}		/* setup for multi-D array */		dims[0] = outer_nelems;		lbs[0] = 1;		for (i = 1; i < ndims; i++)		{			dims[i] = elem_dims[i - 1];			lbs[i] = elem_lbs[i - 1];		}		nbytes = ndatabytes + ARR_OVERHEAD(ndims);		result = (ArrayType *) palloc(nbytes);		result->size = nbytes;		result->ndim = ndims;		result->flags = 0;		result->elemtype = element_type;		memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));		memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));		if (ndatabytes > 0)			memcpy(ARR_DATA_PTR(result), dat, ndatabytes);		if (dat != NULL)			pfree(dat);	}	return PointerGetDatum(result);}/* ---------------------------------------------------------------- *		ExecEvalCoalesce * ---------------------------------------------------------------- */static DatumExecEvalCoalesce(CoalesceExprState *coalesceExpr, ExprContext *econtext,				 bool *isNull){	List	   *arg;	/* Simply loop through until something NOT NULL is found */	foreach(arg, coalesceExpr->args)	{		ExprState  *e = (ExprState *) lfirst(arg);		Datum		value;		value = ExecEvalExpr(e, econtext, isNull, NULL);		if (!*isNull)			return value;	}	/* Else return NULL */	*isNull = true;	return (Datum) 0;}/* ---------------------------------------------------------------- *		ExecEvalNullIf * * 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 DatumExecEvalNullIf(FuncExprState *fcache, ExprContext *econtext,			   bool *isNull){	Datum		result;	FunctionCallInfoData fcinfo;	ExprDoneCond argDone;	List	   *argList;	/*	 * Initialize function cache if first time through	 */	if (fcache->func.fn_oid == InvalidOid)	{		NullIfExpr *op = (NullIfExpr *) 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 */	MemSet(&fcinfo, 0, sizeof(fcinfo));	fcinfo.flinfo = &(fcache->func);	argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);	if (argDone != ExprSingleResult)		ereport(ERROR,				(errcode(ERRCODE_DATATYPE_MISMATCH),				 errmsg("NULLIF does not support set arguments")));	Assert(fcinfo.nargs == 2);	/* if either argument is NULL they can't be equal */	if (!fcinfo.argnull[0] && !fcinfo.argnull[1])	{		fcinfo.isnull = false;		result = FunctionCallInvoke(&fcinfo);		/* if the arguments are equal return null */		if (!fcinfo.isnull && DatumGetBool(result))		{			*isNull = true;			return (Datum) 0;		}	}	/* else return first argument */	*isNull = fcinfo.argnull[0];	return fcinfo.arg[0];}/* ---------------------------------------------------------------- *		ExecEvalNullTest

⌨️ 快捷键说明

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