PostgreSQL Source Code git master
Loading...
Searching...
No Matches
nodeTidrangescan.c File Reference
#include "postgres.h"
#include "access/relscan.h"
#include "access/sysattr.h"
#include "access/tableam.h"
#include "catalog/pg_operator.h"
#include "executor/executor.h"
#include "executor/nodeTidrangescan.h"
#include "nodes/nodeFuncs.h"
#include "utils/rel.h"
Include dependency graph for nodeTidrangescan.c:

Go to the source code of this file.

Data Structures

struct  TidOpExpr
 

Macros

#define IsCTIDVar(node)
 

Typedefs

typedef struct TidOpExpr TidOpExpr
 

Enumerations

enum  TidExprType { TIDEXPR_UPPER_BOUND , TIDEXPR_LOWER_BOUND }
 

Functions

static TidOpExprMakeTidOpExpr (OpExpr *expr, TidRangeScanState *tidstate)
 
static void TidExprListCreate (TidRangeScanState *tidrangestate)
 
static bool TidRangeEval (TidRangeScanState *node)
 
static TupleTableSlotTidRangeNext (TidRangeScanState *node)
 
static bool TidRangeRecheck (TidRangeScanState *node, TupleTableSlot *slot)
 
static TupleTableSlotExecTidRangeScan (PlanState *pstate)
 
void ExecReScanTidRangeScan (TidRangeScanState *node)
 
void ExecEndTidRangeScan (TidRangeScanState *node)
 
TidRangeScanStateExecInitTidRangeScan (TidRangeScan *node, EState *estate, int eflags)
 
void ExecTidRangeScanEstimate (TidRangeScanState *node, ParallelContext *pcxt)
 
void ExecTidRangeScanInitializeDSM (TidRangeScanState *node, ParallelContext *pcxt)
 
void ExecTidRangeScanReInitializeDSM (TidRangeScanState *node, ParallelContext *pcxt)
 
void ExecTidRangeScanInitializeWorker (TidRangeScanState *node, ParallelWorkerContext *pwcxt)
 

Macro Definition Documentation

◆ IsCTIDVar

#define IsCTIDVar (   node)
Value:
((node) != NULL && \
IsA((node), Var) && \
((Var *) (node))->varattno == SelfItemPointerAttributeNumber)
#define IsA(nodeptr, _type_)
Definition nodes.h:164
static int fb(int x)
#define SelfItemPointerAttributeNumber
Definition sysattr.h:21

Definition at line 33 of file nodeTidrangescan.c.

