1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +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:
Tom Lane
2003-02-08 20:20:55 +00:00
parent 893678eda7
commit c15a4c2aef
35 changed files with 1453 additions and 626 deletions

View File

@ -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++;