diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 5bb850e0da2..0bf06c52867 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.87 2001/07/31 17:56:31 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.88 2001/07/31 20:16:33 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -737,8 +737,30 @@ pull_constant_clauses(List *quals, List **constantQual) *****************************************************************************/ /* + * Test whether a sort/group reference value appears in the given list of + * SortClause (or GroupClause) nodes. + * + * Because GroupClause is typedef'd as SortClause, either kind of + * node list can be passed without casting. + */ +static bool +sortgroupref_is_present(Index sortgroupref, List *clauselist) +{ + List *clause; + + foreach(clause, clauselist) + { + SortClause *scl = (SortClause *) lfirst(clause); + + if (scl->tleSortGroupRef == sortgroupref) + return true; + } + return false; +} + +/* * Test whether a query uses DISTINCT ON, ie, has a distinct-list that is - * just a subset of the output columns. + * not the same as the set of output columns. */ bool has_distinct_on_clause(Query *query) @@ -750,30 +772,43 @@ has_distinct_on_clause(Query *query) 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). + * and nothing else (ie, no junk tlist 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). Furthermore, a non-DISTINCT + * junk tlist item that is in the sortClause is also evidence of + * DISTINCT ON, since we don't allow ORDER BY on junk tlist items when + * plain DISTINCT is used. + * + * This code assumes that the DISTINCT list is valid, ie, all its entries + * match some entry of the tlist. */ foreach(targetList, query->targetList) { TargetEntry *tle = (TargetEntry *) lfirst(targetList); - Index ressortgroupref; - List *distinctClause; + Index ressortgroupref = tle->resdom->ressortgroupref; - if (tle->resdom->resjunk) - continue; - ressortgroupref = tle->resdom->ressortgroupref; if (ressortgroupref == 0) + { + if (tle->resdom->resjunk) + continue; /* we can ignore unsorted junk cols */ return true; /* definitely not in DISTINCT list */ - foreach(distinctClause, query->distinctClause) + } + if (sortgroupref_is_present(ressortgroupref, query->distinctClause)) { - SortClause *scl = (SortClause *) lfirst(distinctClause); - - if (scl->tleSortGroupRef == ressortgroupref) - break; /* found TLE in DISTINCT */ + if (tle->resdom->resjunk) + return true; /* junk TLE in DISTINCT means DISTINCT ON */ + /* else this TLE is okay, keep looking */ + } + else + { + /* This TLE is not in DISTINCT list */ + if (!tle->resdom->resjunk) + return true; /* non-junk, non-DISTINCT, so DISTINCT ON */ + if (sortgroupref_is_present(ressortgroupref, query->sortClause)) + return true; /* sorted, non-distinct junk */ + /* unsorted junk is okay, keep looking */ } - if (distinctClause == NIL) - return true; /* this TLE is not in DISTINCT list */ } /* It's a simple DISTINCT */ return false; |