1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* restrictinfo.c
|
1999-02-03 21:15:53 +01:00
|
|
|
* RestrictInfo node manipulation routines.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2010-01-02 17:58:17 +01:00
|
|
|
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-02-26 03:01:40 +01:00
|
|
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.63 2010/02/26 02:00:49 momjian Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include "optimizer/clauses.h"
|
2004-02-27 22:48:04 +01:00
|
|
|
#include "optimizer/cost.h"
|
2002-11-24 22:52:15 +01:00
|
|
|
#include "optimizer/paths.h"
|
2005-07-28 22:26:22 +02:00
|
|
|
#include "optimizer/predtest.h"
|
1999-02-03 21:15:53 +01:00
|
|
|
#include "optimizer/restrictinfo.h"
|
2003-01-24 04:58:44 +01:00
|
|
|
#include "optimizer/var.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2002-11-24 22:52:15 +01:00
|
|
|
|
2004-01-06 00:39:54 +01:00
|
|
|
static RestrictInfo *make_restrictinfo_internal(Expr *clause,
|
2004-08-29 07:07:03 +02:00
|
|
|
Expr *orclause,
|
|
|
|
bool is_pushed_down,
|
2005-11-15 00:54:23 +01:00
|
|
|
bool outerjoin_delayed,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
bool pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
Relids required_relids,
|
|
|
|
Relids nullable_relids);
|
2004-01-06 00:39:54 +01:00
|
|
|
static Expr *make_sub_restrictinfos(Expr *clause,
|
2005-11-15 00:54:23 +01:00
|
|
|
bool is_pushed_down,
|
2005-11-16 18:08:03 +01:00
|
|
|
bool outerjoin_delayed,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
bool pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
Relids required_relids,
|
|
|
|
Relids nullable_relids);
|
2009-05-10 00:51:41 +02:00
|
|
|
static List *select_nonredundant_join_list(List *restrictinfo_list,
|
|
|
|
List *reference_list);
|
|
|
|
static bool join_clause_is_redundant(RestrictInfo *rinfo,
|
2007-01-20 21:45:41 +01:00
|
|
|
List *reference_list);
|
2003-06-16 00:51:45 +02:00
|
|
|
|
|
|
|
|
2004-01-04 01:07:32 +01:00
|
|
|
/*
|
|
|
|
* make_restrictinfo
|
|
|
|
*
|
|
|
|
* Build a RestrictInfo node containing the given subexpression.
|
|
|
|
*
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
* The is_pushed_down, outerjoin_delayed, and pseudoconstant flags for the
|
2009-04-16 22:42:16 +02:00
|
|
|
* RestrictInfo must be supplied by the caller, as well as the correct value
|
|
|
|
* for nullable_relids. required_relids can be NULL, in which case it
|
|
|
|
* defaults to the actual clause contents (i.e., clause_relids).
|
2004-01-05 06:07:36 +01:00
|
|
|
*
|
|
|
|
* We initialize fields that depend only on the given subexpression, leaving
|
|
|
|
* others that depend on context (or may never be needed at all) to be filled
|
|
|
|
* later.
|
2004-01-04 01:07:32 +01:00
|
|
|
*/
|
|
|
|
RestrictInfo *
|
2005-11-15 00:54:23 +01:00
|
|
|
make_restrictinfo(Expr *clause,
|
|
|
|
bool is_pushed_down,
|
|
|
|
bool outerjoin_delayed,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
bool pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
Relids required_relids,
|
|
|
|
Relids nullable_relids)
|
2004-01-06 00:39:54 +01:00
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If it's an OR clause, build a modified copy with RestrictInfos inserted
|
|
|
|
* above each subclause of the top-level AND/OR structure.
|
2004-01-06 00:39:54 +01:00
|
|
|
*/
|
|
|
|
if (or_clause((Node *) clause))
|
2005-11-15 00:54:23 +01:00
|
|
|
return (RestrictInfo *) make_sub_restrictinfos(clause,
|
|
|
|
is_pushed_down,
|
2005-11-16 18:08:03 +01:00
|
|
|
outerjoin_delayed,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
required_relids,
|
|
|
|
nullable_relids);
|
2004-01-06 00:39:54 +01:00
|
|
|
|
2005-04-22 23:58:32 +02:00
|
|
|
/* Shouldn't be an AND clause, else AND/OR flattening messed up */
|
|
|
|
Assert(!and_clause((Node *) clause));
|
2004-01-06 00:39:54 +01:00
|
|
|
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
return make_restrictinfo_internal(clause,
|
|
|
|
NULL,
|
|
|
|
is_pushed_down,
|
|
|
|
outerjoin_delayed,
|
|
|
|
pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
required_relids,
|
|
|
|
nullable_relids);
|
2004-01-06 00:39:54 +01:00
|
|
|
}
|
|
|
|
|
2005-04-25 04:14:48 +02:00
|
|
|
/*
|
|
|
|
* make_restrictinfo_from_bitmapqual
|
|
|
|
*
|
|
|
|
* Given the bitmapqual Path structure for a bitmap indexscan, generate
|
|
|
|
* RestrictInfo node(s) equivalent to the condition represented by the
|
|
|
|
* indexclauses of the Path structure.
|
|
|
|
*
|
2005-07-28 22:26:22 +02:00
|
|
|
* The result is a List (effectively, implicit-AND representation) of
|
|
|
|
* RestrictInfos.
|
|
|
|
*
|
2005-11-15 00:54:23 +01:00
|
|
|
* The caller must pass is_pushed_down, but we assume outerjoin_delayed
|
2009-04-16 22:42:16 +02:00
|
|
|
* and pseudoconstant are false and nullable_relids is NULL (no other
|
|
|
|
* kind of qual should ever get into a bitmapqual).
|
2005-11-15 00:54:23 +01:00
|
|
|
*
|
2005-07-28 22:26:22 +02:00
|
|
|
* If include_predicates is true, we add any partial index predicates to
|
|
|
|
* the explicit index quals. When this is not true, we return a condition
|
|
|
|
* that might be weaker than the actual scan represents.
|
2005-04-25 04:14:48 +02:00
|
|
|
*
|
|
|
|
* To do this through the normal make_restrictinfo() API, callers would have
|
|
|
|
* to strip off the RestrictInfo nodes present in the indexclauses lists, and
|
|
|
|
* then make_restrictinfo() would have to build new ones. It's better to have
|
|
|
|
* a specialized routine to allow sharing of RestrictInfos.
|
2005-07-28 22:26:22 +02:00
|
|
|
*
|
|
|
|
* The qual manipulations here are much the same as in create_bitmap_subplan;
|
|
|
|
* keep the two routines in sync!
|
2005-04-25 04:14:48 +02:00
|
|
|
*/
|
|
|
|
List *
|
2005-07-28 22:26:22 +02:00
|
|
|
make_restrictinfo_from_bitmapqual(Path *bitmapqual,
|
|
|
|
bool is_pushed_down,
|
|
|
|
bool include_predicates)
|
2005-04-25 04:14:48 +02:00
|
|
|
{
|
|
|
|
List *result;
|
2005-07-28 22:26:22 +02:00
|
|
|
ListCell *l;
|
2005-04-25 04:14:48 +02:00
|
|
|
|
|
|
|
if (IsA(bitmapqual, BitmapAndPath))
|
|
|
|
{
|
|
|
|
BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
|
|
|
|
|
2005-07-28 22:26:22 +02:00
|
|
|
/*
|
|
|
|
* There may well be redundant quals among the subplans, since a
|
|
|
|
* top-level WHERE qual might have gotten used to form several
|
2005-10-15 04:49:52 +02:00
|
|
|
* different index quals. We don't try exceedingly hard to eliminate
|
|
|
|
* redundancies, but we do eliminate obvious duplicates by using
|
|
|
|
* list_concat_unique.
|
2005-07-28 22:26:22 +02:00
|
|
|
*/
|
2005-04-25 04:14:48 +02:00
|
|
|
result = NIL;
|
|
|
|
foreach(l, apath->bitmapquals)
|
|
|
|
{
|
|
|
|
List *sublist;
|
|
|
|
|
|
|
|
sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
|
2005-07-28 22:26:22 +02:00
|
|
|
is_pushed_down,
|
|
|
|
include_predicates);
|
|
|
|
result = list_concat_unique(result, sublist);
|
2005-04-25 04:14:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (IsA(bitmapqual, BitmapOrPath))
|
|
|
|
{
|
|
|
|
BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
|
|
|
|
List *withris = NIL;
|
|
|
|
List *withoutris = NIL;
|
|
|
|
|
2005-07-28 22:26:22 +02:00
|
|
|
/*
|
2005-10-13 02:06:46 +02:00
|
|
|
* Here, we only detect qual-free subplans. A qual-free subplan would
|
|
|
|
* cause us to generate "... OR true ..." which we may as well reduce
|
2005-10-15 04:49:52 +02:00
|
|
|
* to just "true". We do not try to eliminate redundant subclauses
|
2005-10-13 02:06:46 +02:00
|
|
|
* because (a) it's not as likely as in the AND case, and (b) we might
|
|
|
|
* well be working with hundreds or even thousands of OR conditions,
|
|
|
|
* perhaps from a long IN list. The performance of list_append_unique
|
|
|
|
* would be unacceptable.
|
2005-07-28 22:26:22 +02:00
|
|
|
*/
|
2005-04-25 04:14:48 +02:00
|
|
|
foreach(l, opath->bitmapquals)
|
|
|
|
{
|
|
|
|
List *sublist;
|
|
|
|
|
|
|
|
sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
|
2005-07-28 22:26:22 +02:00
|
|
|
is_pushed_down,
|
|
|
|
include_predicates);
|
2005-04-25 04:14:48 +02:00
|
|
|
if (sublist == NIL)
|
|
|
|
{
|
2005-07-28 22:26:22 +02:00
|
|
|
/*
|
|
|
|
* If we find a qual-less subscan, it represents a constant
|
2005-10-15 04:49:52 +02:00
|
|
|
* TRUE, and hence the OR result is also constant TRUE, so we
|
|
|
|
* can stop here.
|
2005-07-28 22:26:22 +02:00
|
|
|
*/
|
2005-04-25 04:14:48 +02:00
|
|
|
return NIL;
|
|
|
|
}
|
2006-10-04 02:30:14 +02:00
|
|
|
|
2006-04-07 19:05:39 +02:00
|
|
|
/*
|
|
|
|
* If the sublist contains multiple RestrictInfos, we create an
|
|
|
|
* AND subclause. If there's just one, we have to check if it's
|
|
|
|
* an OR clause, and if so flatten it to preserve AND/OR flatness
|
|
|
|
* of our output.
|
|
|
|
*
|
2006-10-04 02:30:14 +02:00
|
|
|
* We construct lists with and without sub-RestrictInfos, so as
|
|
|
|
* not to have to regenerate duplicate RestrictInfos below.
|
2006-04-07 19:05:39 +02:00
|
|
|
*/
|
|
|
|
if (list_length(sublist) > 1)
|
|
|
|
{
|
|
|
|
withris = lappend(withris, make_andclause(sublist));
|
|
|
|
sublist = get_actual_clauses(sublist);
|
|
|
|
withoutris = lappend(withoutris, make_andclause(sublist));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
RestrictInfo *subri = (RestrictInfo *) linitial(sublist);
|
2006-04-07 19:05:39 +02:00
|
|
|
|
|
|
|
Assert(IsA(subri, RestrictInfo));
|
|
|
|
if (restriction_is_or_clause(subri))
|
|
|
|
{
|
|
|
|
BoolExpr *subor = (BoolExpr *) subri->orclause;
|
|
|
|
|
|
|
|
Assert(or_clause((Node *) subor));
|
|
|
|
withris = list_concat(withris,
|
|
|
|
list_copy(subor->args));
|
|
|
|
subor = (BoolExpr *) subri->clause;
|
|
|
|
Assert(or_clause((Node *) subor));
|
|
|
|
withoutris = list_concat(withoutris,
|
|
|
|
list_copy(subor->args));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
withris = lappend(withris, subri);
|
|
|
|
withoutris = lappend(withoutris, subri->clause);
|
|
|
|
}
|
|
|
|
}
|
2005-07-28 22:26:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Avoid generating one-element ORs, which could happen due to
|
2005-11-25 20:47:50 +01:00
|
|
|
* redundancy elimination or ScalarArrayOpExpr quals.
|
2005-07-28 22:26:22 +02:00
|
|
|
*/
|
|
|
|
if (list_length(withris) <= 1)
|
|
|
|
result = withris;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Here's the magic part not available to outside callers */
|
|
|
|
result =
|
|
|
|
list_make1(make_restrictinfo_internal(make_orclause(withoutris),
|
|
|
|
make_orclause(withris),
|
|
|
|
is_pushed_down,
|
2005-11-15 00:54:23 +01:00
|
|
|
false,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
false,
|
2009-04-16 22:42:16 +02:00
|
|
|
NULL,
|
2005-07-28 22:26:22 +02:00
|
|
|
NULL));
|
2005-04-25 04:14:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (IsA(bitmapqual, IndexPath))
|
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
IndexPath *ipath = (IndexPath *) bitmapqual;
|
2005-04-25 04:14:48 +02:00
|
|
|
|
|
|
|
result = list_copy(ipath->indexclauses);
|
2005-07-28 22:26:22 +02:00
|
|
|
if (include_predicates && ipath->indexinfo->indpred != NIL)
|
|
|
|
{
|
|
|
|
foreach(l, ipath->indexinfo->indpred)
|
|
|
|
{
|
2005-10-15 04:49:52 +02:00
|
|
|
Expr *pred = (Expr *) lfirst(l);
|
2005-07-28 22:26:22 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* We know that the index predicate must have been implied by
|
|
|
|
* the query condition as a whole, but it may or may not be
|
|
|
|
* implied by the conditions that got pushed into the
|
|
|
|
* bitmapqual. Avoid generating redundant conditions.
|
2005-07-28 22:26:22 +02:00
|
|
|
*/
|
|
|
|
if (!predicate_implied_by(list_make1(pred), result))
|
|
|
|
result = lappend(result,
|
|
|
|
make_restrictinfo(pred,
|
|
|
|
is_pushed_down,
|
2005-11-15 00:54:23 +01:00
|
|
|
false,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
false,
|
2009-04-16 22:42:16 +02:00
|
|
|
NULL,
|
2005-07-28 22:26:22 +02:00
|
|
|
NULL));
|
|
|
|
}
|
|
|
|
}
|
2005-04-25 04:14:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
|
|
|
|
result = NIL; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2009-07-06 20:26:30 +02:00
|
|
|
/*
|
|
|
|
* make_restrictinfos_from_actual_clauses
|
|
|
|
*
|
|
|
|
* Given a list of implicitly-ANDed restriction clauses, produce a list
|
|
|
|
* of RestrictInfo nodes. This is used to reconstitute the RestrictInfo
|
|
|
|
* representation after doing transformations of a list of clauses.
|
|
|
|
*
|
|
|
|
* We assume that the clauses are relation-level restrictions and therefore
|
|
|
|
* we don't have to worry about is_pushed_down, outerjoin_delayed, or
|
|
|
|
* nullable_relids (these can be assumed true, false, and NULL, respectively).
|
|
|
|
* We do take care to recognize pseudoconstant clauses properly.
|
|
|
|
*/
|
|
|
|
List *
|
|
|
|
make_restrictinfos_from_actual_clauses(PlannerInfo *root,
|
|
|
|
List *clause_list)
|
|
|
|
{
|
|
|
|
List *result = NIL;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
foreach(l, clause_list)
|
|
|
|
{
|
2010-02-26 03:01:40 +01:00
|
|
|
Expr *clause = (Expr *) lfirst(l);
|
|
|
|
bool pseudoconstant;
|
2009-07-06 20:26:30 +02:00
|
|
|
RestrictInfo *rinfo;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* It's pseudoconstant if it contains no Vars and no volatile
|
|
|
|
* functions. We probably can't see any sublinks here, so
|
2010-02-26 03:01:40 +01:00
|
|
|
* contain_var_clause() would likely be enough, but for safety use
|
|
|
|
* contain_vars_of_level() instead.
|
2009-07-06 20:26:30 +02:00
|
|
|
*/
|
|
|
|
pseudoconstant =
|
|
|
|
!contain_vars_of_level((Node *) clause, 0) &&
|
|
|
|
!contain_volatile_functions((Node *) clause);
|
|
|
|
if (pseudoconstant)
|
|
|
|
{
|
|
|
|
/* tell createplan.c to check for gating quals */
|
|
|
|
root->hasPseudoConstantQuals = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
rinfo = make_restrictinfo(clause,
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
pseudoconstant,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
result = lappend(result, rinfo);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-01-06 00:39:54 +01:00
|
|
|
/*
|
|
|
|
* make_restrictinfo_internal
|
|
|
|
*
|
2005-04-25 04:14:48 +02:00
|
|
|
* Common code for the main entry points and the recursive cases.
|
2004-01-06 00:39:54 +01:00
|
|
|
*/
|
|
|
|
static RestrictInfo *
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
make_restrictinfo_internal(Expr *clause,
|
|
|
|
Expr *orclause,
|
|
|
|
bool is_pushed_down,
|
|
|
|
bool outerjoin_delayed,
|
|
|
|
bool pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
Relids required_relids,
|
|
|
|
Relids nullable_relids)
|
2004-01-04 01:07:32 +01:00
|
|
|
{
|
|
|
|
RestrictInfo *restrictinfo = makeNode(RestrictInfo);
|
|
|
|
|
|
|
|
restrictinfo->clause = clause;
|
2004-01-06 00:39:54 +01:00
|
|
|
restrictinfo->orclause = orclause;
|
2004-01-05 06:07:36 +01:00
|
|
|
restrictinfo->is_pushed_down = is_pushed_down;
|
2005-11-15 00:54:23 +01:00
|
|
|
restrictinfo->outerjoin_delayed = outerjoin_delayed;
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
restrictinfo->pseudoconstant = pseudoconstant;
|
2004-01-05 06:07:36 +01:00
|
|
|
restrictinfo->can_join = false; /* may get set below */
|
2009-04-16 22:42:16 +02:00
|
|
|
restrictinfo->nullable_relids = nullable_relids;
|
2004-01-04 01:07:32 +01:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If it's a binary opclause, set up left/right relids info. In any case
|
|
|
|
* set up the total clause relids info.
|
2004-01-04 01:07:32 +01:00
|
|
|
*/
|
2004-05-31 01:40:41 +02:00
|
|
|
if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
|
2004-01-04 01:07:32 +01:00
|
|
|
{
|
|
|
|
restrictinfo->left_relids = pull_varnos(get_leftop(clause));
|
|
|
|
restrictinfo->right_relids = pull_varnos(get_rightop(clause));
|
|
|
|
|
2004-01-04 04:51:52 +01:00
|
|
|
restrictinfo->clause_relids = bms_union(restrictinfo->left_relids,
|
2005-10-15 04:49:52 +02:00
|
|
|
restrictinfo->right_relids);
|
2004-01-04 04:51:52 +01:00
|
|
|
|
2004-01-04 01:07:32 +01:00
|
|
|
/*
|
|
|
|
* Does it look like a normal join clause, i.e., a binary operator
|
2005-10-15 04:49:52 +02:00
|
|
|
* relating expressions that come from distinct relations? If so we
|
|
|
|
* might be able to use it in a join algorithm. Note that this is a
|
|
|
|
* purely syntactic test that is made regardless of context.
|
2004-01-04 01:07:32 +01:00
|
|
|
*/
|
|
|
|
if (!bms_is_empty(restrictinfo->left_relids) &&
|
|
|
|
!bms_is_empty(restrictinfo->right_relids) &&
|
|
|
|
!bms_overlap(restrictinfo->left_relids,
|
|
|
|
restrictinfo->right_relids))
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
{
|
2004-01-05 06:07:36 +01:00
|
|
|
restrictinfo->can_join = true;
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
/* pseudoconstant should certainly not be true */
|
|
|
|
Assert(!restrictinfo->pseudoconstant);
|
|
|
|
}
|
2004-01-04 01:07:32 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-01-04 04:51:52 +01:00
|
|
|
/* Not a binary opclause, so mark left/right relid sets as empty */
|
2004-01-04 01:07:32 +01:00
|
|
|
restrictinfo->left_relids = NULL;
|
|
|
|
restrictinfo->right_relids = NULL;
|
2004-01-04 04:51:52 +01:00
|
|
|
/* and get the total relid set the hard way */
|
|
|
|
restrictinfo->clause_relids = pull_varnos((Node *) clause);
|
2004-01-04 01:07:32 +01:00
|
|
|
}
|
|
|
|
|
2005-06-09 06:19:00 +02:00
|
|
|
/* required_relids defaults to clause_relids */
|
|
|
|
if (required_relids != NULL)
|
|
|
|
restrictinfo->required_relids = required_relids;
|
|
|
|
else
|
|
|
|
restrictinfo->required_relids = restrictinfo->clause_relids;
|
|
|
|
|
2004-01-04 01:07:32 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Fill in all the cacheable fields with "not yet set" markers. None of
|
|
|
|
* these will be computed until/unless needed. Note in particular that we
|
|
|
|
* don't mark a binary opclause as mergejoinable or hashjoinable here;
|
|
|
|
* that happens only if it appears in the right context (top level of a
|
|
|
|
* joinclause list).
|
2004-01-04 01:07:32 +01:00
|
|
|
*/
|
2007-01-20 21:45:41 +01:00
|
|
|
restrictinfo->parent_ec = NULL;
|
|
|
|
|
2004-01-04 01:07:32 +01:00
|
|
|
restrictinfo->eval_cost.startup = -1;
|
2009-02-07 00:43:24 +01:00
|
|
|
restrictinfo->norm_selec = -1;
|
|
|
|
restrictinfo->outer_selec = -1;
|
2004-01-04 01:07:32 +01:00
|
|
|
|
2007-01-20 21:45:41 +01:00
|
|
|
restrictinfo->mergeopfamilies = NIL;
|
2004-01-04 01:07:32 +01:00
|
|
|
|
2007-01-20 21:45:41 +01:00
|
|
|
restrictinfo->left_ec = NULL;
|
|
|
|
restrictinfo->right_ec = NULL;
|
2007-01-22 21:00:40 +01:00
|
|
|
restrictinfo->left_em = NULL;
|
|
|
|
restrictinfo->right_em = NULL;
|
|
|
|
restrictinfo->scansel_cache = NIL;
|
2004-01-04 01:07:32 +01:00
|
|
|
|
2007-01-20 21:45:41 +01:00
|
|
|
restrictinfo->outer_is_left = false;
|
2004-01-04 01:07:32 +01:00
|
|
|
|
|
|
|
restrictinfo->hashjoinoperator = InvalidOid;
|
|
|
|
|
|
|
|
restrictinfo->left_bucketsize = -1;
|
|
|
|
restrictinfo->right_bucketsize = -1;
|
|
|
|
|
|
|
|
return restrictinfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Recursively insert sub-RestrictInfo nodes into a boolean expression.
|
2005-04-22 23:58:32 +02:00
|
|
|
*
|
|
|
|
* We put RestrictInfos above simple (non-AND/OR) clauses and above
|
|
|
|
* sub-OR clauses, but not above sub-AND clauses, because there's no need.
|
|
|
|
* This may seem odd but it is closely related to the fact that we use
|
|
|
|
* implicit-AND lists at top level of RestrictInfo lists. Only ORs and
|
|
|
|
* simple clauses are valid RestrictInfos.
|
2005-11-16 18:08:03 +01:00
|
|
|
*
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
* The same is_pushed_down, outerjoin_delayed, and pseudoconstant flag
|
2009-04-16 22:42:16 +02:00
|
|
|
* values can be applied to all RestrictInfo nodes in the result. Likewise
|
|
|
|
* for nullable_relids.
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
*
|
2005-11-16 18:08:03 +01:00
|
|
|
* The given required_relids are attached to our top-level output,
|
|
|
|
* but any OR-clause constituents are allowed to default to just the
|
|
|
|
* contained rels.
|
2004-01-04 01:07:32 +01:00
|
|
|
*/
|
|
|
|
static Expr *
|
2005-11-15 00:54:23 +01:00
|
|
|
make_sub_restrictinfos(Expr *clause,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
bool is_pushed_down,
|
|
|
|
bool outerjoin_delayed,
|
|
|
|
bool pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
Relids required_relids,
|
|
|
|
Relids nullable_relids)
|
2004-01-04 01:07:32 +01:00
|
|
|
{
|
|
|
|
if (or_clause((Node *) clause))
|
|
|
|
{
|
|
|
|
List *orlist = NIL;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *temp;
|
2004-01-04 01:07:32 +01:00
|
|
|
|
|
|
|
foreach(temp, ((BoolExpr *) clause)->args)
|
|
|
|
orlist = lappend(orlist,
|
|
|
|
make_sub_restrictinfos(lfirst(temp),
|
2005-11-15 00:54:23 +01:00
|
|
|
is_pushed_down,
|
2005-11-16 18:08:03 +01:00
|
|
|
outerjoin_delayed,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
NULL,
|
|
|
|
nullable_relids));
|
2005-04-22 23:58:32 +02:00
|
|
|
return (Expr *) make_restrictinfo_internal(clause,
|
|
|
|
make_orclause(orlist),
|
|
|
|
is_pushed_down,
|
2005-11-15 00:54:23 +01:00
|
|
|
outerjoin_delayed,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
required_relids,
|
|
|
|
nullable_relids);
|
2004-01-04 01:07:32 +01:00
|
|
|
}
|
|
|
|
else if (and_clause((Node *) clause))
|
|
|
|
{
|
|
|
|
List *andlist = NIL;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *temp;
|
2004-01-04 01:07:32 +01:00
|
|
|
|
|
|
|
foreach(temp, ((BoolExpr *) clause)->args)
|
|
|
|
andlist = lappend(andlist,
|
|
|
|
make_sub_restrictinfos(lfirst(temp),
|
2005-11-15 00:54:23 +01:00
|
|
|
is_pushed_down,
|
2005-11-16 18:08:03 +01:00
|
|
|
outerjoin_delayed,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
required_relids,
|
|
|
|
nullable_relids));
|
2004-01-04 01:07:32 +01:00
|
|
|
return make_andclause(andlist);
|
|
|
|
}
|
|
|
|
else
|
2004-01-06 00:39:54 +01:00
|
|
|
return (Expr *) make_restrictinfo_internal(clause,
|
|
|
|
NULL,
|
|
|
|
is_pushed_down,
|
2005-11-15 00:54:23 +01:00
|
|
|
outerjoin_delayed,
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
pseudoconstant,
|
2009-04-16 22:42:16 +02:00
|
|
|
required_relids,
|
|
|
|
nullable_relids);
|
2004-01-04 01:07:32 +01:00
|
|
|
}
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-07-25 01:21:14 +02:00
|
|
|
* restriction_is_or_clause
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1999-07-25 01:21:14 +02:00
|
|
|
* Returns t iff the restrictinfo node contains an 'or' clause.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
bool
|
1999-07-25 01:21:14 +02:00
|
|
|
restriction_is_or_clause(RestrictInfo *restrictinfo)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2004-01-04 01:07:32 +01:00
|
|
|
if (restrictinfo->orclause != NULL)
|
1998-09-01 05:29:17 +02:00
|
|
|
return true;
|
1997-09-07 07:04:48 +02:00
|
|
|
else
|
1998-09-01 05:29:17 +02:00
|
|
|
return false;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-02-14 00:22:53 +01:00
|
|
|
* get_actual_clauses
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
2002-11-24 22:52:15 +01:00
|
|
|
* Returns a list containing the bare clauses from 'restrictinfo_list'.
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
*
|
|
|
|
* This is only to be used in cases where none of the RestrictInfos can
|
|
|
|
* be pseudoconstant clauses (for instance, it's OK on indexqual lists).
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1998-02-26 05:46:47 +01:00
|
|
|
List *
|
1999-02-03 21:15:53 +01:00
|
|
|
get_actual_clauses(List *restrictinfo_list)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
List *result = NIL;
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
ListCell *l;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
foreach(l, restrictinfo_list)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
|
2004-01-06 00:39:54 +01:00
|
|
|
|
|
|
|
Assert(IsA(rinfo, RestrictInfo));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
Assert(!rinfo->pseudoconstant);
|
|
|
|
|
2004-01-06 00:39:54 +01:00
|
|
|
result = lappend(result, rinfo->clause);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return result;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2000-09-12 23:07:18 +02:00
|
|
|
|
2009-07-06 20:26:30 +02:00
|
|
|
/*
|
|
|
|
* get_all_actual_clauses
|
|
|
|
*
|
|
|
|
* Returns a list containing the bare clauses from 'restrictinfo_list'.
|
|
|
|
*
|
|
|
|
* This loses the distinction between regular and pseudoconstant clauses,
|
|
|
|
* so be careful what you use it for.
|
|
|
|
*/
|
|
|
|
List *
|
|
|
|
get_all_actual_clauses(List *restrictinfo_list)
|
|
|
|
{
|
|
|
|
List *result = NIL;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
foreach(l, restrictinfo_list)
|
|
|
|
{
|
|
|
|
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
|
|
|
|
|
|
|
|
Assert(IsA(rinfo, RestrictInfo));
|
|
|
|
|
|
|
|
result = lappend(result, rinfo->clause);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2000-09-12 23:07:18 +02:00
|
|
|
/*
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
* extract_actual_clauses
|
2000-09-12 23:07:18 +02:00
|
|
|
*
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
* Extract bare clauses from 'restrictinfo_list', returning either the
|
|
|
|
* regular ones or the pseudoconstant ones per 'pseudoconstant'.
|
|
|
|
*/
|
|
|
|
List *
|
|
|
|
extract_actual_clauses(List *restrictinfo_list,
|
|
|
|
bool pseudoconstant)
|
|
|
|
{
|
|
|
|
List *result = NIL;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
foreach(l, restrictinfo_list)
|
|
|
|
{
|
|
|
|
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
|
|
|
|
|
|
|
|
Assert(IsA(rinfo, RestrictInfo));
|
|
|
|
|
|
|
|
if (rinfo->pseudoconstant == pseudoconstant)
|
|
|
|
result = lappend(result, rinfo->clause);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* extract_actual_join_clauses
|
|
|
|
*
|
|
|
|
* Extract bare clauses from 'restrictinfo_list', separating those that
|
2000-09-29 20:21:41 +02:00
|
|
|
* syntactically match the join level from those that were pushed down.
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
* Pseudoconstant clauses are excluded from the results.
|
|
|
|
*
|
|
|
|
* This is only used at outer joins, since for plain joins we don't care
|
|
|
|
* about pushed-down-ness.
|
2000-09-12 23:07:18 +02:00
|
|
|
*/
|
|
|
|
void
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
extract_actual_join_clauses(List *restrictinfo_list,
|
|
|
|
List **joinquals,
|
|
|
|
List **otherquals)
|
2000-09-12 23:07:18 +02:00
|
|
|
{
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
ListCell *l;
|
2000-09-12 23:07:18 +02:00
|
|
|
|
|
|
|
*joinquals = NIL;
|
|
|
|
*otherquals = NIL;
|
|
|
|
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
foreach(l, restrictinfo_list)
|
2000-09-12 23:07:18 +02:00
|
|
|
{
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
|
|
|
|
|
|
|
|
Assert(IsA(rinfo, RestrictInfo));
|
2000-09-12 23:07:18 +02:00
|
|
|
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
if (rinfo->is_pushed_down)
|
|
|
|
{
|
|
|
|
if (!rinfo->pseudoconstant)
|
|
|
|
*otherquals = lappend(*otherquals, rinfo->clause);
|
|
|
|
}
|
2000-09-29 20:21:41 +02:00
|
|
|
else
|
Revise the planner's handling of "pseudoconstant" WHERE clauses, that is
clauses containing no variables and no volatile functions. Such a clause
can be used as a one-time qual in a gating Result plan node, to suppress
plan execution entirely when it is false. Even when the clause is true,
putting it in a gating node wins by avoiding repeated evaluation of the
clause. In previous PG releases, query_planner() would do this for
pseudoconstant clauses appearing at the top level of the jointree, but
there was no ability to generate a gating Result deeper in the plan tree.
To fix it, get rid of the special case in query_planner(), and instead
process pseudoconstant clauses through the normal RestrictInfo qual
distribution mechanism. When a pseudoconstant clause is found attached to
a path node in create_plan(), pull it out and generate a gating Result at
that point. This requires special-casing pseudoconstants in selectivity
estimation and cost_qual_eval, but on the whole it's pretty clean.
It probably even makes the planner a bit faster than before for the normal
case of no pseudoconstants, since removing pull_constant_clauses saves one
useless traversal of the qual tree. Per gripe from Phil Frost.
2006-07-01 20:38:33 +02:00
|
|
|
{
|
|
|
|
/* joinquals shouldn't have been marked pseudoconstant */
|
|
|
|
Assert(!rinfo->pseudoconstant);
|
|
|
|
*joinquals = lappend(*joinquals, rinfo->clause);
|
|
|
|
}
|
2000-09-12 23:07:18 +02:00
|
|
|
}
|
|
|
|
}
|
2002-11-24 22:52:15 +01:00
|
|
|
|
2009-05-10 00:51:41 +02:00
|
|
|
|
2003-06-16 00:51:45 +02:00
|
|
|
/*
|
|
|
|
* select_nonredundant_join_clauses
|
|
|
|
*
|
|
|
|
* Given a list of RestrictInfo clauses that are to be applied in a join,
|
2009-05-10 00:51:41 +02:00
|
|
|
* select the ones that are not redundant with any clause that's enforced
|
|
|
|
* by the inner_path. This is used for nestloop joins, wherein any clause
|
|
|
|
* being used in an inner indexscan need not be checked again at the join.
|
2003-06-16 00:51:45 +02:00
|
|
|
*
|
2007-01-20 21:45:41 +01:00
|
|
|
* "Redundant" means either equal() or derived from the same EquivalenceClass.
|
|
|
|
* We have to check the latter because indxqual.c may select different derived
|
|
|
|
* clauses than were selected by generate_join_implied_equalities().
|
2003-06-16 00:51:45 +02:00
|
|
|
*
|
2009-05-10 00:51:41 +02:00
|
|
|
* Note that we are *not* checking for local redundancies within the given
|
|
|
|
* restrictinfo_list; that should have been handled elsewhere.
|
2003-06-16 00:51:45 +02:00
|
|
|
*/
|
|
|
|
List *
|
2005-06-06 00:32:58 +02:00
|
|
|
select_nonredundant_join_clauses(PlannerInfo *root,
|
2003-06-16 00:51:45 +02:00
|
|
|
List *restrictinfo_list,
|
2009-05-10 00:51:41 +02:00
|
|
|
Path *inner_path)
|
|
|
|
{
|
|
|
|
if (IsA(inner_path, IndexPath))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Check the index quals to see if any of them are join clauses.
|
|
|
|
*
|
|
|
|
* We can skip this if the index path is an ordinary indexpath and not
|
|
|
|
* a special innerjoin path, since it then wouldn't be using any join
|
|
|
|
* clauses.
|
|
|
|
*/
|
|
|
|
IndexPath *innerpath = (IndexPath *) inner_path;
|
|
|
|
|
|
|
|
if (innerpath->isjoininner)
|
|
|
|
restrictinfo_list =
|
|
|
|
select_nonredundant_join_list(restrictinfo_list,
|
|
|
|
innerpath->indexclauses);
|
|
|
|
}
|
|
|
|
else if (IsA(inner_path, BitmapHeapPath))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Same deal for bitmapped index scans.
|
|
|
|
*
|
|
|
|
* Note: both here and above, we ignore any implicit index
|
|
|
|
* restrictions associated with the use of partial indexes. This is
|
|
|
|
* OK because we're only trying to prove we can dispense with some
|
|
|
|
* join quals; failing to prove that doesn't result in an incorrect
|
|
|
|
* plan. It's quite unlikely that a join qual could be proven
|
2009-06-11 16:49:15 +02:00
|
|
|
* redundant by an index predicate anyway. (Also, if we did manage to
|
|
|
|
* prove it, we'd have to have a special case for update targets; see
|
|
|
|
* notes about EvalPlanQual testing in create_indexscan_plan().)
|
2009-05-10 00:51:41 +02:00
|
|
|
*/
|
|
|
|
BitmapHeapPath *innerpath = (BitmapHeapPath *) inner_path;
|
|
|
|
|
|
|
|
if (innerpath->isjoininner)
|
|
|
|
{
|
|
|
|
List *bitmapclauses;
|
|
|
|
|
|
|
|
bitmapclauses =
|
|
|
|
make_restrictinfo_from_bitmapqual(innerpath->bitmapqual,
|
|
|
|
true,
|
|
|
|
false);
|
|
|
|
restrictinfo_list =
|
|
|
|
select_nonredundant_join_list(restrictinfo_list,
|
|
|
|
bitmapclauses);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* XXX the inner path of a nestloop could also be an append relation whose
|
|
|
|
* elements use join quals. However, they might each use different quals;
|
|
|
|
* we could only remove join quals that are enforced by all the appendrel
|
|
|
|
* members. For the moment we don't bother to try.
|
2009-05-10 00:51:41 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
return restrictinfo_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* select_nonredundant_join_list
|
|
|
|
* Select the members of restrictinfo_list that are not redundant with
|
|
|
|
* any member of reference_list. See above for more info.
|
|
|
|
*/
|
|
|
|
static List *
|
|
|
|
select_nonredundant_join_list(List *restrictinfo_list,
|
|
|
|
List *reference_list)
|
2003-06-16 00:51:45 +02:00
|
|
|
{
|
|
|
|
List *result = NIL;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *item;
|
2003-06-16 00:51:45 +02:00
|
|
|
|
|
|
|
foreach(item, restrictinfo_list)
|
|
|
|
{
|
|
|
|
RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
|
|
|
|
|
|
|
|
/* drop it if redundant with any reference clause */
|
2009-05-10 00:51:41 +02:00
|
|
|
if (join_clause_is_redundant(rinfo, reference_list))
|
2003-06-16 00:51:45 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* otherwise, add it to result list */
|
|
|
|
result = lappend(result, rinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* join_clause_is_redundant
|
2007-01-20 21:45:41 +01:00
|
|
|
* Test whether rinfo is redundant with any clause in reference_list.
|
2002-11-24 22:52:15 +01:00
|
|
|
*/
|
2007-01-20 21:45:41 +01:00
|
|
|
static bool
|
2009-05-10 00:51:41 +02:00
|
|
|
join_clause_is_redundant(RestrictInfo *rinfo,
|
2007-01-20 21:45:41 +01:00
|
|
|
List *reference_list)
|
2002-11-24 22:52:15 +01:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *refitem;
|
2004-02-27 22:48:04 +01:00
|
|
|
|
|
|
|
foreach(refitem, reference_list)
|
|
|
|
{
|
|
|
|
RestrictInfo *refrinfo = (RestrictInfo *) lfirst(refitem);
|
|
|
|
|
2007-01-20 21:45:41 +01:00
|
|
|
/* always consider exact duplicates redundant */
|
2004-02-27 22:48:04 +01:00
|
|
|
if (equal(rinfo, refrinfo))
|
2007-01-20 21:45:41 +01:00
|
|
|
return true;
|
2002-11-24 22:52:15 +01:00
|
|
|
|
2007-01-20 21:45:41 +01:00
|
|
|
/* check if derived from same EquivalenceClass */
|
|
|
|
if (rinfo->parent_ec != NULL &&
|
|
|
|
rinfo->parent_ec == refrinfo->parent_ec)
|
|
|
|
return true;
|
2002-11-24 22:52:15 +01:00
|
|
|
}
|
|
|
|
|
2007-01-20 21:45:41 +01:00
|
|
|
return false;
|
2002-11-24 22:52:15 +01:00
|
|
|
}
|