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 "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:167
struct Var Var
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21

Definition at line 37 of file nodeTidscan.c.

Referenced by TidExprListCreate().

Typedef Documentation

◆ TidExpr

typedef struct TidExpr TidExpr

Function Documentation

◆ ExecEndTidScan()

void ExecEndTidScan ( TidScanState node)

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

477 {
478  if (node->ss.ss_currentScanDesc)
480 
481  /*
482  * Free the exprcontext
483  */
484  ExecFreeExprContext(&node->ss.ps);
485 
486  /*
487  * clear out tuple table slots
488  */
489  if (node->ss.ps.ps_ResultTupleSlot)
492 }
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:426
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1333
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1334
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:614
PlanState ps
Definition: execnodes.h:1331
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:978
ScanState ss
Definition: execnodes.h:1619
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:831

◆ ExecInitTidScan()

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

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

507 {
508  TidScanState *tidstate;
509  Relation currentRelation;
510 
511  /*
512  * create state structure
513  */
514  tidstate = makeNode(TidScanState);
515  tidstate->ss.ps.plan = (Plan *) node;
516  tidstate->ss.ps.state = estate;
517  tidstate->ss.ps.ExecProcNode = ExecTidScan;
518 
519  /*
520  * Miscellaneous initialization
521  *
522  * create expression context for node
523  */
524  ExecAssignExprContext(estate, &tidstate->ss.ps);
525 
526  /*
527  * mark tid list as not computed yet
528  */
529  tidstate->tss_TidList = NULL;
530  tidstate->tss_NumTids = 0;
531  tidstate->tss_TidPtr = -1;
532 
533  /*
534  * open the scan relation
535  */
536  currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
537 
538  tidstate->ss.ss_currentRelation = currentRelation;
539  tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
540 
541  /*
542  * get the scan type from the relation descriptor.
543  */
544  ExecInitScanTupleSlot(estate, &tidstate->ss,
545  RelationGetDescr(currentRelation),
546  table_slot_callbacks(currentRelation));
547 
548  /*
549  * Initialize result type and projection.
550  */
551  ExecInitResultTypeTL(&tidstate->ss.ps);
552  ExecAssignScanProjectionInfo(&tidstate->ss);
553 
554  /*
555  * initialize child expressions
556  */
557  tidstate->ss.ps.qual =
558  ExecInitQual(node->scan.plan.qual, (PlanState *) tidstate);
559 
560  TidExprListCreate(tidstate);
561 
562  /*
563  * all done.
564  */
565  return tidstate;
566 }
List * qual
Definition: plannodes.h:141
Plan plan
Definition: plannodes.h:340
Index scanrelid
Definition: plannodes.h:341
#define RelationGetDescr(relation)
Definition: rel.h:445
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition: tableam.c:44
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1333
Relation ss_currentRelation
Definition: execnodes.h:1332
EState * state
Definition: execnodes.h:942
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:207
PlanState ps
Definition: execnodes.h:1331
ScanState ss
Definition: execnodes.h:1619
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:1624
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1776
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1720
static void TidExprListCreate(TidScanState *tidstate)
Definition: nodeTidscan.c:65
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:946
Plan * plan
Definition: execnodes.h:940
#define makeNode(_type_)
Definition: nodes.h:573
Scan scan
Definition: plannodes.h:488
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:444
ExprState * qual
Definition: execnodes.h:961
static TupleTableSlot * ExecTidScan(PlanState *pstate)
Definition: nodeTidscan.c:439

◆ ExecReScanTidScan()

void ExecReScanTidScan ( TidScanState node)

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

454 {
455  if (node->tss_TidList)
456  pfree(node->tss_TidList);
457  node->tss_TidList = NULL;
458  node->tss_NumTids = 0;
459  node->tss_TidPtr = -1;
460 
461  /* not really necessary, but seems good form */
462  if (node->ss.ss_currentScanDesc)
463  table_rescan(node->ss.ss_currentScanDesc, NULL);
464 
465  ExecScanReScan(&node->ss);
466 }
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1333
static void table_rescan(TableScanDesc scan, struct ScanKeyData *key)
Definition: tableam.h:840
void pfree(void *pointer)
Definition: mcxt.c:1056
ScanState ss
Definition: execnodes.h:1619
ItemPointerData * tss_TidList
Definition: execnodes.h:1624
void ExecScanReScan(ScanState *node)
Definition: execScan.c:299

◆ ExecTidScan()

static TupleTableSlot* ExecTidScan ( PlanState pstate)
static

Definition at line 439 of file nodeTidscan.c.

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

Referenced by ExecInitTidScan().

