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 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 202 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().

203 {
204  /*
205  * Tell sampling function that we finished the scan.
206  */
207  if (node->tsmroutine->EndSampleScan)
208  node->tsmroutine->EndSampleScan(node);
209 
210  /*
211  * Free the exprcontext
212  */
213  ExecFreeExprContext(&node->ss.ps);
214 
215  /*
216  * clean out the tuple table
217  */
220 
221  /*
222  * close heap scan
223  */
224  if (node->ss.ss_currentScanDesc)
226 
227  /*
228  * close the heap relation.
229  */
231 }
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1572
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1194
Relation ss_currentRelation
Definition: execnodes.h:1192
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:566
PlanState ps
Definition: execnodes.h:1191
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:945
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:701
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1217
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1193
EndSampleScan_function EndSampleScan
Definition: tsmapi.h:74
ScanState ss
Definition: execnodes.h:1213

◆ ExecInitSampleScan()

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

Definition at line 113 of file nodeSamplescan.c.

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

Referenced by ExecInitNode().

114 {
115  SampleScanState *scanstate;
116  TableSampleClause *tsc = node->tablesample;
117  TsmRoutine *tsm;
118 
119  Assert(outerPlan(node) == NULL);
120  Assert(innerPlan(node) == NULL);
121 
122  /*
123  * create state structure
124  */
125  scanstate = makeNode(SampleScanState);
126  scanstate->ss.ps.plan = (Plan *) node;
127  scanstate->ss.ps.state = estate;
128  scanstate->ss.ps.ExecProcNode = ExecSampleScan;
129 
130  /*
131  * Miscellaneous initialization
132  *
133  * create expression context for node
134  */
135  ExecAssignExprContext(estate, &scanstate->ss.ps);
136 
137  /*
138  * Initialize scan relation.
139  *
140  * Get the relation object id from the relid'th entry in the range table,
141  * open that relation and acquire appropriate lock on it.
142  */
143  scanstate->ss.ss_currentRelation =
144  ExecOpenScanRelation(estate,
145  node->scan.scanrelid,
146  eflags);
147 
148  /* we won't set up the HeapScanDesc till later */
149  scanstate->ss.ss_currentScanDesc = NULL;
150 
151  /* and create slot with appropriate rowtype */
152  ExecInitScanTupleSlot(estate, &scanstate->ss,
154 
155  /*
156  * Initialize result slot, type and projection.
157  * tuple table and result tuple initialization
158  */
159  ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
160  ExecAssignScanProjectionInfo(&scanstate->ss);
161 
162  /*
163  * initialize child expressions
164  */
165  scanstate->ss.ps.qual =
166  ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
167 
168  scanstate->args = ExecInitExprList(tsc->args, (PlanState *) scanstate);
169  scanstate->repeatable =
170  ExecInitExpr(tsc->repeatable, (PlanState *) scanstate);
171 
172  /*
173  * If we don't have a REPEATABLE clause, select a random seed. We want to
174  * do this just once, since the seed shouldn't change over rescans.
175  */
176  if (tsc->repeatable == NULL)
177  scanstate->seed = random();
178 
179  /*
180  * Finally, initialize the TABLESAMPLE method handler.
181  */
182  tsm = GetTsmRoutine(tsc->tsmhandler);
183  scanstate->tsmroutine = tsm;
184  scanstate->tsm_state = NULL;
185 
186  if (tsm->InitSampleScan)
187  tsm->InitSampleScan(scanstate, eflags);
188 
189  /* We'll do BeginSampleScan later; we can't evaluate params yet */
190  scanstate->begun = false;
191 
192  return scanstate;
193 }
InitSampleScan_function InitSampleScan
Definition: tsmapi.h:70
List * qual
Definition: plannodes.h:147
Plan plan
Definition: plannodes.h:342
Index scanrelid
Definition: plannodes.h:343
#define RelationGetDescr(relation)
Definition: rel.h:433
long random(void)
Definition: random.c:22
void * tsm_state
Definition: execnodes.h:1218
struct TableSampleClause * tablesample
Definition: plannodes.h:360
Relation ss_currentRelation
Definition: execnodes.h:1192
EState * state
Definition: execnodes.h:913
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:205
PlanState ps
Definition: execnodes.h:1191
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:235
Scan scan
Definition: plannodes.h:358
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:643
#define innerPlan(node)
Definition: plannodes.h:175
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:314
ExprState * repeatable
Definition: execnodes.h:1215
#define outerPlan(node)
Definition: plannodes.h:176
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:917
void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
Definition: execTuples.c:890
Plan * plan
Definition: execnodes.h:911
TsmRoutine * GetTsmRoutine(Oid tsmhandler)
Definition: tablesample.c:27
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:428
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1217
ExprState * qual
Definition: execnodes.h:929
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1193
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
Definition: execTuples.c:915
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:119
static TupleTableSlot * ExecSampleScan(PlanState *pstate)
ScanState ss
Definition: execnodes.h:1213

◆ ExecReScanSampleScan()

void ExecReScanSampleScan ( SampleScanState node)

Definition at line 241 of file nodeSamplescan.c.

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

Referenced by ExecReScan().

242 {
243  /* Remember we need to do BeginSampleScan again (if we did it at all) */
244  node->begun = false;
245 
246  ExecScanReScan(&node->ss);
247 }
void ExecScanReScan(ScanState *node)
Definition: execScan.c:262
ScanState ss
Definition: execnodes.h:1213

◆ ExecSampleScan()

static TupleTableSlot* ExecSampleScan ( PlanState pstate)
static

Definition at line 99 of file nodeSamplescan.c.

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

Referenced by ExecInitSampleScan().

100 {
101  SampleScanState *node = castNode(SampleScanState, pstate);
102 
103  return ExecScan(&node->ss,
106 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:121
static TupleTableSlot * SampleNext(SampleScanState *node)
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:422
static bool SampleRecheck(SampleScanState *node, TupleTableSlot *slot)
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:421
ScanState ss
Definition: execnodes.h:1213

◆ SampleNext()

static TupleTableSlot * SampleNext ( SampleScanState node)
static

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

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

◆ SampleRecheck()

static bool SampleRecheck ( SampleScanState node,
TupleTableSlot slot 
)
static

Definition at line 80 of file nodeSamplescan.c.

Referenced by ExecSampleScan().

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

◆ SampleTupleVisible()

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

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

536 {
537  if (scan->rs_pageatatime)
538  {
539  /*
540  * In pageatatime mode, heapgetpage() already did visibility checks,
541  * so just look at the info it left in rs_vistuples[].
542  *
543  * We use a binary search over the known-sorted array. Note: we could
544  * save some effort if we insisted that NextSampleTuple select tuples
545  * in increasing order, but it's not clear that there would be enough
546  * gain to justify the restriction.
547  */
548  int start = 0,
549  end = scan->rs_ntuples - 1;
550 
551  while (start <= end)
552  {
553  int mid = (start + end) / 2;
554  OffsetNumber curoffset = scan->rs_vistuples[mid];
555 
556  if (tupoffset == curoffset)
557  return true;
558  else if (tupoffset < curoffset)
559  end = mid - 1;
560  else
561  start = mid + 1;
562  }
563 
564  return false;
565  }
566  else
567  {
568  /* Otherwise, we have to check the tuple individually. */
569  return HeapTupleSatisfiesVisibility(tuple,
570  scan->rs_snapshot,
571  scan->rs_cbuf);
572  }
573 }
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
uint16 OffsetNumber
Definition: off.h:24
bool rs_pageatatime
Definition: relscan.h:55
Snapshot rs_snapshot
Definition: relscan.h:50
Buffer rs_cbuf
Definition: relscan.h:72
OffsetNumber rs_vistuples[MaxHeapTuplesPerPage]
Definition: relscan.h:79

◆ tablesample_getnext()

static HeapTuple tablesample_getnext ( SampleScanState scanstate)
static

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

359 {
360  TsmRoutine *tsm = scanstate->tsmroutine;
361  HeapScanDesc scan = scanstate->ss.ss_currentScanDesc;
362  HeapTuple tuple = &(scan->rs_ctup);
363  Snapshot snapshot = scan->rs_snapshot;
364  bool pagemode = scan->rs_pageatatime;
365  BlockNumber blockno;
366  Page page;
367  bool all_visible;
368  OffsetNumber maxoffset;
369 
370  if (!scan->rs_inited)
371  {
372  /*
373  * return null immediately if relation is empty
374  */
375  if (scan->rs_nblocks == 0)
376  {
377  Assert(!BufferIsValid(scan->rs_cbuf));
378  tuple->t_data = NULL;
379  return NULL;
380  }
381  if (tsm->NextSampleBlock)
382  {
383  blockno = tsm->NextSampleBlock(scanstate);
384  if (!BlockNumberIsValid(blockno))
385  {
386  tuple->t_data = NULL;
387  return NULL;
388  }
389  }
390  else
391  blockno = scan->rs_startblock;
392  Assert(blockno < scan->rs_nblocks);
393  heapgetpage(scan, blockno);
394  scan->rs_inited = true;
395  }
396  else
397  {
398  /* continue from previously returned page/tuple */
399  blockno = scan->rs_cblock; /* current page */
400  }
401 
402  /*
403  * When not using pagemode, we must lock the buffer during tuple
404  * visibility checks.
405  */
406  if (!pagemode)
408 
409  page = (Page) BufferGetPage(scan->rs_cbuf);
410  all_visible = PageIsAllVisible(page) && !snapshot->takenDuringRecovery;
411  maxoffset = PageGetMaxOffsetNumber(page);
412 
413  for (;;)
414  {
415  OffsetNumber tupoffset;
416  bool finished;
417 
419 
420  /* Ask the tablesample method which tuples to check on this page. */
421  tupoffset = tsm->NextSampleTuple(scanstate,
422  blockno,
423  maxoffset);
424 
425  if (OffsetNumberIsValid(tupoffset))
426  {
427  ItemId itemid;
428  bool visible;
429 
430  /* Skip invalid tuple pointers. */
431  itemid = PageGetItemId(page, tupoffset);
432  if (!ItemIdIsNormal(itemid))
433  continue;
434 
435  tuple->t_data = (HeapTupleHeader) PageGetItem(page, itemid);
436  tuple->t_len = ItemIdGetLength(itemid);
437  ItemPointerSet(&(tuple->t_self), blockno, tupoffset);
438 
439  if (all_visible)
440  visible = true;
441  else
442  visible = SampleTupleVisible(tuple, tupoffset, scan);
443 
444  /* in pagemode, heapgetpage did this for us */
445  if (!pagemode)
446  CheckForSerializableConflictOut(visible, scan->rs_rd, tuple,
447  scan->rs_cbuf, snapshot);
448 
449  if (visible)
450  {
451  /* Found visible tuple, return it. */
452  if (!pagemode)
454  break;
455  }
456  else
457  {
458  /* Try next tuple from same page. */
459  continue;
460  }
461  }
462 
463  /*
464  * if we get here, it means we've exhausted the items on this page and
465  * it's time to move to the next.
466  */
467  if (!pagemode)
469 
470  if (tsm->NextSampleBlock)
471  {
472  blockno = tsm->NextSampleBlock(scanstate);
473  Assert(!scan->rs_syncscan);
474  finished = !BlockNumberIsValid(blockno);
475  }
476  else
477  {
478  /* Without NextSampleBlock, just do a plain forward seqscan. */
479  blockno++;
480  if (blockno >= scan->rs_nblocks)
481  blockno = 0;
482 
483  /*
484  * Report our new scan position for synchronization purposes.
485  *
486  * Note: we do this before checking for end of scan so that the
487  * final state of the position hint is back at the start of the
488  * rel. That's not strictly necessary, but otherwise when you run
489  * the same query multiple times the starting position would shift
490  * a little bit backwards on every invocation, which is confusing.
491  * We don't guarantee any specific ordering in general, though.
492  */
493  if (scan->rs_syncscan)
494  ss_report_location(scan->rs_rd, blockno);
495 
496  finished = (blockno == scan->rs_startblock);
497  }
498 
499  /*
500  * Reached end of scan?
501  */
502  if (finished)
503  {
504  if (BufferIsValid(scan->rs_cbuf))
505  ReleaseBuffer(scan->rs_cbuf);
506  scan->rs_cbuf = InvalidBuffer;
508  tuple->t_data = NULL;
509  scan->rs_inited = false;
510  return NULL;
511  }
512 
513  Assert(blockno < scan->rs_nblocks);
514  heapgetpage(scan, blockno);
515 
516  /* Re-establish state for new page */
517  if (!pagemode)
519 
520  page = (Page) BufferGetPage(scan->rs_cbuf);
521  all_visible = PageIsAllVisible(page) && !snapshot->takenDuringRecovery;
522  maxoffset = PageGetMaxOffsetNumber(page);
523  }
524 
525  /* Count successfully-fetched tuples as heap fetches */
527 
528  return &(scan->rs_ctup);
529 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
static bool SampleTupleVisible(HeapTuple tuple, OffsetNumber tupoffset, HeapScanDesc scan)
BlockNumber rs_cblock
Definition: relscan.h:71
#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:351
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:3899
HeapTupleData rs_ctup
Definition: relscan.h:70
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:68
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
NextSampleTuple_function NextSampleTuple
Definition: tsmapi.h:73
bool rs_pageatatime
Definition: relscan.h:55
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
Snapshot rs_snapshot
Definition: relscan.h:50
bool rs_inited
Definition: relscan.h:69
NextSampleBlock_function NextSampleBlock
Definition: tsmapi.h:72
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
BlockNumber rs_startblock
Definition: relscan.h:62
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
BlockNumber rs_nblocks
Definition: relscan.h:61
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
Relation rs_rd
Definition: relscan.h:49
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
Buffer rs_cbuf
Definition: relscan.h:72
#define Assert(condition)
Definition: c.h:699
#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:1217
void ss_report_location(Relation rel, BlockNumber location)
Definition: syncscan.c:288
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1193
#define OffsetNumberIsValid(offsetNumber)
Definition: off.h:40
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
bool rs_syncscan
Definition: relscan.h:66
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define pgstat_count_heap_getnext(rel)
Definition: pgstat.h:1281
#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:1213

◆ tablesample_init()

static void tablesample_init ( SampleScanState scanstate)
static

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

255 {
256  TsmRoutine *tsm = scanstate->tsmroutine;
257  ExprContext *econtext = scanstate->ss.ps.ps_ExprContext;
258  Datum *params;
259  Datum datum;
260  bool isnull;
261  uint32 seed;
262  bool allow_sync;
263  int i;
264  ListCell *arg;
265 
266  params = (Datum *) palloc(list_length(scanstate->args) * sizeof(Datum));
267 
268  i = 0;
269  foreach(arg, scanstate->args)
270  {
271  ExprState *argstate = (ExprState *) lfirst(arg);
272 
273  params[i] = ExecEvalExprSwitchContext(argstate,
274  econtext,
275  &isnull);
276  if (isnull)
277  ereport(ERROR,
278  (errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
279  errmsg("TABLESAMPLE parameter cannot be null")));
280  i++;
281  }
282 
283  if (scanstate->repeatable)
284  {
285  datum = ExecEvalExprSwitchContext(scanstate->repeatable,
286  econtext,
287  &isnull);
288  if (isnull)
289  ereport(ERROR,
290  (errcode(ERRCODE_INVALID_TABLESAMPLE_REPEAT),
291  errmsg("TABLESAMPLE REPEATABLE parameter cannot be null")));
292 
293  /*
294  * The REPEATABLE parameter has been coerced to float8 by the parser.
295  * The reason for using float8 at the SQL level is that it will
296  * produce unsurprising results both for users used to databases that
297  * accept only integers in the REPEATABLE clause and for those who
298  * might expect that REPEATABLE works like setseed() (a float in the
299  * range from -1 to 1).
300  *
301  * We use hashfloat8() to convert the supplied value into a suitable
302  * seed. For regression-testing purposes, that has the convenient
303  * property that REPEATABLE(0) gives a machine-independent result.
304  */
306  }
307  else
308  {
309  /* Use the seed selected by ExecInitSampleScan */
310  seed = scanstate->seed;
311  }
312 
313  /* Set default values for params that BeginSampleScan can adjust */
314  scanstate->use_bulkread = true;
315  scanstate->use_pagemode = true;
316 
317  /* Let tablesample method do its thing */
318  tsm->BeginSampleScan(scanstate,
319  params,
320  list_length(scanstate->args),
321  seed);
322 
323  /* We'll use syncscan if there's no NextSampleBlock function */
324  allow_sync = (tsm->NextSampleBlock == NULL);
325 
326  /* Now we can create or reset the HeapScanDesc */
327  if (scanstate->ss.ss_currentScanDesc == NULL)
328  {
329  scanstate->ss.ss_currentScanDesc =
331  scanstate->ss.ps.state->es_snapshot,
332  0, NULL,
333  scanstate->use_bulkread,
334  allow_sync,
335  scanstate->use_pagemode);
336  }
337  else
338  {
340  scanstate->use_bulkread,
341  allow_sync,
342  scanstate->use_pagemode);
343  }
344 
345  pfree(params);
346 
347  /* And we're initialized. */
348  scanstate->begun = true;
349 }
#define DatumGetUInt32(X)
Definition: postgres.h:469
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:296
ExprContext * ps_ExprContext
Definition: execnodes.h:946
int errcode(int sqlerrcode)
Definition: elog.c:575
Snapshot es_snapshot
Definition: execnodes.h:478
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
Relation ss_currentRelation
Definition: execnodes.h:1192
EState * state
Definition: execnodes.h:913
PlanState ps
Definition: execnodes.h:1191
void pfree(void *pointer)
Definition: mcxt.c:1031
#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:1440
unsigned int uint32
Definition: c.h:325
ExprState * repeatable
Definition: execnodes.h:1215
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:365
#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:1553
static int list_length(const List *l)
Definition: pg_list.h:89
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1217
BeginSampleScan_function BeginSampleScan
Definition: tsmapi.h:71
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1193
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void * arg
ScanState ss
Definition: execnodes.h:1213