clauses.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,256 行 · 第 1/5 页

C
2,256
字号
		/* else fall through to check args */	}	if (IsA(node, OpExpr))	{		OpExpr	   *expr = (OpExpr *) node;		if (expr->opretset)			return true;		/* else fall through to check args */	}	/* Avoid recursion for some cases that can't return a set */	if (IsA(node, Aggref))		return false;	if (IsA(node, DistinctExpr))		return false;	if (IsA(node, ScalarArrayOpExpr))		return false;	if (IsA(node, BoolExpr))		return false;	if (IsA(node, SubLink))		return false;	if (IsA(node, SubPlan))		return false;	if (IsA(node, ArrayExpr))		return false;	if (IsA(node, CoalesceExpr))		return false;	if (IsA(node, NullIfExpr))		return false;	return expression_tree_walker(node, expression_returns_set_walker,								  context);}/***************************************************************************** *		Subplan clause manipulation *****************************************************************************//* * contain_subplans *	  Recursively search for subplan nodes within a clause. * * If we see a SubLink node, we will return TRUE.  This is only possible if * the expression tree hasn't yet been transformed by subselect.c.  We do not * know whether the node will produce a true subplan or just an initplan, * but we make the conservative assumption that it will be a subplan. * * Returns true if any subplan found. */boolcontain_subplans(Node *clause){	return contain_subplans_walker(clause, NULL);}static boolcontain_subplans_walker(Node *node, void *context){	if (node == NULL)		return false;	if (IsA(node, SubPlan) ||		IsA(node, SubLink))		return true;			/* abort the tree traversal and return								 * true */	return expression_tree_walker(node, contain_subplans_walker, context);}/***************************************************************************** *		Check clauses for mutable functions *****************************************************************************//* * contain_mutable_functions *	  Recursively search for mutable functions within a clause. * * Returns true if any mutable function (or operator implemented by a * mutable function) is found.	This test is needed so that we don't * mistakenly think that something like "WHERE random() < 0.5" can be treated * as a constant qualification. * * XXX we do not examine sub-selects to see if they contain uses of * mutable functions.  It's not real clear if that is correct or not... */boolcontain_mutable_functions(Node *clause){	return contain_mutable_functions_walker(clause, NULL);}static boolcontain_mutable_functions_walker(Node *node, void *context){	if (node == NULL)		return false;	if (IsA(node, FuncExpr))	{		FuncExpr   *expr = (FuncExpr *) node;		if (func_volatile(expr->funcid) != PROVOLATILE_IMMUTABLE)			return true;		/* else fall through to check args */	}	if (IsA(node, OpExpr))	{		OpExpr	   *expr = (OpExpr *) node;		if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE)			return true;		/* else fall through to check args */	}	if (IsA(node, DistinctExpr))	{		DistinctExpr *expr = (DistinctExpr *) node;		if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE)			return true;		/* else fall through to check args */	}	if (IsA(node, ScalarArrayOpExpr))	{		ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;		if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE)			return true;		/* else fall through to check args */	}	if (IsA(node, NullIfExpr))	{		NullIfExpr *expr = (NullIfExpr *) node;		if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE)			return true;		/* else fall through to check args */	}	if (IsA(node, SubLink))	{		SubLink    *sublink = (SubLink *) node;		List	   *opid;		foreach(opid, sublink->operOids)		{			if (op_volatile(lfirsto(opid)) != PROVOLATILE_IMMUTABLE)				return true;		}		/* else fall through to check args */	}	return expression_tree_walker(node, contain_mutable_functions_walker,								  context);}/***************************************************************************** *		Check clauses for volatile functions *****************************************************************************//* * contain_volatile_functions *	  Recursively search for volatile functions within a clause. * * Returns true if any volatile function (or operator implemented by a * volatile function) is found. This test prevents invalid conversions * of volatile expressions into indexscan quals. * * XXX we do not examine sub-selects to see if they contain uses of * volatile functions.	It's not real clear if that is correct or not... */boolcontain_volatile_functions(Node *clause){	return contain_volatile_functions_walker(clause, NULL);}static boolcontain_volatile_functions_walker(Node *node, void *context){	if (node == NULL)		return false;	if (IsA(node, FuncExpr))	{		FuncExpr   *expr = (FuncExpr *) node;		if (func_volatile(expr->funcid) == PROVOLATILE_VOLATILE)			return true;		/* else fall through to check args */	}	if (IsA(node, OpExpr))	{		OpExpr	   *expr = (OpExpr *) node;		if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE)			return true;		/* else fall through to check args */	}	if (IsA(node, DistinctExpr))	{		DistinctExpr *expr = (DistinctExpr *) node;		if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE)			return true;		/* else fall through to check args */	}	if (IsA(node, ScalarArrayOpExpr))	{		ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;		if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE)			return true;		/* else fall through to check args */	}	if (IsA(node, NullIfExpr))	{		NullIfExpr *expr = (NullIfExpr *) node;		if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE)			return true;		/* else fall through to check args */	}	if (IsA(node, SubLink))	{		SubLink    *sublink = (SubLink *) node;		List	   *opid;		foreach(opid, sublink->operOids)		{			if (op_volatile(lfirsto(opid)) == PROVOLATILE_VOLATILE)				return true;		}		/* else fall through to check args */	}	return expression_tree_walker(node, contain_volatile_functions_walker,								  context);}/***************************************************************************** *		Check clauses for nonstrict functions *****************************************************************************//* * contain_nonstrict_functions *	  Recursively search for nonstrict functions within a clause. * * Returns true if any nonstrict construct is found --- ie, anything that * could produce non-NULL output with a NULL input. * * XXX we do not examine sub-selects to see if they contain uses of * nonstrict functions. It's not real clear if that is correct or not... * for the current usage it does not matter, since inline_function() * rejects cases with sublinks. */boolcontain_nonstrict_functions(Node *clause){	return contain_nonstrict_functions_walker(clause, NULL);}static boolcontain_nonstrict_functions_walker(Node *node, void *context){	if (node == NULL)		return false;	if (IsA(node, FuncExpr))	{		FuncExpr   *expr = (FuncExpr *) node;		if (!func_strict(expr->funcid))			return true;		/* else fall through to check args */	}	if (IsA(node, OpExpr))	{		OpExpr	   *expr = (OpExpr *) node;		if (!op_strict(expr->opno))			return true;		/* else fall through to check args */	}	if (IsA(node, DistinctExpr))	{		/* IS DISTINCT FROM is inherently non-strict */		return true;	}	if (IsA(node, ScalarArrayOpExpr))	{		/* inherently non-strict, consider null scalar and empty array */		return true;	}	if (IsA(node, BoolExpr))	{		BoolExpr   *expr = (BoolExpr *) node;		switch (expr->boolop)		{			case OR_EXPR:			case AND_EXPR:				/* OR, AND are inherently non-strict */				return true;			default:				break;		}	}	if (IsA(node, CaseExpr))		return true;	/* NB: ArrayExpr might someday be nonstrict */	if (IsA(node, CoalesceExpr))		return true;	if (IsA(node, NullIfExpr))		return true;	if (IsA(node, NullTest))		return true;	if (IsA(node, BooleanTest))		return true;	if (IsA(node, SubLink))	{		SubLink    *sublink = (SubLink *) node;		List	   *opid;		foreach(opid, sublink->operOids)		{			if (!op_strict(lfirsto(opid)))				return true;		}		/* else fall through to check args */	}	return expression_tree_walker(node, contain_nonstrict_functions_walker,								  context);}/***************************************************************************** *		Check for "pseudo-constant" clauses *****************************************************************************//* * is_pseudo_constant_clause *	  Detect whether a clause is "constant", ie, it contains no variables *	  of the current query level and no uses of volatile functions. *	  Such a clause is not necessarily a true constant: it can still contain *	  Params and outer-level Vars, not to mention functions whose results *	  may vary from one statement to the next.	However, the clause's value *	  will be constant over any one scan of the current query, so it can be *	  used as an indexscan key or (if a top-level qual) can be pushed up to *	  become a gating qual. */boolis_pseudo_constant_clause(Node *clause){	/*	 * We could implement this check in one recursive scan.  But since the	 * check for volatile functions is both moderately expensive and	 * unlikely to fail, it seems better to look for Vars first and only	 * check for volatile functions if we find no Vars.	 */	if (!contain_var_clause(clause) &&		!contain_volatile_functions(clause))		return true;	return false;}/* * pull_constant_clauses *		Scan through a list of qualifications and separate "constant" quals *		from those that are not. * * Returns a list of the pseudo-constant clauses in constantQual and the * remaining quals as the return value. */List *pull_constant_clauses(List *quals, List **constantQual){	FastList	constqual,				restqual;	List	   *q;	FastListInit(&constqual);	FastListInit(&restqual);	foreach(q, quals)	{		Node	   *qual = (Node *) lfirst(q);		if (is_pseudo_constant_clause(qual))			FastAppend(&constqual, qual);		else			FastAppend(&restqual, qual);	}	*constantQual = FastListValue(&constqual);	return FastListValue(&restqual);}/***************************************************************************** *		Tests on clauses of queries * * Possibly this code should go someplace else, since this isn't quite the * same meaning of "clause" as is used elsewhere in this module.  But I can't * think of a better place for it... *****************************************************************************//* * Test whether a query uses DISTINCT ON, ie, has a distinct-list that is * not the same as the set of output columns. */boolhas_distinct_on_clause(Query *query){	List	   *targetList;	/* Is there a DISTINCT clause at all? */	if (query->distinctClause == NIL)		return false;	/*	 * If the DISTINCT list contains all the nonjunk targetlist items, and	 * nothing else (ie, no junk tlist items), then it's a simple	 * DISTINCT, else it's DISTINCT ON.  We do not require the lists to be	 * in the same order (since the parser may have adjusted the DISTINCT	 * clause ordering to agree with ORDER BY).  Furthermore, a	 * non-DISTINCT junk tlist item that is in the sortClause is also	 * evidence of DISTINCT ON, since we don't allow ORDER BY on junk	 * tlist items when plain DISTINCT is used.	 *	 * This code assumes that the DISTINCT list is valid, ie, all its entries	 * match some entry of the tlist.	 */	foreach(targetList, query->targetList)	{		TargetEntry *tle = (TargetEntry *) lfirst(targetList);		if (tle->resdom->ressortgroupref == 0)		{			if (tle->resdom->resjunk)				continue;		/* we can ignore unsorted junk cols */			return true;		/* definitely not in DISTINCT list */		}		if (targetIsInSortList(tle, query->distinctClause))		{			if (tle->resdom->resjunk)				return true;	/* junk TLE in DISTINCT means DISTINCT ON */			/* else this TLE is okay, keep looking */		}		else		{			/* This TLE is not in DISTINCT list */			if (!tle->resdom->resjunk)				return true;	/* non-junk, non-DISTINCT, so DISTINCT ON */			if (targetIsInSortList(tle, query->sortClause))				return true;	/* sorted, non-distinct junk */			/* unsorted junk is okay, keep looking */		}

⌨️ 快捷键说明

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