PostgreSQL Source Code  git master
nodeSamplescan.c File Reference
#include "postgres.h"
#include "access/hash.h"
#include "access/relscan.h"
#include "access/tsmapi.h"
#include "executor/executor.h"
#include "executor/nodeSamplescan.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/predicate.h"
#include "utils/builtins.h"
#include "utils/rel.h"
#include "utils/tqual.h"
Include dependency graph for nodeSamplescan.c:

Go to the source code of this file.

Functions

static void InitScanRelation (SampleScanState *node, EState *estate, int eflags)
 
static TupleTableSlotSampleNext (SampleScanState *node)
 
static void tablesample_init (SampleScanState *scanstate)
 
static HeapTuple tablesample_getnext (SampleScanState *scanstate)
 
static bool SampleTupleVisible (HeapTuple tuple, OffsetNumber tupoffset, HeapScanDesc scan)
 
static bool SampleRecheck (SampleScanState *node, TupleTableSlot *slot)
 
static TupleTableSlotExecSampleScan (PlanState *pstate)
 
SampleScanStateExecInitSampleScan (SampleScan *node, EState *estate, int eflags)
 
void ExecEndSampleScan (SampleScanState *node)
 
void ExecReScanSampleScan (SampleScanState *node)
 

Function Documentation

◆ ExecEndSampleScan()

void ExecEndSampleScan ( SampleScanState node)

Definition at line 224 of file nodeSamplescan.c.

References TsmRoutine::EndSampleScan, ExecClearTuple(), ExecCloseScanRelation(), ExecFreeExprContext(), heap_endscan(), ScanState::ps, PlanState::ps_ResultTupleSlot, SampleScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, ScanState::ss_ScanTupleSlot, and SampleScanState::tsmroutine.

Referenced by ExecEndNode().

225 {
226  /*
227  * Tell sampling function that we finished the scan.
228  */
229  if (node->tsmroutine->EndSampleScan)
230  node->tsmroutine->EndSampleScan(node);
231 
232  /*
233  * Free the exprcontext
234  */
235  ExecFreeExprContext(&node->ss.ps);
236 
237  /*
238  * clean out the tuple table
239  */
242 
243  /*
244  * close heap scan
245  */
246  if (node->ss.ss_currentScanDesc)
248 
249  /*
250  * close the heap relation.
251  */
253 }
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1565
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1106
Relation ss_currentRelation
Definition: execnodes.h:1104
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:523
PlanState ps
Definition: execnodes.h:1103
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:882
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:668
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1129
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1105
EndSampleScan_function EndSampleScan
Definition: tsmapi.h:74
ScanState ss
Definition: execnodes.h:1125

◆ ExecInitSampleScan()

SampleScanState* ExecInitSampleScan ( SampleScan node,
EState estate,
int  eflags 
)

Definition at line 143 of file nodeSamplescan.c.

References TableSampleClause::args, Assert, ExecAssignExprContext(), ExecAssignResultTypeFromTL(), ExecAssignScanProjectionInfo(), ExecInitExpr(), ExecInitExprList(), ExecInitQual(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), PlanState::ExecProcNode, ExecSampleScan(), GetTsmRoutine(), TsmRoutine::InitSampleScan, InitScanRelation(), innerPlan, makeNode, outerPlan, Scan::plan, PlanState::plan, ScanState::ps, Plan::qual, PlanState::qual, random(), TableSampleClause::repeatable, SampleScan::scan, SampleScanState::ss, PlanState::state, SampleScan::tablesample, and TableSampleClause::tsmhandler.

Referenced by ExecInitNode().

