PostgreSQL Source Code  git master
nodeTidscan.c File Reference
#include "postgres.h"
#include "access/sysattr.h"
#include "catalog/pg_type.h"
#include "executor/execdebug.h"
#include "executor/nodeTidscan.h"
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "storage/bufmgr.h"
#include "utils/array.h"
#include "utils/rel.h"
Include dependency graph for nodeTidscan.c:

Go to the source code of this file.

Data Structures

struct  TidExpr
 

Macros

#define IsCTIDVar(node)
 

Typedefs

typedef struct TidExpr TidExpr
 

Functions

static void TidExprListCreate (TidScanState *tidstate)
 
static void TidListEval (TidScanState *tidstate)
 
static int itemptr_comparator (const void *a, const void *b)
 
static TupleTableSlotTidNext (TidScanState *node)
 
static bool TidRecheck (TidScanState *node, TupleTableSlot *slot)
 
static TupleTableSlotExecTidScan (PlanState *pstate)
 
void ExecReScanTidScan (TidScanState *node)
 
void ExecEndTidScan (TidScanState *node)
 
TidScanStateExecInitTidScan (TidScan *node, EState *estate, int eflags)
 

Macro Definition Documentation

◆ IsCTIDVar

#define IsCTIDVar (   node)
Value:
((node) != NULL && \
IsA((node), Var) && \
((Var *) (node))->varattno == SelfItemPointerAttributeNumber && \
((Var *) (node))->varlevelsup == 0)
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Definition: primnodes.h:163
struct Var Var
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21

Definition at line 36 of file nodeTidscan.c.

Referenced by TidExprListCreate().

Typedef Documentation

◆ TidExpr

Function Documentation

◆ ExecEndTidScan()

void ExecEndTidScan ( TidScanState node)

Definition at line 482 of file nodeTidscan.c.

References ExecClearTuple(), ExecCloseScanRelation(), ExecFreeExprContext(), ScanState::ps, PlanState::ps_ResultTupleSlot, TidScanState::ss, ScanState::ss_currentRelation, and ScanState::ss_ScanTupleSlot.

Referenced by ExecEndNode().

483 {
484  /*
485  * Free the exprcontext
486  */
487  ExecFreeExprContext(&node->ss.ps);
488 
489  /*
490  * clear out tuple table slots
491  */
494 
495  /*
496  * close the heap relation.
497  */
499 }
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1106
Relation ss_currentRelation
Definition: execnodes.h:1104
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:523
PlanState ps
Definition: execnodes.h:1103
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:882
ScanState ss
Definition: execnodes.h:1388
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:668

◆ ExecInitTidScan()

TidScanState* ExecInitTidScan ( TidScan node,
EState estate,
int  eflags 
)

Definition at line 513 of file nodeTidscan.c.

References ExecAssignExprContext(), ExecAssignResultTypeFromTL(), ExecAssignScanProjectionInfo(), ExecAssignScanType(), ExecInitQual(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), ExecOpenScanRelation(), PlanState::ExecProcNode, ExecTidScan(), makeNode, Scan::plan, PlanState::plan, ScanState::ps, Plan::qual, PlanState::qual, RelationGetDescr, TidScan::scan, Scan::scanrelid, TidScanState::ss, PlanState::state, and TidExprListCreate().

Referenced by ExecInitNode().