440 {
441  TidScanState *node = castNode(TidScanState, pstate);
442 
443  return ExecScan(&node->ss,
446 }
static TupleTableSlot * TidNext(TidScanState *node)
Definition: nodeTidscan.c:318
#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:409
ScanState ss
Definition: execnodes.h:1619
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 289 of file nodeTidscan.c.

References ItemPointerGetBlockNumber, and ItemPointerGetOffsetNumber.

Referenced by TidListEval().

290 {
291  const ItemPointerData *ipa = (const ItemPointerData *) a;
292  const ItemPointerData *ipb = (const ItemPointerData *) b;
297 
298  if (ba < bb)
299  return -1;
300  if (ba > bb)
301  return 1;
302  if (oa < ob)
303  return -1;
304  if (oa > ob)
305  return 1;
306  return 0;
307 }
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 65 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().

66 {
67  TidScan *node = (TidScan *) tidstate->ss.ps.plan;
68  ListCell *l;
69 
70  tidstate->tss_tidexprs = NIL;
71  tidstate->tss_isCurrentOf = false;
72 
73  foreach(l, node->tidquals)
74  {
75  Expr *expr = (Expr *) lfirst(l);
76  TidExpr *tidexpr = (TidExpr *) palloc0(sizeof(TidExpr));
77 
78  if (is_opclause(expr))
79  {
80  Node *arg1;
81  Node *arg2;
82 
83  arg1 = get_leftop(expr);
84  arg2 = get_rightop(expr);
85  if (IsCTIDVar(arg1))
86  tidexpr->exprstate = ExecInitExpr((Expr *) arg2,
87  &tidstate->ss.ps);
88  else if (IsCTIDVar(arg2))
89  tidexpr->exprstate = ExecInitExpr((Expr *) arg1,
90  &tidstate->ss.ps);
91  else
92  elog(ERROR, "could not identify CTID variable");
93  tidexpr->isarray = false;
94  }
95  else if (expr && IsA(expr, ScalarArrayOpExpr))
96  {
97  ScalarArrayOpExpr *saex = (ScalarArrayOpExpr *) expr;
98 
99  Assert(IsCTIDVar(linitial(saex->args)));
100  tidexpr->exprstate = ExecInitExpr(lsecond(saex->args),
101  &tidstate->ss.ps);
102  tidexpr->isarray = true;
103  }
104  else if (expr && IsA(expr, CurrentOfExpr))
105  {
106  CurrentOfExpr *cexpr = (CurrentOfExpr *) expr;
107 
108  tidexpr->cexpr = cexpr;
109  tidstate->tss_isCurrentOf = true;
110  }
111  else
112  elog(ERROR, "could not identify CTID expression");
113 
114  tidstate->tss_tidexprs = lappend(tidstate->tss_tidexprs, tidexpr);
115  }
116 
117  /* CurrentOfExpr could never appear OR'd with something else */
118  Assert(list_length(tidstate->tss_tidexprs) == 1 ||
119  !tidstate->tss_isCurrentOf);
120 }
CurrentOfExpr * cexpr
Definition: nodeTidscan.c:48
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
bool isarray
Definition: nodeTidscan.c:47
List * tidquals
Definition: plannodes.h:489
Definition: nodes.h:525
#define lsecond(l)
Definition: pg_list.h:200
PlanState ps
Definition: execnodes.h:1331
#define linitial(l)
Definition: pg_list.h:195
#define ERROR
Definition: elog.h:43
ScanState ss
Definition: execnodes.h:1619
List * tss_tidexprs
Definition: execnodes.h:1620
bool tss_isCurrentOf
Definition: execnodes.h:1621
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:940
#define Assert(condition)
Definition: c.h:732
#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:37
#define elog(elevel,...)
Definition: elog.h:226
ExprState * exprstate
Definition: nodeTidscan.c:46
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 129 of file nodeTidscan.c.

References Assert, TidExpr::cexpr, DatumGetArrayTypeP, DatumGetPointer, deconstruct_array(), EState::es_snapshot, execCurrentOf(), ExecEvalExprSwitchContext(), TidExpr::exprstate, i, TidExpr::isarray, ItemPointerEquals(), itemptr_comparator(), lfirst, list_length(), palloc(), pfree(), ScanState::ps, PlanState::ps_ExprContext, qsort, 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().

130 {
131  ExprContext *econtext = tidstate->ss.ps.ps_ExprContext;
132  TableScanDesc scan;
133  ItemPointerData *tidList;
134  int numAllocTids;
135  int numTids;
136  ListCell *l;
137 
138  /*
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.
142  */
143  if (tidstate->ss.ss_currentScanDesc == NULL)
144  tidstate->ss.ss_currentScanDesc =
146  tidstate->ss.ps.state->es_snapshot,
147  0, NULL);
148  scan = tidstate->ss.ss_currentScanDesc;
149 
150  /*
151  * We initialize the array with enough slots for the case that all quals
152  * are simple OpExprs or CurrentOfExprs. If there are any
153  * ScalarArrayOpExprs, we may have to enlarge the array.
154  */
155  numAllocTids = list_length(tidstate->tss_tidexprs);
156  tidList = (ItemPointerData *)
157  palloc(numAllocTids * sizeof(ItemPointerData));
158  numTids = 0;
159 
160  foreach(l, tidstate->tss_tidexprs)
161  {
162  TidExpr *tidexpr = (TidExpr *) lfirst(l);
163  ItemPointer itemptr;
164  bool isNull;
165 
166  if (tidexpr->exprstate && !tidexpr->isarray)
167  {
168  itemptr = (ItemPointer)
170  econtext,
171  &isNull));
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)
186  {
187  numAllocTids *= 2;
188  tidList = (ItemPointerData *)
189  repalloc(tidList,
190  numAllocTids * sizeof(ItemPointerData));
191  }
192  tidList[numTids++] = *itemptr;
193  }
194  else if (tidexpr->exprstate && tidexpr->isarray)
195  {
196  Datum arraydatum;
197  ArrayType *itemarray;
198  Datum *ipdatums;
199  bool *ipnulls;
200  int ndatums;
201  int i;
202 
203  arraydatum = ExecEvalExprSwitchContext(tidexpr->exprstate,
204  econtext,
205  &isNull);
206  if (isNull)
207  continue;
208  itemarray = DatumGetArrayTypeP(arraydatum);
209  deconstruct_array(itemarray,
210  TIDOID, sizeof(ItemPointerData), false, 's',
211  &ipdatums, &ipnulls, &ndatums);
212  if (numTids + ndatums > numAllocTids)
213  {
214  numAllocTids = numTids + ndatums;
215  tidList = (ItemPointerData *)
216  repalloc(tidList,
217  numAllocTids * sizeof(ItemPointerData));
218  }
219  for (i = 0; i < ndatums; i++)
220  {
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;
230  }
231  pfree(ipdatums);
232  pfree(ipnulls);
233  }
234  else
235  {
236  ItemPointerData cursor_tid;
237 
238  Assert(tidexpr->cexpr);
239  if (execCurrentOf(tidexpr->cexpr, econtext,
241  &cursor_tid))
242  {
243  if (numTids >= numAllocTids)
244  {
245  numAllocTids *= 2;
246  tidList = (ItemPointerData *)
247  repalloc(tidList,
248  numAllocTids * sizeof(ItemPointerData));
249  }
250  tidList[numTids++] = cursor_tid;
251  }
252  }
253  }
254 
255  /*
256  * Sort the array of TIDs into order, and eliminate duplicates.
257  * Eliminating duplicates is necessary since we want OR semantics across
258  * the list. Sorting makes it easier to detect duplicates, and as a bonus
259  * ensures that we will visit the heap in the most efficient way.
260  */
261  if (numTids > 1)
262  {
263  int lastTid;
264  int i;
265 
266  /* CurrentOfExpr could never appear OR'd with something else */
267  Assert(!tidstate->tss_isCurrentOf);
268 
269  qsort((void *) tidList, numTids, sizeof(ItemPointerData),
271  lastTid = 0;
272  for (i = 1; i < numTids; i++)
273  {
274  if (!ItemPointerEquals(&tidList[lastTid], &tidList[i]))
275  tidList[++lastTid] = tidList[i];
276  }
277  numTids = lastTid + 1;
278  }
279 
280  tidstate->tss_TidList = tidList;
281  tidstate->tss_NumTids = numTids;
282  tidstate->tss_TidPtr = -1;
283 }
CurrentOfExpr * cexpr
Definition: nodeTidscan.c:48
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:300
ExprContext * ps_ExprContext
Definition: execnodes.h:979
bool isarray
Definition: nodeTidscan.c:47
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1333
Snapshot es_snapshot
Definition: execnodes.h:503
Relation ss_currentRelation
Definition: execnodes.h:1332
EState * state
Definition: execnodes.h:942
ItemPointerData * ItemPointer
Definition: itemptr.h:49
PlanState ps
Definition: execnodes.h:1331
void pfree(void *pointer)
Definition: mcxt.c:1056
ScanState ss
Definition: execnodes.h:1619
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:736
List * tss_tidexprs
Definition: execnodes.h:1620
ItemPointerData * tss_TidList
Definition: execnodes.h:1624
bool tss_isCurrentOf
Definition: execnodes.h:1621
static int itemptr_comparator(const void *a, const void *b)
Definition: nodeTidscan.c:289
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
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:1038
ExprState * exprstate
Definition: nodeTidscan.c:46
#define qsort(a, b, c, d)
Definition: port.h:492
#define RelationGetRelid(relation)
Definition: rel.h:419
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ TidNext()

static TupleTableSlot * TidNext ( TidScanState node)
static

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

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

◆ TidRecheck()

static bool TidRecheck ( TidScanState node,
TupleTableSlot slot 
)
static

Definition at line 409 of file nodeTidscan.c.

Referenced by ExecTidScan().

410 {
411  /*
412  * XXX shouldn't we check here to make sure tuple matches TID list? In
413  * runtime-key case this is not certain, is it? However, in the WHERE
414  * CURRENT OF case it might not match anyway ...
415  */
416  return true;
417 }