From 2d98f462551f6bbc0935e531c06e2b4c064b5020 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 29 Jan 2006 17:27:50 +0000 Subject: [PATCH] Fix code that checks to see if an index can be considered to match the query's 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 | 7 ++++--- src/backend/optimizer/path/pathkeys.c | 21 ++++++++++++++------- src/include/optimizer/paths.h | 4 ++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 393cdf691de..f3764344f1d 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.191.2.4 2005/12/06 16:50:46 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.191.2.5 2006/01/29 17:27:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -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 diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index 04d0914f036..f6ea5eb7fa9 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -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.73.2.1 2005/11/22 18:23:10 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.73.2.2 2006/01/29 17:27:50 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++; diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 4020f4bf49a..d71fba25497 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -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.88 2005/10/15 02:49:45 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.88.2.1 2006/01/29 17:27:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -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,