]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Properly check index mark/restore in ExecSupportsMarkRestore.
authorAndrew Gierth <rhodiumtoad@postgresql.org>
Tue, 24 Nov 2020 20:58:32 +0000 (20:58 +0000)
committerAndrew Gierth <rhodiumtoad@postgresql.org>
Tue, 24 Nov 2020 21:19:50 +0000 (21:19 +0000)
Previously this code assumed that all IndexScan nodes supported
mark/restore, which is not true since it depends on optional index AM
support functions. This could lead to errors about missing support
functions in rare edge cases of mergejoins with no sort keys, where an
unordered non-btree index scan was placed on the inner path without a
protecting Materialize node. (Normally, the fact that merge join
requires ordered input would avoid this error.)

Backpatch all the way since this bug is ancient.

Per report from Eugen Konkov on irc.

Discussion: https://postgr.es/m/87o8jn50be.fsf@news-spur.riddles.org.uk

src/backend/executor/execAmi.c
src/backend/optimizer/util/plancat.c
src/include/nodes/relation.h

index 2587ef704626e10b0b744c645cc3a40d89b2c23d..27690ec2fb34927a0d17eb107162edb2933cb678 100644 (file)
@@ -394,6 +394,11 @@ ExecSupportsMarkRestore(Path *pathnode)
        {
                case T_IndexScan:
                case T_IndexOnlyScan:
+                       /*
+                        * Not all index types support mark/restore.
+                        */
+                       return castNode(IndexPath, pathnode)->indexinfo->amcanmarkpos;
+
                case T_Material:
                case T_Sort:
                        return true;
index 945e6e61047cba29596360b2aee67d93f852685b..72fc75d5339d0fa40599a3a737d3f06b93822b77 100644 (file)
@@ -242,6 +242,8 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
                        info->amsearchnulls = amroutine->amsearchnulls;
                        info->amhasgettuple = (amroutine->amgettuple != NULL);
                        info->amhasgetbitmap = (amroutine->amgetbitmap != NULL);
+                       info->amcanmarkpos = (amroutine->ammarkpos != NULL &&
+                                                                 amroutine->amrestrpos != NULL);
                        info->amcostestimate = amroutine->amcostestimate;
                        Assert(info->amcostestimate != NULL);
 
index 7b215f0075e5039bc74f03615ffa845e7918274b..fa68b99a0f0c4b0bf1083d77203f36810f2324a9 100644 (file)
@@ -620,6 +620,7 @@ typedef struct IndexOptInfo
        bool            amsearchnulls;  /* can AM search for NULL/NOT NULL entries? */
        bool            amhasgettuple;  /* does AM have amgettuple interface? */
        bool            amhasgetbitmap; /* does AM have amgetbitmap interface? */
+       bool            amcanmarkpos;   /* does AM support mark/restore? */
        /* Rather than include amapi.h here, we declare amcostestimate like this */
        void            (*amcostestimate) ();   /* AM's cost estimator */
 } IndexOptInfo;