@@ -129,19 +129,23 @@ static void
129129TidListEval (TidScanState * tidstate )
130130{
131131 ExprContext * econtext = tidstate -> ss .ps .ps_ExprContext ;
132- BlockNumber nblocks ;
132+ TableScanDesc scan ;
133133 ItemPointerData * tidList ;
134134 int numAllocTids ;
135135 int numTids ;
136136 ListCell * l ;
137137
138138 /*
139- * We silently discard any TIDs that are out of range at the time of scan
140- * start. (Since we hold at least AccessShareLock on the table, it won't
141- * be possible for someone to truncate away the blocks we intend to
142- * visit.)
139+ * Start scan on-demand - initializing a scan isn't free (e.g. heap stats
140+ * the size of the table), so it makes sense to delay that until needed -
141+ * the node might never get executed.
143142 */
144- nblocks = RelationGetNumberOfBlocks (tidstate -> ss .ss_currentRelation );
143+ if (tidstate -> ss .ss_currentScanDesc == NULL )
144+ tidstate -> ss .ss_currentScanDesc =
145+ table_beginscan (tidstate -> ss .ss_currentRelation ,
146+ tidstate -> ss .ps .state -> es_snapshot ,
147+ 0 , NULL );
148+ scan = tidstate -> ss .ss_currentScanDesc ;
145149
146150 /*
147151 * We initialize the array with enough slots for the case that all quals
@@ -165,19 +169,27 @@ TidListEval(TidScanState *tidstate)
165169 DatumGetPointer (ExecEvalExprSwitchContext (tidexpr -> exprstate ,
166170 econtext ,
167171 & isNull ));
168- if (!isNull &&
169- ItemPointerIsValid (itemptr ) &&
170- ItemPointerGetBlockNumber (itemptr ) < nblocks )
172+ if (isNull )
173+ continue ;
174+
175+ /*
176+ * We silently discard any TIDs that the AM considers invalid
177+ * (E.g. for heap, they could be out of range at the time of scan
178+ * start. Since we hold at least AccessShareLock on the table, it
179+ * won't be possible for someone to truncate away the blocks we
180+ * intend to visit.).
181+ */
182+ if (!table_tuple_tid_valid (scan , itemptr ))
183+ continue ;
184+
185+ if (numTids >= numAllocTids )
171186 {
172- if (numTids >= numAllocTids )
173- {
174- numAllocTids *= 2 ;
175- tidList = (ItemPointerData * )
176- repalloc (tidList ,
177- numAllocTids * sizeof (ItemPointerData ));
178- }
179- tidList [numTids ++ ] = * itemptr ;
187+ numAllocTids *= 2 ;
188+ tidList = (ItemPointerData * )
189+ repalloc (tidList ,
190+ numAllocTids * sizeof (ItemPointerData ));
180191 }
192+ tidList [numTids ++ ] = * itemptr ;
181193 }
182194 else if (tidexpr -> exprstate && tidexpr -> isarray )
183195 {
@@ -206,13 +218,15 @@ TidListEval(TidScanState *tidstate)
206218 }
207219 for (i = 0 ; i < ndatums ; i ++ )
208220 {
209- if (!ipnulls [i ])
210- {
211- itemptr = (ItemPointer ) DatumGetPointer (ipdatums [i ]);
212- if (ItemPointerIsValid (itemptr ) &&
213- ItemPointerGetBlockNumber (itemptr ) < nblocks )
214- tidList [numTids ++ ] = * itemptr ;
215- }
221+ if (ipnulls [i ])
222+ continue ;
223+
224+ itemptr = (ItemPointer ) DatumGetPointer (ipdatums [i ]);
225+
226+ if (!table_tuple_tid_valid (scan , itemptr ))
227+ continue ;
228+
229+ tidList [numTids ++ ] = * itemptr ;
216230 }
217231 pfree (ipdatums );
218232 pfree (ipnulls );
@@ -306,6 +320,7 @@ TidNext(TidScanState *node)
306320 EState * estate ;
307321 ScanDirection direction ;
308322 Snapshot snapshot ;
323+ TableScanDesc scan ;
309324 Relation heapRelation ;
310325 TupleTableSlot * slot ;
311326 ItemPointerData * tidList ;
@@ -327,6 +342,7 @@ TidNext(TidScanState *node)
327342 if (node -> tss_TidList == NULL )
328343 TidListEval (node );
329344
345+ scan = node -> ss .ss_currentScanDesc ;
330346 tidList = node -> tss_TidList ;
331347 numTids = node -> tss_NumTids ;
332348
@@ -365,7 +381,7 @@ TidNext(TidScanState *node)
365381 * current according to our snapshot.
366382 */
367383 if (node -> tss_isCurrentOf )
368- table_get_latest_tid (heapRelation , snapshot , & tid );
384+ table_get_latest_tid (scan , & tid );
369385
370386 if (table_fetch_row_version (heapRelation , & tid , snapshot , slot ))
371387 return slot ;
@@ -442,6 +458,10 @@ ExecReScanTidScan(TidScanState *node)
442458 node -> tss_NumTids = 0 ;
443459 node -> tss_TidPtr = -1 ;
444460
461+ /* not really necessary, but seems good form */
462+ if (node -> ss .ss_currentScanDesc )
463+ table_rescan (node -> ss .ss_currentScanDesc , NULL );
464+
445465 ExecScanReScan (& node -> ss );
446466}
447467
@@ -455,6 +475,9 @@ ExecReScanTidScan(TidScanState *node)
455475void
456476ExecEndTidScan (TidScanState * node )
457477{
478+ if (node -> ss .ss_currentScanDesc )
479+ table_endscan (node -> ss .ss_currentScanDesc );
480+
458481 /*
459482 * Free the exprcontext
460483 */
0 commit comments