514 {
515  TidScanState *tidstate;
516  Relation currentRelation;
517 
518  /*
519  * create state structure
520  */
521  tidstate = makeNode(TidScanState);
522  tidstate->ss.ps.plan = (Plan *) node;
523  tidstate->ss.ps.state = estate;
524  tidstate->ss.ps.ExecProcNode = ExecTidScan;
525 
526  /*
527  * Miscellaneous initialization
528  *
529  * create expression context for node
530  */
531  ExecAssignExprContext(estate, &tidstate->ss.ps);
532 
533  /*
534  * initialize child expressions
535  */
536  tidstate->ss.ps.qual =
537  ExecInitQual(node->scan.plan.qual, (PlanState *) tidstate);
538 
539  TidExprListCreate(tidstate);
540 
541  /*
542  * tuple table initialization
543  */
544  ExecInitResultTupleSlot(estate, &tidstate->ss.ps);
545  ExecInitScanTupleSlot(estate, &tidstate->ss);
546 
547  /*
548  * mark tid list as not computed yet
549  */
550  tidstate->tss_TidList = NULL;
551  tidstate->tss_NumTids = 0;
552  tidstate->tss_TidPtr = -1;
553 
554  /*
555  * open the base relation and acquire appropriate lock on it.
556  */
557  currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
558 
559  tidstate->ss.ss_currentRelation = currentRelation;
560  tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
561 
562  /*
563  * get the scan type from the relation descriptor.
564  */
565  ExecAssignScanType(&tidstate->ss, RelationGetDescr(currentRelation));
566 
567  /*
568  * Initialize result tuple type and projection info.
569  */
570  ExecAssignResultTypeFromTL(&tidstate->ss.ps);
571  ExecAssignScanProjectionInfo(&tidstate->ss);
572 
573  /*
574  * all done.
575  */
576  return tidstate;
577 }
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:328
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
Index scanrelid
Definition: plannodes.h:329
#define RelationGetDescr(relation)
Definition: rel.h:428
Relation ss_currentRelation
Definition: execnodes.h:1104
EState * state
Definition: execnodes.h:851
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:160
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:447
PlanState ps
Definition: execnodes.h:1103
ScanState ss
Definition: execnodes.h:1388
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:237
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:610
ItemPointerData * tss_TidList
Definition: execnodes.h:1393
static void TidExprListCreate(TidScanState *tidstate)
Definition: nodeTidscan.c:64
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:855
Plan * plan
Definition: execnodes.h:849
#define makeNode(_type_)
Definition: nodes.h:558
Scan scan
Definition: plannodes.h:475
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:425
ExprState * qual
Definition: execnodes.h:867
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1105
static TupleTableSlot * ExecTidScan(PlanState *pstate)
Definition: nodeTidscan.c:449
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:547

◆ ExecReScanTidScan()

void ExecReScanTidScan ( TidScanState node)

Definition at line 463 of file nodeTidscan.c.

References ExecScanReScan(), pfree(), TidScanState::ss, TidScanState::tss_NumTids, TidScanState::tss_TidList, and TidScanState::tss_TidPtr.

Referenced by ExecReScan().

464 {
465  if (node->tss_TidList)
466  pfree(node->tss_TidList);
467  node->tss_TidList = NULL;
468  node->tss_NumTids = 0;
469  node->tss_TidPtr = -1;
470 
471  ExecScanReScan(&node->ss);
472 }
void pfree(void *pointer)
Definition: mcxt.c:949
ScanState ss
Definition: execnodes.h:1388
ItemPointerData * tss_TidList
Definition: execnodes.h:1393
void ExecScanReScan(ScanState *node)
Definition: execScan.c:329

◆ ExecTidScan()

static TupleTableSlot* ExecTidScan ( PlanState pstate)
static

Definition at line 449 of file nodeTidscan.c.

References castNode, ExecScan(), TidScanState::ss, TidNext(), and TidRecheck().

Referenced by ExecInitTidScan().

