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

📄 execqual.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
 *		Evaluate a CASE clause. Will have boolean expressions *		inside the WHEN clauses, and will have constants *		for results. *		- thomas 1998-11-09 * ---------------------------------------------------------------- */static DatumExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull){	List	   *clauses;	List	   *clause;	CaseWhen   *wclause;	Datum		const_value = 0;	bool		isDone;	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.	 */	foreach(clause, clauses)	{		/*		 * We don't iterate over sets in the quals, so pass in an isDone		 * flag, but ignore it.		 */		wclause = lfirst(clause);		const_value = ExecEvalExpr((Node *) wclause->expr,								   econtext,								   isNull,								   &isDone);		/*		 * if we have a true test, then we return the result, since the		 * case statement is satisfied.		 */		if (DatumGetInt32(const_value) != 0)		{			const_value = ExecEvalExpr((Node *) wclause->result,									   econtext,									   isNull,									   &isDone);			return (Datum) const_value;		}	}	if (caseExpr->defresult)	{		const_value = ExecEvalExpr((Node *) caseExpr->defresult,								   econtext,								   isNull,								   &isDone);	}	else		*isNull = true;	return const_value;}/* ---------------------------------------------------------------- *		ExecEvalExpr * *		Recursively evaluate a targetlist or qualification expression. * *		This routine is an inner loop routine and should be as fast *		as possible. * *		Node comparison functions were replaced by macros for speed and to plug *		memory leaks incurred by using the planner's Lispy stuff for *		comparisons.  Order of evaluation of node comparisons IS IMPORTANT; *		the macros do no checks.  Order of evaluation: * *		o an isnull check, largely to avoid coredumps since greg doubts this *		  routine is called with a null ptr anyway in proper operation, but is *		  not completely sure... *		o ExactNodeType checks. *		o clause checks or other checks where we look at the lfirst of something. * ---------------------------------------------------------------- */DatumExecEvalExpr(Node *expression,			 ExprContext *econtext,			 bool *isNull,			 bool *isDone){	Datum		retDatum = 0;	*isNull = false;	/*	 * Some callers don't care about is done and only want 1 result.  They	 * indicate this by passing NULL	 */	if (isDone)		*isDone = true;	/*	 * here we dispatch the work to the appropriate type of function given	 * the type of our expression.	 */	if (expression == NULL)	{		*isNull = true;		return (Datum) true;	}	switch (nodeTag(expression))	{		case T_Var:			retDatum = (Datum) ExecEvalVar((Var *) expression, econtext, isNull);			break;		case T_Const:			{				Const	   *con = (Const *) expression;				if (con->constisnull)					*isNull = true;				retDatum = con->constvalue;				break;			}		case T_Param:			retDatum = (Datum) ExecEvalParam((Param *) expression, econtext, isNull);			break;		case T_Iter:			retDatum = (Datum) ExecEvalIter((Iter *) expression,											econtext,											isNull,											isDone);			break;		case T_Aggref:			retDatum = (Datum) ExecEvalAggref((Aggref *) expression,											  econtext,											  isNull);			break;		case T_ArrayRef:			retDatum = (Datum) ExecEvalArrayRef((ArrayRef *) expression,												econtext,												isNull,												isDone);			break;		case T_Expr:			{				Expr	   *expr = (Expr *) expression;				switch (expr->opType)				{					case OP_EXPR:						retDatum = (Datum) ExecEvalOper(expr, econtext, isNull);						break;					case FUNC_EXPR:						retDatum = (Datum) ExecEvalFunc(expr, econtext, isNull, isDone);						break;					case OR_EXPR:						retDatum = (Datum) ExecEvalOr(expr, econtext, isNull);						break;					case AND_EXPR:						retDatum = (Datum) ExecEvalAnd(expr, econtext, isNull);						break;					case NOT_EXPR:						retDatum = (Datum) ExecEvalNot(expr, econtext, isNull);						break;					case SUBPLAN_EXPR:						retDatum = (Datum) ExecSubPlan((SubPlan *) expr->oper, expr->args, econtext);						break;					default:						elog(ERROR, "ExecEvalExpr: unknown expression type %d", expr->opType);						break;				}				break;			}		case T_CaseExpr:			retDatum = (Datum) ExecEvalCase((CaseExpr *) expression, econtext, isNull);			break;		default:			elog(ERROR, "ExecEvalExpr: unknown expression type %d", nodeTag(expression));			break;	}	return retDatum;}	/* ExecEvalExpr() *//* ---------------------------------------------------------------- *					 ExecQual / ExecTargetList * ---------------------------------------------------------------- *//* ---------------------------------------------------------------- *		ExecQualClause * *		this is a workhorse for ExecQual.  ExecQual has to deal *		with a list of qualifications, so it passes each qualification *		in the list to this function one at a time.  ExecQualClause *		returns true when the qualification *fails* and false if *		the qualification succeeded (meaning we have to test the *		rest of the qualification) * ---------------------------------------------------------------- */static boolExecQualClause(Node *clause, ExprContext *econtext){	Datum		expr_value;	bool		isNull;	bool		isDone;	/* when there is a null clause, consider the qualification to be true */	if (clause == NULL)		return true;	/*	 * pass isDone, but ignore it.	We don't iterate over multiple returns	 * in the qualifications.	 */	expr_value = (Datum)		ExecEvalExpr(clause, econtext, &isNull, &isDone);	/*	 * this is interesting behaviour here.	When a clause evaluates to	 * null, then we consider this as passing the qualification. it seems	 * kind of like, if the qual is NULL, then there's no qual..	 */	if (isNull)		return true;	/*	 * remember, we return true when the qualification fails..	 */	if (DatumGetInt32(expr_value) == 0)		return true;	return false;}/* ---------------------------------------------------------------- *		ExecQual * *		Evaluates a conjunctive boolean expression and returns t *		iff none of the subexpressions are false (or null). * ---------------------------------------------------------------- */boolExecQual(List *qual, ExprContext *econtext){	List	   *clause;	bool		result;	/*	 * debugging stuff	 */	EV_printf("ExecQual: qual is ");	EV_nodeDisplay(qual);	EV_printf("\n");	IncrProcessed();	/*	 * return true immediately if no qual	 */	if (qual == NIL)		return true;	/*	 * a "qual" is a list of clauses.  To evaluate the qual, we evaluate	 * each of the clauses in the list.	 *	 * ExecQualClause returns true when we know the qualification *failed* so	 * we just pass each clause in qual to it until we know the qual	 * failed or there are no more clauses.	 */	result = false;	foreach(clause, qual)	{		result = ExecQualClause((Node *) lfirst(clause), econtext);		if (result == true)			break;	}	/*	 * if result is true, then it means a clause failed so we return	 * false.  if result is false then it means no clause failed so we	 * return true.	 */	if (result == true)		return false;	return true;}intExecTargetListLength(List *targetlist){	int			len;	List	   *tl;	TargetEntry *curTle;	len = 0;	foreach(tl, targetlist)	{		curTle = lfirst(tl);		if (curTle->resdom != NULL)			len++;		else			len += curTle->fjoin->fj_nNodes;	}	return len;}/* ---------------------------------------------------------------- *		ExecTargetList * *		Evaluates a targetlist with respect to the current *		expression context and return a tuple. * ---------------------------------------------------------------- */static HeapTupleExecTargetList(List *targetlist,			   int nodomains,			   TupleDesc targettype,			   Datum *values,			   ExprContext *econtext,			   bool *isDone){	char		nulls_array[64];	bool		fjNullArray[64];	bool	   *fjIsNull;	char	   *null_head;	List	   *tl;	TargetEntry *tle;	Node	   *expr;	Resdom	   *resdom;	AttrNumber	resind;	Datum		constvalue;	HeapTuple	newTuple;	bool		isNull;	static struct tupleDesc NullTupleDesc; /* we assume this inits to zeroes */	/*	 * debugging stuff	 */	EV_printf("ExecTargetList: tl is ");	EV_nodeDisplay(targetlist);	EV_printf("\n");	/*	 * There used to be some klugy and demonstrably broken code here that	 * special-cased the situation where targetlist == NIL.  Now we just	 * fall through and return an empty-but-valid tuple.  We do, however,	 * have to cope with the possibility that targettype is NULL ---	 * heap_formtuple won't like that, so pass a dummy descriptor with	 * natts = 0 to deal with it.	 */	if (targettype == NULL)		targettype = &NullTupleDesc;	/*	 * allocate an array of char's to hold the "null" information only if	 * we have a really large targetlist.  otherwise we use the stack.	 */	if (nodomains > 64)	{		null_head = (char *) palloc(nodomains + 1);		fjIsNull = (bool *) palloc(nodomains + 1);	}	else	{		null_head = &nulls_array[0];		fjIsNull = &fjNullArray[0];	}	/*	 * evaluate all the expressions in the target list	 */	EV_printf("ExecTargetList: setting target list values\n");	*isDone = true;	foreach(tl, targetlist)	{		/*		 * remember, a target list is a list of lists:		 *		 * ((<resdom | fjoin> expr) (<resdom | fjoin> expr) ...)		 *		 * tl is a pointer to successive cdr's of the targetlist tle is a		 * pointer to the target list entry in tl		 */		tle = lfirst(tl);		if (tle->resdom != NULL)		{			expr = tle->expr;			resdom = tle->resdom;			resind = resdom->resno - 1;			constvalue = (Datum) ExecEvalExpr(expr,											  econtext,											  &isNull,											  isDone);			if ((IsA(expr, Iter)) && (*isDone))				return (HeapTuple) NULL;			values[resind] = constvalue;			if (!isNull)				null_head[resind] = ' ';			else				null_head[resind] = 'n';		}		else		{			int			curNode;			Resdom	   *fjRes;			List	   *fjTlist = (List *) tle->expr;			Fjoin	   *fjNode = tle->fjoin;			int			nNodes = fjNode->fj_nNodes;			DatumPtr	results = fjNode->fj_results;			ExecEvalFjoin(tle, econtext, fjIsNull, isDone);			if (*isDone)				return (HeapTuple) NULL;			/*			 * get the result from the inner node			 */			fjRes = (Resdom *) fjNode->fj_innerNode;			resind = fjRes->resno - 1;			if (fjIsNull[0])				null_head[resind] = 'n';			else			{				null_head[resind] = ' ';				values[resind] = results[0];			}			/*			 * Get results from all of the outer nodes			 */			for (curNode = 1;				 curNode < nNodes;				 curNode++, fjTlist = lnext(fjTlist))			{#ifdef NOT_USED					/* what is this?? */				Node	   *outernode = lfirst(fjTlist);				fjRes = (Resdom *) outernode->iterexpr;#endif				resind = fjRes->resno - 1;				if (fjIsNull[curNode])					null_head[resind] = 'n';				else				{					null_head[resind] = ' ';					values[resind] = results[curNode];				}			}		}	}	/*	 * form the new result tuple (in the "normal" context)	 */	newTuple = (HeapTuple) heap_formtuple(targettype, values, null_head);	/*	 * free the nulls array if we allocated one..	 */	if (nodomains > 64)	{		pfree(null_head);		pfree(fjIsNull);	}	return newTuple;}/* ---------------------------------------------------------------- *		ExecProject * *		projects a tuple based in projection info and stores *		it in the specified tuple table slot. * *		Note: someday soon the executor can be extended to eliminate *			  redundant projections by storing pointers to datums *			  in the tuple table and then passing these around when *			  possible.  this should make things much quicker. *			  -cim 6/3/91 * ---------------------------------------------------------------- */TupleTableSlot *ExecProject(ProjectionInfo *projInfo, bool *isDone){	TupleTableSlot *slot;	List	   *targetlist;	int			len;	TupleDesc	tupType;	Datum	   *tupValue;	ExprContext *econtext;	HeapTuple	newTuple;	/*	 * sanity checks	 */	if (projInfo == NULL)		return (TupleTableSlot *) NULL;	/*	 * get the projection info we want	 */	slot = projInfo->pi_slot;	targetlist = projInfo->pi_targetlist;	len = projInfo->pi_len;	tupType = slot->ttc_tupleDescriptor;	tupValue = projInfo->pi_tupValue;	econtext = projInfo->pi_exprContext;	/*	 * form a new (result) tuple	 */	newTuple = ExecTargetList(targetlist,							  len,							  tupType,							  tupValue,							  econtext,							  isDone);	/*	 * store the tuple in the projection slot and return the slot.	 */	return (TupleTableSlot *)		ExecStoreTuple(newTuple,/* tuple to store */					   slot,	/* slot to store in */					   InvalidBuffer,	/* tuple has no buffer */					   true);}

⌨️ 快捷键说明

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