38{
42
43/* Upper or lower range bound for scan */
44typedef struct TidOpExpr
45{
46 TidExprType exprtype; /* type of op; lower or upper */
47 ExprState *exprstate; /* ExprState for a TID-yielding subexpr */
48 bool inclusive; /* whether op is inclusive */
49} TidOpExpr;
50
51/*
52 * For the given 'expr', build and return an appropriate TidOpExpr taking into
53 * account the expr's operator and operand order.
54 */
55static TidOpExpr *
57{
58 Node *arg1 = get_leftop((Expr *) expr);
59 Node *arg2 = get_rightop((Expr *) expr);
60 ExprState *exprstate = NULL;
61 bool invert = false;
63
64 if (IsCTIDVar(arg1))
65 exprstate = ExecInitExpr((Expr *) arg2, &tidstate->ss.ps);
66 else if (IsCTIDVar(arg2))
67 {
68 exprstate = ExecInitExpr((Expr *) arg1, &tidstate->ss.ps);
69 invert = true;
70 }
71 else
72 elog(ERROR, "could not identify CTID variable");
73
75 tidopexpr->inclusive = false; /* for now */
76
77 switch (expr->opno)
78 {
80 tidopexpr->inclusive = true;
81 /* fall through */
82 case TIDLessOperator:
84 break;
86 tidopexpr->inclusive = true;
87 /* fall through */
90 break;
91 default:
92 elog(ERROR, "could not identify CTID operator");
93 }
94
95 tidopexpr->exprstate = exprstate;
96
97 return tidopexpr;
98}
99
100/*
101 * Extract the qual subexpressions that yield TIDs to search for,
102 * and compile them into ExprStates if they're ordinary expressions.
103 */
104static void
106{
107 TidRangeScan *node = (TidRangeScan *) tidrangestate->ss.ps.plan;
108 List *tidexprs = NIL;
109 ListCell *l;
110
111 foreach(l, node->tidrangequals)
112 {
113 OpExpr *opexpr = lfirst(l);
115
116 if (!IsA(opexpr, OpExpr))
117 elog(ERROR, "could not identify CTID expression");
118
121 }
122
123 tidrangestate->trss_tidexprs = tidexprs;
124}
125
126/* ----------------------------------------------------------------
127 * TidRangeEval
128 *
129 * Compute and set node's block and offset range to scan by evaluating
130 * node->trss_tidexprs. Returns false if we detect the range cannot
131 * contain any tuples. Returns true if it's possible for the range to
132 * contain tuples. We don't bother validating that trss_mintid is less
133 * than or equal to trss_maxtid, as the scan_set_tidrange() table AM
134 * function will handle that.
135 * ----------------------------------------------------------------
136 */
137static bool
139{
140 ExprContext *econtext = node->ss.ps.ps_ExprContext;
143 ListCell *l;
144
145 /*
146 * Set the upper and lower bounds to the absolute limits of the range of
147 * the ItemPointer type. Below we'll try to narrow this range on either
148 * side by looking at the TidOpExprs.
149 */
152
153 foreach(l, node->trss_tidexprs)
154 {
156 ItemPointer itemptr;
157 bool isNull;
158
159 /* Evaluate this bound. */
160 itemptr = (ItemPointer)
162 econtext,
163 &isNull));
164
165 /* If the bound is NULL, *nothing* matches the qual. */
166 if (isNull)
167 return false;
168
169 if (tidopexpr->exprtype == TIDEXPR_LOWER_BOUND)
170 {
172
173 ItemPointerCopy(itemptr, &lb);
174
175 /*
176 * Normalize non-inclusive ranges to become inclusive. The
177 * resulting ItemPointer here may not be a valid item pointer.
178 */
179 if (!tidopexpr->inclusive)
180 ItemPointerInc(&lb);
181
182 /* Check if we can narrow the range using this qual */
183 if (ItemPointerCompare(&lb, &lowerBound) > 0)
185 }
186
187 else if (tidopexpr->exprtype == TIDEXPR_UPPER_BOUND)
188 {
190
191 ItemPointerCopy(itemptr, &ub);
192
193 /*
194 * Normalize non-inclusive ranges to become inclusive. The
195 * resulting ItemPointer here may not be a valid item pointer.
196 */
197 if (!tidopexpr->inclusive)
199
200 /* Check if we can narrow the range using this qual */
201 if (ItemPointerCompare(&ub, &upperBound) < 0)
203 }
204 }
205
208
209 return true;
210}
211
212/* ----------------------------------------------------------------
213 * TidRangeNext
214 *
215 * Retrieve a tuple from the TidRangeScan node's currentRelation
216 * using the TIDs in the TidRangeScanState information.
217 *
218 * ----------------------------------------------------------------
219 */
220static TupleTableSlot *
222{
223 TableScanDesc scandesc;
224 EState *estate;
225 ScanDirection direction;
226 TupleTableSlot *slot;
227
228 /*
229 * extract necessary information from TID scan node
230 */
231 scandesc = node->ss.ss_currentScanDesc;
232 estate = node->ss.ps.state;
233 slot = node->ss.ss_ScanTupleSlot;
234 direction = estate->es_direction;
235
236 if (!node->trss_inScan)
237 {
238 /* First time through, compute TID range to scan */
239 if (!TidRangeEval(node))
240 return NULL;
241
242 if (scandesc == NULL)
243 {
245 estate->es_snapshot,
246 &node->trss_mintid,
247 &node->trss_maxtid);
248 node->ss.ss_currentScanDesc = scandesc;
249 }
250 else
251 {
252 /* rescan with the updated TID range */
253 table_rescan_tidrange(scandesc, &node->trss_mintid,
254 &node->trss_maxtid);
255 }
256
257 node->trss_inScan = true;
258 }
259
260 /* Fetch the next tuple. */
261 if (!table_scan_getnextslot_tidrange(scandesc, direction, slot))
262 {
263 node->trss_inScan = false;
264 ExecClearTuple(slot);
265 }
266
267 return slot;
268}
269
270/*
271 * TidRangeRecheck -- access method routine to recheck a tuple in EvalPlanQual
272 */
273static bool
275{
276 if (!TidRangeEval(node))
277 return false;
278
280
281 /* Recheck the ctid is still within range */
282 if (ItemPointerCompare(&slot->tts_tid, &node->trss_mintid) < 0 ||
283 ItemPointerCompare(&slot->tts_tid, &node->trss_maxtid) > 0)
284 return false;
285
286 return true;
287}
288
289/* ----------------------------------------------------------------
290 * ExecTidRangeScan(node)
291 *
292 * Scans the relation using tids and returns the next qualifying tuple.
293 * We call the ExecScan() routine and pass it the appropriate
294 * access method functions.
295 *
296 * Conditions:
297 * -- the "cursor" maintained by the AMI is positioned at the tuple
298 * returned previously.
299 *
300 * Initial States:
301 * -- the relation indicated is opened for TID range scanning.
302 * ----------------------------------------------------------------
303 */
304static TupleTableSlot *
306{
308
309 return ExecScan(&node->ss,
312}
313
314/* ----------------------------------------------------------------
315 * ExecReScanTidRangeScan(node)
316 * ----------------------------------------------------------------
317 */
318void
320{
321 /* mark scan as not in progress, and tid range list as not computed yet */
322 node->trss_inScan = false;
323
324 /*
325 * We must wait until TidRangeNext before calling table_rescan_tidrange.
326 */
327 ExecScanReScan(&node->ss);
328}
329
330/* ----------------------------------------------------------------
331 * ExecEndTidRangeScan
332 *
333 * Releases any storage allocated through C routines.
334 * Returns nothing.
335 * ----------------------------------------------------------------
336 */
337void
339{
341
342 if (scan != NULL)
343 table_endscan(scan);
344}
345
346/* ----------------------------------------------------------------
347 * ExecInitTidRangeScan
348 *
349 * Initializes the tid range scan's state information, creates
350 * scan keys, and opens the scan relation.
351 *
352 * Parameters:
353 * node: TidRangeScan node produced by the planner.
354 * estate: the execution state initialized in InitPlan.
355 * ----------------------------------------------------------------
356 */
358ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
359{
362
363 /*
364 * create state structure
365 */
367 tidrangestate->ss.ps.plan = (Plan *) node;
368 tidrangestate->ss.ps.state = estate;
369 tidrangestate->ss.ps.ExecProcNode = ExecTidRangeScan;
370
371 /*
372 * Miscellaneous initialization
373 *
374 * create expression context for node
375 */
376 ExecAssignExprContext(estate, &tidrangestate->ss.ps);
377
378 /*
379 * mark scan as not in progress, and TID range as not computed yet
380 */
381 tidrangestate->trss_inScan = false;
382
383 /*
384 * open the scan relation
385 */
386 currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
387
388 tidrangestate->ss.ss_currentRelation = currentRelation;
389 tidrangestate->ss.ss_currentScanDesc = NULL; /* no table scan here */
390
391 /*
392 * get the scan type from the relation descriptor.
393 */
397
398 /*
399 * Initialize result type and projection.
400 */
403
404 /*
405 * initialize child expressions
406 */
407 tidrangestate->ss.ps.qual =
408 ExecInitQual(node->scan.plan.qual, (PlanState *) tidrangestate);
409
411
412 /*
413 * all done.
414 */
415 return tidrangestate;
416}
417
418/* ----------------------------------------------------------------
419 * Parallel Scan Support
420 * ----------------------------------------------------------------
421 */
422
423/* ----------------------------------------------------------------
424 * ExecTidRangeScanEstimate
425 *
426 * Compute the amount of space we'll need in the parallel
427 * query DSM, and inform pcxt->estimator about our needs.
428 * ----------------------------------------------------------------
429 */
430void
432{
433 EState *estate = node->ss.ps.state;
434
435 node->trss_pscanlen =
437 estate->es_snapshot);
440}
441
442/* ----------------------------------------------------------------
443 * ExecTidRangeScanInitializeDSM
444 *
445 * Set up a parallel TID range scan descriptor.
446 * ----------------------------------------------------------------
447 */
448void
450{
451 EState *estate = node->ss.ps.state;
453
454 pscan = shm_toc_allocate(pcxt->toc, node->trss_pscanlen);
456 pscan,
457 estate->es_snapshot);
458 shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
459 node->ss.ss_currentScanDesc =
461 pscan);
462}
463
464/* ----------------------------------------------------------------
465 * ExecTidRangeScanReInitializeDSM
466 *
467 * Reset shared state before beginning a fresh scan.
468 * ----------------------------------------------------------------
469 */
470void
472 ParallelContext *pcxt)
473{
475
478}
479
480/* ----------------------------------------------------------------
481 * ExecTidRangeScanInitializeWorker
482 *
483 * Copy relevant information from TOC into planstate.
484 * ----------------------------------------------------------------
485 */
486void
489{
491
492 pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
493 node->ss.ss_currentScanDesc =
495 pscan);
496}
#define InvalidBlockNumber
Definition block.h:33
#define Assert(condition)
Definition c.h:873
#define PG_UINT16_MAX
Definition c.h:601
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition execExpr.c:143
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition execExpr.c:229
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition execScan.c:47
void ExecAssignScanProjectionInfo(ScanState *node)
Definition execScan.c:81
void ExecScanReScan(ScanState *node)
Definition execScan.c:108
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
void ExecInitResultTypeTL(PlanState *planstate)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition execUtils.c:485
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition execUtils.c:742
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition executor.h:580
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition executor.h:579
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:436
#define palloc_object(type)
Definition fe_memutils.h:74
void ItemPointerDec(ItemPointer pointer)
Definition itemptr.c:114
int32 ItemPointerCompare(const ItemPointerData *arg1, const ItemPointerData *arg2)
Definition itemptr.c:51
void ItemPointerInc(ItemPointer pointer)
Definition itemptr.c:84
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
Definition itemptr.h:135
ItemPointerData * ItemPointer
Definition itemptr.h:49
static void ItemPointerCopy(const ItemPointerData *fromPointer, ItemPointerData *toPointer)
Definition itemptr.h:172
static bool ItemPointerIsValid(const ItemPointerData *pointer)
Definition itemptr.h:83
List * lappend(List *list, void *datum)
Definition list.c:339
static Node * get_rightop(const void *clause)
Definition nodeFuncs.h:95
static Node * get_leftop(const void *clause)
Definition nodeFuncs.h:83
static void TidExprListCreate(TidRangeScanState *tidrangestate)
void ExecTidRangeScanEstimate(TidRangeScanState *node, ParallelContext *pcxt)
void ExecReScanTidRangeScan(TidRangeScanState *node)
void ExecEndTidRangeScan(TidRangeScanState *node)
static bool TidRangeEval(TidRangeScanState *node)
void ExecTidRangeScanInitializeWorker(TidRangeScanState *node, ParallelWorkerContext *pwcxt)
static TidOpExpr * MakeTidOpExpr(OpExpr *expr, TidRangeScanState *tidstate)
TidRangeScanState * ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
void ExecTidRangeScanInitializeDSM(TidRangeScanState *node, ParallelContext *pcxt)
void ExecTidRangeScanReInitializeDSM(TidRangeScanState *node, ParallelContext *pcxt)
static TupleTableSlot * TidRangeNext(TidRangeScanState *node)
#define IsCTIDVar(node)
TidExprType
@ TIDEXPR_LOWER_BOUND
@ TIDEXPR_UPPER_BOUND
static TupleTableSlot * ExecTidRangeScan(PlanState *pstate)
static bool TidRangeRecheck(TidRangeScanState *node, TupleTableSlot *slot)
#define makeNode(_type_)
Definition nodes.h:161
#define castNode(_type_, nodeptr)
Definition nodes.h:182
#define lfirst(lc)
Definition pg_list.h:172
#define NIL
Definition pg_list.h:68
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:342
#define RelationGetDescr(relation)
Definition rel.h:540
ScanDirection
Definition sdir.h:25
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition shm_toc.c:88
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition shm_toc.c:171
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition shm_toc.c:232
#define shm_toc_estimate_chunk(e, sz)
Definition shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition shm_toc.h:53
ScanDirection es_direction
Definition execnodes.h:661
Snapshot es_snapshot
Definition execnodes.h:662
Definition pg_list.h:54
Definition nodes.h:135
Oid opno
Definition primnodes.h:850
shm_toc_estimator estimator
Definition parallel.h:41
shm_toc * toc
Definition parallel.h:44
Plan * plan
Definition execnodes.h:1167
EState * state
Definition execnodes.h:1169
ExprContext * ps_ExprContext
Definition execnodes.h:1206
int plan_node_id
Definition plannodes.h:227
Relation ss_currentRelation
Definition execnodes.h:1624
TupleTableSlot * ss_ScanTupleSlot
Definition execnodes.h:1626
PlanState ps
Definition execnodes.h:1623
struct TableScanDescData * ss_currentScanDesc
Definition execnodes.h:1625
Index scanrelid
Definition plannodes.h:523
struct ParallelTableScanDescData * rs_parallel
Definition relscan.h:65
ExprState * exprstate
TidExprType exprtype
ItemPointerData trss_maxtid
Definition execnodes.h:1916
ItemPointerData trss_mintid
Definition execnodes.h:1915
ItemPointerData tts_tid
Definition tuptable.h:128
TableScanDesc table_beginscan_parallel_tidrange(Relation relation, ParallelTableScanDesc pscan)
Definition tableam.c:192
Size table_parallelscan_estimate(Relation rel, Snapshot snapshot)
Definition tableam.c:131
void table_parallelscan_initialize(Relation rel, ParallelTableScanDesc pscan, Snapshot snapshot)
Definition tableam.c:146
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition tableam.c:59
static void table_rescan_tidrange(TableScanDesc sscan, ItemPointer mintid, ItemPointer maxtid)
Definition tableam.h:1082
static void table_endscan(TableScanDesc scan)
Definition tableam.h:1005
static TableScanDesc table_beginscan_tidrange(Relation rel, Snapshot snapshot, ItemPointer mintid, ItemPointer maxtid)
Definition tableam.h:1061
static bool table_scan_getnextslot_tidrange(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition tableam.h:1098
static void table_parallelscan_reinitialize(Relation rel, ParallelTableScanDesc pscan)
Definition tableam.h:1161
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:457

Typedef Documentation

◆ TidOpExpr

Enumeration Type Documentation

◆ TidExprType

Enumerator
TIDEXPR_UPPER_BOUND 
TIDEXPR_LOWER_BOUND 

Definition at line 38 of file nodeTidrangescan.c.

Function Documentation

◆ ExecEndTidRangeScan()

void ExecEndTidRangeScan ( TidRangeScanState node)

Definition at line 339 of file nodeTidrangescan.c.

340{
342
343 if (scan != NULL)
344 table_endscan(scan);
345}

References fb(), TidRangeScanState::ss, ScanState::ss_currentScanDesc, and table_endscan().

Referenced by ExecEndNode().

◆ ExecInitTidRangeScan()

TidRangeScanState * ExecInitTidRangeScan ( TidRangeScan node,
EState estate,
int  eflags 
)

Definition at line 359 of file nodeTidrangescan.c.

360{
363
364 /*
365 * create state structure
366 */
368 tidrangestate->ss.ps.plan = (Plan *) node;
369 tidrangestate->ss.ps.state = estate;
370 tidrangestate->ss.ps.ExecProcNode = ExecTidRangeScan;
371
372 /*
373 * Miscellaneous initialization
374 *
375 * create expression context for node
376 */
377 ExecAssignExprContext(estate, &tidrangestate->ss.ps);
378
379 /*
380 * mark scan as not in progress, and TID range as not computed yet
381 */
382 tidrangestate->trss_inScan = false;
383
384 /*
385 * open the scan relation
386 */
387 currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
388
389 tidrangestate->ss.ss_currentRelation = currentRelation;
390 tidrangestate->ss.ss_currentScanDesc = NULL; /* no table scan here */
391
392 /*
393 * get the scan type from the relation descriptor.
394 */
398
399 /*
400 * Initialize result type and projection.
401 */
404
405 /*
406 * initialize child expressions
407 */
408 tidrangestate->ss.ps.qual =
409 ExecInitQual(node->scan.plan.qual, (PlanState *) tidrangestate);
410
412
413 /*
414 * all done.
415 */
416 return tidrangestate;
417}

References ExecAssignExprContext(), ExecAssignScanProjectionInfo(), ExecInitQual(), ExecInitResultTypeTL(), ExecInitScanTupleSlot(), ExecOpenScanRelation(), ExecTidRangeScan(), fb(), makeNode, RelationGetDescr, TidRangeScan::scan, Scan::scanrelid, table_slot_callbacks(), and TidExprListCreate().

Referenced by ExecInitNode().

◆ ExecReScanTidRangeScan()

void ExecReScanTidRangeScan ( TidRangeScanState node)

Definition at line 320 of file nodeTidrangescan.c.

321{
322 /* mark scan as not in progress, and tid range list as not computed yet */
323 node->trss_inScan = false;
324
325 /*
326 * We must wait until TidRangeNext before calling table_rescan_tidrange.
327 */
328 ExecScanReScan(&node->ss);
329}

References ExecScanReScan(), TidRangeScanState::ss, and TidRangeScanState::trss_inScan.

Referenced by ExecReScan().

◆ ExecTidRangeScan()

static TupleTableSlot * ExecTidRangeScan ( PlanState pstate)
static

◆ ExecTidRangeScanEstimate()

◆ ExecTidRangeScanInitializeDSM()

◆ ExecTidRangeScanInitializeWorker()

◆ ExecTidRangeScanReInitializeDSM()

◆ MakeTidOpExpr()

static TidOpExpr * MakeTidOpExpr ( OpExpr expr,
TidRangeScanState tidstate 
)
static

Definition at line 57 of file nodeTidrangescan.c.

58{
59 Node *arg1 = get_leftop((Expr *) expr);
60 Node *arg2 = get_rightop((Expr *) expr);
61 ExprState *exprstate = NULL;
62 bool invert = false;
64
65 if (IsCTIDVar(arg1))
66 exprstate = ExecInitExpr((Expr *) arg2, &tidstate->ss.ps);
67 else if (IsCTIDVar(arg2))
68 {
69 exprstate = ExecInitExpr((Expr *) arg1, &tidstate->ss.ps);
70 invert = true;
71 }
72 else
73 elog(ERROR, "could not identify CTID variable");
74
76 tidopexpr->inclusive = false; /* for now */
77
78 switch (expr->opno)
79 {
81 tidopexpr->inclusive = true;
82 /* fall through */
83 case TIDLessOperator:
85 break;
87 tidopexpr->inclusive = true;
88 /* fall through */
91 break;
92 default:
93 elog(ERROR, "could not identify CTID operator");
94 }
95
96 tidopexpr->exprstate = exprstate;
97
98 return tidopexpr;
99}

References elog, ERROR, ExecInitExpr(), fb(), get_leftop(), get_rightop(), IsCTIDVar, OpExpr::opno, palloc_object, TIDEXPR_LOWER_BOUND, and TIDEXPR_UPPER_BOUND.

Referenced by TidExprListCreate().

◆ TidExprListCreate()

static void TidExprListCreate ( TidRangeScanState tidrangestate)
static

Definition at line 106 of file nodeTidrangescan.c.

107{
108 TidRangeScan *node = (TidRangeScan *) tidrangestate->ss.ps.plan;
109 List *tidexprs = NIL;
110 ListCell *l;
111
112 foreach(l, node->tidrangequals)
113 {
114 OpExpr *opexpr = lfirst(l);
116
117 if (!IsA(opexpr, OpExpr))
118 elog(ERROR, "could not identify CTID expression");
119
122 }
123
124 tidrangestate->trss_tidexprs = tidexprs;
125}

References elog, ERROR, fb(), IsA, lappend(), lfirst, MakeTidOpExpr(), NIL, and TidRangeScan::tidrangequals.

Referenced by ExecInitTidRangeScan().

◆ TidRangeEval()

static bool TidRangeEval ( TidRangeScanState node)
static

Definition at line 139 of file nodeTidrangescan.c.

140{
141 ExprContext *econtext = node->ss.ps.ps_ExprContext;
144 ListCell *l;
145
146 /*
147 * Set the upper and lower bounds to the absolute limits of the range of
148 * the ItemPointer type. Below we'll try to narrow this range on either
149 * side by looking at the TidOpExprs.
150 */
153
154 foreach(l, node->trss_tidexprs)
155 {
157 ItemPointer itemptr;
158 bool isNull;
159
160 /* Evaluate this bound. */
161 itemptr = (ItemPointer)
163 econtext,
164 &isNull));
165
166 /* If the bound is NULL, *nothing* matches the qual. */
167 if (isNull)
168 return false;
169
170 if (tidopexpr->exprtype == TIDEXPR_LOWER_BOUND)
171 {
173
174 ItemPointerCopy(itemptr, &lb);
175
176 /*
177 * Normalize non-inclusive ranges to become inclusive. The
178 * resulting ItemPointer here may not be a valid item pointer.
179 */
180 if (!tidopexpr->inclusive)
181 ItemPointerInc(&lb);
182
183 /* Check if we can narrow the range using this qual */
184 if (ItemPointerCompare(&lb, &lowerBound) > 0)
186 }
187
188 else if (tidopexpr->exprtype == TIDEXPR_UPPER_BOUND)
189 {
191
192 ItemPointerCopy(itemptr, &ub);
193
194 /*
195 * Normalize non-inclusive ranges to become inclusive. The
196 * resulting ItemPointer here may not be a valid item pointer.
197 */
198 if (!tidopexpr->inclusive)
200
201 /* Check if we can narrow the range using this qual */
202 if (ItemPointerCompare(&ub, &upperBound) < 0)
204 }
205 }
206
209
210 return true;
211}