450 {
451  TidScanState *node = castNode(TidScanState, pstate);
452 
453  return ExecScan(&node->ss,
456 }
static TupleTableSlot * TidNext(TidScanState *node)
Definition: nodeTidscan.c:303
#define castNode(_type_, nodeptr)
Definition: nodes.h:579
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:123
static bool TidRecheck(TidScanState *node, TupleTableSlot *slot)
Definition: nodeTidscan.c:419
ScanState ss
Definition: execnodes.h:1388
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:401
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:400

◆ itemptr_comparator()

static int itemptr_comparator ( const void *  a,
const void *  b 
)
static

Definition at line 274 of file nodeTidscan.c.

References ItemPointerGetBlockNumber, and ItemPointerGetOffsetNumber.

Referenced by TidListEval().

275 {
276  const ItemPointerData *ipa = (const ItemPointerData *) a;
277  const ItemPointerData *ipb = (const ItemPointerData *) b;
282 
283  if (ba < bb)
284  return -1;
285  if (ba > bb)
286  return 1;
287  if (oa < ob)
288  return -1;
289  if (oa > ob)
290  return 1;
291  return 0;
292 }
uint32 BlockNumber
Definition: block.h:31
uint16 OffsetNumber
Definition: off.h:24
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76

◆ TidExprListCreate()

static void TidExprListCreate ( TidScanState tidstate)
static

Definition at line 64 of file nodeTidscan.c.

References ScalarArrayOpExpr::args, Assert, TidExpr::cexpr, elog, ERROR, ExecInitExpr(), TidExpr::exprstate, get_leftop(), get_rightop(), is_opclause, IsA, TidExpr::isarray, IsCTIDVar, lappend(), lfirst, linitial, list_length(), lsecond, NIL, palloc0(), PlanState::plan, ScanState::ps, TidScanState::ss, TidScan::tidquals, TidScanState::tss_isCurrentOf, and TidScanState::tss_tidexprs.

Referenced by ExecInitTidScan().

65 {
66  TidScan *node = (TidScan *) tidstate->ss.ps.plan;
67  ListCell *l;
68 
69  tidstate->tss_tidexprs = NIL;
70  tidstate->tss_isCurrentOf = false;
71 
72  foreach(l, node->tidquals)
73  {
74  Expr *expr = (Expr *) lfirst(l);
75  TidExpr *tidexpr = (TidExpr *) palloc0(sizeof(TidExpr));
76 
77  if (is_opclause(expr))
78  {
79  Node *arg1;
80  Node *arg2;
81 
82  arg1 = get_leftop(expr);
83  arg2 = get_rightop(expr);
84  if (IsCTIDVar(arg1))
85  tidexpr->exprstate = ExecInitExpr((Expr *) arg2,
86  &tidstate->ss.ps);
87  else if (IsCTIDVar(arg2))
88  tidexpr->exprstate = ExecInitExpr((Expr *) arg1,
89  &tidstate->ss.ps);
90  else
91  elog(ERROR, "could not identify CTID variable");
92  tidexpr->isarray = false;
93  }
94  else if (expr && IsA(expr, ScalarArrayOpExpr))
95  {
96  ScalarArrayOpExpr *saex = (ScalarArrayOpExpr *) expr;
97 
98  Assert(IsCTIDVar(linitial(saex->args)));
99  tidexpr->exprstate = ExecInitExpr(lsecond(saex->args),
100  &tidstate->ss.ps);
101  tidexpr->isarray = true;
102  }
103  else if (expr && IsA(expr, CurrentOfExpr))
104  {
105  CurrentOfExpr *cexpr = (CurrentOfExpr *) expr;
106 
107  tidexpr->cexpr = cexpr;
108  tidstate->tss_isCurrentOf = true;
109  }
110  else
111  elog(ERROR, "could not identify CTID expression");
112 
113  tidstate->tss_tidexprs = lappend(tidstate->tss_tidexprs, tidexpr);
114  }
115 
116  /* CurrentOfExpr could never appear OR'd with something else */
117  Assert(list_length(tidstate->tss_tidexprs) == 1 ||
118  !tidstate->tss_isCurrentOf);
119 }
CurrentOfExpr * cexpr
Definition: nodeTidscan.c:47
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
bool isarray
Definition: nodeTidscan.c:46
List * tidquals
Definition: plannodes.h:476
Definition: nodes.h:510
#define lsecond(l)
Definition: pg_list.h:116
PlanState ps
Definition: execnodes.h:1103
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
ScanState ss
Definition: execnodes.h:1388
#define is_opclause(clause)
Definition: clauses.h:20
Node * get_leftop(const Expr *clause)
Definition: clauses.c:199
List * tss_tidexprs
Definition: execnodes.h:1389
bool tss_isCurrentOf
Definition: execnodes.h:1390
List * lappend(List *list, void *datum)
Definition: list.c:128
void * palloc0(Size size)
Definition: mcxt.c:877
Plan * plan
Definition: execnodes.h:849
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
#define IsCTIDVar(node)
Definition: nodeTidscan.c:36
Node * get_rightop(const Expr *clause)
Definition: clauses.c:216
ExprState * exprstate
Definition: nodeTidscan.c:45
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:113
#define elog
Definition: elog.h:219

◆ TidListEval()

static void TidListEval ( TidScanState tidstate)
static

Definition at line 128 of file nodeTidscan.c.

References Assert, TidExpr::cexpr, DatumGetArrayTypeP, DatumGetPointer, deconstruct_array(), execCurrentOf(), ExecEvalExprSwitchContext(), TidExpr::exprstate, i, TidExpr::isarray, ItemPointerEquals(), ItemPointerGetBlockNumber, ItemPointerIsValid, itemptr_comparator(), lfirst, list_length(), palloc(), pfree(), ScanState::ps, PlanState::ps_ExprContext, qsort, RelationGetNumberOfBlocks, RelationGetRelid, repalloc(), TidScanState::ss, ScanState::ss_currentRelation, TIDOID, TidScanState::tss_isCurrentOf, TidScanState::tss_NumTids, TidScanState::tss_tidexprs, TidScanState::tss_TidList, and TidScanState::tss_TidPtr.

Referenced by TidNext().

129 {
130  ExprContext *econtext = tidstate->ss.ps.ps_ExprContext;
131  BlockNumber nblocks;
132  ItemPointerData *tidList;
133  int numAllocTids;
134  int numTids;
135  ListCell *l;
136 
137  /*
138  * We silently discard any TIDs that are out of range at the time of scan
139  * start. (Since we hold at least AccessShareLock on the table, it won't
140  * be possible for someone to truncate away the blocks we intend to
141  * visit.)
142  */
143  nblocks = RelationGetNumberOfBlocks(tidstate->ss.ss_currentRelation);
144 
145  /*
146  * We initialize the array with enough slots for the case that all quals
147  * are simple OpExprs or CurrentOfExprs. If there are any
148  * ScalarArrayOpExprs, we may have to enlarge the array.
149  */
150  numAllocTids = list_length(tidstate->tss_tidexprs);
151  tidList = (ItemPointerData *)
152  palloc(numAllocTids * sizeof(ItemPointerData));
153  numTids = 0;
154 
155  foreach(l, tidstate->tss_tidexprs)
156  {
157  TidExpr *tidexpr = (TidExpr *) lfirst(l);
158  ItemPointer itemptr;
159  bool isNull;
160 
161  if (tidexpr->exprstate && !tidexpr->isarray)
162  {
163  itemptr = (ItemPointer)
165  econtext,
166  &isNull));
167  if (!isNull &&
168  ItemPointerIsValid(itemptr) &&
169  ItemPointerGetBlockNumber(itemptr) < nblocks)
170  {
171  if (numTids >= numAllocTids)
172  {
173  numAllocTids *= 2;
174  tidList = (ItemPointerData *)
175  repalloc(tidList,
176  numAllocTids * sizeof(ItemPointerData));
177  }
178  tidList[numTids++] = *itemptr;
179  }
180  }
181  else if (tidexpr->exprstate && tidexpr->isarray)
182  {
183  Datum arraydatum;
184  ArrayType *itemarray;
185  Datum *ipdatums;
186  bool *ipnulls;
187  int ndatums;
188  int i;
189 
190  arraydatum = ExecEvalExprSwitchContext(tidexpr->exprstate,
191  econtext,
192  &isNull);
193  if (isNull)
194  continue;
195  itemarray = DatumGetArrayTypeP(arraydatum);
196  deconstruct_array(itemarray,
197  TIDOID, sizeof(ItemPointerData), false, 's',
198  &ipdatums, &ipnulls, &ndatums);
199  if (numTids + ndatums > numAllocTids)
200  {
201  numAllocTids = numTids + ndatums;
202  tidList = (ItemPointerData *)
203  repalloc(tidList,
204  numAllocTids * sizeof(ItemPointerData));
205  }
206  for (i = 0; i < ndatums; i++)
207  {
208  if (!ipnulls[i])
209  {
210  itemptr = (ItemPointer) DatumGetPointer(ipdatums[i]);
211  if (ItemPointerIsValid(itemptr) &&
212  ItemPointerGetBlockNumber(itemptr) < nblocks)
213  tidList[numTids++] = *itemptr;
214  }
215  }
216  pfree(ipdatums);
217  pfree(ipnulls);
218  }
219  else
220  {
221  ItemPointerData cursor_tid;
222 
223  Assert(tidexpr->cexpr);
224  if (execCurrentOf(tidexpr->cexpr, econtext,
226  &cursor_tid))
227  {
228  if (numTids >= numAllocTids)
229  {
230  numAllocTids *= 2;
231  tidList = (ItemPointerData *)
232  repalloc(tidList,
233  numAllocTids * sizeof(ItemPointerData));
234  }
235  tidList[numTids++] = cursor_tid;
236  }
237  }
238  }
239 
240  /*
241  * Sort the array of TIDs into order, and eliminate duplicates.
242  * Eliminating duplicates is necessary since we want OR semantics across
243  * the list. Sorting makes it easier to detect duplicates, and as a bonus
244  * ensures that we will visit the heap in the most efficient way.
245  */
246  if (numTids > 1)
247  {
248  int lastTid;
249  int i;
250 
251  /* CurrentOfExpr could never appear OR'd with something else */
252  Assert(!tidstate->tss_isCurrentOf);
253 
254  qsort((void *) tidList, numTids, sizeof(ItemPointerData),
256  lastTid = 0;
257  for (i = 1; i < numTids; i++)
258  {
259  if (!ItemPointerEquals(&tidList[lastTid], &tidList[i]))
260  tidList[++lastTid] = tidList[i];
261  }
262  numTids = lastTid + 1;
263  }
264 
265  tidstate->tss_TidList = tidList;
266  tidstate->tss_NumTids = numTids;
267  tidstate->tss_TidPtr = -1;
268 }
CurrentOfExpr * cexpr
Definition: nodeTidscan.c:47
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:291
ExprContext * ps_ExprContext
Definition: execnodes.h:883
bool isarray
Definition: nodeTidscan.c:46
uint32 BlockNumber
Definition: block.h:31
Relation ss_currentRelation
Definition: execnodes.h:1104
ItemPointerData * ItemPointer
Definition: itemptr.h:49
PlanState ps
Definition: execnodes.h:1103
#define TIDOID
Definition: pg_type.h:332
void pfree(void *pointer)
Definition: mcxt.c:949
ScanState ss
Definition: execnodes.h:1388
List * tss_tidexprs
Definition: execnodes.h:1389
ItemPointerData * tss_TidList
Definition: execnodes.h:1393
bool tss_isCurrentOf
Definition: execnodes.h:1390
static int itemptr_comparator(const void *a, const void *b)
Definition: nodeTidscan.c:274
uintptr_t Datum
Definition: postgres.h:372
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:199
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Oid table_oid, ItemPointer current_tid)
Definition: execCurrent.c:41
#define DatumGetPointer(X)
Definition: postgres.h:555
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
void * palloc(Size size)
Definition: mcxt.c:848
int i
ExprState * exprstate
Definition: nodeTidscan.c:45
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76
#define qsort(a, b, c, d)
Definition: port.h:408
#define RelationGetRelid(relation)
Definition: rel.h:416
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ TidNext()

