Fix code that checks to see if an index can be considered to match the query's
authorTom Lane
Sun, 29 Jan 2006 17:27:42 +0000 (17:27 +0000)
committerTom Lane
Sun, 29 Jan 2006 17:27:42 +0000 (17:27 +0000)
requested sort order.  It was assuming that build_index_pathkeys always
generates a pathkey per index column, which was not true if implied equality
deduction had determined that two index columns were effectively equated to
each other.  Simplest fix seems to be to install an option that causes
build_index_pathkeys to support this behavior as well as the original one.
Per report from Brian Hirt.

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

index a00ad764c71f67e0e4e6e6ee81f821cb890f7d05..4eea16a0183d922d155907440fb193802275f70f 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.198 2006/01/26 02:35:49 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.199 2006/01/29 17:27:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -343,7 +343,8 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
        if (istoplevel && index_is_ordered && !isjoininner)
        {
            index_pathkeys = build_index_pathkeys(root, index,
-                                                 ForwardScanDirection);
+                                                 ForwardScanDirection,
+                                                 true);
            useful_pathkeys = truncate_useless_pathkeys(root, rel,
                                                        index_pathkeys);
        }
@@ -1705,7 +1706,7 @@ match_index_to_query_keys(PlannerInfo *root,
    ListCell   *r;
 
    /* Get the pathkeys that exactly describe the index */
-   index_pathkeys = build_index_pathkeys(root, index, indexscandir);
+   index_pathkeys = build_index_pathkeys(root, index, indexscandir, false);
 
    /*
     * Can we match to the query's requested pathkeys?  The inner loop skips
index 4216768212cdf1624e552be5c136ecb7560c4b6e..dc7687916f680d6a69aa94ecea07e95ede89bfd5 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.74 2005/11/22 18:17:12 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.75 2006/01/29 17:27:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -909,13 +909,20 @@ get_cheapest_fractional_path_for_pathkeys(List *paths,
  * If 'scandir' is BackwardScanDirection, attempt to build pathkeys
  * representing a backwards scan of the index. Return NIL if can't do it.
  *
+ * If 'canonical' is TRUE, we remove duplicate pathkeys (which can occur
+ * if two index columns are equijoined, eg WHERE x = 1 AND y = 1).  This
+ * is required if the result is to be compared directly to a canonical query
+ * pathkeys list.  However, some callers want a list with exactly one entry
+ * per index column, and they must pass FALSE.
+ *
  * We generate the full pathkeys list whether or not all are useful for the
  * current query.  Caller should do truncate_useless_pathkeys().
  */
 List *
 build_index_pathkeys(PlannerInfo *root,
                     IndexOptInfo *index,
-                    ScanDirection scandir)
+                    ScanDirection scandir,
+                    bool canonical)
 {
    List       *retval = NIL;
    int        *indexkeys = index->indexkeys;
@@ -956,11 +963,11 @@ build_index_pathkeys(PlannerInfo *root,
        item = makePathKeyItem(indexkey, sortop, true);
        cpathkey = make_canonical_pathkey(root, item);
 
-       /*
-        * Eliminate redundant ordering info; could happen if query is such
-        * that index keys are equijoined...
-        */
-       retval = list_append_unique_ptr(retval, cpathkey);
+       /* Eliminate redundant ordering info if requested */
+       if (canonical)
+           retval = list_append_unique_ptr(retval, cpathkey);
+       else
+           retval = lappend(retval, cpathkey);
 
        indexkeys++;
        ordering++;
index afe3a70d71bd489647dcd5bbb7b9e5a1dc25b01e..d9fab6ac04205b635addf67e13967476f232f291 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.90 2005/12/20 02:30:36 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.91 2006/01/29 17:27:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -114,7 +114,7 @@ extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
                                          List *pathkeys,
                                          double fraction);
 extern List *build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index,
-                    ScanDirection scandir);
+                    ScanDirection scandir, bool canonical);
 extern List *convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
                          List *subquery_pathkeys);
 extern List *build_join_pathkeys(PlannerInfo *root,