1111 * Portions Copyright (c) 1994, Regents of the University of California
1212 *
1313 * 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 $
1515 *
1616 *-------------------------------------------------------------------------
1717 */
@@ -752,25 +752,43 @@ find_mergeclauses_for_pathkeys(Query *root,
752752List * mergeclauses = NIL ;
753753List * i ;
754754
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+
755763foreach (i ,pathkeys )
756764{
757765List * pathkey = lfirst (i );
758- RestrictInfo * matched_restrictinfo = NULL ;
766+ List * matched_restrictinfos = NIL ;
759767List * j ;
760768
761769/*
762770 * 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.
767787 */
768788foreach (j ,restrictinfos )
769789{
770790RestrictInfo * restrictinfo = lfirst (j );
771791
772- cache_mergeclause_pathkeys (root ,restrictinfo );
773-
774792/*
775793 * We can compare canonical pathkey sublists by simple pointer
776794 * equality; see compare_pathkeys.
@@ -779,8 +797,8 @@ find_mergeclauses_for_pathkeys(Query *root,
779797pathkey == restrictinfo -> right_pathkey )&&
780798!ptrMember (restrictinfo ,mergeclauses ))
781799{
782- matched_restrictinfo = restrictinfo ;
783- break ;
800+ matched_restrictinfos = lappend ( matched_restrictinfos ,
801+ restrictinfo ) ;
784802}
785803}
786804
@@ -789,14 +807,14 @@ find_mergeclauses_for_pathkeys(Query *root,
789807 * sort-key positions in the pathkeys are useless.(But we can
790808 * still mergejoin if we found at least one mergeclause.)
791809 */
792- if (! matched_restrictinfo )
810+ if (matched_restrictinfos == NIL )
793811break ;
794812
795813/*
796- * If we did finda usable mergeclause for this sort-key position,
797- * addit to result list.
814+ * If we did find usable mergeclause(s) for this sort-key position,
815+ * addthem to result list.
798816 */
799- mergeclauses = lappend (mergeclauses ,matched_restrictinfo );
817+ mergeclauses = nconc (mergeclauses ,matched_restrictinfos );
800818}
801819
802820return mergeclauses ;