144 {
145  SampleScanState *scanstate;
146  TableSampleClause *tsc = node->tablesample;
147  TsmRoutine *tsm;
148 
149  Assert(outerPlan(node) == NULL);
150  Assert(innerPlan(node) == NULL);
151 
152  /*
153  * create state structure
154  */
155  scanstate = makeNode(SampleScanState);
156  scanstate->ss.ps.plan = (Plan *) node;
157  scanstate->ss.ps.state = estate;
158  scanstate->ss.ps.ExecProcNode = ExecSampleScan;
159 
160  /*
161  * Miscellaneous initialization
162  *
163  * create expression context for node
164  */
165  ExecAssignExprContext(estate, &scanstate->ss.ps);
166 
167  /*
168  * initialize child expressions
169  */
170  scanstate->ss.ps.qual =
171  ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
172 
173  scanstate->args = ExecInitExprList(tsc->args, (PlanState *) scanstate);
174  scanstate->repeatable =
175  ExecInitExpr(tsc->repeatable, (PlanState *) scanstate);
176 
177  /*
178  * tuple table initialization
179  */
180  ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
181  ExecInitScanTupleSlot(estate, &scanstate->ss);
182 
183  /*
184  * initialize scan relation
185  */
186  InitScanRelation(scanstate, estate, eflags);
187 
188  /*
189  * Initialize result tuple type and projection info.
190  */
191  ExecAssignResultTypeFromTL(&scanstate->ss.ps);
192  ExecAssignScanProjectionInfo(&scanstate->ss);
193 
194  /*
195  * If we don't have a REPEATABLE clause, select a random seed. We want to
196  * do this just once, since the seed shouldn't change over rescans.
197  */
198  if (tsc->repeatable == NULL)
199  scanstate->seed = random();
200 
201  /*
202  * Finally, initialize the TABLESAMPLE method handler.
203  */
204  tsm = GetTsmRoutine(tsc->tsmhandler);
205  scanstate->tsmroutine = tsm;
206  scanstate->tsm_state = NULL;
207 
208  if (tsm->InitSampleScan)
209  tsm->InitSampleScan(scanstate, eflags);
210 
211  /* We'll do BeginSampleScan later; we can't evaluate params yet */
212  scanstate->begun = false;
213 
214  return scanstate;
215 }
InitSampleScan_function InitSampleScan
Definition: tsmapi.h:70
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:328
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
long random(void)
Definition: random.c:22
void * tsm_state
Definition: execnodes.h:1130
struct TableSampleClause * tablesample
Definition: plannodes.h:346
EState * state
Definition: execnodes.h:851
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:160
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:447
PlanState ps
Definition: execnodes.h:1103
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:237
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
Scan scan
Definition: plannodes.h:344
#define innerPlan(node)
Definition: plannodes.h:173
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:266
ExprState * repeatable
Definition: execnodes.h:1127
#define outerPlan(node)
Definition: plannodes.h:174
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:855
Plan * plan
Definition: execnodes.h:849
TsmRoutine * GetTsmRoutine(Oid tsmhandler)
Definition: tablesample.c:27
#define makeNode(_type_)
Definition: nodes.h:558
#define Assert(condition)
Definition: c.h:670
static void InitScanRelation(SampleScanState *node, EState *estate, int eflags)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:425
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1129
ExprState * qual
Definition: execnodes.h:867
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:113
static TupleTableSlot * ExecSampleScan(PlanState *pstate)
ScanState ss
Definition: execnodes.h:1125

◆ ExecReScanSampleScan()

void ExecReScanSampleScan ( SampleScanState node)

Definition at line 263 of file nodeSamplescan.c.

References SampleScanState::begun, ExecScanReScan(), and SampleScanState::ss.

Referenced by ExecReScan().

264 {
265  /* Remember we need to do BeginSampleScan again (if we did it at all) */
266  node->begun = false;
267 
268  ExecScanReScan(&node->ss);
269 }
void ExecScanReScan(ScanState *node)
Definition: execScan.c:329
ScanState ss
Definition: execnodes.h:1125

◆ ExecSampleScan()

static TupleTableSlot* ExecSampleScan ( PlanState pstate)
static

Definition at line 100 of file nodeSamplescan.c.

