Commit cc5e80b8 authored by Tom Lane's avatar Tom Lane

Teach planner about some cases where a restriction clause can be

propagated inside an outer join.  In particular, given
LEFT JOIN ON (A = B) WHERE A = constant, we cannot conclude that
B = constant at the top level (B might be null instead), but we
can nonetheless put a restriction B = constant into the quals for
B's relation, since no inner-side rows not meeting that condition
can contribute to the final result.  Similarly, given
FULL JOIN USING (J) WHERE J = constant, we can't directly conclude
that either input J variable = constant, but it's OK to push such
quals into each input rel.  Per recent gripe from Kim Bisgaard.
Along the way, remove 'valid_everywhere' flag from RestrictInfo,
as on closer analysis it was not being used for anything, and was
defined backwards anyway.
parent ea1e2b94
......@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.310 2005/06/28 05:08:56 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.311 2005/07/02 23:00:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1249,7 +1249,6 @@ _copyRestrictInfo(RestrictInfo *from)
COPY_NODE_FIELD(clause);
COPY_SCALAR_FIELD(is_pushed_down);
COPY_SCALAR_FIELD(valid_everywhere);
COPY_SCALAR_FIELD(can_join);
COPY_BITMAPSET_FIELD(clause_relids);
COPY_BITMAPSET_FIELD(required_relids);
......
......@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.247 2005/06/28 05:08:57 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.248 2005/07/02 23:00:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -603,7 +603,6 @@ _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
{
COMPARE_NODE_FIELD(clause);
COMPARE_SCALAR_FIELD(is_pushed_down);
COMPARE_SCALAR_FIELD(valid_everywhere);
COMPARE_BITMAPSET_FIELD(required_relids);
/*
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.257 2005/06/28 05:08:57 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.258 2005/07/02 23:00:39 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
......@@ -1164,9 +1164,13 @@ _outPlannerInfo(StringInfo str, PlannerInfo *node)
WRITE_NODE_FIELD(parse);
WRITE_NODE_FIELD(join_rel_list);
WRITE_NODE_FIELD(equi_key_list);
WRITE_NODE_FIELD(left_join_clauses);
WRITE_NODE_FIELD(right_join_clauses);
WRITE_NODE_FIELD(full_join_clauses);
WRITE_NODE_FIELD(in_info_list);
WRITE_NODE_FIELD(query_pathkeys);
WRITE_BOOL_FIELD(hasJoinRTEs);
WRITE_BOOL_FIELD(hasOuterJoins);
WRITE_BOOL_FIELD(hasHavingQual);
}
......@@ -1234,7 +1238,6 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node)
/* NB: this isn't a complete set of fields */
WRITE_NODE_FIELD(clause);
WRITE_BOOL_FIELD(is_pushed_down);
WRITE_BOOL_FIELD(valid_everywhere);
WRITE_BOOL_FIELD(can_join);
WRITE_BITMAPSET_FIELD(clause_relids);
WRITE_BITMAPSET_FIELD(required_relids);
......
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.185 2005/06/14 04:04:30 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.186 2005/07/02 23:00:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1882,7 +1882,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
{
resultquals = lappend(resultquals,
make_restrictinfo(boolqual,
true, true,
true,
NULL));
continue;
}
......@@ -2132,7 +2132,7 @@ prefix_quals(Node *leftop, Oid opclass,
elog(ERROR, "no = operator for opclass %u", opclass);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) prefix_const);
result = list_make1(make_restrictinfo(expr, true, true, NULL));
result = list_make1(make_restrictinfo(expr, true, NULL));
return result;
}
......@@ -2147,7 +2147,7 @@ prefix_quals(Node *leftop, Oid opclass,
elog(ERROR, "no >= operator for opclass %u", opclass);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) prefix_const);
result = list_make1(make_restrictinfo(expr, true, true, NULL));
result = list_make1(make_restrictinfo(expr, true, NULL));
/*-------
* If we can create a string larger than the prefix, we can say
......@@ -2163,7 +2163,7 @@ prefix_quals(Node *leftop, Oid opclass,
elog(ERROR, "no < operator for opclass %u", opclass);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) greaterstr);
result = lappend(result, make_restrictinfo(expr, true, true, NULL));
result = lappend(result, make_restrictinfo(expr, true, NULL));
}
return result;
......@@ -2234,7 +2234,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
(Expr *) leftop,
(Expr *) makeConst(datatype, -1, opr1right,
false, false));
result = list_make1(make_restrictinfo(expr, true, true, NULL));
result = list_make1(make_restrictinfo(expr, true, NULL));
/* create clause "key <= network_scan_last( rightop )" */
......@@ -2249,7 +2249,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
(Expr *) leftop,
(Expr *) makeConst(datatype, -1, opr2right,
false, false));
result = lappend(result, make_restrictinfo(expr, true, true, NULL));
result = lappend(result, make_restrictinfo(expr, true, NULL));
return result;
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.72 2005/06/09 04:18:59 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.73 2005/07/02 23:00:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -90,16 +90,13 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel)
ListCell *i;
/*
* Find potentially interesting OR joinclauses. We must ignore any
* joinclauses that are not marked valid_everywhere, because they
* cannot be pushed down due to outer-join rules.
* Find potentially interesting OR joinclauses.
*/
foreach(i, rel->joininfo)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(i);
if (restriction_is_or_clause(rinfo) &&
rinfo->valid_everywhere)
if (restriction_is_or_clause(rinfo))
{
/*
* Use the generate_bitmap_or_paths() machinery to estimate
......@@ -140,8 +137,7 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel)
* Convert the path's indexclauses structure to a RestrictInfo tree,
* and add it to the rel's restriction list.
*/
newrinfos = make_restrictinfo_from_bitmapqual((Path *) bestpath,
true, true);
newrinfos = make_restrictinfo_from_bitmapqual((Path *) bestpath, true);
Assert(list_length(newrinfos) == 1);
or_rinfo = (RestrictInfo *) linitial(newrinfos);
Assert(IsA(or_rinfo, RestrictInfo));
......
This diff is collapsed.
......@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.192 2005/06/10 22:25:36 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.193 2005/07/02 23:00:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1176,8 +1176,7 @@ create_nestloop_plan(PlannerInfo *root,
List *bitmapclauses;
bitmapclauses =
make_restrictinfo_from_bitmapqual(innerpath->bitmapqual,
true, true);
make_restrictinfo_from_bitmapqual(innerpath->bitmapqual, true);
joinrestrictclauses =
select_nonredundant_join_clauses(root,
joinrestrictclauses,
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.107 2005/06/09 04:18:59 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.108 2005/07/02 23:00:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -374,8 +374,8 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
Relids qualscope)
{
Relids relids;
bool valid_everywhere;
bool can_be_equijoin;
bool maybe_equijoin;
bool maybe_outer_join;
RestrictInfo *restrictinfo;
RelOptInfo *rel;
List *vars;
......@@ -409,14 +409,15 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
if (isdeduced)
{
/*
* If the qual came from implied-equality deduction, we can
* evaluate the qual at its natural semantic level. It is not
* affected by any outer-join rules (else we'd not have decided
* the vars were equal).
* If the qual came from implied-equality deduction, we always
* evaluate the qual at its natural semantic level. It is the
* responsibility of the deducer not to create any quals that
* should be delayed by outer-join rules.
*/
Assert(bms_equal(relids, qualscope));
valid_everywhere = true;
can_be_equijoin = true;
/* Needn't feed it back for more deductions */
maybe_equijoin = false;
maybe_outer_join = false;
}
else if (bms_overlap(relids, outerjoin_nonnullable))
{
......@@ -434,8 +435,14 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
* result, so we treat it the same as an ordinary inner-join qual.
*/
relids = qualscope;
valid_everywhere = false;
can_be_equijoin = false;
/*
* We can't use such a clause to deduce equijoin (the left and
* right sides might be unequal above the join because one of
* them has gone to NULL) ... but we might be able to use it
* for more limited purposes.
*/
maybe_equijoin = false;
maybe_outer_join = true;
}
else
{
......@@ -449,34 +456,25 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
* time we are called, the outerjoinset of each baserel will show
* exactly those outer joins that are below the qual in the join
* tree.
*
* We also need to determine whether the qual is "valid everywhere",
* which is true if the qual mentions no variables that are
* involved in lower-level outer joins (this may be an overly
* strong test).
*/
Relids addrelids = NULL;
Relids tmprelids;
int relno;
valid_everywhere = true;
tmprelids = bms_copy(relids);
while ((relno = bms_first_member(tmprelids)) >= 0)
{
RelOptInfo *rel = find_base_rel(root, relno);
if (rel->outerjoinset != NULL)
{
addrelids = bms_add_members(addrelids, rel->outerjoinset);
valid_everywhere = false;
}
}
bms_free(tmprelids);
if (bms_is_subset(addrelids, relids))
{
/* Qual is not affected by any outer-join restriction */
can_be_equijoin = true;
maybe_equijoin = true;
}
else
{
......@@ -488,9 +486,10 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
* Because application of the qual will be delayed by outer
* join, we mustn't assume its vars are equal everywhere.
*/
can_be_equijoin = false;
maybe_equijoin = false;
}
bms_free(addrelids);
maybe_outer_join = false;
}
/*
......@@ -508,7 +507,6 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
*/
restrictinfo = make_restrictinfo((Expr *) clause,
is_pushed_down,
valid_everywhere,
relids);
/*
......@@ -533,8 +531,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
* allows us to consider z and q equal after their rels are
* joined.
*/
if (can_be_equijoin)
check_mergejoinable(restrictinfo);
check_mergejoinable(restrictinfo);
/*
* If the clause was deduced from implied equality, check to
......@@ -601,18 +598,60 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
}
/*
* If the clause has a mergejoinable operator, and is not an
* outer-join qualification nor bubbled up due to an outer join, then
* the two sides represent equivalent PathKeyItems for path keys: any
* path that is sorted by one side will also be sorted by the other
* (as soon as the two rels are joined, that is). Record the key
* equivalence for future use. (We can skip this for a deduced
* clause, since the keys are already known equivalent in that case.)
* If the clause has a mergejoinable operator, we may be able to
* deduce more things from it under the principle of transitivity.
*
* If it is not an outer-join qualification nor bubbled up due to an outer
* join, then the two sides represent equivalent PathKeyItems for path
* keys: any path that is sorted by one side will also be sorted by the
* other (as soon as the two rels are joined, that is). Pass such clauses
* to add_equijoined_keys.
*
* If it is a left or right outer-join qualification that relates the two
* sides of the outer join (no funny business like leftvar1 = leftvar2 +
* rightvar), we add it to root->left_join_clauses or
* root->right_join_clauses according to which side the nonnullable
* variable appears on.
*
* If it is a full outer-join qualification, we add it to
* root->full_join_clauses. (Ideally we'd discard cases that aren't
* leftvar = rightvar, as we do for left/right joins, but this routine
* doesn't have the info needed to do that; and the current usage of the
* full_join_clauses list doesn't require that, so it's not currently
* worth complicating this routine's API to make it possible.)
*/
if (can_be_equijoin &&
restrictinfo->mergejoinoperator != InvalidOid &&
!isdeduced)
add_equijoined_keys(root, restrictinfo);
if (restrictinfo->mergejoinoperator != InvalidOid)
{
if (maybe_equijoin)
add_equijoined_keys(root, restrictinfo);
else if (maybe_outer_join && restrictinfo->can_join)
{
if (bms_is_subset(restrictinfo->left_relids,
outerjoin_nonnullable) &&
!bms_overlap(restrictinfo->right_relids,
outerjoin_nonnullable))
{
/* we have outervar = innervar */
root->left_join_clauses = lappend(root->left_join_clauses,
restrictinfo);
}
else if (bms_is_subset(restrictinfo->right_relids,
outerjoin_nonnullable) &&
!bms_overlap(restrictinfo->left_relids,
outerjoin_nonnullable))
{
/* we have innervar = outervar */
root->right_join_clauses = lappend(root->right_join_clauses,
restrictinfo);
}
else if (bms_equal(outerjoin_nonnullable, qualscope))
{
/* FULL JOIN (above tests cannot match in this case) */
root->full_join_clauses = lappend(root->full_join_clauses,
restrictinfo);
}
}
}
}
/*
......
......@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.85 2005/06/10 03:32:23 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.86 2005/07/02 23:00:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -121,6 +121,9 @@ query_planner(PlannerInfo *root, List *tlist, double tuple_fraction,
root->join_rel_list = NIL;
root->join_rel_hash = NULL;
root->equi_key_list = NIL;
root->left_join_clauses = NIL;
root->right_join_clauses = NIL;
root->full_join_clauses = NIL;
/*
* Construct RelOptInfo nodes for all base relations in query.
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.189 2005/06/10 02:21:04 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.190 2005/07/02 23:00:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -194,7 +194,6 @@ subquery_planner(Query *parse, double tuple_fraction,
int saved_planid = PlannerPlanId;
PlannerInfo *root;
Plan *plan;
bool hasOuterJoins;
List *newHaving;
List *lst;
ListCell *l;
......@@ -228,12 +227,16 @@ subquery_planner(Query *parse, double tuple_fraction,
/*
* Detect whether any rangetable entries are RTE_JOIN kind; if not, we
* can avoid the expense of doing flatten_join_alias_vars(). Also
* check for outer joins --- if none, we can skip
* reduce_outer_joins(). This must be done after we have done
* check for outer joins --- if none, we can skip reduce_outer_joins()
* and some other processing. This must be done after we have done
* pull_up_subqueries, of course.
*
* Note: if reduce_outer_joins manages to eliminate all outer joins,
* root->hasOuterJoins is not reset currently. This is OK since its
* purpose is merely to suppress unnecessary processing in simple cases.
*/
root->hasJoinRTEs = false;
hasOuterJoins = false;
root->hasOuterJoins = false;
foreach(l, parse->rtable)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
......@@ -243,7 +246,7 @@ subquery_planner(Query *parse, double tuple_fraction,
root->hasJoinRTEs = true;
if (IS_OUTER_JOIN(rte->jointype))
{
hasOuterJoins = true;
root->hasOuterJoins = true;
/* Can quit scanning once we find an outer join */
break;
}
......@@ -347,7 +350,7 @@ subquery_planner(Query *parse, double tuple_fraction,
* joins. This step is most easily done after we've done expression
* preprocessing.
*/
if (hasOuterJoins)
if (root->hasOuterJoins)
reduce_outer_joins(root);
/*
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.37 2005/06/09 04:19:00 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.38 2005/07/02 23:00:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -24,11 +24,9 @@
static RestrictInfo *make_restrictinfo_internal(Expr *clause,
Expr *orclause,
bool is_pushed_down,
bool valid_everywhere,
Relids required_relids);
static Expr *make_sub_restrictinfos(Expr *clause,
bool is_pushed_down,
bool valid_everywhere);
bool is_pushed_down);
static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
RestrictInfo *rinfo,
List *reference_list,
......@@ -40,8 +38,8 @@ static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
*
* Build a RestrictInfo node containing the given subexpression.
*
* The is_pushed_down and valid_everywhere flags must be supplied by the
* caller. required_relids can be NULL, in which case it defaults to the
* The is_pushed_down flag must be supplied by the caller.
* required_relids can be NULL, in which case it defaults to the
* actual clause contents (i.e., clause_relids).
*
* We initialize fields that depend only on the given subexpression, leaving
......@@ -49,23 +47,19 @@ static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
* later.
*/
RestrictInfo *
make_restrictinfo(Expr *clause, bool is_pushed_down, bool valid_everywhere,
Relids required_relids)
make_restrictinfo(Expr *clause, bool is_pushed_down, Relids required_relids)
{
/*
* If it's an OR clause, build a modified copy with RestrictInfos
* inserted above each subclause of the top-level AND/OR structure.
*/
if (or_clause((Node *) clause))
return (RestrictInfo *) make_sub_restrictinfos(clause,
is_pushed_down,
valid_everywhere);
return (RestrictInfo *) make_sub_restrictinfos(clause, is_pushed_down);
/* Shouldn't be an AND clause, else AND/OR flattening messed up */
Assert(!and_clause((Node *) clause));
return make_restrictinfo_internal(clause, NULL,
is_pushed_down, valid_everywhere,
return make_restrictinfo_internal(clause, NULL, is_pushed_down,
required_relids);
}
......@@ -84,9 +78,7 @@ make_restrictinfo(Expr *clause, bool is_pushed_down, bool valid_everywhere,
* a specialized routine to allow sharing of RestrictInfos.
*/
List *
make_restrictinfo_from_bitmapqual(Path *bitmapqual,
bool is_pushed_down,
bool valid_everywhere)
make_restrictinfo_from_bitmapqual(Path *bitmapqual, bool is_pushed_down)
{
List *result;
......@@ -101,8 +93,7 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
List *sublist;
sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
is_pushed_down,
valid_everywhere);
is_pushed_down);
result = list_concat(result, sublist);
}
}
......@@ -118,8 +109,7 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
List *sublist;
sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
is_pushed_down,
valid_everywhere);
is_pushed_down);
if (sublist == NIL)
{
/* constant TRUE input yields constant TRUE OR result */
......@@ -137,7 +127,6 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
list_make1(make_restrictinfo_internal(make_orclause(withoutris),
make_orclause(withris),
is_pushed_down,
valid_everywhere,
NULL));
}
else if (IsA(bitmapqual, IndexPath))
......@@ -162,15 +151,13 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
*/
static RestrictInfo *
make_restrictinfo_internal(Expr *clause, Expr *orclause,
bool is_pushed_down, bool valid_everywhere,
Relids required_relids)
bool is_pushed_down, Relids required_relids)
{
RestrictInfo *restrictinfo = makeNode(RestrictInfo);
restrictinfo->clause = clause;
restrictinfo->orclause = orclause;
restrictinfo->is_pushed_down = is_pushed_down;
restrictinfo->valid_everywhere = valid_everywhere;
restrictinfo->can_join = false; /* may get set below */
/*
......@@ -250,8 +237,7 @@ make_restrictinfo_internal(Expr *clause, Expr *orclause,
* simple clauses are valid RestrictInfos.
*/
static Expr *
make_sub_restrictinfos(Expr *clause, bool is_pushed_down,
bool valid_everywhere)
make_sub_restrictinfos(Expr *clause, bool is_pushed_down)
{
if (or_clause((Node *) clause))
{
......@@ -261,12 +247,10 @@ make_sub_restrictinfos(Expr *clause, bool is_pushed_down,
foreach(temp, ((BoolExpr *) clause)->args)
orlist = lappend(orlist,
make_sub_restrictinfos(lfirst(temp),
is_pushed_down,
valid_everywhere));
is_pushed_down));
return (Expr *) make_restrictinfo_internal(clause,
make_orclause(orlist),
is_pushed_down,
valid_everywhere,
NULL);
}
else if (and_clause((Node *) clause))
......@@ -277,15 +261,13 @@ make_sub_restrictinfos(Expr *clause, bool is_pushed_down,
foreach(temp, ((BoolExpr *) clause)->args)
andlist = lappend(andlist,
make_sub_restrictinfos(lfirst(temp),
is_pushed_down,
valid_everywhere));
is_pushed_down));
return make_andclause(andlist);
}
else
return (Expr *) make_restrictinfo_internal(clause,
NULL,
is_pushed_down,
valid_everywhere,
NULL);
}
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.115 2005/06/13 23:14:49 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.116 2005/07/02 23:00:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -87,6 +87,15 @@ typedef struct PlannerInfo
List *equi_key_list; /* list of lists of equijoined
* PathKeyItems */
List *left_join_clauses; /* list of RestrictInfos for outer join
* clauses w/nonnullable var on left */
List *right_join_clauses; /* list of RestrictInfos for outer join
* clauses w/nonnullable var on right */
List *full_join_clauses; /* list of RestrictInfos for full outer
* join clauses */
List *in_info_list; /* list of InClauseInfos */
List *query_pathkeys; /* desired pathkeys for query_planner(),
......@@ -95,6 +104,7 @@ typedef struct PlannerInfo
double tuple_fraction; /* tuple_fraction passed to query_planner */
bool hasJoinRTEs; /* true if any RTEs are RTE_JOIN kind */
bool hasOuterJoins; /* true if any RTEs are outer joins */
bool hasHavingQual; /* true if havingQual was non-null */
} PlannerInfo;
......@@ -695,10 +705,6 @@ typedef struct HashPath
* joined, will also have is_pushed_down set because it will get attached to
* some lower joinrel.
*
* We also store a valid_everywhere flag, which says that the clause is not
* affected by any lower-level outer join, and therefore any conditions it
* asserts can be presumed true throughout the plan tree.
*
* In general, the referenced clause might be arbitrarily complex. The
* kinds of clauses we can handle as indexscan quals, mergejoin clauses,
* or hashjoin clauses are fairly limited --- the code for each kind of
......@@ -725,8 +731,6 @@ typedef struct RestrictInfo
bool is_pushed_down; /* TRUE if clause was pushed down in level */
bool valid_everywhere; /* TRUE if valid on every level */
/*
* This flag is set true if the clause looks potentially useful as a
* merge or hash join clause, that is if it is a binary opclause with
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.31 2005/06/09 04:19:00 tgl Exp $
* $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.32 2005/07/02 23:00:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -19,11 +19,9 @@
extern RestrictInfo *make_restrictinfo(Expr *clause,
bool is_pushed_down,
bool valid_everywhere,
Relids required_relids);
extern List *make_restrictinfo_from_bitmapqual(Path *bitmapqual,
bool is_pushed_down,
bool valid_everywhere);
bool is_pushed_down);
extern bool restriction_is_or_clause(RestrictInfo *restrictinfo);
extern List *get_actual_clauses(List *restrictinfo_list);
extern void get_actual_join_clauses(List *restrictinfo_list,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment