mirror of
https://github.com/postgres/postgres.git
synced 2025-05-18 17:41:14 +03:00
Repair planner failure for cases involving Cartesian products inside
IN (sub-SELECT) constructs. We must force a clauseless join of the sub-select member relations, but it wasn't happening because the code thought it would be able to use the join clause arising from the IN.
This commit is contained in:
parent
052cd647c7
commit
67a1bf1bb1
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.63.4.1 2003/12/17 17:08:06 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.63.4.2 2004/01/24 00:37:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -24,6 +24,7 @@ static List *make_rels_by_clause_joins(Query *root,
|
|||||||
static List *make_rels_by_clauseless_joins(Query *root,
|
static List *make_rels_by_clauseless_joins(Query *root,
|
||||||
RelOptInfo *old_rel,
|
RelOptInfo *old_rel,
|
||||||
List *other_rels);
|
List *other_rels);
|
||||||
|
static bool is_inside_IN(Query *root, RelOptInfo *rel);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -76,14 +77,26 @@ make_rels_by_joins(Query *root, int level, List **joinrels)
|
|||||||
/*
|
/*
|
||||||
* 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. In most cases that's OK; it'll be
|
||||||
* "bushy plan" join code in a higher-level pass where we have
|
* considered by "bushy plan" join code in a higher-level pass
|
||||||
* those other rels collected into a join rel. See also the
|
* where we have those other rels collected into a join rel.
|
||||||
* last-ditch case below.
|
|
||||||
*/
|
*/
|
||||||
new_rels = make_rels_by_clause_joins(root,
|
new_rels = make_rels_by_clause_joins(root,
|
||||||
old_rel,
|
old_rel,
|
||||||
other_rels);
|
other_rels);
|
||||||
|
/*
|
||||||
|
* An exception occurs when there is a clauseless join inside an
|
||||||
|
* IN (sub-SELECT) construct. Here, the members of the subselect
|
||||||
|
* all have join clauses (against the stuff outside the IN), but
|
||||||
|
* they *must* be joined to each other before we can make use of
|
||||||
|
* those join clauses. So do the clauseless join bit.
|
||||||
|
*
|
||||||
|
* See also the last-ditch case below.
|
||||||
|
*/
|
||||||
|
if (new_rels == NIL && is_inside_IN(root, old_rel))
|
||||||
|
new_rels = make_rels_by_clauseless_joins(root,
|
||||||
|
old_rel,
|
||||||
|
other_rels);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -347,6 +360,29 @@ make_rels_by_clauseless_joins(Query *root,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* is_inside_IN
|
||||||
|
* Detect whether the specified relation is inside an IN (sub-SELECT).
|
||||||
|
*
|
||||||
|
* Note that we are actually only interested in rels that have been pulled up
|
||||||
|
* out of an IN, so the routine name is a slight misnomer.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
is_inside_IN(Query *root, RelOptInfo *rel)
|
||||||
|
{
|
||||||
|
List *i;
|
||||||
|
|
||||||
|
foreach(i, root->in_info_list)
|
||||||
|
{
|
||||||
|
InClauseInfo *ininfo = (InClauseInfo *) lfirst(i);
|
||||||
|
|
||||||
|
if (bms_is_subset(rel->relids, ininfo->righthand))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make_jointree_rel
|
* make_jointree_rel
|
||||||
* Find or build a RelOptInfo join rel representing a specific
|
* Find or build a RelOptInfo join rel representing a specific
|
||||||
|
Loading…
x
Reference in New Issue
Block a user