PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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)
 
TupleTableSlotExecSampleScan (SampleScanState *node)
 
SampleScanStateExecInitSampleScan (SampleScan *node, EState *estate, int eflags)
 
void ExecEndSampleScan (SampleScanState *node)
 
void ExecReScanSampleScan (SampleScanState *node)
 

Function Documentation

void ExecEndSampleScan ( SampleScanState node)

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

229 {
230  /*
231  * Tell sampling function that we finished the scan.
232  */
233  if (node->tsmroutine->EndSampleScan)
234  node->tsmroutine->EndSampleScan(node);
235 
236  /*
237  * Free the exprcontext
238  */
239  ExecFreeExprContext(&node->ss.ps);
240 
241  /*
242  * clean out the tuple table
243  */
246 
247  /*
248  * close heap scan
249  */
250  if (node->ss.ss_currentScanDesc)
252 
253  /*
254  * close the heap relation.
255  */
257 }
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1581
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1291
Relation ss_currentRelation
Definition: execnodes.h:1289
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:685
PlanState ps
Definition: execnodes.h:1288
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1077
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:830
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1314
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1290
EndSampleScan_function EndSampleScan
Definition: tsmapi.h:74
ScanState ss
Definition: execnodes.h:1310
SampleScanState* ExecInitSampleScan ( SampleScan node,
EState estate,
int  eflags 
)

Definition at line 141 of file nodeSamplescan.c.

References TableSampleClause::args, SampleScanState::args, Assert, SampleScanState::begun, ExecAssignExprContext(), ExecAssignResultTypeFromTL(), ExecAssignScanProjectionInfo(), ExecInitExpr(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), GetTsmRoutine(), TsmRoutine::InitSampleScan, InitScanRelation(), innerPlan, makeNode, NULL, outerPlan, Scan::plan, PlanState::plan, ScanState::ps, Plan::qual, PlanState::qual, random(), TableSampleClause::repeatable, SampleScanState::repeatable, SampleScan::scan, SampleScanState::seed, SampleScanState::ss, PlanState::state, SampleScan::tablesample, Plan::targetlist, PlanState::targetlist, SampleScanState::tsm_state, TableSampleClause::tsmhandler, and SampleScanState::tsmroutine.

Referenced by ExecInitNode().

142 {
143  SampleScanState *scanstate;
144  TableSampleClause *tsc = node->tablesample;
145  TsmRoutine *tsm;
146 
147  Assert(outerPlan(node) == NULL);
148  Assert(innerPlan(node) == NULL);
149 
150  /*
151  * create state structure
152  */
153  scanstate = makeNode(SampleScanState);
154  scanstate->ss.ps.plan = (Plan *) node;
155  scanstate->ss.ps.state = estate;
156 
157  /*
158  * Miscellaneous initialization
159  *
160  * create expression context for node
161  */
162  ExecAssignExprContext(estate, &scanstate->ss.ps);
163 
164  /*
165  * initialize child expressions
166  */
167  scanstate->ss.ps.targetlist = (List *)
169  (PlanState *) scanstate);
170  scanstate->ss.ps.qual = (List *)
171  ExecInitExpr((Expr *) node->scan.plan.qual,
172  (PlanState *) scanstate);
173 
174  scanstate->args = (List *)
175  ExecInitExpr((Expr *) tsc->args,
176  (PlanState *) scanstate);
177  scanstate->repeatable =
179  (PlanState *) scanstate);
180 
181  /*
182  * tuple table initialization
183  */
184  ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
185  ExecInitScanTupleSlot(estate, &scanstate->ss);
186 
187  /*
188  * initialize scan relation
189  */
190  InitScanRelation(scanstate, estate, eflags);
191 
192  /*
193  * Initialize result tuple type and projection info.
194  */
195  ExecAssignResultTypeFromTL(&scanstate->ss.ps);
196  ExecAssignScanProjectionInfo(&scanstate->ss);
197 
198  /*
199  * If we don't have a REPEATABLE clause, select a random seed. We want to
200  * do this just once, since the seed shouldn't change over rescans.
201  */
202  if (tsc->repeatable == NULL)
203  scanstate->seed = random();
204 
205  /*
206  * Finally, initialize the TABLESAMPLE method handler.
207  */
208  tsm = GetTsmRoutine(tsc->tsmhandler);
209  scanstate->tsmroutine = tsm;
210  scanstate->tsm_state = NULL;
211 
212  if (tsm->InitSampleScan)
213  tsm->InitSampleScan(scanstate, eflags);
214 
215  /* We'll do BeginSampleScan later; we can't evaluate params yet */
216  scanstate->begun = false;
217 
218  return scanstate;
219 }
InitSampleScan_function InitSampleScan
Definition: tsmapi.h:70
List * qual
Definition: plannodes.h:130
Plan plan
Definition: plannodes.h:305
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
long random(void)
Definition: random.c:22
void * tsm_state
Definition: execnodes.h:1315
struct TableSampleClause * tablesample
Definition: plannodes.h:323
List * qual
Definition: execnodes.h:1062
List * targetlist
Definition: execnodes.h:1061
EState * state
Definition: execnodes.h:1049
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:430
PlanState ps
Definition: execnodes.h:1288
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4266
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:235
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
Scan scan
Definition: plannodes.h:321
#define innerPlan(node)
Definition: plannodes.h:158
ExprState * repeatable
Definition: execnodes.h:1312
#define outerPlan(node)
Definition: plannodes.h:159
Plan * plan
Definition: execnodes.h:1047
TsmRoutine * GetTsmRoutine(Oid tsmhandler)
Definition: tablesample.c:27
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
static void InitScanRelation(SampleScanState *node, EState *estate, int eflags)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:408
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1314
List * targetlist
Definition: plannodes.h:129
Definition: pg_list.h:45
ScanState ss
Definition: execnodes.h:1310
void ExecReScanSampleScan ( SampleScanState node)

