Hi hackers! Experimenting with the new pluggable storage API, I found that amcanbackward flag is not checked in build_index_paths() before build_index_pathkeys(... BackwardScanDirection) call when we are building paths for ORDER BY. And this flag is even not copied into IndexOptInfo struct. Obviously, this can lead to misuse of Backward Index [Only] Scan plans.
Attached patch with the corresponding fix. There are no test cases because now only btree supports ordered scans but it supports backward scans too. -- Nikita Glukhov Postgres Professional: http://www.postgrespro.com The Russian Postgres Company
>From 2bb9a17a8efb166339bcd5618157728a4b596430 Mon Sep 17 00:00:00 2001 From: Nikita Glukhov <n.glu...@postgrespro.ru> Date: Sun, 13 May 2018 16:37:00 +0300 Subject: [PATCH] Disable backward scans on indices that do not support it --- src/backend/optimizer/path/indxpath.c | 2 +- src/backend/optimizer/util/plancat.c | 1 + src/include/nodes/relation.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index f295558..caa688c 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -1084,7 +1084,7 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel, /* * 5. If the index is ordered, a backwards scan might be interesting. */ - if (index_is_ordered && pathkeys_possibly_useful) + if (index_is_ordered && pathkeys_possibly_useful && index->amcanbackward) { index_pathkeys = build_index_pathkeys(root, index, BackwardScanDirection); diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 8369e3a..470d38e 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -271,6 +271,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, info->amsearcharray = amroutine->amsearcharray; info->amsearchnulls = amroutine->amsearchnulls; info->amcanparallel = amroutine->amcanparallel; + info->amcanbackward = amroutine->amcanbackward; info->amhasgettuple = (amroutine->amgettuple != NULL); info->amhasgetbitmap = (amroutine->amgetbitmap != NULL); info->amcostestimate = amroutine->amcostestimate; diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 3b28d19..593ee48 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -798,6 +798,7 @@ typedef struct IndexOptInfo bool amhasgettuple; /* does AM have amgettuple interface? */ bool amhasgetbitmap; /* does AM have amgetbitmap interface? */ bool amcanparallel; /* does AM support parallel scan? */ + bool amcanbackward; /* does AM support backward scan? */ /* Rather than include amapi.h here, we declare amcostestimate like this */ void (*amcostestimate) (); /* AM's cost estimator */ } IndexOptInfo; -- 2.7.4