PostgreSQL Source Code  git master
nodeTidscan.c File Reference
#include "postgres.h"
#include "access/sysattr.h"
#include "access/tableam.h"
#include "catalog/pg_type.h"
#include "executor/execdebug.h"
#include "executor/nodeTidscan.h"
#include "lib/qunique.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.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:576
Definition: primnodes.h:181
struct Var Var
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21

Definition at line 38 of file nodeTidscan.c.

Referenced by TidExprListCreate().

Typedef Documentation

◆ TidExpr

typedef struct TidExpr TidExpr

Function Documentation

◆ ExecEndTidScan()

void ExecEndTidScan ( TidScanState node)

Definition at line 469 of file nodeTidscan.c.

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

Referenced by ExecEndNode().

470 {
471  if (node->ss.ss_currentScanDesc)
473 
474  /*
475  * Free the exprcontext
476  */
477  ExecFreeExprContext(&node->ss.ps);
478 
479  /*
480  * clear out tuple table slots
481  */
482  if (node->ss.ps.ps_ResultTupleSlot)
485 }
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1328
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1329
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:614
PlanState ps
Definition: execnodes.h:1326
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:977
ScanState ss
Definition: execnodes.h:1614
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:849

◆ ExecInitTidScan()

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

Definition at line 499 of file nodeTidscan.c.

References ExecAssignExprContext(), ExecAssignScanProjectionInfo(), ExecInitQual(), ExecInitResultTypeTL(), ExecInitScanTupleSlot(), ExecOpenScanRelation(), PlanState::ExecProcNode, ExecTidScan(), makeNode, Scan::plan, PlanState::plan, ScanState::ps, Plan::qual, PlanState::qual, RelationGetDescr, TidScan::scan, Scan::scanrelid, TidScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, PlanState::state, table_slot_callbacks(), TidExprListCreate(), TidScanState::tss_NumTids, TidScanState::tss_TidList, and TidScanState::tss_TidPtr.

Referenced by ExecInitNode().

500 {
501  TidScanState *tidstate;
502  Relation currentRelation;
503 
504  /*
505  * create state structure
506  */
507  tidstate = makeNode(TidScanState);
508  tidstate->ss.ps.plan = (Plan *) node;
509  tidstate->ss.ps.state = estate;
510  tidstate->ss.ps.ExecProcNode = ExecTidScan;
511 
512  /*
513  * Miscellaneous initialization
514  *
515  * create expression context for node
516  */
517  ExecAssignExprContext(estate, &tidstate->ss.ps);
518 
519  /*
520  * mark tid list as not computed yet
521  */
522  tidstate->tss_TidList = NULL;
523  tidstate->tss_NumTids = 0;
524  tidstate->tss_TidPtr = -1;
525 
526  /*
527  * open the scan relation
528  */
529  currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
530 
531  tidstate->ss.ss_currentRelation = currentRelation;
532  tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
533 
534  /*
535  * get the scan type from the relation descriptor.
536  */
537  ExecInitScanTupleSlot(estate, &tidstate->ss,
538  RelationGetDescr(currentRelation),
539  table_slot_callbacks(currentRelation));
540 
541  /*
542  * Initialize result type and projection.
543  */
544  ExecInitResultTypeTL(&tidstate->ss.ps);
545  ExecAssignScanProjectionInfo(&tidstate->ss);
546 
547  /*
548  * initialize child expressions
549  */
550  tidstate->ss.ps.qual =
551  ExecInitQual(node->scan.plan.qual, (PlanState *) tidstate);
552 
553  TidExprListCreate(tidstate);
554 
555  /*
556  * all done.
557  */
558  return tidstate;
559 }
List * qual
Definition: plannodes.h:143
Plan plan
Definition: plannodes.h:344
Index scanrelid
Definition: plannodes.h:345
#define RelationGetDescr(relation)
Definition: rel.h:454
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition: tableam.c:44
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1328
Relation ss_currentRelation
Definition: execnodes.h:1327
EState * state
Definition: execnodes.h:941
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:207
PlanState ps
Definition: execnodes.h:1326
ScanState ss
Definition: execnodes.h:1614
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:272
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:693
ItemPointerData * tss_TidList
Definition: execnodes.h:1619
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1781
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1725
static void TidExprListCreate(TidScanState *tidstate)
Definition: nodeTidscan.c:66
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:945
Plan * plan
Definition: execnodes.h:939
#define makeNode(_type_)
Definition: nodes.h:573
Scan scan
Definition: plannodes.h:492
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:444
ExprState * qual
Definition: execnodes.h:960
static TupleTableSlot * ExecTidScan(PlanState *pstate)
Definition: nodeTidscan.c:432

