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

📄 clauses.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * clauses.c *	  routines to manipulate qualification clauses * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.201.2.1 2005/11/22 18:23:12 momjian Exp $ * * HISTORY *	  AUTHOR			DATE			MAJOR EVENT *	  Andrew Yu			Nov 3, 1994		clause.c and clauses.c combined * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "catalog/pg_aggregate.h"#include "catalog/pg_language.h"#include "catalog/pg_operator.h"#include "catalog/pg_proc.h"#include "catalog/pg_type.h"#include "executor/executor.h"#include "executor/functions.h"#include "miscadmin.h"#include "nodes/makefuncs.h"#include "optimizer/clauses.h"#include "optimizer/cost.h"#include "optimizer/planmain.h"#include "optimizer/planner.h"#include "optimizer/var.h"#include "parser/analyze.h"#include "parser/parse_clause.h"#include "parser/parse_coerce.h"#include "parser/parse_expr.h"#include "tcop/tcopprot.h"#include "utils/acl.h"#include "utils/builtins.h"#include "utils/datum.h"#include "utils/lsyscache.h"#include "utils/memutils.h"#include "utils/syscache.h"#include "utils/typcache.h"typedef struct{	List	   *active_fns;	Node	   *case_val;	bool		estimate;} eval_const_expressions_context;typedef struct{	int			nargs;	List	   *args;	int		   *usecounts;} substitute_actual_parameters_context;static bool contain_agg_clause_walker(Node *node, void *context);static bool count_agg_clauses_walker(Node *node, AggClauseCounts *counts);static bool expression_returns_set_walker(Node *node, void *context);static bool contain_subplans_walker(Node *node, void *context);static bool contain_mutable_functions_walker(Node *node, void *context);static bool contain_volatile_functions_walker(Node *node, void *context);static bool contain_nonstrict_functions_walker(Node *node, void *context);static bool set_coercionform_dontcare_walker(Node *node, void *context);static Node *eval_const_expressions_mutator(Node *node,							   eval_const_expressions_context *context);static List *simplify_or_arguments(List *args,					  eval_const_expressions_context *context,					  bool *haveNull, bool *forceTrue);static List *simplify_and_arguments(List *args,					   eval_const_expressions_context *context,					   bool *haveNull, bool *forceFalse);static Expr *simplify_boolean_equality(List *args);static Expr *simplify_function(Oid funcid, Oid result_type, List *args,				  bool allow_inline,				  eval_const_expressions_context *context);static Expr *evaluate_function(Oid funcid, Oid result_type, List *args,				  HeapTuple func_tuple,				  eval_const_expressions_context *context);static Expr *inline_function(Oid funcid, Oid result_type, List *args,				HeapTuple func_tuple,				eval_const_expressions_context *context);static Node *substitute_actual_parameters(Node *expr, int nargs, List *args,							 int *usecounts);static Node *substitute_actual_parameters_mutator(Node *node,							  substitute_actual_parameters_context *context);static void sql_inline_error_callback(void *arg);static Expr *evaluate_expr(Expr *expr, Oid result_type);/***************************************************************************** *		OPERATOR clause functions *****************************************************************************//* * make_opclause *	  Creates an operator clause given its operator info, left operand, *	  and right operand (pass NULL to create single-operand clause). */Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset,			  Expr *leftop, Expr *rightop){	OpExpr	   *expr = makeNode(OpExpr);	expr->opno = opno;	expr->opfuncid = InvalidOid;	expr->opresulttype = opresulttype;	expr->opretset = opretset;	if (rightop)		expr->args = list_make2(leftop, rightop);	else		expr->args = list_make1(leftop);	return (Expr *) expr;}/* * get_leftop * * Returns the left operand of a clause of the form (op expr expr) *		or (op expr) */Node *get_leftop(Expr *clause){	OpExpr	   *expr = (OpExpr *) clause;	if (expr->args != NIL)		return linitial(expr->args);	else		return NULL;}/* * get_rightop * * Returns the right operand in a clause of the form (op expr expr). * NB: result will be NULL if applied to a unary op clause. */Node *get_rightop(Expr *clause){	OpExpr	   *expr = (OpExpr *) clause;	if (list_length(expr->args) >= 2)		return lsecond(expr->args);	else		return NULL;}/***************************************************************************** *		NOT clause functions *****************************************************************************//* * not_clause * * Returns t iff this is a 'not' clause: (NOT expr). */boolnot_clause(Node *clause){	return (clause != NULL &&			IsA(clause, BoolExpr) &&			((BoolExpr *) clause)->boolop == NOT_EXPR);}/* * make_notclause * * Create a 'not' clause given the expression to be negated. */Expr *make_notclause(Expr *notclause){	BoolExpr   *expr = makeNode(BoolExpr);	expr->boolop = NOT_EXPR;	expr->args = list_make1(notclause);	return (Expr *) expr;}/* * get_notclausearg * * Retrieve the clause within a 'not' clause */Expr *get_notclausearg(Expr *notclause){	return linitial(((BoolExpr *) notclause)->args);}/***************************************************************************** *		OR clause functions *****************************************************************************//* * or_clause * * Returns t iff the clause is an 'or' clause: (OR { expr }). */boolor_clause(Node *clause){	return (clause != NULL &&			IsA(clause, BoolExpr) &&			((BoolExpr *) clause)->boolop == OR_EXPR);}/* * make_orclause * * Creates an 'or' clause given a list of its subclauses. */Expr *make_orclause(List *orclauses){	BoolExpr   *expr = makeNode(BoolExpr);	expr->boolop = OR_EXPR;	expr->args = orclauses;	return (Expr *) expr;}/***************************************************************************** *		AND clause functions *****************************************************************************//* * and_clause * * Returns t iff its argument is an 'and' clause: (AND { expr }). */booland_clause(Node *clause){	return (clause != NULL &&			IsA(clause, BoolExpr) &&			((BoolExpr *) clause)->boolop == AND_EXPR);}/* * make_andclause * * Creates an 'and' clause given a list of its subclauses. */Expr *make_andclause(List *andclauses){	BoolExpr   *expr = makeNode(BoolExpr);	expr->boolop = AND_EXPR;	expr->args = andclauses;	return (Expr *) expr;}/* * make_and_qual * * Variant of make_andclause for ANDing two qual conditions together. * Qual conditions have the property that a NULL nodetree is interpreted * as 'true'. * * NB: this makes no attempt to preserve AND/OR flatness; so it should not * be used on a qual that has already been run through prepqual.c. */Node *make_and_qual(Node *qual1, Node *qual2){	if (qual1 == NULL)		return qual2;	if (qual2 == NULL)		return qual1;	return (Node *) make_andclause(list_make2(qual1, qual2));}/* * Sometimes (such as in the input of ExecQual), we use lists of expression * nodes with implicit AND semantics. * * These functions convert between an AND-semantics expression list and the * ordinary representation of a boolean expression. * * Note that an empty list is considered equivalent to TRUE. */Expr *make_ands_explicit(List *andclauses){	if (andclauses == NIL)		return (Expr *) makeBoolConst(true, false);	else if (list_length(andclauses) == 1)		return (Expr *) linitial(andclauses);	else		return make_andclause(andclauses);}List *make_ands_implicit(Expr *clause){	/*	 * NB: because the parser sets the qual field to NULL in a query that has	 * no WHERE clause, we must consider a NULL input clause as TRUE, even	 * though one might more reasonably think it FALSE.  Grumble. If this	 * causes trouble, consider changing the parser's behavior.	 */	if (clause == NULL)		return NIL;				/* NULL -> NIL list == TRUE */	else if (and_clause((Node *) clause))		return ((BoolExpr *) clause)->args;	else if (IsA(clause, Const) &&			 !((Const *) clause)->constisnull &&			 DatumGetBool(((Const *) clause)->constvalue))		return NIL;				/* constant TRUE input -> NIL list */	else		return list_make1(clause);}/***************************************************************************** *		Aggregate-function clause manipulation *****************************************************************************//* * contain_agg_clause *	  Recursively search for Aggref nodes within a clause. * *	  Returns true if any aggregate found. * * This does not descend into subqueries, and so should be used only after * reduction of sublinks to subplans, or in contexts where it's known there * are no subqueries.  There mustn't be outer-aggregate references either. * * (If you want something like this but able to deal with subqueries, * see rewriteManip.c's checkExprHasAggs().) */boolcontain_agg_clause(Node *clause){	return contain_agg_clause_walker(clause, NULL);}static boolcontain_agg_clause_walker(Node *node, void *context){	if (node == NULL)		return false;	if (IsA(node, Aggref))	{		Assert(((Aggref *) node)->agglevelsup == 0);		return true;			/* abort the tree traversal and return true */	}	Assert(!IsA(node, SubLink));	return expression_tree_walker(node, contain_agg_clause_walker, context);}/* * count_agg_clauses *	  Recursively count the Aggref nodes in an expression tree. * *	  Note: this also checks for nested aggregates, which are an error. * * We not only count the nodes, but attempt to estimate the total space * needed for their transition state values if all are evaluated in parallel * (as would be done in a HashAgg plan).  See AggClauseCounts for the exact * set of statistics returned. * * NOTE that the counts are ADDED to those already in *counts ... so the * caller is responsible for zeroing the struct initially. * * This does not descend into subqueries, and so should be used only after * reduction of sublinks to subplans, or in contexts where it's known there * are no subqueries.  There mustn't be outer-aggregate references either. */voidcount_agg_clauses(Node *clause, AggClauseCounts *counts){	/* no setup needed */	count_agg_clauses_walker(clause, counts);}static boolcount_agg_clauses_walker(Node *node, AggClauseCounts *counts){	if (node == NULL)		return false;	if (IsA(node, Aggref))	{		Aggref	   *aggref = (Aggref *) node;		Oid			inputType;		HeapTuple	aggTuple;		Form_pg_aggregate aggform;		Oid			aggtranstype;		Assert(aggref->agglevelsup == 0);		counts->numAggs++;		if (aggref->aggdistinct)			counts->numDistinctAggs++;		inputType = exprType((Node *) aggref->target);		/* fetch aggregate transition datatype from pg_aggregate */		aggTuple = SearchSysCache(AGGFNOID,								  ObjectIdGetDatum(aggref->aggfnoid),								  0, 0, 0);		if (!HeapTupleIsValid(aggTuple))			elog(ERROR, "cache lookup failed for aggregate %u",				 aggref->aggfnoid);		aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);		aggtranstype = aggform->aggtranstype;		ReleaseSysCache(aggTuple);		/* resolve actual type of transition state, if polymorphic */		if (aggtranstype == ANYARRAYOID || aggtranstype == ANYELEMENTOID)		{			/* have to fetch the agg's declared input type... */			Oid		   *agg_arg_types;			int			agg_nargs;			(void) get_func_signature(aggref->aggfnoid,									  &agg_arg_types, &agg_nargs);			Assert(agg_nargs == 1);			aggtranstype = resolve_generic_type(aggtranstype,												inputType,												agg_arg_types[0]);			pfree(agg_arg_types);		}		/*		 * If the transition type is pass-by-value then it doesn't add		 * anything to the required size of the hashtable.	If it is		 * pass-by-reference then we have to add the estimated size of the		 * value itself, plus palloc overhead.		 */		if (!get_typbyval(aggtranstype))		{			int32		aggtranstypmod;			int32		avgwidth;			/*			 * If transition state is of same type as input, assume it's the			 * same typmod (same width) as well.  This works for cases like			 * MAX/MIN and is probably somewhat reasonable otherwise.			 */			if (aggtranstype == inputType)				aggtranstypmod = exprTypmod((Node *) aggref->target);

⌨️ 快捷键说明

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