static TupleTableSlot * TidNext ( TidScanState node)
static

Definition at line 303 of file nodeTidscan.c.

References buffer, CHECK_FOR_INTERRUPTS, EState::es_direction, EState::es_snapshot, ExecClearTuple(), ExecStoreTuple(), heap_fetch(), heap_get_latest_tid(), InvalidBuffer, ScanState::ps, ReleaseBuffer(), ScanDirectionIsBackward, TidScanState::ss, ScanState::ss_currentRelation, ScanState::ss_ScanTupleSlot, PlanState::state, HeapTupleData::t_self, TidListEval(), TidScanState::tss_htup, TidScanState::tss_isCurrentOf, TidScanState::tss_NumTids, TidScanState::tss_TidList, and TidScanState::tss_TidPtr.

Referenced by ExecTidScan().

304 {
305  EState *estate;
306  ScanDirection direction;
307  Snapshot snapshot;
308  Relation heapRelation;
309  HeapTuple tuple;
310  TupleTableSlot *slot;
312  ItemPointerData *tidList;
313  int numTids;
314  bool bBackward;
315 
316  /*
317  * extract necessary information from tid scan node
318  */
319  estate = node->ss.ps.state;
320  direction = estate->es_direction;
321  snapshot = estate->es_snapshot;
322  heapRelation = node->ss.ss_currentRelation;
323  slot = node->ss.ss_ScanTupleSlot;
324 
325  /*
326  * First time through, compute the list of TIDs to be visited
327  */
328  if (node->tss_TidList == NULL)
329  TidListEval(node);
330 
331  tidList = node->tss_TidList;
332  numTids = node->tss_NumTids;
333 
334  /*
335  * We use node->tss_htup as the tuple pointer; note this can't just be a
336  * local variable here, as the scan tuple slot will keep a pointer to it.
337  */
338  tuple = &(node->tss_htup);
339 
340  /*
341  * Initialize or advance scan position, depending on direction.
342  */
343  bBackward = ScanDirectionIsBackward(direction);
344  if (bBackward)
345  {
346  if (node->tss_TidPtr < 0)
347  {
348  /* initialize for backward scan */
349  node->tss_TidPtr = numTids - 1;
350  }
351  else
352  node->tss_TidPtr--;
353  }
354  else
355  {
356  if (node->tss_TidPtr < 0)
357  {
358  /* initialize for forward scan */
359  node->tss_TidPtr = 0;
360  }
361  else
362  node->tss_TidPtr++;
363  }
364 
365  while (node->tss_TidPtr >= 0 && node->tss_TidPtr < numTids)
366  {
367  tuple->t_self = tidList[node->tss_TidPtr];
368 
369  /*
370  * For WHERE CURRENT OF, the tuple retrieved from the cursor might
371  * since have been updated; if so, we should fetch the version that is
372  * current according to our snapshot.
373  */
374  if (node->tss_isCurrentOf)
375  heap_get_latest_tid(heapRelation, snapshot, &tuple->t_self);
376 
377  if (heap_fetch(heapRelation, snapshot, tuple, &buffer, false, NULL))
378  {
379  /*
380  * store the scanned tuple in the scan tuple slot of the scan
381  * state. Eventually we will only do this and not return a tuple.
382  * Note: we pass 'false' because tuples returned by amgetnext are
383  * pointers onto disk pages and were not created with palloc() and
384  * so should not be pfree()'d.
385  */
386  ExecStoreTuple(tuple, /* tuple to store */
387  slot, /* slot to store in */
388  buffer, /* buffer associated with tuple */
389  false); /* don't pfree */
390 
391  /*
392  * At this point we have an extra pin on the buffer, because
393  * ExecStoreTuple incremented the pin count. Drop our local pin.
394  */
395  ReleaseBuffer(buffer);
396 
397  return slot;
398  }
399  /* Bad TID or failed snapshot qual; try next */
400  if (bBackward)
401  node->tss_TidPtr--;
402  else
403  node->tss_TidPtr++;
404 
406  }
407 
408  /*
409  * if we get here it means the tid scan failed so we are at the end of the
410  * scan..
411  */
412  return ExecClearTuple(slot);
413 }
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
bool heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tuple, Buffer *userbuf, bool keep_buf, Relation stats_relation)
Definition: heapam.c:1876
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
void heap_get_latest_tid(Relation relation, Snapshot snapshot, ItemPointer tid)
Definition: heapam.c:2184
#define InvalidBuffer
Definition: buf.h:25
Snapshot es_snapshot
Definition: execnodes.h:429
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1106
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
Relation ss_currentRelation
Definition: execnodes.h:1104
EState * state
Definition: execnodes.h:851
static void TidListEval(TidScanState *tidstate)
Definition: nodeTidscan.c:128
ScanDirection es_direction
Definition: execnodes.h:428
HeapTupleData tss_htup
Definition: execnodes.h:1394
PlanState ps
Definition: execnodes.h:1103
#define ScanDirectionIsBackward(direction)
Definition: sdir.h:41
ScanState ss
Definition: execnodes.h:1388
ItemPointerData t_self
Definition: htup.h:65
ItemPointerData * tss_TidList
Definition: execnodes.h:1393
ScanDirection
Definition: sdir.h:22
bool tss_isCurrentOf
Definition: execnodes.h:1390
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
int Buffer
Definition: buf.h:23

◆ TidRecheck()

static bool TidRecheck ( TidScanState node,
TupleTableSlot slot 
)
static

Definition at line 419 of file nodeTidscan.c.

Referenced by ExecTidScan().

420 {
421  /*
422  * XXX shouldn't we check here to make sure tuple matches TID list? In
423  * runtime-key case this is not certain, is it? However, in the WHERE
424  * CURRENT OF case it might not match anyway ...
425  */
426  return true;
427 }