◆ ExecReScanTidScan()

void ExecReScanTidScan ( TidScanState node)

Definition at line 446 of file nodeTidscan.c.

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

Referenced by ExecReScan().

447 {
448  if (node->tss_TidList)
449  pfree(node->tss_TidList);
450  node->tss_TidList = NULL;
451  node->tss_NumTids = 0;
452  node->tss_TidPtr = -1;
453 
454  /* not really necessary, but seems good form */
455  if (node->ss.ss_currentScanDesc)
456  table_rescan(node->ss.ss_currentScanDesc, NULL);
457 
458  ExecScanReScan(&node->ss);
459 }
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1328
static void table_rescan(TableScanDesc scan, struct ScanKeyData *key)
Definition: tableam.h:858
void pfree(void *pointer)
Definition: mcxt.c:1056
ScanState ss
Definition: execnodes.h:1614
ItemPointerData * tss_TidList
Definition: execnodes.h:1619
void ExecScanReScan(ScanState *node)
Definition: execScan.c:299

◆ ExecTidScan()

static TupleTableSlot* ExecTidScan ( PlanState pstate)
static

Definition at line 432 of file nodeTidscan.c.

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

Referenced by ExecInitTidScan().

433 {
434  TidScanState *node = castNode(TidScanState, pstate);
435 
436  return ExecScan(&node->ss,
439 }
static TupleTableSlot * TidNext(TidScanState *node)
Definition: nodeTidscan.c:311
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:158
static bool TidRecheck(TidScanState *node, TupleTableSlot *slot)
Definition: nodeTidscan.c:402
ScanState ss
Definition: execnodes.h:1614
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:426
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:425

◆ itemptr_comparator()

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

Definition at line 282 of file nodeTidscan.c.

References ItemPointerGetBlockNumber, and ItemPointerGetOffsetNumber.

Referenced by TidListEval().

283 {
284  const ItemPointerData *ipa = (const ItemPointerData *) a;
285  const ItemPointerData *ipb = (const ItemPointerData *) b;
290 
291  if (ba < bb)
292  return -1;
293  if (ba > bb)
294  return 1;
295  if (oa < ob)
296  return -1;
297  if (oa > ob)
298  return 1;
299  return 0;
300 }
uint32 BlockNumber
Definition: block.h:31
uint16 OffsetNumber
Definition: off.h:24
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:98

◆ TidExprListCreate()

static void TidExprListCreate ( TidScanState tidstate)
static

Definition at line 66 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().

67 {
68  TidScan *node = (TidScan *) tidstate->ss.ps.plan;
69  ListCell *l;
70 
71  tidstate->tss_tidexprs = NIL;
72  tidstate->tss_isCurrentOf = false;
73 
74  foreach(l, node->tidquals)
75  {
76  Expr *expr = (Expr *) lfirst(l);
77  TidExpr *tidexpr = (TidExpr *) palloc0(sizeof(TidExpr));
78 
79  if (is_opclause(expr))
80  {
81  Node *arg1;
82  Node *arg2;
83 
84  arg1 = get_leftop(expr);
85  arg2 = get_rightop(expr);
86  if (IsCTIDVar(arg1))
87  tidexpr->exprstate = ExecInitExpr((Expr *) arg2,
88  &tidstate->ss.ps);
89  else if (IsCTIDVar(arg2))
90  tidexpr->exprstate = ExecInitExpr((Expr *) arg1,
91  &tidstate->ss.ps);
92  else
93  elog(ERROR, "could not identify CTID variable");
94  tidexpr->isarray = false;
95  }
96  else if (expr && IsA(expr, ScalarArrayOpExpr))
97  {
98  ScalarArrayOpExpr *saex = (ScalarArrayOpExpr *) expr;
99 
100  Assert(IsCTIDVar(linitial(saex->args)));
101  tidexpr->exprstate = ExecInitExpr(lsecond(saex->args),
102  &tidstate->ss.ps);
103  tidexpr->isarray = true;
104  }
105  else if (expr && IsA(expr, CurrentOfExpr))
106  {
107  CurrentOfExpr *cexpr = (CurrentOfExpr *) expr;
108 
109  tidexpr->cexpr = cexpr;
110  tidstate->tss_isCurrentOf = true;
111  }
112  else
113  elog(ERROR, "could not identify CTID expression");
114 
115  tidstate->tss_tidexprs = lappend(tidstate->tss_tidexprs, tidexpr);
116  }
117 
118  /* CurrentOfExpr could never appear OR'd with something else */
119  Assert(list_length(tidstate->tss_tidexprs) == 1 ||
120  !tidstate->tss_isCurrentOf);
121 }
CurrentOfExpr * cexpr
Definition: nodeTidscan.c:49
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
bool isarray
Definition: nodeTidscan.c:48
List * tidquals
Definition: plannodes.h:493
Definition: nodes.h:525
#define lsecond(l)
Definition: pg_list.h:200
PlanState ps
Definition: execnodes.h:1326
#define linitial(l)
Definition: pg_list.h:195
#define ERROR
Definition: elog.h:43
ScanState ss
Definition: execnodes.h:1614
List * tss_tidexprs
Definition: execnodes.h:1615
bool tss_isCurrentOf
Definition: execnodes.h:1616
static Node * get_leftop(const void *clause)
Definition: nodeFuncs.h:70
List * lappend(List *list, void *datum)
Definition: list.c:322
void * palloc0(Size size)
Definition: mcxt.c:980
static Node * get_rightop(const void *clause)
Definition: nodeFuncs.h:82
Plan * plan
Definition: execnodes.h:939
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
#define IsCTIDVar(node)
Definition: nodeTidscan.c:38
#define elog(elevel,...)
Definition: elog.h:228
ExprState * exprstate
Definition: nodeTidscan.c:47
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:121
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:63

◆ TidListEval()

static void TidListEval ( TidScanState tidstate)
static

Definition at line 130 of file nodeTidscan.c.

References Assert, TidExpr::cexpr, DatumGetArrayTypeP, DatumGetPointer, deconstruct_array(), EState::es_snapshot, execCurrentOf(), ExecEvalExprSwitchContext(), TidExpr::exprstate, i, TidExpr::isarray, itemptr_comparator(), lfirst, list_length(), palloc(), pfree(), ScanState::ps, PlanState::ps_ExprContext, qsort, qunique(), RelationGetRelid, repalloc(), TidScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, PlanState::state, table_beginscan(), table_tuple_tid_valid(), TidScanState::tss_isCurrentOf, TidScanState::tss_NumTids, TidScanState::tss_tidexprs, TidScanState::tss_TidList, and TidScanState::tss_TidPtr.

Referenced by TidNext().

131 {
132  ExprContext *econtext = tidstate->ss.ps.ps_ExprContext;
133  TableScanDesc scan;
134  ItemPointerData *tidList;
135  int numAllocTids;
136  int numTids;
137  ListCell *l;
138 
139  /*
140  * Start scan on-demand - initializing a scan isn't free (e.g. heap stats
141  * the size of the table), so it makes sense to delay that until needed -
142  * the node might never get executed.
143  */
144  if (tidstate->ss.ss_currentScanDesc == NULL)
145  tidstate->ss.ss_currentScanDesc =
147  tidstate->ss.ps.state->es_snapshot,
148  0, NULL);
149  scan = tidstate->ss.ss_currentScanDesc;
150 
151  /*
152  * We initialize the array with enough slots for the case that all quals
153  * are simple OpExprs or CurrentOfExprs. If there are any
154  * ScalarArrayOpExprs, we may have to enlarge the array.
155  */
156  numAllocTids = list_length(tidstate->tss_tidexprs);
157  tidList = (ItemPointerData *)
158  palloc(numAllocTids * sizeof(ItemPointerData));
159  numTids = 0;
160 
161  foreach(l, tidstate->tss_tidexprs)
162  {
163  TidExpr *tidexpr = (TidExpr *) lfirst(l);
164  ItemPointer itemptr;
165  bool isNull;
166 
167  if (tidexpr->exprstate && !tidexpr->isarray)
168  {
169  itemptr = (ItemPointer)
171  econtext,
172  &isNull));
173  if (isNull)
174  continue;
175 
176  /*
177  * We silently discard any TIDs that the AM considers invalid
178  * (E.g. for heap, they could be out of range at the time of scan
179  * start. Since we hold at least AccessShareLock on the table, it
180  * won't be possible for someone to truncate away the blocks we
181  * intend to visit.).
182  */
183  if (!table_tuple_tid_valid(scan, itemptr))
184  continue;
185 
186  if (numTids >= numAllocTids)
187  {
188  numAllocTids *= 2;
189  tidList = (ItemPointerData *)
190  repalloc(tidList,
191  numAllocTids * sizeof(ItemPointerData));
192  }
193  tidList[numTids++] = *itemptr;
194  }
195  else if (tidexpr->exprstate && tidexpr->isarray)
196  {
197  Datum arraydatum;
198  ArrayType *itemarray;
199  Datum *ipdatums;
200  bool *ipnulls;
201  int ndatums;
202  int i;
203 
204  arraydatum = ExecEvalExprSwitchContext(tidexpr->exprstate,
205  econtext,
206  &isNull);
207  if (isNull)
208  continue;
209  itemarray = DatumGetArrayTypeP(arraydatum);
210  deconstruct_array(itemarray,
211  TIDOID, sizeof(ItemPointerData), false, 's',
212  &ipdatums, &ipnulls, &ndatums);
213  if (numTids + ndatums > numAllocTids)
214  {
215  numAllocTids = numTids + ndatums;
216  tidList = (ItemPointerData *)
217  repalloc(tidList,
218  numAllocTids * sizeof(ItemPointerData));
219  }
220  for (i = 0; i < ndatums; i++)
221  {
222  if (ipnulls[i])
223  continue;
224 
225  itemptr = (ItemPointer) DatumGetPointer(ipdatums[i]);
226 
227  if (!table_tuple_tid_valid(scan, itemptr))
228  continue;
229 
230  tidList[numTids++] = *itemptr;
231  }
232  pfree(ipdatums);
233  pfree(ipnulls);
234  }
235  else
236  {
237  ItemPointerData cursor_tid;
238 
239  Assert(tidexpr->cexpr);
240  if (execCurrentOf(tidexpr->cexpr, econtext,
242  &cursor_tid))
243  {
244  if (numTids >= numAllocTids)
245  {
246  numAllocTids *= 2;
247  tidList = (ItemPointerData *)
248  repalloc(tidList,
249  numAllocTids * sizeof(ItemPointerData));
250  }
251  tidList[numTids++] = cursor_tid;
252  }
253  }
254  }
255 
256  /*
257  * Sort the array of TIDs into order, and eliminate duplicates.
258  * Eliminating duplicates is necessary since we want OR semantics across
259  * the list. Sorting makes it easier to detect duplicates, and as a bonus
260  * ensures that we will visit the heap in the most efficient way.
261  */
262  if (numTids > 1)
263  {
264  /* CurrentOfExpr could never appear OR'd with something else */
265  Assert(!tidstate->tss_isCurrentOf);
266 
267  qsort((void *) tidList, numTids, sizeof(ItemPointerData),
269  numTids = qunique(tidList, numTids, sizeof(ItemPointerData),
271  }
272 
273  tidstate->tss_TidList = tidList;
274  tidstate->tss_NumTids = numTids;
275  tidstate->tss_TidPtr = -1;
276 }
CurrentOfExpr * cexpr
Definition: nodeTidscan.c:49
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:300
ExprContext * ps_ExprContext
Definition: execnodes.h:978
bool isarray
Definition: nodeTidscan.c:48
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1328
Snapshot es_snapshot
Definition: execnodes.h:502
Relation ss_currentRelation
Definition: execnodes.h:1327
EState * state
Definition: execnodes.h:941
ItemPointerData * ItemPointer
Definition: itemptr.h:49
PlanState ps
Definition: execnodes.h:1326
void pfree(void *pointer)
Definition: mcxt.c:1056
ScanState ss
Definition: execnodes.h:1614
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:754
List * tss_tidexprs
Definition: execnodes.h:1615
ItemPointerData * tss_TidList
Definition: execnodes.h:1619
bool tss_isCurrentOf
Definition: execnodes.h:1616
static int itemptr_comparator(const void *a, const void *b)
Definition: nodeTidscan.c:282
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
Definition: qunique.h:21
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Oid table_oid, ItemPointer current_tid)
Definition: execCurrent.c:44
#define DatumGetPointer(X)
Definition: postgres.h:549
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
void * palloc(Size size)
Definition: mcxt.c:949
int i
static bool table_tuple_tid_valid(TableScanDesc scan, ItemPointer tid)
Definition: tableam.h:1056
ExprState * exprstate
Definition: nodeTidscan.c:47
#define qsort(a, b, c, d)
Definition: port.h:491
#define RelationGetRelid(relation)
Definition: rel.h:428
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ TidNext()

