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

📄 predtest.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 3 页
字号:
					}					iterate_end(clause_info);					return result;			}			break;		case CLASS_OR:			switch (pclass)			{				case CLASS_OR:					/*					 * OR-clause R=> OR-clause if A refutes each of B's items					 */					result = true;					iterate_begin(pitem, predicate, pred_info)					{						if (!predicate_refuted_by_recurse(clause, pitem))						{							result = false;							break;						}					}					iterate_end(pred_info);					return result;				case CLASS_AND:					/*					 * OR-clause R=> AND-clause if each of A's items refutes					 * any of B's items.					 */					result = true;					iterate_begin(citem, clause, clause_info)					{						bool		presult = false;						iterate_begin(pitem, predicate, pred_info)						{							if (predicate_refuted_by_recurse(citem, pitem))							{								presult = true;								break;							}						}						iterate_end(pred_info);						if (!presult)						{							result = false;		/* citem refutes nothing */							break;						}					}					iterate_end(clause_info);					return result;				case CLASS_ATOM:					/*					 * If B is a NOT-clause, A R=> B if A => B's arg					 */					not_arg = extract_not_arg(predicate);					if (not_arg &&						predicate_implied_by_recurse(clause, not_arg))						return true;					/*					 * OR-clause R=> atom if each of A's items refutes B					 */					result = true;					iterate_begin(citem, clause, clause_info)					{						if (!predicate_refuted_by_recurse(citem, predicate))						{							result = false;							break;						}					}					iterate_end(clause_info);					return result;			}			break;		case CLASS_ATOM:#ifdef NOT_USED			/*			 * If A is a NOT-clause, A R=> B if B => A's arg			 *			 * Unfortunately not: this would only prove that B is not-TRUE,			 * not that it's not NULL either.  Keep this code as a comment			 * because it would be useful if we ever had a need for the			 * weak form of refutation.			 */			not_arg = extract_not_arg(clause);			if (not_arg &&				predicate_implied_by_recurse(predicate, not_arg))				return true;#endif			switch (pclass)			{				case CLASS_AND:					/*					 * atom R=> AND-clause if A refutes any of B's items					 */					result = false;					iterate_begin(pitem, predicate, pred_info)					{						if (predicate_refuted_by_recurse(clause, pitem))						{							result = true;							break;						}					}					iterate_end(pred_info);					return result;				case CLASS_OR:					/*					 * atom R=> OR-clause if A refutes each of B's items					 */					result = true;					iterate_begin(pitem, predicate, pred_info)					{						if (!predicate_refuted_by_recurse(clause, pitem))						{							result = false;							break;						}					}					iterate_end(pred_info);					return result;				case CLASS_ATOM:					/*					 * If B is a NOT-clause, A R=> B if A => B's arg					 */					not_arg = extract_not_arg(predicate);					if (not_arg &&						predicate_implied_by_recurse(clause, not_arg))						return true;					/*					 * atom R=> atom is the base case					 */					return						predicate_refuted_by_simple_clause((Expr *) predicate,														   clause);			}			break;	}	/* can't get here */	elog(ERROR, "predicate_classify returned a bogus value");	return false;}/* * predicate_classify *	  Classify an expression node as AND-type, OR-type, or neither (an atom). * * If the expression is classified as AND- or OR-type, then *info is filled * in with the functions needed to iterate over its components. */static PredClasspredicate_classify(Node *clause, PredIterInfo info){	/* Caller should not pass us NULL, nor a RestrictInfo clause */	Assert(clause != NULL);	Assert(!IsA(clause, RestrictInfo));	/*	 * If we see a List, assume it's an implicit-AND list; this is the correct	 * semantics for lists of RestrictInfo nodes.	 */	if (IsA(clause, List))	{		info->startup_fn = list_startup_fn;		info->next_fn = list_next_fn;		info->cleanup_fn = list_cleanup_fn;		return CLASS_AND;	}	/* Handle normal AND and OR boolean clauses */	if (and_clause(clause))	{		info->startup_fn = boolexpr_startup_fn;		info->next_fn = list_next_fn;		info->cleanup_fn = list_cleanup_fn;		return CLASS_AND;	}	if (or_clause(clause))	{		info->startup_fn = boolexpr_startup_fn;		info->next_fn = list_next_fn;		info->cleanup_fn = list_cleanup_fn;		return CLASS_OR;	}	/* Handle ScalarArrayOpExpr */	if (IsA(clause, ScalarArrayOpExpr))	{		ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;		Node	   *arraynode = (Node *) lsecond(saop->args);		/*		 * We can break this down into an AND or OR structure, but only if we		 * know how to iterate through expressions for the array's elements.		 * We can do that if the array operand is a non-null constant or a		 * simple ArrayExpr.		 */		if (arraynode && IsA(arraynode, Const) &&			!((Const *) arraynode)->constisnull)		{			info->startup_fn = arrayconst_startup_fn;			info->next_fn = arrayconst_next_fn;			info->cleanup_fn = arrayconst_cleanup_fn;			return saop->useOr ? CLASS_OR : CLASS_AND;		}		if (arraynode && IsA(arraynode, ArrayExpr) &&			!((ArrayExpr *) arraynode)->multidims)		{			info->startup_fn = arrayexpr_startup_fn;			info->next_fn = arrayexpr_next_fn;			info->cleanup_fn = arrayexpr_cleanup_fn;			return saop->useOr ? CLASS_OR : CLASS_AND;		}	}	/* None of the above, so it's an atom */	return CLASS_ATOM;}/* * PredIterInfo routines for iterating over regular Lists.	The iteration * state variable is the next ListCell to visit. */static voidlist_startup_fn(Node *clause, PredIterInfo info){	info->state = (void *) list_head((List *) clause);}static Node *list_next_fn(PredIterInfo info){	ListCell   *l = (ListCell *) info->state;	Node	   *n;	if (l == NULL)		return NULL;	n = lfirst(l);	info->state = (void *) lnext(l);	return n;}static voidlist_cleanup_fn(PredIterInfo info){	/* Nothing to clean up */}/* * BoolExpr needs its own startup function, but can use list_next_fn and * list_cleanup_fn. */static voidboolexpr_startup_fn(Node *clause, PredIterInfo info){	info->state = (void *) list_head(((BoolExpr *) clause)->args);}/* * PredIterInfo routines for iterating over a ScalarArrayOpExpr with a * constant array operand. */typedef struct{	OpExpr		opexpr;	Const		constexpr;	int			next_elem;	int			num_elems;	Datum	   *elem_values;	bool	   *elem_nulls;} ArrayConstIterState;static voidarrayconst_startup_fn(Node *clause, PredIterInfo info){	ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;	ArrayConstIterState *state;	Const	   *arrayconst;	ArrayType  *arrayval;	int16		elmlen;	bool		elmbyval;	char		elmalign;	/* Create working state struct */	state = (ArrayConstIterState *) palloc(sizeof(ArrayConstIterState));	info->state = (void *) state;	/* Deconstruct the array literal */	arrayconst = (Const *) lsecond(saop->args);	arrayval = DatumGetArrayTypeP(arrayconst->constvalue);	get_typlenbyvalalign(ARR_ELEMTYPE(arrayval),						 &elmlen, &elmbyval, &elmalign);	deconstruct_array(arrayval,					  ARR_ELEMTYPE(arrayval),					  elmlen, elmbyval, elmalign,					  &state->elem_values, &state->elem_nulls,					  &state->num_elems);	/* Set up a dummy OpExpr to return as the per-item node */	state->opexpr.xpr.type = T_OpExpr;	state->opexpr.opno = saop->opno;	state->opexpr.opfuncid = saop->opfuncid;	state->opexpr.opresulttype = BOOLOID;	state->opexpr.opretset = false;	state->opexpr.args = list_copy(saop->args);	/* Set up a dummy Const node to hold the per-element values */	state->constexpr.xpr.type = T_Const;	state->constexpr.consttype = ARR_ELEMTYPE(arrayval);	state->constexpr.consttypmod = -1;	state->constexpr.constlen = elmlen;	state->constexpr.constbyval = elmbyval;	lsecond(state->opexpr.args) = &state->constexpr;	/* Initialize iteration state */	state->next_elem = 0;}static Node *arrayconst_next_fn(PredIterInfo info){	ArrayConstIterState *state = (ArrayConstIterState *) info->state;	if (state->next_elem >= state->num_elems)		return NULL;	state->constexpr.constvalue = state->elem_values[state->next_elem];	state->constexpr.constisnull = state->elem_nulls[state->next_elem];	state->next_elem++;	return (Node *) &(state->opexpr);}static voidarrayconst_cleanup_fn(PredIterInfo info){	ArrayConstIterState *state = (ArrayConstIterState *) info->state;	pfree(state->elem_values);	pfree(state->elem_nulls);	list_free(state->opexpr.args);	pfree(state);}/* * PredIterInfo routines for iterating over a ScalarArrayOpExpr with a * one-dimensional ArrayExpr array operand. */typedef struct{	OpExpr		opexpr;	ListCell   *next;} ArrayExprIterState;static voidarrayexpr_startup_fn(Node *clause, PredIterInfo info){	ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;	ArrayExprIterState *state;	ArrayExpr  *arrayexpr;	/* Create working state struct */	state = (ArrayExprIterState *) palloc(sizeof(ArrayExprIterState));	info->state = (void *) state;	/* Set up a dummy OpExpr to return as the per-item node */	state->opexpr.xpr.type = T_OpExpr;	state->opexpr.opno = saop->opno;	state->opexpr.opfuncid = saop->opfuncid;	state->opexpr.opresulttype = BOOLOID;	state->opexpr.opretset = false;	state->opexpr.args = list_copy(saop->args);	/* Initialize iteration variable to first member of ArrayExpr */	arrayexpr = (ArrayExpr *) lsecond(saop->args);	state->next = list_head(arrayexpr->elements);}static Node *arrayexpr_next_fn(PredIterInfo info){	ArrayExprIterState *state = (ArrayExprIterState *) info->state;	if (state->next == NULL)		return NULL;	lsecond(state->opexpr.args) = lfirst(state->next);	state->next = lnext(state->next);	return (Node *) &(state->opexpr);}static voidarrayexpr_cleanup_fn(PredIterInfo info){	ArrayExprIterState *state = (ArrayExprIterState *) info->state;	list_free(state->opexpr.args);	pfree(state);}/*---------- * predicate_implied_by_simple_clause *	  Does the predicate implication test for a "simple clause" predicate *	  and a "simple clause" restriction. * * We return TRUE if able to prove the implication, FALSE if not. * * We have three strategies for determining whether one simple clause * implies another: * * A simple and general way is to see if they are equal(); this works for any * kind of expression.	(Actually, there is an implied assumption that the * functions in the expression are immutable, ie dependent only on their input * arguments --- but this was checked for the predicate by the caller.) * * When the predicate is of the form "foo IS NOT NULL", we can conclude that * the predicate is implied if the clause is a strict operator or function * that has "foo" as an input.	In this case the clause must yield NULL when * "foo" is NULL, which we can take as equivalent to FALSE because we know * we are within an AND/OR subtree of a WHERE clause.  (Again, "foo" is * already known immutable, so the clause will certainly always fail.) * * Finally, we may be able to deduce something using knowledge about btree * operator families; this is encapsulated in btree_predicate_proof(). *---------- */static boolpredicate_implied_by_simple_clause(Expr *predicate, Node *clause){	/* First try the equal() test */	if (equal((Node *) predicate, clause))		return true;	/* Next try the IS NOT NULL case */	if (predicate && IsA(predicate, NullTest) &&		((NullTest *) predicate)->nulltesttype == IS_NOT_NULL)	{		Expr	   *nonnullarg = ((NullTest *) predicate)->arg;		/* row IS NOT NULL does not act in the simple way we have in mind */		if (!type_is_rowtype(exprType((Node *) nonnullarg)))		{			if (is_opclause(clause) &&				list_member_strip(((OpExpr *) clause)->args, nonnullarg) &&				op_strict(((OpExpr *) clause)->opno))				return true;			if (is_funcclause(clause) &&				list_member_strip(((FuncExpr *) clause)->args, nonnullarg) &&				func_strict(((FuncExpr *) clause)->funcid))				return true;		}		return false;			/* we can't succeed below... */	}	/* Else try btree operator knowledge */	return btree_predicate_proof(predicate, clause, false);}/*---------- * predicate_refuted_by_simple_clause *	  Does the predicate refutation test for a "simple clause" predicate *	  and a "simple clause" restriction. * * We return TRUE if able to prove the refutation, FALSE if not. * * Unlike the implication case, checking for equal() clauses isn't * helpful. * * When the predicate is of the form "foo IS NULL", we can conclude that * the predicate is refuted if the clause is a strict operator or function * that has "foo" as an input (see notes for implication case), or if the * clause is "foo IS NOT NULL".  A clause "foo IS NULL" refutes a predicate * "foo IS NOT NULL", but unfortunately does not refute strict predicates, * because we are looking for strong refutation.  (The motivation for covering * these cases is to support using IS NULL/IS NOT NULL as partition-defining * constraints.) * * Finally, we may be able to deduce something using knowledge about btree * operator families; this is encapsulated in btree_predicate_proof(). *---------- */static boolpredicate_refuted_by_simple_clause(Expr *predicate, Node *clause){	/* A simple clause can't refute itself */	/* Worth checking because of relation_excluded_by_constraints() */	if ((Node *) predicate == clause)		return false;	/* Try the predicate-IS-NULL case */	if (predicate && IsA(predicate, NullTest) &&		((NullTest *) predicate)->nulltesttype == IS_NULL)	{		Expr	   *isnullarg = ((NullTest *) predicate)->arg;		/* row IS NULL does not act in the simple way we have in mind */		if (type_is_rowtype(exprType((Node *) isnullarg)))			return false;		/* Any strict op/func on foo refutes foo IS NULL */		if (is_opclause(clause) &&			list_member_strip(((OpExpr *) clause)->args, isnullarg) &&			op_strict(((OpExpr *) clause)->opno))			return true;		if (is_funcclause(clause) &&

⌨️ 快捷键说明

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