References castNode, ExecScan(), SampleNext(), SampleRecheck(), and SampleScanState::ss.

Referenced by ExecInitSampleScan().

101 {
102  SampleScanState *node = castNode(SampleScanState, pstate);
103 
104  return ExecScan(&node->ss,
107 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:579
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:123
static TupleTableSlot * SampleNext(SampleScanState *node)
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:401
static bool SampleRecheck(SampleScanState *node, TupleTableSlot *slot)
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:400
ScanState ss
Definition: execnodes.h:1125

◆ InitScanRelation()

static void InitScanRelation ( SampleScanState node,
EState estate,
int  eflags 
)
static

Definition at line 116 of file nodeSamplescan.c.

References ExecAssignScanType(), ExecOpenScanRelation(), PlanState::plan, ScanState::ps, RelationGetDescr, SampleScanState::ss, ScanState::ss_currentRelation, and ScanState::ss_currentScanDesc.

Referenced by ExecInitSampleScan().

117 {
118  Relation currentRelation;
119 
120  /*
121  * get the relation object id from the relid'th entry in the range table,
122  * open that relation and acquire appropriate lock on it.
123  */
124  currentRelation = ExecOpenScanRelation(estate,
125  ((SampleScan *) node->ss.ps.plan)->scan.scanrelid,
126  eflags);
127 
128  node->ss.ss_currentRelation = currentRelation;
129 
130  /* we won't set up the HeapScanDesc till later */
131  node->ss.ss_currentScanDesc = NULL;
132 
133  /* and report the scan tuple slot's rowtype */
134  ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
135 }
#define RelationGetDescr(relation)
Definition: rel.h:437
Relation ss_currentRelation
Definition: execnodes.h:1104
PlanState ps
Definition: execnodes.h:1103
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:610
Plan * plan
Definition: execnodes.h:849
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1105
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:547
ScanState ss
Definition: execnodes.h:1125

◆ SampleNext()

static TupleTableSlot * SampleNext ( SampleScanState node)
static

Definition at line 48 of file nodeSamplescan.c.

References SampleScanState::begun, ExecClearTuple(), ExecStoreTuple(), HeapScanDescData::rs_cbuf, SampleScanState::ss, ScanState::ss_currentScanDesc, ScanState::ss_ScanTupleSlot, tablesample_getnext(), and tablesample_init().

Referenced by ExecSampleScan().

49 {
50  HeapTuple tuple;
51  TupleTableSlot *slot;
52 
53  /*
54  * if this is first call within a scan, initialize
55  */
56  if (!node->begun)
57  tablesample_init(node);
58 
59  /*
60  * get the next tuple, and store it in our result slot
61  */
62  tuple = tablesample_getnext(node);
63 
64  slot = node->ss.ss_ScanTupleSlot;
65 
66  if (tuple)
67  ExecStoreTuple(tuple, /* tuple to store */
68  slot, /* slot to store in */
69  node->ss.ss_currentScanDesc->rs_cbuf, /* tuple's buffer */
70  false); /* don't pfree this pointer */
71  else
72  ExecClearTuple(slot);
73 
74  return slot;
75 }
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
static HeapTuple tablesample_getnext(SampleScanState *scanstate)
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1106
static void tablesample_init(SampleScanState *scanstate)
Buffer rs_cbuf
Definition: relscan.h:71
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1105
ScanState ss
Definition: execnodes.h:1125

◆ SampleRecheck()

static bool SampleRecheck ( SampleScanState node,
TupleTableSlot slot 
)
static

Definition at line 81 of file nodeSamplescan.c.

Referenced by ExecSampleScan().

82 {
83  /*
84  * No need to recheck for SampleScan, since like SeqScan we don't pass any
85  * checkable keys to heap_beginscan.
86  */
87  return true;
88 }

◆ SampleTupleVisible()

static bool SampleTupleVisible ( HeapTuple  tuple,
OffsetNumber  tupoffset,
HeapScanDesc  scan 
)
static

Definition at line 557 of file nodeSamplescan.c.

References HeapTupleSatisfiesVisibility, HeapScanDescData::rs_cbuf, HeapScanDescData::rs_ntuples, HeapScanDescData::rs_pageatatime, HeapScanDescData::rs_snapshot, and HeapScanDescData::rs_vistuples.

Referenced by tablesample_getnext().

558 {
559  if (scan->rs_pageatatime)
560  {
561  /*
562  * In pageatatime mode, heapgetpage() already did visibility checks,
563  * so just look at the info it left in rs_vistuples[].
564  *
565  * We use a binary search over the known-sorted array. Note: we could
566  * save some effort if we insisted that NextSampleTuple select tuples
567  * in increasing order, but it's not clear that there would be enough
568  * gain to justify the restriction.
569  */
570  int start = 0,
571  end = scan->rs_ntuples - 1;
572 
573  while (start <= end)
574  {
575  int mid = (start + end) / 2;
576  OffsetNumber curoffset = scan->rs_vistuples[mid];
577 
578  if (tupoffset == curoffset)
579  return true;
580  else if (tupoffset < curoffset)
581  end = mid - 1;
582  else
583  start = mid + 1;
584  }
585 
586  return false;
587  }
588  else
589  {
590  /* Otherwise, we have to check the tuple individually. */
591  return HeapTupleSatisfiesVisibility(tuple,
592  scan->rs_snapshot,
593  scan->rs_cbuf);
594  }
595 }
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
uint16 OffsetNumber
Definition: off.h:24
bool rs_pageatatime
Definition: relscan.h:54
Snapshot rs_snapshot
Definition: relscan.h:49
Buffer rs_cbuf
Definition: relscan.h:71
OffsetNumber rs_vistuples[MaxHeapTuplesPerPage]
Definition: relscan.h:78

◆ tablesample_getnext()

static HeapTuple tablesample_getnext ( SampleScanState scanstate)
static

Definition at line 380 of file nodeSamplescan.c.

References Assert, BlockNumberIsValid, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage, BufferIsValid, CHECK_FOR_INTERRUPTS, CheckForSerializableConflictOut(), heapgetpage(), InvalidBlockNumber, InvalidBuffer, ItemIdGetLength, ItemIdIsNormal, ItemPointerSet, LockBuffer(), TsmRoutine::NextSampleBlock, TsmRoutine::NextSampleTuple, OffsetNumberIsValid, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PageIsAllVisible, pgstat_count_heap_getnext, ReleaseBuffer(), HeapScanDescData::rs_cblock, HeapScanDescData::rs_cbuf, HeapScanDescData::rs_ctup, HeapScanDescData::rs_inited, HeapScanDescData::rs_nblocks, HeapScanDescData::rs_pageatatime, HeapScanDescData::rs_rd, HeapScanDescData::rs_snapshot, HeapScanDescData::rs_startblock, HeapScanDescData::rs_syncscan, SampleTupleVisible(), SampleScanState::ss, ScanState::ss_currentScanDesc, ss_report_location(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, SnapshotData::takenDuringRecovery, and SampleScanState::tsmroutine.

Referenced by SampleNext().

381 {
382  TsmRoutine *tsm = scanstate->tsmroutine;
383  HeapScanDesc scan = scanstate->ss.ss_currentScanDesc;
384  HeapTuple tuple = &(scan->rs_ctup);
385  Snapshot snapshot = scan->rs_snapshot;
386  bool pagemode = scan->rs_pageatatime;
387  BlockNumber blockno;
388  Page page;
389  bool all_visible;
390  OffsetNumber maxoffset;
391 
392  if (!scan->rs_inited)
393  {
394  /*
395  * return null immediately if relation is empty
396  */
397  if (scan->rs_nblocks == 0)
398  {
399  Assert(!BufferIsValid(scan->rs_cbuf));
400  tuple->t_data = NULL;
401  return NULL;
402  }
403  if (tsm->NextSampleBlock)
404  {
405  blockno = tsm->NextSampleBlock(scanstate);
406  if (!BlockNumberIsValid(blockno))
407  {
408  tuple->t_data = NULL;
409  return NULL;
410  }
411  }
412  else
413  blockno = scan->rs_startblock;
414  Assert(blockno < scan->rs_nblocks);
415  heapgetpage(scan, blockno);
416  scan->rs_inited = true;
417  }
418  else
419  {
420  /* continue from previously returned page/tuple */
421  blockno = scan->rs_cblock; /* current page */
422  }
423 
424  /*
425  * When not using pagemode, we must lock the buffer during tuple
426  * visibility checks.
427  */
428  if (!pagemode)
430 
431  page = (Page) BufferGetPage(scan->rs_cbuf);
432  all_visible = PageIsAllVisible(page) && !snapshot->takenDuringRecovery;
433  maxoffset = PageGetMaxOffsetNumber(page);
434 
435  for (;;)
436  {
437  OffsetNumber tupoffset;
438  bool finished;
439 
441 
442  /* Ask the tablesample method which tuples to check on this page. */
443  tupoffset = tsm->NextSampleTuple(scanstate,
444  blockno,
445  maxoffset);
446 
447  if (OffsetNumberIsValid(tupoffset))
448  {
449  ItemId itemid;
450  bool visible;
451 
452  /* Skip invalid tuple pointers. */
453  itemid = PageGetItemId(page, tupoffset);
454  if (!ItemIdIsNormal(itemid))
455  continue;
456 
457  tuple->t_data = (HeapTupleHeader) PageGetItem(page, itemid);
458  tuple->t_len = ItemIdGetLength(itemid);
459  ItemPointerSet(&(tuple->t_self), blockno, tupoffset);
460 
461  if (all_visible)
462  visible = true;
463  else
464  visible = SampleTupleVisible(tuple, tupoffset, scan);
465 
466  /* in pagemode, heapgetpage did this for us */
467  if (!pagemode)
468  CheckForSerializableConflictOut(visible, scan->rs_rd, tuple,
469  scan->rs_cbuf, snapshot);
470 
471  if (visible)
472  {
473  /* Found visible tuple, return it. */
474  if (!pagemode)
476  break;
477  }
478  else
479  {
480  /* Try next tuple from same page. */
481  continue;
482  }
483  }
484 
485  /*
486  * if we get here, it means we've exhausted the items on this page and
487  * it's time to move to the next.
488  */
489  if (!pagemode)
491 
492  if (tsm->NextSampleBlock)
493  {
494  blockno = tsm->NextSampleBlock(scanstate);
495  Assert(!scan->rs_syncscan);
496  finished = !BlockNumberIsValid(blockno);
497  }
498  else
499  {
500  /* Without NextSampleBlock, just do a plain forward seqscan. */
501  blockno++;
502  if (blockno >= scan->rs_nblocks)
503  blockno = 0;
504 
505  /*
506  * Report our new scan position for synchronization purposes.
507  *
508  * Note: we do this before checking for end of scan so that the
509  * final state of the position hint is back at the start of the
510  * rel. That's not strictly necessary, but otherwise when you run
511  * the same query multiple times the starting position would shift
512  * a little bit backwards on every invocation, which is confusing.
513  * We don't guarantee any specific ordering in general, though.
514  */
515  if (scan->rs_syncscan)
516  ss_report_location(scan->rs_rd, blockno);
517 
518  finished = (blockno == scan->rs_startblock);
519  }
520 
521  /*
522  * Reached end of scan?
523  */
524  if (finished)
525  {
526  if (BufferIsValid(scan->rs_cbuf))
527  ReleaseBuffer(scan->rs_cbuf);
528  scan->rs_cbuf = InvalidBuffer;
530  tuple->t_data = NULL;
531  scan->rs_inited = false;
532  return NULL;
533  }
534 
535  Assert(blockno < scan->rs_nblocks);
536  heapgetpage(scan, blockno);
537 
538  /* Re-establish state for new page */
539  if (!pagemode)
541 
542  page = (Page) BufferGetPage(scan->rs_cbuf);
543  all_visible = PageIsAllVisible(page) && !snapshot->takenDuringRecovery;
544  maxoffset = PageGetMaxOffsetNumber(page);
545  }
546 
547  /* Count successfully-fetched tuples as heap fetches */
549 
550  return &(scan->rs_ctup);
551 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
static bool SampleTupleVisible(HeapTuple tuple, OffsetNumber tupoffset, HeapScanDesc scan)
BlockNumber rs_cblock
Definition: relscan.h:70
#define PageIsAllVisible(page)
Definition: bufpage.h:381
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define InvalidBuffer
Definition: buf.h:25
void heapgetpage(HeapScanDesc scan, BlockNumber page)
Definition: heapam.c:347
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
void CheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
Definition: predicate.c:3945
HeapTupleData rs_ctup
Definition: relscan.h:69
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:67
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
NextSampleTuple_function NextSampleTuple
Definition: tsmapi.h:73
bool rs_pageatatime
Definition: relscan.h:54
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
Snapshot rs_snapshot
Definition: relscan.h:49
bool rs_inited
Definition: relscan.h:68
NextSampleBlock_function NextSampleBlock
Definition: tsmapi.h:72
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
BlockNumber rs_startblock
Definition: relscan.h:61
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
BlockNumber rs_nblocks
Definition: relscan.h:60
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
Relation rs_rd
Definition: relscan.h:48
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
Buffer rs_cbuf
Definition: relscan.h:71
#define Assert(condition)
Definition: c.h:670
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
bool takenDuringRecovery
Definition: snapshot.h:95
#define InvalidBlockNumber
Definition: block.h:33
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1129
void ss_report_location(Relation rel, BlockNumber location)
Definition: syncscan.c:288
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1105
#define OffsetNumberIsValid(offsetNumber)
Definition: off.h:40
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
bool rs_syncscan
Definition: relscan.h:65
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define pgstat_count_heap_getnext(rel)
Definition: pgstat.h:1265
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:105
ScanState ss
Definition: execnodes.h:1125

◆ tablesample_init()

static void tablesample_init ( SampleScanState scanstate)
static

Definition at line 276 of file nodeSamplescan.c.

References arg, SampleScanState::args, TsmRoutine::BeginSampleScan, SampleScanState::begun, DatumGetUInt32, DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, EState::es_snapshot, ExecEvalExprSwitchContext(), hashfloat8(), heap_beginscan_sampling(), heap_rescan_set_params(), i, lfirst, list_length(), TsmRoutine::NextSampleBlock, palloc(), pfree(), ScanState::ps, PlanState::ps_ExprContext, SampleScanState::repeatable, SampleScanState::seed, SampleScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, PlanState::state, SampleScanState::tsmroutine, SampleScanState::use_bulkread, and SampleScanState::use_pagemode.

Referenced by SampleNext().

277 {
278  TsmRoutine *tsm = scanstate->tsmroutine;
279  ExprContext *econtext = scanstate->ss.ps.ps_ExprContext;
280  Datum *params;
281  Datum datum;
282  bool isnull;
283  uint32 seed;
284  bool allow_sync;
285  int i;
286  ListCell *arg;
287 
288  params = (Datum *) palloc(list_length(scanstate->args) * sizeof(Datum));
289 
290  i = 0;
291  foreach(arg, scanstate->args)
292  {
293  ExprState *argstate = (ExprState *) lfirst(arg);
294 
295  params[i] = ExecEvalExprSwitchContext(argstate,
296  econtext,
297  &isnull);
298  if (isnull)
299  ereport(ERROR,
300  (errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
301  errmsg("TABLESAMPLE parameter cannot be null")));
302  i++;
303  }
304 
305  if (scanstate->repeatable)
306  {
307  datum = ExecEvalExprSwitchContext(scanstate->repeatable,
308  econtext,
309  &isnull);
310  if (isnull)
311  ereport(ERROR,
312  (errcode(ERRCODE_INVALID_TABLESAMPLE_REPEAT),
313  errmsg("TABLESAMPLE REPEATABLE parameter cannot be null")));
314 
315  /*
316  * The REPEATABLE parameter has been coerced to float8 by the parser.
317  * The reason for using float8 at the SQL level is that it will
318  * produce unsurprising results both for users used to databases that
319  * accept only integers in the REPEATABLE clause and for those who
320  * might expect that REPEATABLE works like setseed() (a float in the
321  * range from -1 to 1).
322  *
323  * We use hashfloat8() to convert the supplied value into a suitable
324  * seed. For regression-testing purposes, that has the convenient
325  * property that REPEATABLE(0) gives a machine-independent result.
326  */
328  }
329  else
330  {
331  /* Use the seed selected by ExecInitSampleScan */
332  seed = scanstate->seed;
333  }
334 
335  /* Set default values for params that BeginSampleScan can adjust */
336  scanstate->use_bulkread = true;
337  scanstate->use_pagemode = true;
338 
339  /* Let tablesample method do its thing */
340  tsm->BeginSampleScan(scanstate,
341  params,
342  list_length(scanstate->args),
343  seed);
344 
345  /* We'll use syncscan if there's no NextSampleBlock function */
346  allow_sync = (tsm->NextSampleBlock == NULL);
347 
348  /* Now we can create or reset the HeapScanDesc */
349  if (scanstate->ss.ss_currentScanDesc == NULL)
350  {
351  scanstate->ss.ss_currentScanDesc =
353  scanstate->ss.ps.state->es_snapshot,
354  0, NULL,
355  scanstate->use_bulkread,
356  allow_sync,
357  scanstate->use_pagemode);
358  }
359  else
360  {
362  scanstate->use_bulkread,
363  allow_sync,
364  scanstate->use_pagemode);
365  }
366 
367  pfree(params);
368 
369  /* And we're initialized. */
370  scanstate->begun = true;
371 }
#define DatumGetUInt32(X)
Definition: postgres.h:492
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:291
ExprContext * ps_ExprContext
Definition: execnodes.h:883
int errcode(int sqlerrcode)
Definition: elog.c:575
Snapshot es_snapshot
Definition: execnodes.h:429
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
Relation ss_currentRelation
Definition: execnodes.h:1104
EState * state
Definition: execnodes.h:851
PlanState ps
Definition: execnodes.h:1103
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
HeapScanDesc heap_beginscan_sampling(Relation relation, Snapshot snapshot, int nkeys, ScanKey key, bool allow_strat, bool allow_sync, bool allow_pagemode)
Definition: heapam.c:1433
unsigned int uint32
Definition: c.h:296
ExprState * repeatable
Definition: execnodes.h:1127
NextSampleBlock_function NextSampleBlock
Definition: tsmapi.h:72
#define ereport(elevel, rest)
Definition: elog.h:122
Datum hashfloat8(PG_FUNCTION_ARGS)
Definition: hashfunc.c:178
uintptr_t Datum
Definition: postgres.h:372
#define lfirst(lc)
Definition: pg_list.h:106
void heap_rescan_set_params(HeapScanDesc scan, ScanKey key, bool allow_strat, bool allow_sync, bool allow_pagemode)
Definition: heapam.c:1546
static int list_length(const List *l)
Definition: pg_list.h:89
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1129
BeginSampleScan_function BeginSampleScan
Definition: tsmapi.h:71
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1105
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void * arg
ScanState ss
Definition: execnodes.h:1125