static TupleTableSlot * TidNext ( TidScanState node)
static

Definition at line 311 of file nodeTidscan.c.

References CHECK_FOR_INTERRUPTS, EState::es_direction, EState::es_snapshot, ExecClearTuple(), ScanState::ps, ScanDirectionIsBackward, TidScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, ScanState::ss_ScanTupleSlot, PlanState::state, table_tuple_fetch_row_version(), table_tuple_get_latest_tid(), TidListEval(), TidScanState::tss_isCurrentOf, TidScanState::tss_NumTids, TidScanState::tss_TidList, and TidScanState::tss_TidPtr.

Referenced by ExecTidScan().

312 {
313  EState *estate;
314  ScanDirection direction;
315  Snapshot snapshot;
316  TableScanDesc scan;
317  Relation heapRelation;
318  TupleTableSlot *slot;
319  ItemPointerData *tidList;
320  int numTids;
321  bool bBackward;
322 
323  /*
324  * extract necessary information from tid scan node
325  */
326  estate = node->ss.ps.state;
327  direction = estate->es_direction;
328  snapshot = estate->es_snapshot;
329  heapRelation = node->ss.ss_currentRelation;
330  slot = node->ss.ss_ScanTupleSlot;
331 
332  /*
333  * First time through, compute the list of TIDs to be visited
334  */
335  if (node->tss_TidList == NULL)
336  TidListEval(node);
337 
338  scan = node->ss.ss_currentScanDesc;
339  tidList = node->tss_TidList;
340  numTids = node->tss_NumTids;
341 
342  /*
343  * Initialize or advance scan position, depending on direction.
344  */
345  bBackward = ScanDirectionIsBackward(direction);
346  if (bBackward)
347  {
348  if (node->tss_TidPtr < 0)
349  {
350  /* initialize for backward scan */
351  node->tss_TidPtr = numTids - 1;
352  }
353  else
354  node->tss_TidPtr--;
355  }
356  else
357  {
358  if (node->tss_TidPtr < 0)
359  {
360  /* initialize for forward scan */
361  node->tss_TidPtr = 0;
362  }
363  else
364  node->tss_TidPtr++;
365  }
366 
367  while (node->tss_TidPtr >= 0 && node->tss_TidPtr < numTids)
368  {
369  ItemPointerData tid = tidList[node->tss_TidPtr];
370 
371  /*
372  * For WHERE CURRENT OF, the tuple retrieved from the cursor might
373  * since have been updated; if so, we should fetch the version that is
374  * current according to our snapshot.
375  */
376  if (node->tss_isCurrentOf)
377  table_tuple_get_latest_tid(scan, &tid);
378 
379  if (table_tuple_fetch_row_version(heapRelation, &tid, snapshot, slot))
380  return slot;
381 
382  /* Bad TID or failed snapshot qual; try next */
383  if (bBackward)
384  node->tss_TidPtr--;
385  else
386  node->tss_TidPtr++;
387 
389  }
390 
391  /*
392  * if we get here it means the tid scan failed so we are at the end of the
393  * scan..
394  */
395  return ExecClearTuple(slot);
396 }
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1328
Snapshot es_snapshot
Definition: execnodes.h:502
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1329
Relation ss_currentRelation
Definition: execnodes.h:1327
EState * state
Definition: execnodes.h:941
static void TidListEval(TidScanState *tidstate)
Definition: nodeTidscan.c:130
ScanDirection es_direction
Definition: execnodes.h:501
PlanState ps
Definition: execnodes.h:1326
#define ScanDirectionIsBackward(direction)
Definition: sdir.h:41
ScanState ss
Definition: execnodes.h:1614
ItemPointerData * tss_TidList
Definition: execnodes.h:1619
ScanDirection
Definition: sdir.h:22
bool tss_isCurrentOf
Definition: execnodes.h:1616
void table_tuple_get_latest_tid(TableScanDesc scan, ItemPointer tid)
Definition: tableam.c:228
static bool table_tuple_fetch_row_version(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot)
Definition: tableam.h:1039
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99

◆ TidRecheck()

static bool TidRecheck ( TidScanState node,
TupleTableSlot slot 
)
static

Definition at line 402 of file nodeTidscan.c.

Referenced by ExecTidScan().

403 {
404  /*
405  * XXX shouldn't we check here to make sure tuple matches TID list? In
406  * runtime-key case this is not certain, is it? However, in the WHERE
407  * CURRENT OF case it might not match anyway ...
408  */
409  return true;
410 }