References DatumGetPointer(), ExecEvalExprSwitchContext(), fb(), InvalidBlockNumber, ItemPointerCompare(), ItemPointerCopy(), ItemPointerDec(), ItemPointerInc(), ItemPointerSet(), lfirst, PG_UINT16_MAX, ScanState::ps, PlanState::ps_ExprContext, TidRangeScanState::ss, TIDEXPR_LOWER_BOUND, TIDEXPR_UPPER_BOUND, TidRangeScanState::trss_maxtid, TidRangeScanState::trss_mintid, and TidRangeScanState::trss_tidexprs.

Referenced by TidRangeNext(), and TidRangeRecheck().

◆ TidRangeNext()

static TupleTableSlot * TidRangeNext ( TidRangeScanState node)
static

Definition at line 222 of file nodeTidrangescan.c.

223{
224 TableScanDesc scandesc;
225 EState *estate;
226 ScanDirection direction;
227 TupleTableSlot *slot;
228
229 /*
230 * extract necessary information from TID scan node
231 */
232 scandesc = node->ss.ss_currentScanDesc;
233 estate = node->ss.ps.state;
234 slot = node->ss.ss_ScanTupleSlot;
235 direction = estate->es_direction;
236
237 if (!node->trss_inScan)
238 {
239 /* First time through, compute TID range to scan */
240 if (!TidRangeEval(node))
241 return NULL;
242
243 if (scandesc == NULL)
244 {
246 estate->es_snapshot,
247 &node->trss_mintid,
248 &node->trss_maxtid);
249 node->ss.ss_currentScanDesc = scandesc;
250 }
251 else
252 {
253 /* rescan with the updated TID range */
254 table_rescan_tidrange(scandesc, &node->trss_mintid,
255 &node->trss_maxtid);
256 }
257
258 node->trss_inScan = true;
259 }
260
261 /* Fetch the next tuple. */
262 if (!table_scan_getnextslot_tidrange(scandesc, direction, slot))
263 {
264 node->trss_inScan = false;
265 ExecClearTuple(slot);
266 }
267
268 return slot;
269}

