mirror of
https://github.com/postgres/postgres.git
synced 2025-11-13 16:22:44 +03:00
Replace planner's representation of relation sets, per pghackers discussion.
Instead of Lists of integers, we now store variable-length bitmap sets. This should be faster as well as less error-prone.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.95 2003/01/25 23:10:27 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.96 2003/02/08 20:20:54 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -79,7 +79,7 @@ make_one_rel(Query *root)
|
||||
/*
|
||||
* The result should join all the query's base rels.
|
||||
*/
|
||||
Assert(length(rel->relids) == length(root->base_rel_list));
|
||||
Assert(bms_num_members(rel->relids) == length(root->base_rel_list));
|
||||
|
||||
return rel;
|
||||
}
|
||||
@@ -98,12 +98,11 @@ set_base_rel_pathlists(Query *root)
|
||||
foreach(rellist, root->base_rel_list)
|
||||
{
|
||||
RelOptInfo *rel = (RelOptInfo *) lfirst(rellist);
|
||||
Index rti;
|
||||
Index rti = rel->relid;
|
||||
RangeTblEntry *rte;
|
||||
List *inheritlist;
|
||||
|
||||
Assert(length(rel->relids) == 1); /* better be base rel */
|
||||
rti = lfirsti(rel->relids);
|
||||
Assert(rti > 0); /* better be base rel */
|
||||
rte = rt_fetch(rti, root->rtable);
|
||||
|
||||
if (rel->rtekind == RTE_SUBQUERY)
|
||||
@@ -696,14 +695,19 @@ recurse_push_qual(Node *setOp, Query *topquery,
|
||||
static void
|
||||
print_relids(Relids relids)
|
||||
{
|
||||
List *l;
|
||||
Relids tmprelids;
|
||||
int x;
|
||||
bool first = true;
|
||||
|
||||
foreach(l, relids)
|
||||
tmprelids = bms_copy(relids);
|
||||
while ((x = bms_first_member(tmprelids)) >= 0)
|
||||
{
|
||||
printf("%d", lfirsti(l));
|
||||
if (lnext(l))
|
||||
if (!first)
|
||||
printf(" ");
|
||||
printf("%d", x);
|
||||
first = false;
|
||||
}
|
||||
bms_free(tmprelids);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.104 2003/01/28 22:13:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.105 2003/02/08 20:20:54 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -124,7 +124,7 @@ cost_seqscan(Path *path, Query *root,
|
||||
Cost cpu_per_tuple;
|
||||
|
||||
/* Should only be applied to base relations */
|
||||
Assert(length(baserel->relids) == 1);
|
||||
Assert(baserel->relid > 0);
|
||||
Assert(baserel->rtekind == RTE_RELATION);
|
||||
|
||||
if (!enable_seqscan)
|
||||
@@ -241,7 +241,7 @@ cost_index(Path *path, Query *root,
|
||||
/* Should only be applied to base relations */
|
||||
Assert(IsA(baserel, RelOptInfo) &&
|
||||
IsA(index, IndexOptInfo));
|
||||
Assert(length(baserel->relids) == 1);
|
||||
Assert(baserel->relid > 0);
|
||||
Assert(baserel->rtekind == RTE_RELATION);
|
||||
|
||||
if (!enable_indexscan)
|
||||
@@ -397,7 +397,7 @@ cost_tidscan(Path *path, Query *root,
|
||||
int ntuples = length(tideval);
|
||||
|
||||
/* Should only be applied to base relations */
|
||||
Assert(length(baserel->relids) == 1);
|
||||
Assert(baserel->relid > 0);
|
||||
Assert(baserel->rtekind == RTE_RELATION);
|
||||
|
||||
if (!enable_tidscan)
|
||||
@@ -427,7 +427,7 @@ cost_functionscan(Path *path, Query *root, RelOptInfo *baserel)
|
||||
Cost cpu_per_tuple;
|
||||
|
||||
/* Should only be applied to base relations that are functions */
|
||||
Assert(length(baserel->relids) == 1);
|
||||
Assert(baserel->relid > 0);
|
||||
Assert(baserel->rtekind == RTE_FUNCTION);
|
||||
|
||||
/*
|
||||
@@ -886,7 +886,7 @@ cost_mergejoin(MergePath *path, Query *root)
|
||||
&firstclause->left_mergescansel,
|
||||
&firstclause->right_mergescansel);
|
||||
|
||||
if (is_subseti(firstclause->left_relids, outer_path->parent->relids))
|
||||
if (bms_is_subset(firstclause->left_relids, outer_path->parent->relids))
|
||||
{
|
||||
/* left side of clause is outer */
|
||||
outerscansel = firstclause->left_mergescansel;
|
||||
@@ -1116,8 +1116,8 @@ cost_hashjoin(HashPath *path, Query *root)
|
||||
* planning a large query, we cache the bucketsize estimate in the
|
||||
* RestrictInfo node to avoid repeated lookups of statistics.
|
||||
*/
|
||||
if (is_subseti(restrictinfo->right_relids,
|
||||
inner_path->parent->relids))
|
||||
if (bms_is_subset(restrictinfo->right_relids,
|
||||
inner_path->parent->relids))
|
||||
{
|
||||
/* righthand side is inner */
|
||||
thisbucketsize = restrictinfo->right_bucketsize;
|
||||
@@ -1133,8 +1133,8 @@ cost_hashjoin(HashPath *path, Query *root)
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(is_subseti(restrictinfo->left_relids,
|
||||
inner_path->parent->relids));
|
||||
Assert(bms_is_subset(restrictinfo->left_relids,
|
||||
inner_path->parent->relids));
|
||||
/* lefthand side is inner */
|
||||
thisbucketsize = restrictinfo->left_bucketsize;
|
||||
if (thisbucketsize < 0)
|
||||
@@ -1635,12 +1635,12 @@ set_baserel_size_estimates(Query *root, RelOptInfo *rel)
|
||||
double temp;
|
||||
|
||||
/* Should only be applied to base relations */
|
||||
Assert(length(rel->relids) == 1);
|
||||
Assert(rel->relid > 0);
|
||||
|
||||
temp = rel->tuples *
|
||||
restrictlist_selectivity(root,
|
||||
rel->baserestrictinfo,
|
||||
lfirsti(rel->relids),
|
||||
rel->relid,
|
||||
JOIN_INNER);
|
||||
|
||||
/*
|
||||
@@ -1803,7 +1803,7 @@ set_function_size_estimates(Query *root, RelOptInfo *rel)
|
||||
double temp;
|
||||
|
||||
/* Should only be applied to base relations that are functions */
|
||||
Assert(length(rel->relids) == 1);
|
||||
Assert(rel->relid > 0);
|
||||
Assert(rel->rtekind == RTE_FUNCTION);
|
||||
|
||||
/*
|
||||
@@ -1818,7 +1818,7 @@ set_function_size_estimates(Query *root, RelOptInfo *rel)
|
||||
temp = rel->tuples *
|
||||
restrictlist_selectivity(root,
|
||||
rel->baserestrictinfo,
|
||||
lfirsti(rel->relids),
|
||||
rel->relid,
|
||||
JOIN_INNER);
|
||||
|
||||
/*
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.134 2003/01/28 22:13:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.135 2003/02/08 20:20:54 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -133,7 +133,7 @@ create_index_paths(Query *root, RelOptInfo *rel)
|
||||
{
|
||||
List *restrictinfo_list = rel->baserestrictinfo;
|
||||
List *joininfo_list = rel->joininfo;
|
||||
Relids all_join_outerrelids = NIL;
|
||||
Relids all_join_outerrelids = NULL;
|
||||
List *ilist;
|
||||
|
||||
foreach(ilist, rel->indexlist)
|
||||
@@ -151,7 +151,7 @@ create_index_paths(Query *root, RelOptInfo *rel)
|
||||
*/
|
||||
if (index->indpred != NIL)
|
||||
if (!pred_test(index->indpred, restrictinfo_list, joininfo_list,
|
||||
lfirsti(rel->relids)))
|
||||
rel->relid))
|
||||
continue;
|
||||
|
||||
/*
|
||||
@@ -227,15 +227,15 @@ create_index_paths(Query *root, RelOptInfo *rel)
|
||||
|
||||
/*
|
||||
* 6. Examine join clauses to see which ones are potentially
|
||||
* usable with this index, and generate a list of all other relids
|
||||
* that participate in such join clauses. We'll use this list later
|
||||
* usable with this index, and generate the set of all other relids
|
||||
* that participate in such join clauses. We'll use this set later
|
||||
* to recognize outer rels that are equivalent for joining purposes.
|
||||
* We compute both per-index and overall-for-relation lists.
|
||||
* We compute both per-index and overall-for-relation sets.
|
||||
*/
|
||||
join_outerrelids = indexable_outerrelids(rel, index);
|
||||
index->outer_relids = join_outerrelids;
|
||||
all_join_outerrelids = set_unioni(all_join_outerrelids,
|
||||
join_outerrelids);
|
||||
all_join_outerrelids = bms_add_members(all_join_outerrelids,
|
||||
join_outerrelids);
|
||||
}
|
||||
|
||||
rel->index_outer_relids = all_join_outerrelids;
|
||||
@@ -609,7 +609,7 @@ group_clauses_by_indexkey_for_join(RelOptInfo *rel, IndexOptInfo *index,
|
||||
JoinInfo *joininfo = (JoinInfo *) lfirst(i);
|
||||
List *j;
|
||||
|
||||
if (!is_subseti(joininfo->unjoined_relids, outer_relids))
|
||||
if (!bms_is_subset(joininfo->unjoined_relids, outer_relids))
|
||||
continue;
|
||||
|
||||
foreach(j, joininfo->jinfo_restrictinfo)
|
||||
@@ -820,27 +820,27 @@ match_join_clause_to_indexkey(RelOptInfo *rel,
|
||||
*/
|
||||
if (match_index_to_operand(indexkey, leftop, rel, index))
|
||||
{
|
||||
List *othervarnos = pull_varnos(rightop);
|
||||
Relids othervarnos = pull_varnos(rightop);
|
||||
bool isIndexable;
|
||||
|
||||
isIndexable =
|
||||
!intMember(lfirsti(rel->relids), othervarnos) &&
|
||||
!bms_overlap(rel->relids, othervarnos) &&
|
||||
!contain_volatile_functions(rightop) &&
|
||||
is_indexable_operator(clause, opclass, true);
|
||||
freeList(othervarnos);
|
||||
bms_free(othervarnos);
|
||||
return isIndexable;
|
||||
}
|
||||
|
||||
if (match_index_to_operand(indexkey, rightop, rel, index))
|
||||
{
|
||||
List *othervarnos = pull_varnos(leftop);
|
||||
Relids othervarnos = pull_varnos(leftop);
|
||||
bool isIndexable;
|
||||
|
||||
isIndexable =
|
||||
!intMember(lfirsti(rel->relids), othervarnos) &&
|
||||
!bms_overlap(rel->relids, othervarnos) &&
|
||||
!contain_volatile_functions(leftop) &&
|
||||
is_indexable_operator(clause, opclass, false);
|
||||
freeList(othervarnos);
|
||||
bms_free(othervarnos);
|
||||
return isIndexable;
|
||||
}
|
||||
|
||||
@@ -1312,14 +1312,14 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
|
||||
/*
|
||||
* indexable_outerrelids
|
||||
* Finds all other relids that participate in any indexable join clause
|
||||
* for the specified index. Returns a list of relids.
|
||||
* for the specified index. Returns a set of relids.
|
||||
*
|
||||
* 'rel' is the relation for which 'index' is defined
|
||||
*/
|
||||
static Relids
|
||||
indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index)
|
||||
{
|
||||
Relids outer_relids = NIL;
|
||||
Relids outer_relids = NULL;
|
||||
List *i;
|
||||
|
||||
foreach(i, rel->joininfo)
|
||||
@@ -1368,8 +1368,8 @@ indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index)
|
||||
|
||||
if (match_found)
|
||||
{
|
||||
outer_relids = set_unioni(outer_relids,
|
||||
joininfo->unjoined_relids);
|
||||
outer_relids = bms_add_members(outer_relids,
|
||||
joininfo->unjoined_relids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1419,7 +1419,7 @@ best_inner_indexscan(Query *root, RelOptInfo *rel,
|
||||
/*
|
||||
* If there are no indexable joinclauses for this rel, exit quickly.
|
||||
*/
|
||||
if (!rel->index_outer_relids)
|
||||
if (bms_is_empty(rel->index_outer_relids))
|
||||
return NULL;
|
||||
/*
|
||||
* Otherwise, we have to do path selection in the memory context of
|
||||
@@ -1433,9 +1433,10 @@ best_inner_indexscan(Query *root, RelOptInfo *rel,
|
||||
* to find the set of outer relids actually relevant for this index.
|
||||
* If there are none, again we can fail immediately.
|
||||
*/
|
||||
outer_relids = set_intersecti(rel->index_outer_relids, outer_relids);
|
||||
if (!outer_relids)
|
||||
outer_relids = bms_intersect(rel->index_outer_relids, outer_relids);
|
||||
if (bms_is_empty(outer_relids))
|
||||
{
|
||||
bms_free(outer_relids);
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1448,10 +1449,10 @@ best_inner_indexscan(Query *root, RelOptInfo *rel,
|
||||
foreach(jlist, rel->index_inner_paths)
|
||||
{
|
||||
info = (InnerIndexscanInfo *) lfirst(jlist);
|
||||
if (sameseti(info->other_relids, outer_relids) &&
|
||||
if (bms_equal(info->other_relids, outer_relids) &&
|
||||
info->isouterjoin == isouterjoin)
|
||||
{
|
||||
freeList(outer_relids);
|
||||
bms_free(outer_relids);
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
return info->best_innerpath;
|
||||
}
|
||||
@@ -1470,24 +1471,25 @@ best_inner_indexscan(Query *root, RelOptInfo *rel,
|
||||
Relids index_outer_relids;
|
||||
Path *path = NULL;
|
||||
|
||||
/* skip quickly if index has no useful join clauses */
|
||||
if (!index->outer_relids)
|
||||
continue;
|
||||
/* identify set of relevant outer relids for this index */
|
||||
index_outer_relids = set_intersecti(index->outer_relids, outer_relids);
|
||||
if (!index_outer_relids)
|
||||
index_outer_relids = bms_intersect(index->outer_relids, outer_relids);
|
||||
/* skip if none */
|
||||
if (bms_is_empty(index_outer_relids))
|
||||
{
|
||||
bms_free(index_outer_relids);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Look to see if we already computed the result for this index.
|
||||
*/
|
||||
foreach(jlist, index->inner_paths)
|
||||
{
|
||||
info = (InnerIndexscanInfo *) lfirst(jlist);
|
||||
if (sameseti(info->other_relids, index_outer_relids) &&
|
||||
if (bms_equal(info->other_relids, index_outer_relids) &&
|
||||
info->isouterjoin == isouterjoin)
|
||||
{
|
||||
path = info->best_innerpath;
|
||||
freeList(index_outer_relids); /* not needed anymore */
|
||||
bms_free(index_outer_relids); /* not needed anymore */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1607,7 +1609,7 @@ make_innerjoin_index_path(Query *root,
|
||||
restrictlist_selectivity(root,
|
||||
set_ptrUnion(rel->baserestrictinfo,
|
||||
clausegroup),
|
||||
lfirsti(rel->relids),
|
||||
rel->relid,
|
||||
JOIN_INNER);
|
||||
/* Like costsize.c, force estimate to be at least one row */
|
||||
if (pathnode->rows < 1.0)
|
||||
@@ -1649,7 +1651,7 @@ match_index_to_operand(int indexkey,
|
||||
* Simple index.
|
||||
*/
|
||||
if (operand && IsA(operand, Var) &&
|
||||
lfirsti(rel->relids) == ((Var *) operand)->varno &&
|
||||
rel->relid == ((Var *) operand)->varno &&
|
||||
indexkey == ((Var *) operand)->varattno)
|
||||
return true;
|
||||
else
|
||||
@@ -1665,7 +1667,6 @@ match_index_to_operand(int indexkey,
|
||||
static bool
|
||||
function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
|
||||
{
|
||||
int relvarno = lfirsti(rel->relids);
|
||||
FuncExpr *function;
|
||||
List *funcargs;
|
||||
int *indexKeys = index->indexkeys;
|
||||
@@ -1705,7 +1706,7 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
|
||||
return false;
|
||||
if (indexKeys[i] == 0)
|
||||
return false;
|
||||
if (var->varno != relvarno || var->varattno != indexKeys[i])
|
||||
if (var->varno != rel->relid || var->varattno != indexKeys[i])
|
||||
return false;
|
||||
|
||||
i++;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.77 2003/01/27 20:51:51 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.78 2003/02/08 20:20:54 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -689,7 +689,7 @@ hash_inner_and_outer(Query *root,
|
||||
{
|
||||
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(i);
|
||||
|
||||
if (restrictinfo->left_relids == NIL ||
|
||||
if (restrictinfo->left_relids == NULL ||
|
||||
restrictinfo->hashjoinoperator == InvalidOid)
|
||||
continue; /* not hashjoinable */
|
||||
|
||||
@@ -703,13 +703,13 @@ hash_inner_and_outer(Query *root,
|
||||
/*
|
||||
* Check if clause is usable with these input rels.
|
||||
*/
|
||||
if (is_subseti(restrictinfo->left_relids, outerrel->relids) &&
|
||||
is_subseti(restrictinfo->right_relids, innerrel->relids))
|
||||
if (bms_is_subset(restrictinfo->left_relids, outerrel->relids) &&
|
||||
bms_is_subset(restrictinfo->right_relids, innerrel->relids))
|
||||
{
|
||||
/* righthand side is inner */
|
||||
}
|
||||
else if (is_subseti(restrictinfo->left_relids, innerrel->relids) &&
|
||||
is_subseti(restrictinfo->right_relids, outerrel->relids))
|
||||
else if (bms_is_subset(restrictinfo->left_relids, innerrel->relids) &&
|
||||
bms_is_subset(restrictinfo->right_relids, outerrel->relids))
|
||||
{
|
||||
/* lefthand side is inner */
|
||||
}
|
||||
@@ -808,12 +808,12 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
|
||||
switch (jointype)
|
||||
{
|
||||
case JOIN_RIGHT:
|
||||
if (restrictinfo->left_relids == NIL ||
|
||||
if (restrictinfo->left_relids == NULL ||
|
||||
restrictinfo->mergejoinoperator == InvalidOid)
|
||||
return NIL; /* not mergejoinable */
|
||||
break;
|
||||
case JOIN_FULL:
|
||||
if (restrictinfo->left_relids == NIL ||
|
||||
if (restrictinfo->left_relids == NULL ||
|
||||
restrictinfo->mergejoinoperator == InvalidOid)
|
||||
elog(ERROR, "FULL JOIN is only supported with mergejoinable join conditions");
|
||||
break;
|
||||
@@ -823,7 +823,7 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
|
||||
}
|
||||
}
|
||||
|
||||
if (restrictinfo->left_relids == NIL ||
|
||||
if (restrictinfo->left_relids == NULL ||
|
||||
restrictinfo->mergejoinoperator == InvalidOid)
|
||||
continue; /* not mergejoinable */
|
||||
|
||||
@@ -832,13 +832,13 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
|
||||
* needed on each side of the clause must be available from one or
|
||||
* the other of the input rels.
|
||||
*/
|
||||
if (is_subseti(restrictinfo->left_relids, outerrel->relids) &&
|
||||
is_subseti(restrictinfo->right_relids, innerrel->relids))
|
||||
if (bms_is_subset(restrictinfo->left_relids, outerrel->relids) &&
|
||||
bms_is_subset(restrictinfo->right_relids, innerrel->relids))
|
||||
{
|
||||
/* righthand side is inner */
|
||||
}
|
||||
else if (is_subseti(restrictinfo->left_relids, innerrel->relids) &&
|
||||
is_subseti(restrictinfo->right_relids, outerrel->relids))
|
||||
else if (bms_is_subset(restrictinfo->left_relids, innerrel->relids) &&
|
||||
bms_is_subset(restrictinfo->right_relids, outerrel->relids))
|
||||
{
|
||||
/* lefthand side is inner */
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.59 2003/01/20 18:54:51 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.60 2003/02/08 20:20:54 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -151,7 +151,7 @@ make_rels_by_joins(Query *root, int level, List **joinrels)
|
||||
{
|
||||
RelOptInfo *new_rel = (RelOptInfo *) lfirst(r2);
|
||||
|
||||
if (nonoverlap_setsi(old_rel->relids, new_rel->relids))
|
||||
if (!bms_overlap(old_rel->relids, new_rel->relids))
|
||||
{
|
||||
List *i;
|
||||
|
||||
@@ -164,8 +164,8 @@ make_rels_by_joins(Query *root, int level, List **joinrels)
|
||||
{
|
||||
JoinInfo *joininfo = (JoinInfo *) lfirst(i);
|
||||
|
||||
if (is_subseti(joininfo->unjoined_relids,
|
||||
new_rel->relids))
|
||||
if (bms_is_subset(joininfo->unjoined_relids,
|
||||
new_rel->relids))
|
||||
{
|
||||
RelOptInfo *jrel;
|
||||
|
||||
@@ -268,7 +268,7 @@ make_rels_by_clause_joins(Query *root,
|
||||
{
|
||||
RelOptInfo *other_rel = (RelOptInfo *) lfirst(j);
|
||||
|
||||
if (is_subseti(unjoined_relids, other_rel->relids))
|
||||
if (bms_is_subset(unjoined_relids, other_rel->relids))
|
||||
{
|
||||
RelOptInfo *jrel;
|
||||
|
||||
@@ -312,7 +312,7 @@ make_rels_by_clauseless_joins(Query *root,
|
||||
{
|
||||
RelOptInfo *other_rel = (RelOptInfo *) lfirst(i);
|
||||
|
||||
if (nonoverlap_setsi(other_rel->relids, old_rel->relids))
|
||||
if (!bms_overlap(other_rel->relids, old_rel->relids))
|
||||
{
|
||||
RelOptInfo *jrel;
|
||||
|
||||
@@ -406,15 +406,15 @@ RelOptInfo *
|
||||
make_join_rel(Query *root, RelOptInfo *rel1, RelOptInfo *rel2,
|
||||
JoinType jointype)
|
||||
{
|
||||
List *joinrelids;
|
||||
Relids joinrelids;
|
||||
RelOptInfo *joinrel;
|
||||
List *restrictlist;
|
||||
|
||||
/* We should never try to join two overlapping sets of rels. */
|
||||
Assert(nonoverlap_setsi(rel1->relids, rel2->relids));
|
||||
Assert(!bms_overlap(rel1->relids, rel2->relids));
|
||||
|
||||
/* Construct Relids set that identifies the joinrel. */
|
||||
joinrelids = nconc(listCopy(rel1->relids), listCopy(rel2->relids));
|
||||
joinrelids = bms_union(rel1->relids, rel2->relids);
|
||||
|
||||
/*
|
||||
* If we are implementing IN clauses as joins, there are some joins
|
||||
@@ -433,15 +433,12 @@ make_join_rel(Query *root, RelOptInfo *rel1, RelOptInfo *rel2,
|
||||
/*
|
||||
* Cannot join if proposed join contains part, but only
|
||||
* part, of the RHS, *and* it contains rels not in the RHS.
|
||||
*
|
||||
* Singleton RHS cannot be a problem, so skip expensive tests.
|
||||
*/
|
||||
if (length(ininfo->righthand) > 1 &&
|
||||
overlap_setsi(ininfo->righthand, joinrelids) &&
|
||||
!is_subseti(ininfo->righthand, joinrelids) &&
|
||||
!is_subseti(joinrelids, ininfo->righthand))
|
||||
if (bms_overlap(ininfo->righthand, joinrelids) &&
|
||||
!bms_is_subset(ininfo->righthand, joinrelids) &&
|
||||
!bms_is_subset(joinrelids, ininfo->righthand))
|
||||
{
|
||||
freeList(joinrelids);
|
||||
bms_free(joinrelids);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -449,19 +446,19 @@ make_join_rel(Query *root, RelOptInfo *rel1, RelOptInfo *rel2,
|
||||
* No issue unless we are looking at a join of the IN's RHS
|
||||
* to other stuff.
|
||||
*/
|
||||
if (! (length(ininfo->righthand) < length(joinrelids) &&
|
||||
is_subseti(ininfo->righthand, joinrelids)))
|
||||
if (! (bms_is_subset(ininfo->righthand, joinrelids) &&
|
||||
!bms_equal(ininfo->righthand, joinrelids)))
|
||||
continue;
|
||||
/*
|
||||
* If we already joined IN's RHS to any part of its LHS in either
|
||||
* input path, then this join is not constrained (the necessary
|
||||
* work was done at a lower level).
|
||||
*/
|
||||
if (overlap_setsi(ininfo->lefthand, rel1->relids) &&
|
||||
is_subseti(ininfo->righthand, rel1->relids))
|
||||
if (bms_overlap(ininfo->lefthand, rel1->relids) &&
|
||||
bms_is_subset(ininfo->righthand, rel1->relids))
|
||||
continue;
|
||||
if (overlap_setsi(ininfo->lefthand, rel2->relids) &&
|
||||
is_subseti(ininfo->righthand, rel2->relids))
|
||||
if (bms_overlap(ininfo->lefthand, rel2->relids) &&
|
||||
bms_is_subset(ininfo->righthand, rel2->relids))
|
||||
continue;
|
||||
/*
|
||||
* JOIN_IN technique will work if outerrel includes LHS and
|
||||
@@ -477,31 +474,31 @@ make_join_rel(Query *root, RelOptInfo *rel1, RelOptInfo *rel2,
|
||||
*/
|
||||
if (jointype != JOIN_INNER)
|
||||
{
|
||||
freeList(joinrelids);
|
||||
bms_free(joinrelids);
|
||||
return NULL;
|
||||
}
|
||||
if (is_subseti(ininfo->lefthand, rel1->relids) &&
|
||||
sameseti(ininfo->righthand, rel2->relids))
|
||||
if (bms_is_subset(ininfo->lefthand, rel1->relids) &&
|
||||
bms_equal(ininfo->righthand, rel2->relids))
|
||||
{
|
||||
jointype = JOIN_IN;
|
||||
}
|
||||
else if (is_subseti(ininfo->lefthand, rel2->relids) &&
|
||||
sameseti(ininfo->righthand, rel1->relids))
|
||||
else if (bms_is_subset(ininfo->lefthand, rel2->relids) &&
|
||||
bms_equal(ininfo->righthand, rel1->relids))
|
||||
{
|
||||
jointype = JOIN_REVERSE_IN;
|
||||
}
|
||||
else if (sameseti(ininfo->righthand, rel1->relids))
|
||||
else if (bms_equal(ininfo->righthand, rel1->relids))
|
||||
{
|
||||
jointype = JOIN_UNIQUE_OUTER;
|
||||
}
|
||||
else if (sameseti(ininfo->righthand, rel2->relids))
|
||||
else if (bms_equal(ininfo->righthand, rel2->relids))
|
||||
{
|
||||
jointype = JOIN_UNIQUE_INNER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* invalid join path */
|
||||
freeList(joinrelids);
|
||||
bms_free(joinrelids);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -579,7 +576,7 @@ make_join_rel(Query *root, RelOptInfo *rel1, RelOptInfo *rel2,
|
||||
break;
|
||||
}
|
||||
|
||||
freeList(joinrelids);
|
||||
bms_free(joinrelids);
|
||||
|
||||
return joinrel;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.45 2003/01/24 03:58:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.46 2003/02/08 20:20:54 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -198,7 +198,7 @@ generate_implied_equalities(Query *root)
|
||||
* Collect info about relids mentioned in each item. For this
|
||||
* routine we only really care whether there are any at all in
|
||||
* each item, but process_implied_equality() needs the exact
|
||||
* lists, so we may as well pull them here.
|
||||
* sets, so we may as well pull them here.
|
||||
*/
|
||||
relids = (Relids *) palloc(nitems * sizeof(Relids));
|
||||
have_consts = false;
|
||||
@@ -208,7 +208,7 @@ generate_implied_equalities(Query *root)
|
||||
PathKeyItem *item1 = (PathKeyItem *) lfirst(ptr1);
|
||||
|
||||
relids[i1] = pull_varnos(item1->key);
|
||||
if (relids[i1] == NIL)
|
||||
if (bms_is_empty(relids[i1]))
|
||||
have_consts = true;
|
||||
i1++;
|
||||
}
|
||||
@@ -221,12 +221,14 @@ generate_implied_equalities(Query *root)
|
||||
foreach(ptr1, curset)
|
||||
{
|
||||
PathKeyItem *item1 = (PathKeyItem *) lfirst(ptr1);
|
||||
bool i1_is_variable = !bms_is_empty(relids[i1]);
|
||||
List *ptr2;
|
||||
int i2 = i1 + 1;
|
||||
|
||||
foreach(ptr2, lnext(ptr1))
|
||||
{
|
||||
PathKeyItem *item2 = (PathKeyItem *) lfirst(ptr2);
|
||||
bool i2_is_variable = !bms_is_empty(relids[i2]);
|
||||
|
||||
/*
|
||||
* If it's "const = const" then just ignore it altogether.
|
||||
@@ -235,7 +237,7 @@ generate_implied_equalities(Query *root)
|
||||
* propagating the comparison to Vars will cause us to
|
||||
* produce zero rows out, as expected.)
|
||||
*/
|
||||
if (relids[i1] != NIL || relids[i2] != NIL)
|
||||
if (i1_is_variable || i2_is_variable)
|
||||
{
|
||||
/*
|
||||
* Tell process_implied_equality to delete the clause,
|
||||
@@ -243,8 +245,9 @@ generate_implied_equalities(Query *root)
|
||||
* present in the list.
|
||||
*/
|
||||
bool delete_it = (have_consts &&
|
||||
relids[i1] != NIL &&
|
||||
relids[i2] != NIL);
|
||||
i1_is_variable &&
|
||||
i2_is_variable);
|
||||
|
||||
process_implied_equality(root,
|
||||
item1->key, item2->key,
|
||||
item1->sortop, item2->sortop,
|
||||
@@ -689,7 +692,7 @@ static Var *
|
||||
find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno)
|
||||
{
|
||||
List *temp;
|
||||
int relid;
|
||||
Index relid;
|
||||
Oid reloid,
|
||||
vartypeid;
|
||||
int32 type_mod;
|
||||
@@ -702,7 +705,8 @@ find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno)
|
||||
return tle_var;
|
||||
}
|
||||
|
||||
relid = lfirsti(rel->relids);
|
||||
relid = rel->relid;
|
||||
Assert(relid > 0);
|
||||
reloid = getrelid(relid, root->rtable);
|
||||
vartypeid = get_atttype(reloid, varattno);
|
||||
type_mod = get_atttypmod(reloid, varattno);
|
||||
@@ -953,12 +957,12 @@ make_pathkeys_for_mergeclauses(Query *root,
|
||||
|
||||
cache_mergeclause_pathkeys(root, restrictinfo);
|
||||
|
||||
if (is_subseti(restrictinfo->left_relids, rel->relids))
|
||||
if (bms_is_subset(restrictinfo->left_relids, rel->relids))
|
||||
{
|
||||
/* Rel is left side of mergeclause */
|
||||
pathkey = restrictinfo->left_pathkey;
|
||||
}
|
||||
else if (is_subseti(restrictinfo->right_relids, rel->relids))
|
||||
else if (bms_is_subset(restrictinfo->right_relids, rel->relids))
|
||||
{
|
||||
/* Rel is right side of mergeclause */
|
||||
pathkey = restrictinfo->right_pathkey;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.13 2002/12/12 15:49:32 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.14 2003/02/08 20:20:54 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "parser/parse_coerce.h"
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
static List *TidqualFromRestrictinfo(List *relids, List *restrictinfo);
|
||||
static List *TidqualFromRestrictinfo(Relids relids, List *restrictinfo);
|
||||
static bool isEvaluable(int varno, Node *node);
|
||||
static Node *TidequalClause(int varno, OpExpr *node);
|
||||
static List *TidqualFromExpr(int varno, Expr *expr);
|
||||
@@ -198,7 +198,7 @@ TidqualFromExpr(int varno, Expr *expr)
|
||||
}
|
||||
|
||||
static List *
|
||||
TidqualFromRestrictinfo(List *relids, List *restrictinfo)
|
||||
TidqualFromRestrictinfo(Relids relids, List *restrictinfo)
|
||||
{
|
||||
List *lst,
|
||||
*rlst = NIL;
|
||||
@@ -206,9 +206,9 @@ TidqualFromRestrictinfo(List *relids, List *restrictinfo)
|
||||
Node *node;
|
||||
Expr *expr;
|
||||
|
||||
if (length(relids) != 1)
|
||||
if (bms_membership(relids) != BMS_SINGLETON)
|
||||
return NIL;
|
||||
varno = lfirsti(relids);
|
||||
varno = bms_singleton_member(relids);
|
||||
foreach(lst, restrictinfo)
|
||||
{
|
||||
node = lfirst(lst);
|
||||
|
||||
Reference in New Issue
Block a user