aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/initsplan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/initsplan.c')
-rw-r--r--src/backend/optimizer/plan/initsplan.c134
1 files changed, 74 insertions, 60 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 1025a9b7f6b..2b2ebf238fe 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.57 2001/02/16 03:16:57 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.58 2001/03/22 03:59:36 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -35,11 +35,11 @@
static void mark_baserels_for_outer_join(Query *root, Relids rels,
- Relids outerrels);
+ Relids outerrels);
static void distribute_qual_to_rels(Query *root, Node *clause,
- bool ispusheddown,
- bool isouterjoin,
- Relids qualscope);
+ bool ispusheddown,
+ bool isouterjoin,
+ Relids qualscope);
static void add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo,
Relids join_relids);
static void add_vars_to_targetlist(Query *root, List *vars);
@@ -57,7 +57,7 @@ static void check_hashjoinable(RestrictInfo *restrictinfo);
* build_base_rel_tlists
* Creates rel nodes for every relation mentioned in the target list
* 'tlist' (if a node hasn't already been created) and adds them to
- * root->base_rel_list. Creates targetlist entries for each var seen
+ * root->base_rel_list. Creates targetlist entries for each var seen
* in 'tlist' and adds them to the tlist of the appropriate rel node.
*/
void
@@ -118,6 +118,7 @@ add_missing_rels_to_query(Query *root, Node *jtnode)
if (IsA(jtnode, RangeTblRef))
{
int varno = ((RangeTblRef *) jtnode)->rtindex;
+
/* This call to get_base_rel does the primary work... */
RelOptInfo *rel = get_base_rel(root, varno);
@@ -160,7 +161,7 @@ add_missing_rels_to_query(Query *root, Node *jtnode)
* distribute_quals_to_rels
* Recursively scan the query's join tree for WHERE and JOIN/ON qual
* clauses, and add these to the appropriate RestrictInfo and JoinInfo
- * lists belonging to base RelOptInfos. New base rel entries are created
+ * lists belonging to base RelOptInfos. New base rel entries are created
* as needed. Also, base RelOptInfos are marked with outerjoinset
* information, to aid in proper positioning of qual clauses that appear
* above outer joins.
@@ -169,7 +170,7 @@ add_missing_rels_to_query(Query *root, Node *jtnode)
* be evaluated at the lowest level where all the variables it mentions are
* available. However, we cannot push a qual down into the nullable side(s)
* of an outer join since the qual might eliminate matching rows and cause a
- * NULL row to be incorrectly emitted by the join. Therefore, rels appearing
+ * NULL row to be incorrectly emitted by the join. Therefore, rels appearing
* within the nullable side(s) of an outer join are marked with
* outerjoinset = list of Relids used at the outer join node.
* This list will be added to the list of rels referenced by quals using such
@@ -228,14 +229,14 @@ distribute_quals_to_rels(Query *root, Node *jtnode)
List *qual;
/*
- * Order of operations here is subtle and critical. First we recurse
- * to handle sub-JOINs. Their join quals will be placed without
- * regard for whether this level is an outer join, which is correct.
- * Then, if we are an outer join, we mark baserels contained within
- * the nullable side(s) with our own rel list; this will restrict
- * placement of subsequent quals using those rels, including our own
- * quals and quals above us in the join tree.
- * Finally we place our own join quals.
+ * Order of operations here is subtle and critical. First we
+ * recurse to handle sub-JOINs. Their join quals will be placed
+ * without regard for whether this level is an outer join, which
+ * is correct. Then, if we are an outer join, we mark baserels
+ * contained within the nullable side(s) with our own rel list;
+ * this will restrict placement of subsequent quals using those
+ * rels, including our own quals and quals above us in the join
+ * tree. Finally we place our own join quals.
*/
leftids = distribute_quals_to_rels(root, j->larg);
rightids = distribute_quals_to_rels(root, j->rarg);
@@ -261,9 +262,10 @@ distribute_quals_to_rels(Query *root, Node *jtnode)
isouterjoin = true;
break;
case JOIN_UNION:
+
/*
- * This is where we fail if upper levels of planner haven't
- * rewritten UNION JOIN as an Append ...
+ * This is where we fail if upper levels of planner
+ * haven't rewritten UNION JOIN as an Append ...
*/
elog(ERROR, "UNION JOIN is not implemented yet");
break;
@@ -338,12 +340,12 @@ distribute_qual_to_rels(Query *root, Node *clause,
bool can_be_equijoin;
restrictinfo->clause = (Expr *) clause;
- restrictinfo->eval_cost = -1; /* not computed until needed */
+ restrictinfo->eval_cost = -1; /* not computed until needed */
restrictinfo->subclauseindices = NIL;
restrictinfo->mergejoinoperator = InvalidOid;
restrictinfo->left_sortop = InvalidOid;
restrictinfo->right_sortop = InvalidOid;
- restrictinfo->left_pathkey = NIL; /* not computable yet */
+ restrictinfo->left_pathkey = NIL; /* not computable yet */
restrictinfo->right_pathkey = NIL;
restrictinfo->hashjoinoperator = InvalidOid;
restrictinfo->left_dispersion = -1; /* not computed until needed */
@@ -358,7 +360,7 @@ distribute_qual_to_rels(Query *root, Node *clause,
* Cross-check: clause should contain no relids not within its scope.
* Otherwise the parser messed up.
*/
- if (! is_subseti(relids, qualscope))
+ if (!is_subseti(relids, qualscope))
elog(ERROR, "JOIN qualification may not refer to other relations");
/*
@@ -377,14 +379,14 @@ distribute_qual_to_rels(Query *root, Node *clause,
* This ensures that the clause will be evaluated exactly at the level
* of joining corresponding to the outer join.
*
- * For a non-outer-join qual, we can evaluate the qual as soon as
- * (1) we have all the rels it mentions, and (2) we are at or above any
- * outer joins that can null any of these rels and are below the syntactic
- * location of the given qual. To enforce the latter, scan the base rels
- * listed in relids, and merge their outer-join lists into the clause's
- * own reference list. At the time we are called, the outerjoinset list
- * of each baserel will show exactly those outer joins that are below the
- * qual in the join tree.
+ * For a non-outer-join qual, we can evaluate the qual as soon as (1) we
+ * have all the rels it mentions, and (2) we are at or above any outer
+ * joins that can null any of these rels and are below the syntactic
+ * location of the given qual. To enforce the latter, scan the base
+ * rels listed in relids, and merge their outer-join lists into the
+ * clause's own reference list. At the time we are called, the
+ * outerjoinset list of each baserel will show exactly those outer
+ * joins that are below the qual in the join tree.
*/
if (isouterjoin)
{
@@ -396,19 +398,24 @@ distribute_qual_to_rels(Query *root, Node *clause,
Relids newrelids = relids;
List *relid;
- /* We rely on set_unioni to be nondestructive of its input lists... */
+ /*
+ * We rely on set_unioni to be nondestructive of its input
+ * lists...
+ */
can_be_equijoin = true;
foreach(relid, relids)
{
RelOptInfo *rel = get_base_rel(root, lfirsti(relid));
if (rel->outerjoinset &&
- ! is_subseti(rel->outerjoinset, relids))
+ !is_subseti(rel->outerjoinset, relids))
{
newrelids = set_unioni(newrelids, rel->outerjoinset);
+
/*
- * Because application of the qual will be delayed by outer
- * join, we mustn't assume its vars are equal everywhere.
+ * Because application of the qual will be delayed by
+ * outer join, we mustn't assume its vars are equal
+ * everywhere.
*/
can_be_equijoin = false;
}
@@ -419,10 +426,11 @@ distribute_qual_to_rels(Query *root, Node *clause,
}
/*
- * Mark the qual as "pushed down" if it can be applied at a level below
- * its original syntactic level. This allows us to distinguish original
- * JOIN/ON quals from higher-level quals pushed down to the same joinrel.
- * A qual originating from WHERE is always considered "pushed down".
+ * Mark the qual as "pushed down" if it can be applied at a level
+ * below its original syntactic level. This allows us to distinguish
+ * original JOIN/ON quals from higher-level quals pushed down to the
+ * same joinrel. A qual originating from WHERE is always considered
+ * "pushed down".
*/
restrictinfo->ispusheddown = ispusheddown || !sameseti(relids,
qualscope);
@@ -458,10 +466,10 @@ distribute_qual_to_rels(Query *root, Node *clause,
* the relid list. Set additional RestrictInfo fields for
* joining.
*
- * We don't bother setting the merge/hashjoin info if we're not
- * going to need it. We do want to know about mergejoinable ops
- * in any potential equijoin clause (see later in this routine),
- * and we ignore enable_mergejoin if isouterjoin is true, because
+ * We don't bother setting the merge/hashjoin info if we're not going
+ * to need it. We do want to know about mergejoinable ops in any
+ * potential equijoin clause (see later in this routine), and we
+ * ignore enable_mergejoin if isouterjoin is true, because
* mergejoin is the only implementation we have for full and right
* outer joins.
*/
@@ -485,6 +493,7 @@ distribute_qual_to_rels(Query *root, Node *clause,
}
else
{
+
/*
* 'clause' references no rels, and therefore we have no place to
* attach it. Shouldn't get here if callers are working properly.
@@ -493,12 +502,12 @@ distribute_qual_to_rels(Query *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.
+ * 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.
*/
if (can_be_equijoin && restrictinfo->mergejoinoperator != InvalidOid)
add_equijoined_keys(root, restrictinfo);
@@ -569,15 +578,16 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
Expr *clause;
/*
- * Currently, since check_mergejoinable only accepts Var = Var clauses,
- * we should only see Var nodes here. Would have to work a little
- * harder to locate the right rel(s) if more-general mergejoin clauses
- * were accepted.
+ * Currently, since check_mergejoinable only accepts Var = Var
+ * clauses, we should only see Var nodes here. Would have to work a
+ * little harder to locate the right rel(s) if more-general mergejoin
+ * clauses were accepted.
*/
Assert(IsA(item1, Var));
irel1 = ((Var *) item1)->varno;
Assert(IsA(item2, Var));
irel2 = ((Var *) item2)->varno;
+
/*
* If both vars belong to same rel, we need to look at that rel's
* baserestrictinfo list. If different rels, each will have a
@@ -593,6 +603,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
restrictlist = joininfo->jinfo_restrictinfo;
}
+
/*
* Scan to see if equality is already known.
*/
@@ -611,6 +622,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
(equal(item2, left) && equal(item1, right)))
return; /* found a matching clause */
}
+
/*
* This equality is new information, so construct a clause
* representing it to add to the query data structures.
@@ -620,6 +632,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
eq_operator = compatible_oper("=", ltype, rtype, true);
if (!HeapTupleIsValid(eq_operator))
{
+
/*
* Would it be safe to just not add the equality to the query if
* we have no suitable equality operator for the combination of
@@ -629,6 +642,7 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
typeidTypeName(ltype), typeidTypeName(rtype));
}
pgopform = (Form_pg_operator) GETSTRUCT(eq_operator);
+
/*
* Let's just make sure this appears to be a compatible operator.
*/
@@ -641,21 +655,21 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
clause = makeNode(Expr);
clause->typeOid = BOOLOID;
clause->opType = OP_EXPR;
- clause->oper = (Node *) makeOper(oprid(eq_operator), /* opno */
- InvalidOid, /* opid */
- BOOLOID); /* operator result type */
+ clause->oper = (Node *) makeOper(oprid(eq_operator), /* opno */
+ InvalidOid, /* opid */
+ BOOLOID); /* operator result type */
clause->args = makeList2(item1, item2);
ReleaseSysCache(eq_operator);
/*
* Note: we mark the qual "pushed down" to ensure that it can never be
- * taken for an original JOIN/ON clause. We also claim it is an outer-
- * join clause, which it isn't, but that keeps distribute_qual_to_rels
- * from examining the outerjoinsets of the relevant rels (which are no
- * longer of interest, but could keep the qual from being pushed down
- * to where it should be). It'll also save a useless call to
- * add_equijoined keys...
+ * taken for an original JOIN/ON clause. We also claim it is an
+ * outer- join clause, which it isn't, but that keeps
+ * distribute_qual_to_rels from examining the outerjoinsets of the
+ * relevant rels (which are no longer of interest, but could keep the
+ * qual from being pushed down to where it should be). It'll also
+ * save a useless call to add_equijoined keys...
*/
distribute_qual_to_rels(root, (Node *) clause,
true, true,