aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan')
-rw-r--r--src/backend/optimizer/plan/createplan.c80
-rw-r--r--src/backend/optimizer/plan/initsplan.c283
-rw-r--r--src/backend/optimizer/plan/subselect.c8
3 files changed, 191 insertions, 180 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index d78dd2c1e83..8bb651ae5cc 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.134 2003/02/03 15:07:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.135 2003/02/08 20:20:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -65,13 +65,14 @@ static HashJoin *create_hashjoin_plan(Query *root,
static void fix_indxqual_references(List *indexquals, IndexPath *index_path,
List **fixed_indexquals,
List **recheck_indexquals);
-static void fix_indxqual_sublist(List *indexqual, int baserelid,
- IndexOptInfo *index,
- List **fixed_quals, List **recheck_quals);
+static void fix_indxqual_sublist(List *indexqual,
+ Relids baserelids, int baserelid,
+ IndexOptInfo *index,
+ List **fixed_quals, List **recheck_quals);
static Node *fix_indxqual_operand(Node *node, int baserelid,
IndexOptInfo *index,
Oid *opclass);
-static List *get_switched_clauses(List *clauses, List *outerrelids);
+static List *get_switched_clauses(List *clauses, Relids outerrelids);
static List *order_qual_clauses(Query *root, List *clauses);
static void copy_path_costsize(Plan *dest, Path *src);
static void copy_plan_costsize(Plan *dest, Plan *src);
@@ -100,7 +101,7 @@ static MergeJoin *make_mergejoin(List *tlist,
Plan *lefttree, Plan *righttree,
JoinType jointype);
static Sort *make_sort_from_pathkeys(Query *root, Plan *lefttree,
- List *relids, List *pathkeys);
+ Relids relids, List *pathkeys);
/*
@@ -502,7 +503,7 @@ create_unique_plan(Query *root, UniquePath *best_path)
{
InClauseInfo *ininfo = (InClauseInfo *) lfirst(l);
- if (sameseti(ininfo->righthand, best_path->path.parent->relids))
+ if (bms_equal(ininfo->righthand, best_path->path.parent->relids))
{
sub_targetlist = ininfo->sub_targetlist;
break;
@@ -601,14 +602,12 @@ static SeqScan *
create_seqscan_plan(Path *best_path, List *tlist, List *scan_clauses)
{
SeqScan *scan_plan;
- Index scan_relid;
+ Index scan_relid = best_path->parent->relid;
- /* there should be exactly one base rel involved... */
- Assert(length(best_path->parent->relids) == 1);
+ /* it should be a base rel... */
+ Assert(scan_relid > 0);
Assert(best_path->parent->rtekind == RTE_RELATION);
- scan_relid = (Index) lfirsti(best_path->parent->relids);
-
scan_plan = make_seqscan(tlist,
scan_clauses,
scan_relid);
@@ -638,7 +637,7 @@ create_indexscan_plan(Query *root,
List *scan_clauses)
{
List *indxqual = best_path->indexqual;
- Index baserelid;
+ Index baserelid = best_path->path.parent->relid;
List *qpqual;
Expr *indxqual_or_expr = NULL;
List *fixed_indxqual;
@@ -647,12 +646,10 @@ create_indexscan_plan(Query *root,
List *ixinfo;
IndexScan *scan_plan;
- /* there should be exactly one base rel involved... */
- Assert(length(best_path->path.parent->relids) == 1);
+ /* it should be a base rel... */
+ Assert(baserelid > 0);
Assert(best_path->path.parent->rtekind == RTE_RELATION);
- baserelid = lfirsti(best_path->path.parent->relids);
-
/*
* Build list of index OIDs.
*/
@@ -763,14 +760,12 @@ static TidScan *
create_tidscan_plan(TidPath *best_path, List *tlist, List *scan_clauses)
{
TidScan *scan_plan;
- Index scan_relid;
+ Index scan_relid = best_path->path.parent->relid;
- /* there should be exactly one base rel involved... */
- Assert(length(best_path->path.parent->relids) == 1);
+ /* it should be a base rel... */
+ Assert(scan_relid > 0);
Assert(best_path->path.parent->rtekind == RTE_RELATION);
- scan_relid = (Index) lfirsti(best_path->path.parent->relids);
-
scan_plan = make_tidscan(tlist,
scan_clauses,
scan_relid,
@@ -790,15 +785,12 @@ static SubqueryScan *
create_subqueryscan_plan(Path *best_path, List *tlist, List *scan_clauses)
{
SubqueryScan *scan_plan;
- Index scan_relid;
+ Index scan_relid = best_path->parent->relid;
- /* there should be exactly one base rel involved... */
- Assert(length(best_path->parent->relids) == 1);
- /* and it must be a subquery */
+ /* it should be a subquery base rel... */
+ Assert(scan_relid > 0);
Assert(best_path->parent->rtekind == RTE_SUBQUERY);
- scan_relid = (Index) lfirsti(best_path->parent->relids);
-
scan_plan = make_subqueryscan(tlist,
scan_clauses,
scan_relid,
@@ -816,15 +808,12 @@ static FunctionScan *
create_functionscan_plan(Path *best_path, List *tlist, List *scan_clauses)
{
FunctionScan *scan_plan;
- Index scan_relid;
+ Index scan_relid = best_path->parent->relid;
- /* there should be exactly one base rel involved... */
- Assert(length(best_path->parent->relids) == 1);
- /* and it must be a function */
+ /* it should be a function base rel... */
+ Assert(scan_relid > 0);
Assert(best_path->parent->rtekind == RTE_FUNCTION);
- scan_relid = (Index) lfirsti(best_path->parent->relids);
-
scan_plan = make_functionscan(tlist, scan_clauses, scan_relid);
copy_path_costsize(&scan_plan->scan.plan, best_path);
@@ -1055,7 +1044,8 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path,
{
List *fixed_quals = NIL;
List *recheck_quals = NIL;
- int baserelid = lfirsti(index_path->path.parent->relids);
+ Relids baserelids = index_path->path.parent->relids;
+ int baserelid = index_path->path.parent->relid;
List *ixinfo = index_path->indexinfo;
List *i;
@@ -1066,7 +1056,7 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path,
List *fixed_qual;
List *recheck_qual;
- fix_indxqual_sublist(indexqual, baserelid, index,
+ fix_indxqual_sublist(indexqual, baserelids, baserelid, index,
&fixed_qual, &recheck_qual);
fixed_quals = lappend(fixed_quals, fixed_qual);
if (recheck_qual != NIL)
@@ -1092,7 +1082,9 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path,
* the index is lossy for this operator type.
*/
static void
-fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index,
+fix_indxqual_sublist(List *indexqual,
+ Relids baserelids, int baserelid,
+ IndexOptInfo *index,
List **fixed_quals, List **recheck_quals)
{
List *fixed_qual = NIL;
@@ -1103,7 +1095,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index,
{
OpExpr *clause = (OpExpr *) lfirst(i);
OpExpr *newclause;
- List *leftvarnos;
+ Relids leftvarnos;
Oid opclass;
if (!IsA(clause, OpExpr) || length(clause->args) != 2)
@@ -1124,9 +1116,9 @@ fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index,
* (only) the base relation.
*/
leftvarnos = pull_varnos((Node *) lfirst(newclause->args));
- if (length(leftvarnos) != 1 || lfirsti(leftvarnos) != baserelid)
+ if (!bms_equal(leftvarnos, baserelids))
CommuteClause(newclause);
- freeList(leftvarnos);
+ bms_free(leftvarnos);
/*
* Now, determine which index attribute this is, change the
@@ -1222,7 +1214,7 @@ fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index,
* a modified list is returned.
*/
static List *
-get_switched_clauses(List *clauses, List *outerrelids)
+get_switched_clauses(List *clauses, Relids outerrelids)
{
List *t_list = NIL;
List *i;
@@ -1233,7 +1225,7 @@ get_switched_clauses(List *clauses, List *outerrelids)
OpExpr *clause = (OpExpr *) restrictinfo->clause;
Assert(is_opclause(clause));
- if (is_subseti(restrictinfo->right_relids, outerrelids))
+ if (bms_is_subset(restrictinfo->right_relids, outerrelids))
{
/*
* Duplicate just enough of the structure to allow commuting
@@ -1628,7 +1620,7 @@ make_sort(Query *root, List *tlist, Plan *lefttree, int keycount)
*/
static Sort *
make_sort_from_pathkeys(Query *root, Plan *lefttree,
- List *relids, List *pathkeys)
+ Relids relids, List *pathkeys)
{
List *tlist = lefttree->targetlist;
List *sort_tlist;
@@ -1671,7 +1663,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree,
foreach(j, keysublist)
{
pathkey = lfirst(j);
- if (is_subseti(pull_varnos(pathkey->key), relids))
+ if (bms_is_subset(pull_varnos(pathkey->key), relids))
break;
}
if (!j)
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 3a824d55d72..86ffc2906f0 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.83 2003/01/24 03:58:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.84 2003/02/08 20:20:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -165,18 +165,18 @@ add_vars_to_targetlist(Query *root, List *vars)
* 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
* 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
+ * outerjoinset = set of Relids used at the outer join node.
+ * This set will be added to the set of rels referenced by quals using such
* a rel, thereby forcing them up the join tree to the right level.
*
* To ease the calculation of these values, distribute_quals_to_rels() returns
- * the list of base Relids involved in its own level of join. This is just an
+ * the set of base Relids involved in its own level of join. This is just an
* internal convenience; no outside callers pay attention to the result.
*/
Relids
distribute_quals_to_rels(Query *root, Node *jtnode)
{
- Relids result = NIL;
+ Relids result = NULL;
if (jtnode == NULL)
return result;
@@ -185,7 +185,7 @@ distribute_quals_to_rels(Query *root, Node *jtnode)
int varno = ((RangeTblRef *) jtnode)->rtindex;
/* No quals to deal with, just return correct result */
- result = makeListi1(varno);
+ result = bms_make_singleton(varno);
}
else if (IsA(jtnode, FromExpr))
{
@@ -195,14 +195,12 @@ distribute_quals_to_rels(Query *root, Node *jtnode)
/*
* First, recurse to handle child joins.
- *
- * Note: we assume it's impossible to see same RT index from more
- * than one subtree, so nconc() is OK rather than set_unioni().
*/
foreach(l, f->fromlist)
{
- result = nconc(result,
- distribute_quals_to_rels(root, lfirst(l)));
+ result = bms_add_members(result,
+ distribute_quals_to_rels(root,
+ lfirst(l)));
}
/*
@@ -226,7 +224,7 @@ distribute_quals_to_rels(Query *root, Node *jtnode)
* 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;
+ * contained within the nullable side(s) with our own rel set;
* 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.
@@ -234,7 +232,7 @@ distribute_quals_to_rels(Query *root, Node *jtnode)
leftids = distribute_quals_to_rels(root, j->larg);
rightids = distribute_quals_to_rels(root, j->rarg);
- result = nconc(listCopy(leftids), rightids);
+ result = bms_union(leftids, rightids);
isouterjoin = false;
switch (j->jointype)
@@ -286,18 +284,19 @@ distribute_quals_to_rels(Query *root, Node *jtnode)
static void
mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels)
{
- List *relid;
+ Relids tmprelids;
+ int relno;
- foreach(relid, rels)
+ tmprelids = bms_copy(rels);
+ while ((relno = bms_first_member(tmprelids)) >= 0)
{
- int relno = lfirsti(relid);
RelOptInfo *rel = find_base_rel(root, relno);
/*
* Since we do this bottom-up, any outer-rels previously marked
* should be within the new outer join set.
*/
- Assert(is_subseti(rel->outerjoinset, outerrels));
+ Assert(bms_is_subset(rel->outerjoinset, outerrels));
/*
* Presently the executor cannot support FOR UPDATE marking of
@@ -308,7 +307,7 @@ mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels)
* It's sufficient to make this check once per rel, so do it only
* if rel wasn't already known nullable.
*/
- if (rel->outerjoinset == NIL)
+ if (rel->outerjoinset == NULL)
{
if (intMember(relno, root->rowMarks))
elog(ERROR, "SELECT FOR UPDATE cannot be applied to the nullable side of an OUTER JOIN");
@@ -316,6 +315,7 @@ mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels)
rel->outerjoinset = outerrels;
}
+ bms_free(tmprelids);
}
/*
@@ -332,7 +332,7 @@ mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels)
* (this indicates the clause came from a FromExpr, not a JoinExpr)
* 'isouterjoin': TRUE if the qual came from an OUTER JOIN's ON-clause
* 'isdeduced': TRUE if the qual came from implied-equality deduction
- * 'qualscope': list of baserels the qual's syntactic scope covers
+ * 'qualscope': set of baserels the qual's syntactic scope covers
*
* 'qualscope' identifies what level of JOIN the qual came from. For a top
* level qual (WHERE qual), qualscope lists all baserel ids and in addition
@@ -346,6 +346,7 @@ distribute_qual_to_rels(Query *root, Node *clause,
Relids qualscope)
{
RestrictInfo *restrictinfo = makeNode(RestrictInfo);
+ RelOptInfo *rel;
Relids relids;
List *vars;
bool can_be_equijoin;
@@ -354,8 +355,8 @@ distribute_qual_to_rels(Query *root, Node *clause,
restrictinfo->subclauseindices = NIL;
restrictinfo->eval_cost.startup = -1; /* not computed until needed */
restrictinfo->this_selec = -1; /* not computed until needed */
- restrictinfo->left_relids = NIL; /* set below, if join clause */
- restrictinfo->right_relids = NIL;
+ restrictinfo->left_relids = NULL; /* set below, if join clause */
+ restrictinfo->right_relids = NULL;
restrictinfo->mergejoinoperator = InvalidOid;
restrictinfo->left_sortop = InvalidOid;
restrictinfo->right_sortop = InvalidOid;
@@ -377,7 +378,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 (!bms_is_subset(relids, qualscope))
elog(ERROR, "JOIN qualification may not refer to other relations");
/*
@@ -387,7 +388,7 @@ distribute_qual_to_rels(Query *root, Node *clause,
* it will happen for variable-free JOIN/ON clauses. We don't have to
* be real smart about such a case, we just have to be correct.
*/
- if (relids == NIL)
+ if (bms_is_empty(relids))
relids = qualscope;
/*
@@ -400,9 +401,9 @@ distribute_qual_to_rels(Query *root, Node *clause,
* 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
+ * rels listed in relids, and merge their outer-join sets into the
* clause's own reference list. At the time we are called, the
- * outerjoinset list of each baserel will show exactly those outer
+ * outerjoinset of each baserel will show exactly those outer
* joins that are below the qual in the join tree.
*
* If the qual came from implied-equality deduction, we can evaluate the
@@ -411,7 +412,7 @@ distribute_qual_to_rels(Query *root, Node *clause,
*/
if (isdeduced)
{
- Assert(sameseti(relids, qualscope));
+ Assert(bms_equal(relids, qualscope));
can_be_equijoin = true;
}
else if (isouterjoin)
@@ -421,22 +422,20 @@ distribute_qual_to_rels(Query *root, Node *clause,
}
else
{
- Relids newrelids = relids;
- List *relid;
+ /* copy to ensure we don't change caller's qualscope set */
+ Relids newrelids = bms_copy(relids);
+ Relids tmprelids;
+ int relno;
- /*
- * We rely on set_unioni to be nondestructive of its input
- * lists...
- */
can_be_equijoin = true;
- foreach(relid, relids)
+ tmprelids = bms_copy(relids);
+ while ((relno = bms_first_member(tmprelids)) >= 0)
{
- RelOptInfo *rel = find_base_rel(root, lfirsti(relid));
+ RelOptInfo *rel = find_base_rel(root, relno);
- if (rel->outerjoinset &&
- !is_subseti(rel->outerjoinset, relids))
+ if (!bms_is_subset(rel->outerjoinset, relids))
{
- newrelids = set_unioni(newrelids, rel->outerjoinset);
+ newrelids = bms_add_members(newrelids, rel->outerjoinset);
/*
* Because application of the qual will be delayed by
@@ -446,9 +445,10 @@ distribute_qual_to_rels(Query *root, Node *clause,
can_be_equijoin = false;
}
}
+ bms_free(tmprelids);
relids = newrelids;
/* Should still be a subset of current scope ... */
- Assert(is_subseti(relids, qualscope));
+ Assert(bms_is_subset(relids, qualscope));
}
/*
@@ -458,102 +458,104 @@ distribute_qual_to_rels(Query *root, Node *clause,
* same joinrel. A qual originating from WHERE is always considered
* "pushed down".
*/
- restrictinfo->ispusheddown = ispusheddown || !sameseti(relids,
- qualscope);
+ restrictinfo->ispusheddown = ispusheddown || !bms_equal(relids,
+ qualscope);
- if (length(relids) == 1)
+ switch (bms_membership(relids))
{
- /*
- * There is only one relation participating in 'clause', so
- * 'clause' is a restriction clause for that relation.
- */
- RelOptInfo *rel = find_base_rel(root, lfirsti(relids));
-
- /*
- * Check for a "mergejoinable" clause even though it's not a join
- * clause. This is so that we can recognize that "a.x = a.y"
- * makes x and y eligible to be considered equal, even when they
- * belong to the same rel. Without this, we would not recognize
- * that "a.x = a.y AND a.x = b.z AND a.y = c.q" allows us to
- * consider z and q equal after their rels are joined.
- */
- if (can_be_equijoin)
- check_mergejoinable(restrictinfo);
+ case BMS_SINGLETON:
+ /*
+ * There is only one relation participating in 'clause', so
+ * 'clause' is a restriction clause for that relation.
+ */
+ rel = find_base_rel(root, bms_singleton_member(relids));
- /*
- * If the clause was deduced from implied equality, check to see
- * whether it is redundant with restriction clauses we already
- * have for this rel. Note we cannot apply this check to
- * user-written clauses, since we haven't found the canonical
- * pathkey sets yet while processing user clauses. (NB: no
- * comparable check is done in the join-clause case; redundancy
- * will be detected when the join clause is moved into a join
- * rel's restriction list.)
- */
- if (!isdeduced ||
- !qual_is_redundant(root, restrictinfo, rel->baserestrictinfo))
- {
- /* Add clause to rel's restriction list */
- rel->baserestrictinfo = lappend(rel->baserestrictinfo,
- restrictinfo);
- }
- }
- else if (relids != NIL)
- {
- /*
- * 'clause' is a join clause, since there is more than one rel in
- * the relid list. Set additional RestrictInfo fields for
- * joining. First, does it look like a normal join clause, i.e.,
- * a binary operator relating expressions that come from distinct
- * relations? If so we might be able to use it in a join algorithm.
- */
- if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2)
- {
- List *left_relids;
- List *right_relids;
+ /*
+ * Check for a "mergejoinable" clause even though it's not a join
+ * clause. This is so that we can recognize that "a.x = a.y"
+ * makes x and y eligible to be considered equal, even when they
+ * belong to the same rel. Without this, we would not recognize
+ * that "a.x = a.y AND a.x = b.z AND a.y = c.q" allows us to
+ * consider z and q equal after their rels are joined.
+ */
+ if (can_be_equijoin)
+ check_mergejoinable(restrictinfo);
- left_relids = pull_varnos(get_leftop((Expr *) clause));
- right_relids = pull_varnos(get_rightop((Expr *) clause));
- if (left_relids && right_relids &&
- nonoverlap_setsi(left_relids, right_relids))
+ /*
+ * If the clause was deduced from implied equality, check to see
+ * whether it is redundant with restriction clauses we already
+ * have for this rel. Note we cannot apply this check to
+ * user-written clauses, since we haven't found the canonical
+ * pathkey sets yet while processing user clauses. (NB: no
+ * comparable check is done in the join-clause case; redundancy
+ * will be detected when the join clause is moved into a join
+ * rel's restriction list.)
+ */
+ if (!isdeduced ||
+ !qual_is_redundant(root, restrictinfo, rel->baserestrictinfo))
{
- restrictinfo->left_relids = left_relids;
- restrictinfo->right_relids = right_relids;
+ /* Add clause to rel's restriction list */
+ rel->baserestrictinfo = lappend(rel->baserestrictinfo,
+ restrictinfo);
+ }
+ break;
+ case BMS_MULTIPLE:
+ /*
+ * 'clause' is a join clause, since there is more than one rel in
+ * the relid set. Set additional RestrictInfo fields for
+ * joining. First, does it look like a normal join clause, i.e.,
+ * a binary operator relating expressions that come from distinct
+ * relations? If so we might be able to use it in a join
+ * algorithm.
+ */
+ if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2)
+ {
+ Relids left_relids;
+ Relids right_relids;
+
+ left_relids = pull_varnos(get_leftop((Expr *) clause));
+ right_relids = pull_varnos(get_rightop((Expr *) clause));
+ if (!bms_is_empty(left_relids) &&
+ !bms_is_empty(right_relids) &&
+ !bms_overlap(left_relids, right_relids))
+ {
+ restrictinfo->left_relids = left_relids;
+ restrictinfo->right_relids = right_relids;
+ }
}
- }
- /*
- * Now check for hash or mergejoinable operators.
- *
- * We don't bother setting the hashjoin info if we're not going
- * to need it. We do want to know about mergejoinable ops in all
- * cases, however, because we use mergejoinable ops for other
- * purposes such as detecting redundant clauses.
- */
- check_mergejoinable(restrictinfo);
- if (enable_hashjoin)
- check_hashjoinable(restrictinfo);
+ /*
+ * Now check for hash or mergejoinable operators.
+ *
+ * We don't bother setting the hashjoin info if we're not going
+ * to need it. We do want to know about mergejoinable ops in all
+ * cases, however, because we use mergejoinable ops for other
+ * purposes such as detecting redundant clauses.
+ */
+ check_mergejoinable(restrictinfo);
+ if (enable_hashjoin)
+ check_hashjoinable(restrictinfo);
- /*
- * Add clause to the join lists of all the relevant relations.
- */
- add_join_clause_to_rels(root, restrictinfo, relids);
+ /*
+ * Add clause to the join lists of all the relevant relations.
+ */
+ add_join_clause_to_rels(root, restrictinfo, relids);
- /*
- * Add vars used in the join clause to targetlists of their
- * relations, so that they will be emitted by the plan nodes that
- * scan those relations (else they won't be available at the join
- * node!).
- */
- add_vars_to_targetlist(root, vars);
- }
- else
- {
- /*
- * 'clause' references no rels, and therefore we have no place to
- * attach it. Shouldn't get here if callers are working properly.
- */
- elog(ERROR, "distribute_qual_to_rels: can't cope with variable-free clause");
+ /*
+ * Add vars used in the join clause to targetlists of their
+ * relations, so that they will be emitted by the plan nodes that
+ * scan those relations (else they won't be available at the join
+ * node!).
+ */
+ add_vars_to_targetlist(root, vars);
+ break;
+ default:
+ /*
+ * 'clause' references no rels, and therefore we have no place to
+ * attach it. Shouldn't get here if callers are working properly.
+ */
+ elog(ERROR, "distribute_qual_to_rels: can't cope with variable-free clause");
+ break;
}
/*
@@ -589,6 +591,7 @@ process_implied_equality(Query *root,
bool delete_it)
{
Relids relids;
+ BMS_Membership membership;
RelOptInfo *rel1;
List *restrictlist;
List *itm;
@@ -598,27 +601,43 @@ process_implied_equality(Query *root,
Form_pg_operator pgopform;
Expr *clause;
- /* Get list of relids referenced in the two expressions */
- relids = set_unioni(item1_relids, item2_relids);
+ /* Get set of relids referenced in the two expressions */
+ relids = bms_union(item1_relids, item2_relids);
+ membership = bms_membership(relids);
/*
* generate_implied_equalities() shouldn't call me on two constants.
*/
- Assert(relids != NIL);
+ Assert(membership != BMS_EMPTY_SET);
/*
* If the exprs involve a single rel, we need to look at that rel's
* baserestrictinfo list. If multiple rels, any one will have a
* joininfo node for the rest, and we can scan any of 'em.
*/
- rel1 = find_base_rel(root, lfirsti(relids));
- if (lnext(relids) == NIL)
+ if (membership == BMS_SINGLETON)
+ {
+ rel1 = find_base_rel(root, bms_singleton_member(relids));
restrictlist = rel1->baserestrictinfo;
+ }
else
{
- JoinInfo *joininfo = find_joininfo_node(rel1, lnext(relids));
+ Relids other_rels;
+ int first_rel;
+ JoinInfo *joininfo;
+
+ /* Copy relids, find and remove one member */
+ other_rels = bms_copy(relids);
+ first_rel = bms_first_member(other_rels);
+
+ rel1 = find_base_rel(root, first_rel);
+
+ /* use remaining members to find join node */
+ joininfo = find_joininfo_node(rel1, other_rels);
restrictlist = joininfo ? joininfo->jinfo_restrictinfo : NIL;
+
+ bms_free(other_rels);
}
/*
@@ -642,7 +661,7 @@ process_implied_equality(Query *root,
/* found a matching clause */
if (delete_it)
{
- if (lnext(relids) == NIL)
+ if (membership == BMS_SINGLETON)
{
/* delete it from local restrictinfo list */
rel1->baserestrictinfo = lremove(restrictinfo,
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 9f56a9f38d5..a2c8053b5dc 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.69 2003/01/28 22:13:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.70 2003/02/08 20:20:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -607,7 +607,7 @@ Node *
convert_IN_to_join(Query *parse, SubLink *sublink)
{
Query *subselect = (Query *) sublink->subselect;
- List *left_varnos;
+ Relids left_varnos;
int rtindex;
RangeTblEntry *rte;
RangeTblRef *rtr;
@@ -635,7 +635,7 @@ convert_IN_to_join(Query *parse, SubLink *sublink)
* query, else it's not gonna be a join.
*/
left_varnos = pull_varnos((Node *) sublink->lefthand);
- if (left_varnos == NIL)
+ if (bms_is_empty(left_varnos))
return NULL;
/*
* The left-hand expressions mustn't be volatile. (Perhaps we should
@@ -666,7 +666,7 @@ convert_IN_to_join(Query *parse, SubLink *sublink)
*/
ininfo = makeNode(InClauseInfo);
ininfo->lefthand = left_varnos;
- ininfo->righthand = makeListi1(rtindex);
+ ininfo->righthand = bms_make_singleton(rtindex);
parse->in_info_list = lcons(ininfo, parse->in_info_list);
/*
* Build the result qual expressions. As a side effect,