References EState::es_direction, EState::es_snapshot, ExecClearTuple(), fb(), ScanState::ps, TidRangeScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, ScanState::ss_ScanTupleSlot, PlanState::state, table_beginscan_tidrange(), table_rescan_tidrange(), table_scan_getnextslot_tidrange(), TidRangeEval(), TidRangeScanState::trss_inScan, TidRangeScanState::trss_maxtid, and TidRangeScanState::trss_mintid.

Referenced by ExecTidRangeScan().

◆ TidRangeRecheck()

static bool TidRangeRecheck ( TidRangeScanState node,
TupleTableSlot slot 
)
static

Definition at line 275 of file nodeTidrangescan.c.

276{
277 if (!TidRangeEval(node))
278 return false;
279
281
282 /* Recheck the ctid is still within range */
283 if (ItemPointerCompare(&slot->tts_tid, &node->trss_mintid) < 0 ||
284 ItemPointerCompare(&slot->tts_tid, &node->trss_maxtid) > 0)
285 return false;
286
287 return true;
288}

References Assert, ItemPointerCompare(), ItemPointerIsValid(), TidRangeEval(), TidRangeScanState::trss_maxtid, TidRangeScanState::trss_mintid, and TupleTableSlot::tts_tid.

Referenced by ExecTidRangeScan().