8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.87 2001/07/31 17:56:31 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.88 2001/07/31 20:16:33 tgl Exp $
12
12
*
13
13
* HISTORY
14
14
* AUTHOR DATE MAJOR EVENT
@@ -736,9 +736,31 @@ pull_constant_clauses(List *quals, List **constantQual)
736
736
* think of a better place for it...
737
737
*****************************************************************************/
738
738
739
+ /*
740
+ * Test whether a sort/group reference value appears in the given list of
741
+ * SortClause (or GroupClause) nodes.
742
+ *
743
+ * Because GroupClause is typedef'd as SortClause, either kind of
744
+ * node list can be passed without casting.
745
+ */
746
+ static bool
747
+ sortgroupref_is_present (Index sortgroupref , List * clauselist )
748
+ {
749
+ List * clause ;
750
+
751
+ foreach (clause , clauselist )
752
+ {
753
+ SortClause * scl = (SortClause * ) lfirst (clause );
754
+
755
+ if (scl -> tleSortGroupRef == sortgroupref )
756
+ return true;
757
+ }
758
+ return false;
759
+ }
760
+
739
761
/*
740
762
* Test whether a query uses DISTINCT ON, ie, has a distinct-list that is
741
- * just a subset of the output columns.
763
+ * not the same as the set of output columns.
742
764
*/
743
765
bool
744
766
has_distinct_on_clause (Query * query )
@@ -750,30 +772,43 @@ has_distinct_on_clause(Query *query)
750
772
return false;
751
773
/*
752
774
* If the DISTINCT list contains all the nonjunk targetlist items,
753
- * then it's a simple DISTINCT, else it's DISTINCT ON. We do not
754
- * require the lists to be in the same order (since the parser may
755
- * have adjusted the DISTINCT clause ordering to agree with ORDER BY).
775
+ * and nothing else (ie, no junk tlist items), then it's a simple
776
+ * DISTINCT, else it's DISTINCT ON. We do not require the lists to be
777
+ * in the same order (since the parser may have adjusted the DISTINCT
778
+ * clause ordering to agree with ORDER BY). Furthermore, a non-DISTINCT
779
+ * junk tlist item that is in the sortClause is also evidence of
780
+ * DISTINCT ON, since we don't allow ORDER BY on junk tlist items when
781
+ * plain DISTINCT is used.
782
+ *
783
+ * This code assumes that the DISTINCT list is valid, ie, all its entries
784
+ * match some entry of the tlist.
756
785
*/
757
786
foreach (targetList , query -> targetList )
758
787
{
759
788
TargetEntry * tle = (TargetEntry * ) lfirst (targetList );
760
- Index ressortgroupref ;
761
- List * distinctClause ;
789
+ Index ressortgroupref = tle -> resdom -> ressortgroupref ;
762
790
763
- if (tle -> resdom -> resjunk )
764
- continue ;
765
- ressortgroupref = tle -> resdom -> ressortgroupref ;
766
791
if (ressortgroupref == 0 )
792
+ {
793
+ if (tle -> resdom -> resjunk )
794
+ continue ; /* we can ignore unsorted junk cols */
767
795
return true; /* definitely not in DISTINCT list */
768
- foreach (distinctClause , query -> distinctClause )
796
+ }
797
+ if (sortgroupref_is_present (ressortgroupref , query -> distinctClause ))
769
798
{
770
- SortClause * scl = (SortClause * ) lfirst (distinctClause );
771
-
772
- if (scl -> tleSortGroupRef == ressortgroupref )
773
- break ; /* found TLE in DISTINCT */
799
+ if (tle -> resdom -> resjunk )
800
+ return true; /* junk TLE in DISTINCT means DISTINCT ON */
801
+ /* else this TLE is okay, keep looking */
802
+ }
803
+ else
804
+ {
805
+ /* This TLE is not in DISTINCT list */
806
+ if (!tle -> resdom -> resjunk )
807
+ return true; /* non-junk, non-DISTINCT, so DISTINCT ON */
808
+ if (sortgroupref_is_present (ressortgroupref , query -> sortClause ))
809
+ return true; /* sorted, non-distinct junk */
810
+ /* unsorted junk is okay, keep looking */
774
811
}
775
- if (distinctClause == NIL )
776
- return true; /* this TLE is not in DISTINCT list */
777
812
}
778
813
/* It's a simple DISTINCT */
779
814
return false;
0 commit comments