Definition at line 267 of file nodeSamplescan.c.

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

Referenced by ExecReScan().

268 {
269  /* Remember we need to do BeginSampleScan again (if we did it at all) */
270  node->begun = false;
271 
272  ExecScanReScan(&node->ss);
273 }
void ExecScanReScan(ScanState *node)
Definition: execScan.c:327
ScanState ss
Definition: execnodes.h:1310
TupleTableSlot* ExecSampleScan ( SampleScanState node)

Definition at line 100 of file nodeSamplescan.c.

References ExecScan(), SampleNext(), and SampleRecheck().

Referenced by ExecProcNode().

101 {
102  return ExecScan((ScanState *) node,
105 }
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:121
static TupleTableSlot * SampleNext(SampleScanState *node)
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:271
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:272
static bool SampleRecheck(SampleScanState *node, TupleTableSlot *slot)
static void InitScanRelation ( SampleScanState node,
EState estate,
int  eflags 
)
static

Definition at line 114 of file nodeSamplescan.c.

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

Referenced by ExecInitSampleScan().

115 {
116  Relation currentRelation;
117 
118  /*
119  * get the relation object id from the relid'th entry in the range table,
120  * open that relation and acquire appropriate lock on it.
121  */
122  currentRelation = ExecOpenScanRelation(estate,
123  ((SampleScan *) node->ss.ps.plan)->scan.scanrelid,
124  eflags);
125 
126  node->ss.ss_currentRelation = currentRelation;
127 
128  /* we won't set up the HeapScanDesc till later */
129  node->ss.ss_currentScanDesc = NULL;
130 
131  /* and report the scan tuple slot's rowtype */
132  ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
133 }
#define RelationGetDescr(relation)
Definition: rel.h:425
Relation ss_currentRelation
Definition: execnodes.h:1289
PlanState ps
Definition: execnodes.h:1288
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:772
Plan * plan
Definition: execnodes.h:1047
#define NULL
Definition: c.h:226
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1290
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:709
ScanState ss
Definition: execnodes.h:1310
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:1291
static void tablesample_init(SampleScanState *scanstate)
Buffer rs_cbuf
Definition: relscan.h:70
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1290
ScanState ss
Definition: execnodes.h:1310
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 }
static bool SampleTupleVisible ( HeapTuple  tuple,
OffsetNumber  tupoffset,
HeapScanDesc  scan 
)
static

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

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

Definition at line 384 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, NULL, 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().

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

Definition at line 280 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, NULL, 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().

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