Fix code that checks to see if an index can be considered to match the query's
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 29 Jan 2006 17:27:50 +0000 (17:27 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 29 Jan 2006 17:27:50 +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 0d185d8785cdbfff2375b28378f2668327369603..15b0f4d5ce7f718acb0d6789eb0cc2984d22cab0 100644 (file)
@@ -326,7 +326,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);
                }
@@ -1512,7 +1513,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 b480535fb1ff062b511c6345a93b27cb49b00f42..6fc66fb4bfe318c734b6bdd8fdb615925f8fa997 100644 (file)
@@ -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 667cffd0ddd3f4b841c83e044a6c79a01c35de32..417c2437463db8459148dfe7695fb79c2ce2f53e 100644 (file)
@@ -108,7 +108,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,