Repair problem noted by Elphick: make_rels_by_joins failed to handle
cases where joinclauses were present but some joins have to be made by cartesian-product join anyway. An example is SELECT * FROM a,b,c WHERE (a.f1 + b.f2 + c.f3) = 0; Even though all the rels have joinclauses, we must join two of them in cartesian style before we can use the join clause...
This commit is contained in:
parent
85a5303877
commit
d6eac08f11
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.44 2000/04/12 17:15:20 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.45 2000/04/27 18:35:04 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -39,6 +39,7 @@ static RelOptInfo *make_join_rel(Query *root, RelOptInfo *rel1,
|
|||||||
void
|
void
|
||||||
make_rels_by_joins(Query *root, int level)
|
make_rels_by_joins(Query *root, int level)
|
||||||
{
|
{
|
||||||
|
List *first_old_rel = root->join_rel_list;
|
||||||
List *r;
|
List *r;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -85,7 +86,9 @@ make_rels_by_joins(Query *root, int level)
|
|||||||
* Note that if all available join clauses for this rel
|
* Note that if all available join clauses for this rel
|
||||||
* require more than one other rel, we will fail to make any
|
* require more than one other rel, we will fail to make any
|
||||||
* joins against it here. That's OK; it'll be considered by
|
* joins against it here. That's OK; it'll be considered by
|
||||||
* "bushy plan" join code in a higher-level pass.
|
* "bushy plan" join code in a higher-level pass where we
|
||||||
|
* have those other rels collected into a join rel. See also
|
||||||
|
* the last-ditch case below.
|
||||||
*/
|
*/
|
||||||
make_rels_by_clause_joins(root,
|
make_rels_by_clause_joins(root,
|
||||||
old_rel,
|
old_rel,
|
||||||
@ -161,6 +164,52 @@ make_rels_by_joins(Query *root, int level)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Last-ditch effort: if we failed to find any usable joins so far,
|
||||||
|
* force a set of cartesian-product joins to be generated. This
|
||||||
|
* handles the special case where all the available rels have join
|
||||||
|
* clauses but we cannot use any of the joins yet. An example is
|
||||||
|
*
|
||||||
|
* SELECT * FROM a,b,c WHERE (a.f1 + b.f2 + c.f3) = 0;
|
||||||
|
*
|
||||||
|
* The join clause will be usable at level 3, but at level 2 we have
|
||||||
|
* no choice but to make cartesian joins. We consider only left-sided
|
||||||
|
* and right-sided cartesian joins in this case (no bushy).
|
||||||
|
*/
|
||||||
|
if (root->join_rel_list == first_old_rel)
|
||||||
|
{
|
||||||
|
/* This loop is just like the first one, except we always call
|
||||||
|
* make_rels_by_clauseless_joins().
|
||||||
|
*/
|
||||||
|
if (level == 2)
|
||||||
|
r = root->base_rel_list; /* level-1 is base rels */
|
||||||
|
else
|
||||||
|
r = root->join_rel_list;
|
||||||
|
for (; r != NIL; r = lnext(r))
|
||||||
|
{
|
||||||
|
RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
|
||||||
|
int old_level = length(old_rel->relids);
|
||||||
|
List *other_rels;
|
||||||
|
|
||||||
|
if (old_level != level - 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (level == 2)
|
||||||
|
other_rels = lnext(r); /* only consider remaining base
|
||||||
|
* rels */
|
||||||
|
else
|
||||||
|
other_rels = root->base_rel_list; /* consider all base rels */
|
||||||
|
|
||||||
|
make_rels_by_clauseless_joins(root,
|
||||||
|
old_rel,
|
||||||
|
other_rels);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root->join_rel_list == first_old_rel)
|
||||||
|
elog(ERROR, "make_rels_by_joins: failed to build any %d-way joins",
|
||||||
|
level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user