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/execParallel.h"
#include "executor/executor.h"
#include "executor/instrument.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)
 
void ExecTidRangeScanInstrumentEstimate (TidRangeScanState *node, ParallelContext *pcxt)
 
void ExecTidRangeScanInstrumentInitDSM (TidRangeScanState *node, ParallelContext *pcxt)
 
void ExecTidRangeScanInstrumentInitWorker (TidRangeScanState *node, ParallelWorkerContext *pwcxt)
 
void ExecTidRangeScanRetrieveInstrumentation (TidRangeScanState *node)
 

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 35 of file nodeTidrangescan.c.

40{
44
45/* Upper or lower range bound for scan */
46typedef struct TidOpExpr
47{
48 TidExprType exprtype; /* type of op; lower or upper */
49 ExprState *exprstate; /* ExprState for a TID-yielding subexpr */
50 bool inclusive; /* whether op is inclusive */
51} TidOpExpr;
52
53/*
54 * For the given 'expr', build and return an appropriate TidOpExpr taking into
55 * account the expr's operator and operand order.
56 */
57static TidOpExpr *
59{
60 Node *arg1 = get_leftop((Expr *) expr);
61 Node *arg2 = get_rightop((Expr *) expr);
62 ExprState *exprstate = NULL;
63 bool invert = false;
65
66 if (IsCTIDVar(arg1))
67 exprstate = ExecInitExpr((Expr *) arg2, &tidstate->ss.ps);
68 else if (IsCTIDVar(arg2))
69 {
70 exprstate = ExecInitExpr((Expr *) arg1, &tidstate->ss.ps);
71 invert = true;
72 }
73 else
74 elog(ERROR, "could not identify CTID variable");
75
77 tidopexpr->inclusive = false; /* for now */
78
79 switch (expr->opno)
80 {
82 tidopexpr->inclusive = true;
84 case TIDLessOperator:
86 break;
88 tidopexpr->inclusive = true;
92 break;
93 default:
94 elog(ERROR, "could not identify CTID operator");
95 }
96
97 tidopexpr->exprstate = exprstate;
98
99 return tidopexpr;
100}
101
102/*
103 * Extract the qual subexpressions that yield TIDs to search for,
104 * and compile them into ExprStates if they're ordinary expressions.
105 */
106static void
108{
109 TidRangeScan *node = (TidRangeScan *) tidrangestate->ss.ps.plan;
110 List *tidexprs = NIL;
111 ListCell *l;
112
113 foreach(l, node->tidrangequals)
114 {
115 OpExpr *opexpr = lfirst(l);
117
118 if (!IsA(opexpr, OpExpr))
119 elog(ERROR, "could not identify CTID expression");
120
123 }
124
125 tidrangestate->trss_tidexprs = tidexprs;
126}
127
128/* ----------------------------------------------------------------
129 * TidRangeEval
130 *
131 * Compute and set node's block and offset range to scan by evaluating
132 * node->trss_tidexprs. Returns false if we detect the range cannot
133 * contain any tuples. Returns true if it's possible for the range to
134 * contain tuples. We don't bother validating that trss_mintid is less
135 * than or equal to trss_maxtid, as the scan_set_tidrange() table AM
136 * function will handle that.
137 * ----------------------------------------------------------------
138 */
139static bool
141{
142 ExprContext *econtext = node->ss.ps.ps_ExprContext;
145 ListCell *l;
146
147 /*
148 * Set the upper and lower bounds to the absolute limits of the range of
149 * the ItemPointer type. Below we'll try to narrow this range on either
150 * side by looking at the TidOpExprs.
151 */
154
155 foreach(l, node->trss_tidexprs)
156 {
158 ItemPointer itemptr;
159 bool isNull;
160
161 /* Evaluate this bound. */
162 itemptr = (ItemPointer)
164 econtext,
165 &isNull));
166
167 /* If the bound is NULL, *nothing* matches the qual. */
168 if (isNull)
169 return false;
170
171 if (tidopexpr->exprtype == TIDEXPR_LOWER_BOUND)
172 {
174
175 ItemPointerCopy(itemptr, &lb);
176
177 /*
178 * Normalize non-inclusive ranges to become inclusive. The
179 * resulting ItemPointer here may not be a valid item pointer.
180 */
181 if (!tidopexpr->inclusive)
182 ItemPointerInc(&lb);
183
184 /* Check if we can narrow the range using this qual */
185 if (ItemPointerCompare(&lb, &lowerBound) > 0)
187 }
188
189 else if (tidopexpr->exprtype == TIDEXPR_UPPER_BOUND)
190 {
192
193 ItemPointerCopy(itemptr, &ub);
194
195 /*
196 * Normalize non-inclusive ranges to become inclusive. The
197 * resulting ItemPointer here may not be a valid item pointer.
198 */
199 if (!tidopexpr->inclusive)
201
202 /* Check if we can narrow the range using this qual */
203 if (ItemPointerCompare(&ub, &upperBound) < 0)
205 }
206 }
207
210
211 return true;
212}
213
214/* ----------------------------------------------------------------
215 * TidRangeNext
216 *
217 * Retrieve a tuple from the TidRangeScan node's currentRelation
218 * using the TIDs in the TidRangeScanState information.
219 *
220 * ----------------------------------------------------------------
221 */
222static TupleTableSlot *
224{
225 TableScanDesc scandesc;
226 EState *estate;
227 ScanDirection direction;
228 TupleTableSlot *slot;
229
230 /*
231 * extract necessary information from TID scan node
232 */
233 scandesc = node->ss.ss_currentScanDesc;
234 estate = node->ss.ps.state;
235 slot = node->ss.ss_ScanTupleSlot;
236 direction = estate->es_direction;
237
238 if (!node->trss_inScan)
239 {
240 /* First time through, compute TID range to scan */
241 if (!TidRangeEval(node))
242 return NULL;
243
244 if (scandesc == NULL)
245 {
246 uint32 flags = SO_NONE;
247
248 if (ScanRelIsReadOnly(&node->ss))
249 flags |= SO_HINT_REL_READ_ONLY;
250
251 if (estate->es_instrument & INSTRUMENT_IO)
252 flags |= SO_SCAN_INSTRUMENT;
253
255 estate->es_snapshot,
256 &node->trss_mintid,
257 &node->trss_maxtid,
258 flags);
259 node->ss.ss_currentScanDesc = scandesc;
260 }
261 else
262 {
263 /* rescan with the updated TID range */
264 table_rescan_tidrange(scandesc, &node->trss_mintid,
265 &node->trss_maxtid);
266 }
267
268 node->trss_inScan = true;
269 }
270
271 /* Fetch the next tuple. */
272 if (!table_scan_getnextslot_tidrange(scandesc, direction, slot))
273 {
274 node->trss_inScan = false;
275 ExecClearTuple(slot);
276 }
277
278 return slot;
279}
280
281/*
282 * TidRangeRecheck -- access method routine to recheck a tuple in EvalPlanQual
283 */
284static bool
286{
287 if (!TidRangeEval(node))
288 return false;
289
291
292 /* Recheck the ctid is still within range */
293 if (ItemPointerCompare(&slot->tts_tid, &node->trss_mintid) < 0 ||
294 ItemPointerCompare(&slot->tts_tid, &node->trss_maxtid) > 0)
295 return false;
296
297 return true;
298}
299
300/* ----------------------------------------------------------------
301 * ExecTidRangeScan(node)
302 *
303 * Scans the relation using tids and returns the next qualifying tuple.
304 * We call the ExecScan() routine and pass it the appropriate
305 * access method functions.
306 *
307 * Conditions:
308 * -- the "cursor" maintained by the AMI is positioned at the tuple
309 * returned previously.
310 *
311 * Initial States:
312 * -- the relation indicated is opened for TID range scanning.
313 * ----------------------------------------------------------------
314 */
315static TupleTableSlot *
317{
319
320 return ExecScan(&node->ss,
323}
324
325/* ----------------------------------------------------------------
326 * ExecReScanTidRangeScan(node)
327 * ----------------------------------------------------------------
328 */
329void
331{
332 /* mark scan as not in progress, and tid range list as not computed yet */
333 node->trss_inScan = false;
334
335 /*
336 * We must wait until TidRangeNext before calling table_rescan_tidrange.
337 */
338 ExecScanReScan(&node->ss);
339}
340
341/* ----------------------------------------------------------------
342 * ExecEndTidRangeScan
343 *
344 * Releases any storage allocated through C routines.
345 * Returns nothing.
346 * ----------------------------------------------------------------
347 */
348void
350{
352
353 /* Collect IO stats for this process into shared instrumentation */
354 if (node->trss_sinstrument != NULL && IsParallelWorker())
355 {
357
358 Assert(ParallelWorkerNumber < node->trss_sinstrument->num_workers);
360
361 if (scan && scan->rs_instrument)
362 {
363 AccumulateIOStats(&si->stats.io, &scan->rs_instrument->io);
364 }
365 }
366
367 if (scan != NULL)
368 table_endscan(scan);
369}
370
371/* ----------------------------------------------------------------
372 * ExecInitTidRangeScan
373 *
374 * Initializes the tid range scan's state information, creates
375 * scan keys, and opens the scan relation.
376 *
377 * Parameters:
378 * node: TidRangeScan node produced by the planner.
379 * estate: the execution state initialized in InitPlan.
380 * ----------------------------------------------------------------
381 */
383ExecInitTidRangeScan(TidRangeScan *node, EState *estate, int eflags)
384{
387
388 /*
389 * create state structure
390 */
392 tidrangestate->ss.ps.plan = (Plan *) node;
393 tidrangestate->ss.ps.state = estate;
394 tidrangestate->ss.ps.ExecProcNode = ExecTidRangeScan;
395
396 /*
397 * Miscellaneous initialization
398 *
399 * create expression context for node
400 */
401 ExecAssignExprContext(estate, &tidrangestate->ss.ps);
402
403 /*
404 * mark scan as not in progress, and TID range as not computed yet
405 */
406 tidrangestate->trss_inScan = false;
407
408 /*
409 * open the scan relation
410 */
411 currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
412
413 tidrangestate->ss.ss_currentRelation = currentRelation;
414 tidrangestate->ss.ss_currentScanDesc = NULL; /* no table scan here */
415
416 /*
417 * get the scan type from the relation descriptor.
418 */
423
424 /*
425 * Initialize result type and projection.
426 */
429
430 /*
431 * initialize child expressions
432 */
433 tidrangestate->ss.ps.qual =
434 ExecInitQual(node->scan.plan.qual, (PlanState *) tidrangestate);
435
437
438 /*
439 * all done.
440 */
441 return tidrangestate;
442}
443
444/* ----------------------------------------------------------------
445 * Parallel Scan Support
446 * ----------------------------------------------------------------
447 */
448
449/* ----------------------------------------------------------------
450 * ExecTidRangeScanEstimate
451 *
452 * Compute the amount of space we'll need in the parallel
453 * query DSM, and inform pcxt->estimator about our needs.
454 * ----------------------------------------------------------------
455 */
456void
458{
459 EState *estate = node->ss.ps.state;
460
461 node->trss_pscanlen =
463 estate->es_snapshot);
466}
467
468/* ----------------------------------------------------------------
469 * ExecTidRangeScanInitializeDSM
470 *
471 * Set up a parallel TID range scan descriptor.
472 * ----------------------------------------------------------------
473 */
474void
476{
477 EState *estate = node->ss.ps.state;
479 uint32 flags = SO_NONE;
480
481 if (ScanRelIsReadOnly(&node->ss))
482 flags |= SO_HINT_REL_READ_ONLY;
483
484 if (estate->es_instrument & INSTRUMENT_IO)
485 flags |= SO_SCAN_INSTRUMENT;
486
487 pscan = shm_toc_allocate(pcxt->toc, node->trss_pscanlen);
489 pscan,
490 estate->es_snapshot);
491 shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
492 node->ss.ss_currentScanDesc =
494 pscan, flags);
495}
496
497/* ----------------------------------------------------------------
498 * ExecTidRangeScanReInitializeDSM
499 *
500 * Reset shared state before beginning a fresh scan.
501 * ----------------------------------------------------------------
502 */
503void
505 ParallelContext *pcxt)
506{
508
511}
512
513/* ----------------------------------------------------------------
514 * ExecTidRangeScanInitializeWorker
515 *
516 * Copy relevant information from TOC into planstate.
517 * ----------------------------------------------------------------
518 */
519void
522{
524 uint32 flags = SO_NONE;
525
526 if (ScanRelIsReadOnly(&node->ss))
527 flags |= SO_HINT_REL_READ_ONLY;
528
530 flags |= SO_SCAN_INSTRUMENT;
531
532 pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
533 node->ss.ss_currentScanDesc =
535 pscan, flags);
536}
537
538/*
539 * Compute the amount of space we'll need for the shared instrumentation and
540 * inform pcxt->estimator.
541 */
542void
544 ParallelContext *pcxt)
545{
546 EState *estate = node->ss.ps.state;
547 Size size;
548
549 if ((estate->es_instrument & INSTRUMENT_IO) == 0 || pcxt->nworkers == 0)
550 return;
551
554
555 shm_toc_estimate_chunk(&pcxt->estimator, size);
557}
558
559/*
560 * Set up parallel scan instrumentation.
561 */
562void
564 ParallelContext *pcxt)
565{
566 EState *estate = node->ss.ps.state;
568 Size size;
569
570 if ((estate->es_instrument & INSTRUMENT_IO) == 0 || pcxt->nworkers == 0)
571 return;
572
575 sinstrument = shm_toc_allocate(pcxt->toc, size);
576 memset(sinstrument, 0, size);
577 sinstrument->num_workers = pcxt->nworkers;
578 shm_toc_insert(pcxt->toc,
579 node->ss.ps.plan->plan_node_id +
581 sinstrument);
582 node->trss_sinstrument = sinstrument;
583}
584
585/*
586 * Look up and save the location of the shared instrumentation.
587 */
588void
591{
592 EState *estate = node->ss.ps.state;
593
594 if ((estate->es_instrument & INSTRUMENT_IO) == 0)
595 return;
596
598 node->ss.ps.plan->plan_node_id +
600 false);
601}
602
603/*
604 * Transfer scan instrumentation from DSM to private memory.
605 */
606void
608{
610 Size size;
611
612 if (sinstrument == NULL)
613 return;
614
616 + sinstrument->num_workers * sizeof(TidRangeScanInstrumentation);
617
618 node->trss_sinstrument = palloc(size);
619 memcpy(node->trss_sinstrument, sinstrument, size);
620}
int ParallelWorkerNumber
Definition parallel.c:117
#define InvalidBlockNumber
Definition block.h:33
#define Assert(condition)
Definition c.h:943
uint32_t uint32
Definition c.h:624
#define PG_UINT16_MAX
Definition c.h:671
#define pg_fallthrough
Definition c.h:161
size_t Size
Definition c.h:689
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition execExpr.c:143
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition execExpr.c:250
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, uint16 flags)
void ExecInitResultTypeTL(PlanState *planstate)
bool ScanRelIsReadOnly(ScanState *ss)
Definition execUtils.c:751
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition execUtils.c:490
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition execUtils.c:768
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition executor.h:590
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition executor.h:589
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:446
#define palloc_object(type)
Definition fe_memutils.h:74
#define IsParallelWorker()
Definition parallel.h:62
@ INSTRUMENT_IO
Definition instrument.h:67
#define PARALLEL_KEY_SCAN_INSTRUMENT_OFFSET
static void AccumulateIOStats(IOStats *dst, IOStats *src)
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
void * palloc(Size size)
Definition mcxt.c:1387
static Node * get_rightop(const void *clause)
Definition nodeFuncs.h:95
static Node * get_leftop(const void *clause)
Definition nodeFuncs.h:83
void ExecTidRangeScanInstrumentEstimate(TidRangeScanState *node, ParallelContext *pcxt)
static void TidExprListCreate(TidRangeScanState *tidrangestate)
void ExecTidRangeScanEstimate(TidRangeScanState *node, ParallelContext *pcxt)
void ExecTidRangeScanInstrumentInitDSM(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)
void ExecTidRangeScanRetrieveInstrumentation(TidRangeScanState *node)
#define IsCTIDVar(node)
TidExprType
@ TIDEXPR_LOWER_BOUND
@ TIDEXPR_UPPER_BOUND
void ExecTidRangeScanInstrumentInitWorker(TidRangeScanState *node, ParallelWorkerContext *pwcxt)
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:332
#define RelationGetDescr(relation)
Definition rel.h:542
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:239
#define shm_toc_estimate_chunk(e, sz)
Definition shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition shm_toc.h:53
Size add_size(Size s1, Size s2)
Definition shmem.c:1048
Size mul_size(Size s1, Size s2)
Definition shmem.c:1063
int es_instrument
Definition execnodes.h:756
ScanDirection es_direction
Definition execnodes.h:695
Snapshot es_snapshot
Definition execnodes.h:696
Definition pg_list.h:54
Definition nodes.h:135
Oid opno
Definition primnodes.h:851
shm_toc_estimator estimator
Definition parallel.h:43
shm_toc * toc
Definition parallel.h:46
Plan * plan
Definition execnodes.h:1201
EState * state
Definition execnodes.h:1203
ExprContext * ps_ExprContext
Definition execnodes.h:1242
int plan_node_id
Definition plannodes.h:233
Relation ss_currentRelation
Definition execnodes.h:1660
TupleTableSlot * ss_ScanTupleSlot
Definition execnodes.h:1662
PlanState ps
Definition execnodes.h:1659
struct TableScanDescData * ss_currentScanDesc
Definition execnodes.h:1661
Index scanrelid
Definition plannodes.h:544
TidRangeScanInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER]
struct TableScanInstrumentation * rs_instrument
Definition relscan.h:72
struct ParallelTableScanDescData * rs_parallel
Definition relscan.h:66
ExprState * exprstate
TidExprType exprtype
ItemPointerData trss_maxtid
Definition execnodes.h:1922
struct SharedTidRangeScanInstrumentation * trss_sinstrument
Definition execnodes.h:1925
ItemPointerData trss_mintid
Definition execnodes.h:1921
ItemPointerData tts_tid
Definition tuptable.h:142
TableScanDesc table_beginscan_parallel_tidrange(Relation relation, ParallelTableScanDesc pscan, uint32 flags)
Definition tableam.c:193
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
@ SO_HINT_REL_READ_ONLY
Definition tableam.h:71
@ SO_NONE
Definition tableam.h:49
@ SO_SCAN_INSTRUMENT
Definition tableam.h:74
static void table_rescan_tidrange(TableScanDesc sscan, ItemPointer mintid, ItemPointer maxtid)
Definition tableam.h:1141
static void table_endscan(TableScanDesc scan)
Definition tableam.h:1061
static TableScanDesc table_beginscan_tidrange(Relation rel, Snapshot snapshot, ItemPointer mintid, ItemPointer maxtid, uint32 flags)
Definition tableam.h:1119
static bool table_scan_getnextslot_tidrange(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition tableam.h:1157
static void table_parallelscan_reinitialize(Relation rel, ParallelTableScanDesc pscan)
Definition tableam.h:1226
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:476
#define TTS_FLAG_OBEYS_NOT_NULL_CONSTRAINTS
Definition tuptable.h:102

Typedef Documentation

◆ TidOpExpr

Enumeration Type Documentation

◆ TidExprType

Enumerator
TIDEXPR_UPPER_BOUND 
TIDEXPR_LOWER_BOUND 

Definition at line 40 of file nodeTidrangescan.c.

Function Documentation

◆ ExecEndTidRangeScan()

void ExecEndTidRangeScan ( TidRangeScanState node)

Definition at line 350 of file nodeTidrangescan.c.

351{
353
354 /* Collect IO stats for this process into shared instrumentation */
355 if (node->trss_sinstrument != NULL && IsParallelWorker())
356 {
358
359 Assert(ParallelWorkerNumber < node->trss_sinstrument->num_workers);
361
362 if (scan && scan->rs_instrument)
363 {
364 AccumulateIOStats(&si->stats.io, &scan->rs_instrument->io);
365 }
366 }
367
368 if (scan != NULL)
369 table_endscan(scan);
370}

References AccumulateIOStats(), Assert, fb(), TableScanInstrumentation::io, IsParallelWorker, ParallelWorkerNumber, TableScanDescData::rs_instrument, SharedTidRangeScanInstrumentation::sinstrument, TidRangeScanState::ss, ScanState::ss_currentScanDesc, table_endscan(), and TidRangeScanState::trss_sinstrument.

Referenced by ExecEndNode().

◆ ExecInitTidRangeScan()

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

Definition at line 384 of file nodeTidrangescan.c.

385{
388
389 /*
390 * create state structure
391 */
393 tidrangestate->ss.ps.plan = (Plan *) node;
394 tidrangestate->ss.ps.state = estate;
395 tidrangestate->ss.ps.ExecProcNode = ExecTidRangeScan;
396
397 /*
398 * Miscellaneous initialization
399 *
400 * create expression context for node
401 */
402 ExecAssignExprContext(estate, &tidrangestate->ss.ps);
403
404 /*
405 * mark scan as not in progress, and TID range as not computed yet
406 */
407 tidrangestate->trss_inScan = false;
408
409 /*
410 * open the scan relation
411 */
412 currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
413
414 tidrangestate->ss.ss_currentRelation = currentRelation;
415 tidrangestate->ss.ss_currentScanDesc = NULL; /* no table scan here */
416
417 /*
418 * get the scan type from the relation descriptor.
419 */
424
425 /*
426 * Initialize result type and projection.
427 */
430
431 /*
432 * initialize child expressions
433 */
434 tidrangestate->ss.ps.qual =
435 ExecInitQual(node->scan.plan.qual, (PlanState *) tidrangestate);
436
438
439 /*
440 * all done.
441 */
442 return tidrangestate;
443}

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

Referenced by ExecInitNode().

◆ ExecReScanTidRangeScan()

void ExecReScanTidRangeScan ( TidRangeScanState node)

Definition at line 331 of file nodeTidrangescan.c.

332{
333 /* mark scan as not in progress, and tid range list as not computed yet */
334 node->trss_inScan = false;
335
336 /*
337 * We must wait until TidRangeNext before calling table_rescan_tidrange.
338 */
339 ExecScanReScan(&node->ss);
340}

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

Referenced by ExecReScan().

◆ ExecTidRangeScan()

static TupleTableSlot * ExecTidRangeScan ( PlanState pstate)
static

◆ ExecTidRangeScanEstimate()

◆ ExecTidRangeScanInitializeDSM()

◆ ExecTidRangeScanInitializeWorker()

◆ ExecTidRangeScanInstrumentEstimate()

void ExecTidRangeScanInstrumentEstimate ( TidRangeScanState node,
ParallelContext pcxt 
)

◆ ExecTidRangeScanInstrumentInitDSM()

void ExecTidRangeScanInstrumentInitDSM ( TidRangeScanState node,
ParallelContext pcxt 
)

◆ ExecTidRangeScanInstrumentInitWorker()

void ExecTidRangeScanInstrumentInitWorker ( TidRangeScanState node,
ParallelWorkerContext pwcxt 
)

◆ ExecTidRangeScanReInitializeDSM()

◆ ExecTidRangeScanRetrieveInstrumentation()

void ExecTidRangeScanRetrieveInstrumentation ( TidRangeScanState node)

Definition at line 608 of file nodeTidrangescan.c.

609{
611 Size size;
612
613 if (sinstrument == NULL)
614 return;
615
617 + sinstrument->num_workers * sizeof(TidRangeScanInstrumentation);
618
619 node->trss_sinstrument = palloc(size);
620 memcpy(node->trss_sinstrument, sinstrument, size);
621}

References fb(), memcpy(), SharedTidRangeScanInstrumentation::num_workers, palloc(), and TidRangeScanState::trss_sinstrument.

Referenced by ExecParallelRetrieveInstrumentation().

◆ MakeTidOpExpr()

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

Definition at line 59 of file nodeTidrangescan.c.

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

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

Referenced by TidExprListCreate().

◆ TidExprListCreate()

static void TidExprListCreate ( TidRangeScanState tidrangestate)
static

Definition at line 108 of file nodeTidrangescan.c.

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

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 141 of file nodeTidrangescan.c.

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

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 224 of file nodeTidrangescan.c.

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

References EState::es_direction, EState::es_instrument, EState::es_snapshot, ExecClearTuple(), fb(), INSTRUMENT_IO, ScanState::ps, ScanRelIsReadOnly(), SO_HINT_REL_READ_ONLY, SO_NONE, SO_SCAN_INSTRUMENT, 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 286 of file nodeTidrangescan.c.

287{
288 if (!TidRangeEval(node))
289 return false;
290
292
293 /* Recheck the ctid is still within range */
294 if (ItemPointerCompare(&slot->tts_tid, &node->trss_mintid) < 0 ||
295 ItemPointerCompare(&slot->tts_tid, &node->trss_maxtid) > 0)
296 return false;
297
298 return true;
299}

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

Referenced by ExecTidRangeScan().