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

📄 clauses.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
		 * The expression cannot be simplified any further, so build and		 * return a replacement OpExpr node using the possibly-simplified		 * arguments.		 */		newexpr = makeNode(OpExpr);		newexpr->opno = expr->opno;		newexpr->opfuncid = expr->opfuncid;		newexpr->opresulttype = expr->opresulttype;		newexpr->opretset = expr->opretset;		newexpr->args = args;		return (Node *) newexpr;	}	if (IsA(node, DistinctExpr))	{		DistinctExpr *expr = (DistinctExpr *) node;		List	   *args;		ListCell   *arg;		bool		has_null_input = false;		bool		all_null_input = true;		bool		has_nonconst_input = false;		Expr	   *simple;		DistinctExpr *newexpr;		/*		 * Reduce constants in the DistinctExpr's arguments.  We know args is		 * either NIL or a List node, so we can call expression_tree_mutator		 * directly rather than recursing to self.		 */		args = (List *) expression_tree_mutator((Node *) expr->args,											  eval_const_expressions_mutator,												(void *) context);		/*		 * We must do our own check for NULLs because DistinctExpr has		 * different results for NULL input than the underlying operator does.		 */		foreach(arg, args)		{			if (IsA(lfirst(arg), Const))			{				has_null_input |= ((Const *) lfirst(arg))->constisnull;				all_null_input &= ((Const *) lfirst(arg))->constisnull;			}			else				has_nonconst_input = true;		}		/* all constants? then can optimize this out */		if (!has_nonconst_input)		{			/* all nulls? then not distinct */			if (all_null_input)				return makeBoolConst(false, false);			/* one null? then distinct */			if (has_null_input)				return makeBoolConst(true, false);			/* otherwise try to evaluate the '=' operator */			/* (NOT okay to try to inline it, though!) */			/*			 * Need to get OID of underlying function.	Okay to scribble on			 * input to this extent.			 */			set_opfuncid((OpExpr *) expr);		/* rely on struct equivalence */			/*			 * Code for op/func reduction is pretty bulky, so split it out as			 * a separate function.			 */			simple = simplify_function(expr->opfuncid, expr->opresulttype,									   args, false, context);			if (simple)			/* successfully simplified it */			{				/*				 * Since the underlying operator is "=", must negate its				 * result				 */				Const	   *csimple = (Const *) simple;				Assert(IsA(csimple, Const));				csimple->constvalue =					BoolGetDatum(!DatumGetBool(csimple->constvalue));				return (Node *) csimple;			}		}		/*		 * The expression cannot be simplified any further, so build and		 * return a replacement DistinctExpr node using the		 * possibly-simplified arguments.		 */		newexpr = makeNode(DistinctExpr);		newexpr->opno = expr->opno;		newexpr->opfuncid = expr->opfuncid;		newexpr->opresulttype = expr->opresulttype;		newexpr->opretset = expr->opretset;		newexpr->args = args;		return (Node *) newexpr;	}	if (IsA(node, BoolExpr))	{		BoolExpr   *expr = (BoolExpr *) node;		switch (expr->boolop)		{			case OR_EXPR:				{					List	   *newargs;					bool		haveNull = false;					bool		forceTrue = false;					newargs = simplify_or_arguments(expr->args, context,													&haveNull, &forceTrue);					if (forceTrue)						return makeBoolConst(true, false);					if (haveNull)						newargs = lappend(newargs, makeBoolConst(false, true));					/* If all the inputs are FALSE, result is FALSE */					if (newargs == NIL)						return makeBoolConst(false, false);					/* If only one nonconst-or-NULL input, it's the result */					if (list_length(newargs) == 1)						return (Node *) linitial(newargs);					/* Else we still need an OR node */					return (Node *) make_orclause(newargs);				}			case AND_EXPR:				{					List	   *newargs;					bool		haveNull = false;					bool		forceFalse = false;					newargs = simplify_and_arguments(expr->args, context,													 &haveNull, &forceFalse);					if (forceFalse)						return makeBoolConst(false, false);					if (haveNull)						newargs = lappend(newargs, makeBoolConst(false, true));					/* If all the inputs are TRUE, result is TRUE */					if (newargs == NIL)						return makeBoolConst(true, false);					/* If only one nonconst-or-NULL input, it's the result */					if (list_length(newargs) == 1)						return (Node *) linitial(newargs);					/* Else we still need an AND node */					return (Node *) make_andclause(newargs);				}			case NOT_EXPR:				{					Node	   *arg;					Assert(list_length(expr->args) == 1);					arg = eval_const_expressions_mutator(linitial(expr->args),														 context);					if (IsA(arg, Const))					{						Const	   *const_input = (Const *) arg;						/* NOT NULL => NULL */						if (const_input->constisnull)							return makeBoolConst(false, true);						/* otherwise pretty easy */						return makeBoolConst(!DatumGetBool(const_input->constvalue),											 false);					}					else if (not_clause(arg))					{						/* Cancel NOT/NOT */						return (Node *) get_notclausearg((Expr *) arg);					}					/* Else we still need a NOT node */					return (Node *) make_notclause((Expr *) arg);				}			default:				elog(ERROR, "unrecognized boolop: %d",					 (int) expr->boolop);				break;		}	}	if (IsA(node, SubPlan))	{		/*		 * Return a SubPlan unchanged --- too late to do anything with it.		 *		 * XXX should we ereport() here instead?  Probably this routine should		 * never be invoked after SubPlan creation.		 */		return node;	}	if (IsA(node, RelabelType))	{		/*		 * If we can simplify the input to a constant, then we don't need the		 * RelabelType node anymore: just change the type field of the Const		 * node.  Otherwise, must copy the RelabelType node.		 */		RelabelType *relabel = (RelabelType *) node;		Node	   *arg;		arg = eval_const_expressions_mutator((Node *) relabel->arg,											 context);		/*		 * If we find stacked RelabelTypes (eg, from foo :: int :: oid) we can		 * discard all but the top one.		 */		while (arg && IsA(arg, RelabelType))			arg = (Node *) ((RelabelType *) arg)->arg;		if (arg && IsA(arg, Const))		{			Const	   *con = (Const *) arg;			con->consttype = relabel->resulttype;			/*			 * relabel's resulttypmod is discarded, which is OK for now; if			 * the type actually needs a runtime length coercion then there			 * should be a function call to do it just above this node.			 */			return (Node *) con;		}		else		{			RelabelType *newrelabel = makeNode(RelabelType);			newrelabel->arg = (Expr *) arg;			newrelabel->resulttype = relabel->resulttype;			newrelabel->resulttypmod = relabel->resulttypmod;			return (Node *) newrelabel;		}	}	if (IsA(node, CaseExpr))	{		/*----------		 * CASE expressions can be simplified if there are constant		 * condition clauses:		 *		FALSE (or NULL): drop the alternative		 *		TRUE: drop all remaining alternatives		 * If the first non-FALSE alternative is a constant TRUE, we can		 * simplify the entire CASE to that alternative's expression.		 * If there are no non-FALSE alternatives, we simplify the entire		 * CASE to the default result (ELSE result).		 *		 * If we have a simple-form CASE with constant test expression,		 * we substitute the constant value for contained CaseTestExpr		 * placeholder nodes, so that we have the opportunity to reduce		 * constant test conditions.  For example this allows		 *		CASE 0 WHEN 0 THEN 1 ELSE 1/0 END		 * to reduce to 1 rather than drawing a divide-by-0 error.		 *----------		 */		CaseExpr   *caseexpr = (CaseExpr *) node;		CaseExpr   *newcase;		Node	   *save_case_val;		Node	   *newarg;		List	   *newargs;		bool		const_true_cond;		Node	   *defresult = NULL;		ListCell   *arg;		/* Simplify the test expression, if any */		newarg = eval_const_expressions_mutator((Node *) caseexpr->arg,												context);		/* Set up for contained CaseTestExpr nodes */		save_case_val = context->case_val;		if (newarg && IsA(newarg, Const))			context->case_val = newarg;		else			context->case_val = NULL;		/* Simplify the WHEN clauses */		newargs = NIL;		const_true_cond = false;		foreach(arg, caseexpr->args)		{			CaseWhen   *oldcasewhen = (CaseWhen *) lfirst(arg);			Node	   *casecond;			Node	   *caseresult;			Assert(IsA(oldcasewhen, CaseWhen));			/* Simplify this alternative's test condition */			casecond =				eval_const_expressions_mutator((Node *) oldcasewhen->expr,											   context);			/*			 * If the test condition is constant FALSE (or NULL), then drop			 * this WHEN clause completely, without processing the result.			 */			if (casecond && IsA(casecond, Const))			{				Const	   *const_input = (Const *) casecond;				if (const_input->constisnull ||					!DatumGetBool(const_input->constvalue))					continue;	/* drop alternative with FALSE condition */				/* Else it's constant TRUE */				const_true_cond = true;			}			/* Simplify this alternative's result value */			caseresult =				eval_const_expressions_mutator((Node *) oldcasewhen->result,											   context);			/* If non-constant test condition, emit a new WHEN node */			if (!const_true_cond)			{				CaseWhen   *newcasewhen = makeNode(CaseWhen);				newcasewhen->expr = (Expr *) casecond;				newcasewhen->result = (Expr *) caseresult;				newargs = lappend(newargs, newcasewhen);				continue;			}			/*			 * Found a TRUE condition, so none of the remaining alternatives			 * can be reached.	We treat the result as the default result.			 */			defresult = caseresult;			break;		}		/* Simplify the default result, unless we replaced it above */		if (!const_true_cond)			defresult =				eval_const_expressions_mutator((Node *) caseexpr->defresult,											   context);		context->case_val = save_case_val;		/* If no non-FALSE alternatives, CASE reduces to the default result */		if (newargs == NIL)			return defresult;		/* Otherwise we need a new CASE node */		newcase = makeNode(CaseExpr);		newcase->casetype = caseexpr->casetype;		newcase->arg = (Expr *) newarg;		newcase->args = newargs;		newcase->defresult = (Expr *) defresult;		return (Node *) newcase;	}	if (IsA(node, CaseTestExpr))	{		/*		 * If we know a constant test value for the current CASE construct,		 * substitute it for the placeholder.  Else just return the		 * placeholder as-is.		 */		if (context->case_val)			return copyObject(context->case_val);		else			return copyObject(node);	}	if (IsA(node, ArrayExpr))	{		ArrayExpr  *arrayexpr = (ArrayExpr *) node;		ArrayExpr  *newarray;		bool		all_const = true;		List	   *newelems;		ListCell   *element;		newelems = NIL;		foreach(element, arrayexpr->elements)		{			Node	   *e;			e = eval_const_expressions_mutator((Node *) lfirst(element),											   context);			if (!IsA(e, Const))				all_const = false;			newelems = lappend(newelems, e);		}		newarray = makeNode(ArrayExpr);		newarray->array_typeid = arrayexpr->array_typeid;		newarray->element_typeid = arrayexpr->element_typeid;		newarray->elements = newelems;		newarray->multidims = arrayexpr->multidims;		if (all_const)			return (Node *) evaluate_expr((Expr *) newarray,										  newarray->array_typeid);		return (Node *) newarray;	}	if (IsA(node, CoalesceExpr))	{		CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;		CoalesceExpr *newcoalesce;		List	   *newargs;		ListCell   *arg;		newargs = NIL;		foreach(arg, coalesceexpr->args)		{			Node	   *e;			e = eval_const_expressions_mutator((Node *) lfirst(arg),											   context);			/*			 * We can remove null constants from the list. For a non-null			 * constant, if it has not been preceded by any other			 * non-null-constant expressions then that is the result.			 */			if (IsA(e, Const))			{				if (((Const *) e)->constisnull)					continue;	/* drop null constant */				if (newargs == NIL)					return e;	/* first expr */			}			newargs = lappend(newargs, e);		}		/* If all the arguments were constant null, the result is just null */		if (newargs == NIL)			return (Node *) makeNullConst(coalesceexpr->coalescetype);		newcoalesce = makeNode(CoalesceExpr);		newcoalesce->coalescetype = coalesceexpr->coalescetype;		newcoalesce->args = newargs;		return (Node *) newcoalesce;	}	if (IsA(node, FieldSelect))	{		/*		 * We can optimize field selection from a whole-row Var into a simple		 * Var.  (This case won't be generated directly by the parser, because		 * ParseComplexProjection short-circuits it. But it can arise while		 * simplifying functions.)	Also, we can optimize field selection from		 * a RowExpr construct.		 *		 * We must however check that the declared type of the field is still		 * the same as when the FieldSelect was created --- this can change if		 * someone did ALTER COLUMN TYPE on the rowtype.		 */		FieldSelect *fselect = (FieldSelect *) node;		FieldSelect *newfselect;		Node	   *arg;		arg = eval_const_expressions_mutator((Node *) fselect->arg,											 context);		if (arg && IsA(arg, Var) &&			((Var *) arg)->varattno == InvalidAttrNumber)		{			if (rowtype_field_matches(((Var *) arg)->vartype,									  fselect->fieldnum,

⌨️ 快捷键说明

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