11
11
* Portions Copyright (c) 1994, Regents of the University of California
12
12
*
13
13
* IDENTIFICATION
14
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.35 2001/10/28 06:25:44 momjian Exp $
14
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.36 2001/11/11 20:33:53 tgl Exp $
15
15
*
16
16
*-------------------------------------------------------------------------
17
17
*/
@@ -752,25 +752,43 @@ find_mergeclauses_for_pathkeys(Query *root,
752
752
List * mergeclauses = NIL ;
753
753
List * i ;
754
754
755
+ /* make sure we have pathkeys cached in the clauses */
756
+ foreach (i , restrictinfos )
757
+ {
758
+ RestrictInfo * restrictinfo = lfirst (i );
759
+
760
+ cache_mergeclause_pathkeys (root , restrictinfo );
761
+ }
762
+
755
763
foreach (i , pathkeys )
756
764
{
757
765
List * pathkey = lfirst (i );
758
- RestrictInfo * matched_restrictinfo = NULL ;
766
+ List * matched_restrictinfos = NIL ;
759
767
List * j ;
760
768
761
769
/*
762
770
* We can match a pathkey against either left or right side of any
763
- * mergejoin clause we haven't used yet. For the moment we use a
764
- * dumb "greedy" algorithm with no backtracking. Is it worth
765
- * being any smarter to make a longer list of usable mergeclauses?
766
- * Probably not.
771
+ * mergejoin clause. (We examine both sides since we aren't told if
772
+ * the given pathkeys are for inner or outer input path; no confusion
773
+ * is possible.) Furthermore, if there are multiple matching
774
+ * clauses, take them all. In plain inner-join scenarios we expect
775
+ * only one match, because redundant-mergeclause elimination will
776
+ * have removed any redundant mergeclauses from the input list.
777
+ * However, in outer-join scenarios there might be multiple matches.
778
+ * An example is
779
+ *
780
+ * select * from a full join b on
781
+ * a.v1 = b.v1 and a.v2 = b.v2 and a.v1 = b.v2;
782
+ *
783
+ * Given the pathkeys ((a.v1), (a.v2)) it is okay to return all
784
+ * three clauses (in the order a.v1=b.v1, a.v1=b.v2, a.v2=b.v2)
785
+ * and indeed we *must* do so or we will be unable to form a
786
+ * valid plan.
767
787
*/
768
788
foreach (j , restrictinfos )
769
789
{
770
790
RestrictInfo * restrictinfo = lfirst (j );
771
791
772
- cache_mergeclause_pathkeys (root , restrictinfo );
773
-
774
792
/*
775
793
* We can compare canonical pathkey sublists by simple pointer
776
794
* equality; see compare_pathkeys.
@@ -779,8 +797,8 @@ find_mergeclauses_for_pathkeys(Query *root,
779
797
pathkey == restrictinfo -> right_pathkey ) &&
780
798
!ptrMember (restrictinfo , mergeclauses ))
781
799
{
782
- matched_restrictinfo = restrictinfo ;
783
- break ;
800
+ matched_restrictinfos = lappend ( matched_restrictinfos ,
801
+ restrictinfo ) ;
784
802
}
785
803
}
786
804
@@ -789,14 +807,14 @@ find_mergeclauses_for_pathkeys(Query *root,
789
807
* sort-key positions in the pathkeys are useless. (But we can
790
808
* still mergejoin if we found at least one mergeclause.)
791
809
*/
792
- if (! matched_restrictinfo )
810
+ if (matched_restrictinfos == NIL )
793
811
break ;
794
812
795
813
/*
796
- * If we did find a usable mergeclause for this sort-key position,
797
- * add it to result list.
814
+ * If we did find usable mergeclause(s) for this sort-key position,
815
+ * add them to result list.
798
816
*/
799
- mergeclauses = lappend (mergeclauses , matched_restrictinfo );
817
+ mergeclauses = nconc (mergeclauses , matched_restrictinfos );
800
818
}
801
819
802
820
return mergeclauses ;
0 commit comments