1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-14 08:21:07 +03:00

Fix optimizer to not try to push WHERE clauses down into a sub-SELECT that

has a DISTINCT ON clause, per bug report from Anthony Wood.  While at it,
improve the DISTINCT-ON-clause recognizer routine to not be fooled by out-
of-order DISTINCT lists.
This commit is contained in:
Tom Lane
2001-07-31 17:56:31 +00:00
parent 6fbf442d5a
commit 421467cdc8
4 changed files with 70 additions and 40 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.77 2001/07/16 17:57:02 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.78 2001/07/31 17:56:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -296,8 +296,12 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel,
* the quals down into the component queries of the setop, but getting it
* right seems nontrivial. Work on this later.)
*
* 2. If the subquery has a LIMIT clause we must not push down any quals,
* since that could change the set of rows returned.
* 2. If the subquery has a LIMIT clause or a DISTINCT ON clause, we must
* not push down any quals, since that could change the set of rows
* returned. (Actually, we could push down quals into a DISTINCT ON
* subquery if they refer only to DISTINCT-ed output columns, but checking
* that seems more work than it's worth. In any case, a plain DISTINCT is
* safe to push down past.)
*
* 3. We do not push down clauses that contain subselects, mainly because
* I'm not sure it will work correctly (the subplan hasn't yet transformed
@ -311,7 +315,8 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel,
*/
if (subquery->setOperations == NULL &&
subquery->limitOffset == NULL &&
subquery->limitCount == NULL)
subquery->limitCount == NULL &&
!has_distinct_on_clause(subquery))
{
/* OK to consider pushing down individual quals */
List *upperrestrictlist = NIL;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.86 2001/06/19 22:39:11 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.87 2001/07/31 17:56:31 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -728,6 +728,58 @@ pull_constant_clauses(List *quals, List **constantQual)
}
/*****************************************************************************
* Tests on clauses of queries
*
* Possibly this code should go someplace else, since this isn't quite the
* same meaning of "clause" as is used elsewhere in this module. But I can't
* think of a better place for it...
*****************************************************************************/
/*
* Test whether a query uses DISTINCT ON, ie, has a distinct-list that is
* just a subset of the output columns.
*/
bool
has_distinct_on_clause(Query *query)
{
List *targetList;
/* Is there a DISTINCT clause at all? */
if (query->distinctClause == NIL)
return false;
/*
* If the DISTINCT list contains all the nonjunk targetlist items,
* then it's a simple DISTINCT, else it's DISTINCT ON. We do not
* require the lists to be in the same order (since the parser may
* have adjusted the DISTINCT clause ordering to agree with ORDER BY).
*/
foreach(targetList, query->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(targetList);
Index ressortgroupref;
List *distinctClause;
if (tle->resdom->resjunk)
continue;
ressortgroupref = tle->resdom->ressortgroupref;
if (ressortgroupref == 0)
return true; /* definitely not in DISTINCT list */
foreach(distinctClause, query->distinctClause)
{
SortClause *scl = (SortClause *) lfirst(distinctClause);
if (scl->tleSortGroupRef == ressortgroupref)
break; /* found TLE in DISTINCT */
}
if (distinctClause == NIL)
return true; /* this TLE is not in DISTINCT list */
}
/* It's a simple DISTINCT */
return false;
}
/*****************************************************************************
* *
* General clause-manipulating routines *
@ -735,7 +787,7 @@ pull_constant_clauses(List *quals, List **constantQual)
*****************************************************************************/
/*
* clause_relids_vars
* clause_get_relids_vars
* Retrieves distinct relids and vars appearing within a clause.
*
* '*relids' is set to an integer list of all distinct "varno"s appearing