The result of a FULL or RIGHT join can't be assumed to be sorted by the
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 23 Jan 2005 02:26:05 +0000 (02:26 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 23 Jan 2005 02:26:05 +0000 (02:26 +0000)
left input's sorting, because null rows may be inserted at various points.
Per report from Ferenc Lutischá¸n.

src/backend/optimizer/path/joinpath.c
src/backend/optimizer/path/pathkeys.c
src/include/optimizer/paths.h

index 4d60569e7ef6fc01ab9e5fb283c56dc5df7c35a8..26fa7dea16cc3ee2e8edf0f232962d37be2605de 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.67 2001/11/11 19:18:54 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.67.2.1 2005/01/23 02:25:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -253,7 +253,8 @@ sort_inner_and_outer(Query *root,
                                                   cur_mergeclauses,
                                                   innerrel);
        /* Build pathkeys representing output sort order. */
-       merge_pathkeys = build_join_pathkeys(root, joinrel, outerkeys);
+       merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
+                                            outerkeys);
 
        /*
         * And now we can make the path.  We only consider the cheapest-
@@ -371,7 +372,7 @@ match_unsorted_outer(Query *root,
         * as a nestloop, and even if some of the mergeclauses are
         * implemented by qpquals rather than as true mergeclauses):
         */
-       merge_pathkeys = build_join_pathkeys(root, joinrel,
+       merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
                                             outerpath->pathkeys);
 
        if (nestjoinOK)
index f91e25cdb4fc986056efa91f0e86c314d90e8f05..0c9cc21edc900e7e37052d6d5f2e7f632ea315b4 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.36 2001/11/11 20:33:53 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.36.2.1 2005/01/23 02:25:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -621,7 +621,12 @@ find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno)
  *   vars they were joined with; furthermore, it doesn't matter what kind
  *   of join algorithm is actually used.
  *
+ *   EXCEPTION: in a FULL or RIGHT join, we cannot treat the result as
+ *   having the outer path's path keys, because null lefthand rows may be
+ *   inserted at random points.  It must be treated as unsorted.
+ *
  * 'joinrel' is the join relation that paths are being formed for
+ * 'jointype' is the join type (inner, left, full, etc)
  * 'outer_pathkeys' is the list of the current outer path's path keys
  *
  * Returns the list of new path keys.
@@ -629,8 +634,12 @@ find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno)
 List *
 build_join_pathkeys(Query *root,
                    RelOptInfo *joinrel,
+                   JoinType jointype,
                    List *outer_pathkeys)
 {
+   if (jointype == JOIN_FULL || jointype == JOIN_RIGHT)
+       return NIL;
+
    /*
     * This used to be quite a complex bit of code, but now that all
     * pathkey sublists start out life canonicalized, we don't have to do
index 81b87141751f91a552fe9001b227edfc4564269c..a3f30e0094df06defc924398793fa1afe65a1450 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: paths.h,v 1.59 2001/11/05 17:46:34 momjian Exp $
+ * $Id: paths.h,v 1.59.2.1 2005/01/23 02:26:05 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -112,6 +112,7 @@ extern List *build_index_pathkeys(Query *root, RelOptInfo *rel,
                     ScanDirection scandir);
 extern List *build_join_pathkeys(Query *root,
                    RelOptInfo *joinrel,
+                   JoinType jointype,
                    List *outer_pathkeys);
 extern List *make_pathkeys_for_sortclauses(List *sortclauses,
                              List *tlist);