]> granicus.if.org Git - postgresql/commitdiff
Fix confusion on different kinds of slots in IndexOnlyScans.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 6 Jun 2019 06:46:52 +0000 (09:46 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 6 Jun 2019 06:46:52 +0000 (09:46 +0300)
We used the same slot to store a tuple from the index, and to store a
tuple from the table. That's not OK. It worked with the heap, because
heapam_getnextslot() stores a HeapTuple to the slot, and doesn't care how
large the tts_values/nulls arrays are. But when I played with a toy table
AM implementation that used a virtual tuple, it caused memory overruns.

In the passing, tidy up comments on the ioss_PscanLen fields.

src/backend/executor/nodeIndexonlyscan.c
src/include/nodes/execnodes.h

index ee5b1c493b7e9a81a06a7ad72fa740136f76738d..8a4d795d1a9fe91515bd8b2f097a8c3bf155acca 100644 (file)
@@ -166,10 +166,10 @@ IndexOnlyNext(IndexOnlyScanState *node)
                         * Rats, we have to visit the heap to check visibility.
                         */
                        InstrCountTuples2(node, 1);
-                       if (!index_fetch_heap(scandesc, slot))
+                       if (!index_fetch_heap(scandesc, node->ioss_TableSlot))
                                continue;               /* no visible tuple, try next index entry */
 
-                       ExecClearTuple(slot);
+                       ExecClearTuple(node->ioss_TableSlot);
 
                        /*
                         * Only MVCC snapshots are supported here, so there should be no
@@ -528,7 +528,17 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
         */
        tupDesc = ExecTypeFromTL(node->indextlist);
        ExecInitScanTupleSlot(estate, &indexstate->ss, tupDesc,
-                                                 table_slot_callbacks(currentRelation));
+                                                 &TTSOpsVirtual);
+
+       /*
+        * We need another slot, in a format that's suitable for the table AM,
+        * for when we need to fetch a tuple from the table for rechecking
+        * visibility.
+        */
+       indexstate->ioss_TableSlot =
+               ExecAllocTableSlot(&estate->es_tupleTable,
+                                                  RelationGetDescr(currentRelation),
+                                                  table_slot_callbacks(currentRelation));
 
        /*
         * Initialize result type and projection info.  The node's targetlist will
index 112a9a53683f197b4f5cebcf45ff5bec1523f629..99b9fa414f138678b74a639cd249169b5dc2d122 100644 (file)
@@ -1359,7 +1359,7 @@ typedef struct
  *             SortSupport                for reordering ORDER BY exprs
  *             OrderByTypByVals   is the datatype of order by expression pass-by-value?
  *             OrderByTypLens     typlens of the datatypes of order by expressions
- *             pscan_len                  size of parallel index scan descriptor
+ *             PscanLen                   size of parallel index scan descriptor
  * ----------------
  */
 typedef struct IndexScanState
@@ -1403,8 +1403,9 @@ typedef struct IndexScanState
  *             RuntimeContext     expr context for evaling runtime Skeys
  *             RelationDesc       index relation descriptor
  *             ScanDesc                   index scan descriptor
+ *             TableSlot                  slot for holding tuples fetched from the table
  *             VMBuffer                   buffer in use for visibility map testing, if any
- *             ioss_PscanLen      Size of parallel index-only scan descriptor
+ *             PscanLen                   size of parallel index-only scan descriptor
  * ----------------
  */
 typedef struct IndexOnlyScanState
@@ -1421,6 +1422,7 @@ typedef struct IndexOnlyScanState
        ExprContext *ioss_RuntimeContext;
        Relation        ioss_RelationDesc;
        struct IndexScanDescData *ioss_ScanDesc;
+       TupleTableSlot *ioss_TableSlot;
        Buffer          ioss_VMBuffer;
        Size            ioss_PscanLen;
 } IndexOnlyScanState;