PostgreSQL Source Code  git master
nodeSamplescan.c File Reference
#include "postgres.h"
#include "access/relscan.h"
#include "access/tableam.h"
#include "access/tsmapi.h"
#include "executor/executor.h"
#include "executor/nodeSamplescan.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/bufmgr.h"
#include "storage/predicate.h"
#include "utils/builtins.h"
#include "utils/rel.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 TupleTableSlottablesample_getnext (SampleScanState *scanstate)
 
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 182 of file nodeSamplescan.c.

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

Referenced by ExecEndNode().

183 {
184  /*
185  * Tell sampling function that we finished the scan.
186  */
187  if (node->tsmroutine->EndSampleScan)
188  node->tsmroutine->EndSampleScan(node);
189 
190  /*
191  * Free the exprcontext
192  */
193  ExecFreeExprContext(&node->ss.ps);
194 
195  /*
196  * clean out the tuple table
197  */
198  if (node->ss.ps.ps_ResultTupleSlot)
201 
202  /*
203  * close heap scan
204  */
205  if (node->ss.ss_currentScanDesc)
207 }
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:426
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1333
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1334
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:614
PlanState ps
Definition: execnodes.h:1331
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:978
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1357
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:831
EndSampleScan_function EndSampleScan
Definition: tsmapi.h:75
ScanState ss
Definition: execnodes.h:1353

◆ ExecInitSampleScan()

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

Definition at line 96 of file nodeSamplescan.c.

References TableSampleClause::args, Assert, ExecAssignExprContext(), ExecAssignScanProjectionInfo(), ExecInitExpr(), ExecInitExprList(), ExecInitQual(), ExecInitResultTypeTL(), 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, table_slot_callbacks(), SampleScan::tablesample, and TableSampleClause::tsmhandler.

Referenced by ExecInitNode().

97 {
98  SampleScanState *scanstate;
99  TableSampleClause *tsc = node->tablesample;
100  TsmRoutine *tsm;
101 
102  Assert(outerPlan(node) == NULL);
103  Assert(innerPlan(node) == NULL);
104 
105  /*
106  * create state structure
107  */
108  scanstate = makeNode(SampleScanState);
109  scanstate->ss.ps.plan = (Plan *) node;
110  scanstate->ss.ps.state = estate;
111  scanstate->ss.ps.ExecProcNode = ExecSampleScan;
112 
113  /*
114  * Miscellaneous initialization
115  *
116  * create expression context for node
117  */
118  ExecAssignExprContext(estate, &scanstate->ss.ps);
119 
120  /*
121  * open the scan relation
122  */
123  scanstate->ss.ss_currentRelation =
124  ExecOpenScanRelation(estate,
125  node->scan.scanrelid,
126  eflags);
127 
128  /* we won't set up the HeapScanDesc till later */
129  scanstate->ss.ss_currentScanDesc = NULL;
130 
131  /* and create slot with appropriate rowtype */
132  ExecInitScanTupleSlot(estate, &scanstate->ss,
135 
136  /*
137  * Initialize result type and projection.
138  */
139  ExecInitResultTypeTL(&scanstate->ss.ps);
140  ExecAssignScanProjectionInfo(&scanstate->ss);
141 
142  /*
143  * initialize child expressions
144  */
145  scanstate->ss.ps.qual =
146  ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
147 
148  scanstate->args = ExecInitExprList(tsc->args, (PlanState *) scanstate);
149  scanstate->repeatable =
150  ExecInitExpr(tsc->repeatable, (PlanState *) scanstate);
151 
152  /*
153  * If we don't have a REPEATABLE clause, select a random seed. We want to
154  * do this just once, since the seed shouldn't change over rescans.
155  */
156  if (tsc->repeatable == NULL)
157  scanstate->seed = random();
158 
159  /*
160  * Finally, initialize the TABLESAMPLE method handler.
161  */
162  tsm = GetTsmRoutine(tsc->tsmhandler);
163  scanstate->tsmroutine = tsm;
164  scanstate->tsm_state = NULL;
165 
166  if (tsm->InitSampleScan)
167  tsm->InitSampleScan(scanstate, eflags);
168 
169  /* We'll do BeginSampleScan later; we can't evaluate params yet */
170  scanstate->begun = false;
171 
172  return scanstate;
173 }
InitSampleScan_function InitSampleScan
Definition: tsmapi.h:71
List * qual
Definition: plannodes.h:141
Plan plan
Definition: plannodes.h:340
Index scanrelid
Definition: plannodes.h:341
#define RelationGetDescr(relation)
Definition: rel.h:445
long random(void)
Definition: random.c:22
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition: tableam.c:44
void * tsm_state
Definition: execnodes.h:1358
struct TableSampleClause * tablesample
Definition: plannodes.h:358
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1333
Relation ss_currentRelation
Definition: execnodes.h:1332
EState * state
Definition: execnodes.h:942
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:207
PlanState ps
Definition: execnodes.h:1331
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:272
Scan scan
Definition: plannodes.h:356
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:693
#define innerPlan(node)
Definition: plannodes.h:169
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1776
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1720
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:316
ExprState * repeatable
Definition: execnodes.h:1355
#define outerPlan(node)
Definition: plannodes.h:170
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:946
Plan * plan
Definition: execnodes.h:940
TsmRoutine * GetTsmRoutine(Oid tsmhandler)
Definition: tablesample.c:27
#define makeNode(_type_)
Definition: nodes.h:573
#define Assert(condition)
Definition: c.h:732
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:444
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1357
ExprState * qual
Definition: execnodes.h:961
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:121
static TupleTableSlot * ExecSampleScan(PlanState *pstate)
ScanState ss
Definition: execnodes.h:1353

◆ ExecReScanSampleScan()

void ExecReScanSampleScan ( SampleScanState node)

Definition at line 217 of file nodeSamplescan.c.

References SampleScanState::begun, SampleScanState::done, SampleScanState::donetuples, ExecScanReScan(), SampleScanState::haveblock, and SampleScanState::ss.

Referenced by ExecReScan().

218 {
219  /* Remember we need to do BeginSampleScan again (if we did it at all) */
220  node->begun = false;
221  node->done = false;
222  node->haveblock = false;
223  node->donetuples = 0;
224 
225  ExecScanReScan(&node->ss);
226 }
void ExecScanReScan(ScanState *node)
Definition: execScan.c:299
ScanState ss
Definition: execnodes.h:1353

◆ ExecSampleScan()

static TupleTableSlot* ExecSampleScan ( PlanState pstate)
static

Definition at line 82 of file nodeSamplescan.c.

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

Referenced by ExecInitSampleScan().

83 {
84  SampleScanState *node = castNode(SampleScanState, pstate);
85 
86  return ExecScan(&node->ss,
89 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:158
static TupleTableSlot * SampleNext(SampleScanState *node)
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:426
static bool SampleRecheck(SampleScanState *node, TupleTableSlot *slot)
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:425
ScanState ss
Definition: execnodes.h:1353

◆ SampleNext()

static TupleTableSlot * SampleNext ( SampleScanState node)
static

Definition at line 45 of file nodeSamplescan.c.

References SampleScanState::begun, tablesample_getnext(), and tablesample_init().

Referenced by ExecSampleScan().

46 {
47  /*
48  * if this is first call within a scan, initialize
49  */
50  if (!node->begun)
51  tablesample_init(node);
52 
53  /*
54  * get the next tuple, and store it in our result slot
55  */
56  return tablesample_getnext(node);
57 }
static TupleTableSlot * tablesample_getnext(SampleScanState *scanstate)
static void tablesample_init(SampleScanState *scanstate)

◆ SampleRecheck()

static bool SampleRecheck ( SampleScanState node,
TupleTableSlot slot 
)
static

Definition at line 63 of file nodeSamplescan.c.

Referenced by ExecSampleScan().

64 {
65  /*
66  * No need to recheck for SampleScan, since like SeqScan we don't pass any
67  * checkable keys to heap_beginscan.
68  */
69  return true;
70 }

◆ tablesample_getnext()

static TupleTableSlot * tablesample_getnext ( SampleScanState scanstate)
static

Definition at line 335 of file nodeSamplescan.c.

References SampleScanState::done, SampleScanState::donetuples, ExecClearTuple(), SampleScanState::haveblock, SampleScanState::ss, ScanState::ss_currentScanDesc, ScanState::ss_ScanTupleSlot, table_scan_sample_next_block(), and table_scan_sample_next_tuple().

Referenced by SampleNext().

336 {
337  TableScanDesc scan = scanstate->ss.ss_currentScanDesc;
338  TupleTableSlot *slot = scanstate->ss.ss_ScanTupleSlot;
339 
340  ExecClearTuple(slot);
341 
342  if (scanstate->done)
343  return NULL;
344 
345  for (;;)
346  {
347  if (!scanstate->haveblock)
348  {
349  if (!table_scan_sample_next_block(scan, scanstate))
350  {
351  scanstate->haveblock = false;
352  scanstate->done = true;
353 
354  /* exhausted relation */
355  return NULL;
356  }
357 
358  scanstate->haveblock = true;
359  }
360 
361  if (!table_scan_sample_next_tuple(scan, scanstate, slot))
362  {
363  /*
364  * If we get here, it means we've exhausted the items on this page
365  * and it's time to move to the next.
366  */
367  scanstate->haveblock = false;
368  continue;
369  }
370 
371  /* Found visible tuple, return it. */
372  break;
373  }
374 
375  scanstate->donetuples++;
376 
377  return slot;
378 }
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:426
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1333
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1334
static bool table_scan_sample_next_block(TableScanDesc scan, struct SampleScanState *scanstate)
Definition: tableam.h:1676
static bool table_scan_sample_next_tuple(TableScanDesc scan, struct SampleScanState *scanstate, TupleTableSlot *slot)
Definition: tableam.h:1691
ScanState ss
Definition: execnodes.h:1353

◆ tablesample_init()

static void tablesample_init ( SampleScanState scanstate)
static

Definition at line 233 of file nodeSamplescan.c.

References arg, SampleScanState::args, TsmRoutine::BeginSampleScan, SampleScanState::begun, DatumGetUInt32, DirectFunctionCall1, SampleScanState::donetuples, ereport, errcode(), errmsg(), ERROR, EState::es_snapshot, ExecEvalExprSwitchContext(), hashfloat8(), 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, table_beginscan_sampling(), table_rescan_set_params(), SampleScanState::tsmroutine, SampleScanState::use_bulkread, and SampleScanState::use_pagemode.

Referenced by SampleNext().

234 {
235  TsmRoutine *tsm = scanstate->tsmroutine;
236  ExprContext *econtext = scanstate->ss.ps.ps_ExprContext;
237  Datum *params;
238  Datum datum;
239  bool isnull;
240  uint32 seed;
241  bool allow_sync;
242  int i;
243  ListCell *arg;
244 
245  scanstate->donetuples = 0;
246  params = (Datum *) palloc(list_length(scanstate->args) * sizeof(Datum));
247 
248  i = 0;
249  foreach(arg, scanstate->args)
250  {
251  ExprState *argstate = (ExprState *) lfirst(arg);
252 
253  params[i] = ExecEvalExprSwitchContext(argstate,
254  econtext,
255  &isnull);
256  if (isnull)
257  ereport(ERROR,
258  (errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
259  errmsg("TABLESAMPLE parameter cannot be null")));
260  i++;
261  }
262 
263  if (scanstate->repeatable)
264  {
265  datum = ExecEvalExprSwitchContext(scanstate->repeatable,
266  econtext,
267  &isnull);
268  if (isnull)
269  ereport(ERROR,
270  (errcode(ERRCODE_INVALID_TABLESAMPLE_REPEAT),
271  errmsg("TABLESAMPLE REPEATABLE parameter cannot be null")));
272 
273  /*
274  * The REPEATABLE parameter has been coerced to float8 by the parser.
275  * The reason for using float8 at the SQL level is that it will
276  * produce unsurprising results both for users used to databases that
277  * accept only integers in the REPEATABLE clause and for those who
278  * might expect that REPEATABLE works like setseed() (a float in the
279  * range from -1 to 1).
280  *
281  * We use hashfloat8() to convert the supplied value into a suitable
282  * seed. For regression-testing purposes, that has the convenient
283  * property that REPEATABLE(0) gives a machine-independent result.
284  */
286  }
287  else
288  {
289  /* Use the seed selected by ExecInitSampleScan */
290  seed = scanstate->seed;
291  }
292 
293  /* Set default values for params that BeginSampleScan can adjust */
294  scanstate->use_bulkread = true;
295  scanstate->use_pagemode = true;
296 
297  /* Let tablesample method do its thing */
298  tsm->BeginSampleScan(scanstate,
299  params,
300  list_length(scanstate->args),
301  seed);
302 
303  /* We'll use syncscan if there's no NextSampleBlock function */
304  allow_sync = (tsm->NextSampleBlock == NULL);
305 
306  /* Now we can create or reset the HeapScanDesc */
307  if (scanstate->ss.ss_currentScanDesc == NULL)
308  {
309  scanstate->ss.ss_currentScanDesc =
311  scanstate->ss.ps.state->es_snapshot,
312  0, NULL,
313  scanstate->use_bulkread,
314  allow_sync,
315  scanstate->use_pagemode);
316  }
317  else
318  {
320  scanstate->use_bulkread,
321  allow_sync,
322  scanstate->use_pagemode);
323  }
324 
325  pfree(params);
326 
327  /* And we're initialized. */
328  scanstate->begun = true;
329 }
#define DatumGetUInt32(X)
Definition: postgres.h:486
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:300
ExprContext * ps_ExprContext
Definition: execnodes.h:979
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1333
int errcode(int sqlerrcode)
Definition: elog.c:570
Snapshot es_snapshot
Definition: execnodes.h:503
static TableScanDesc table_beginscan_sampling(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key, bool allow_strat, bool allow_sync, bool allow_pagemode)
Definition: tableam.h:797
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:617
Relation ss_currentRelation
Definition: execnodes.h:1332
EState * state
Definition: execnodes.h:942
PlanState ps
Definition: execnodes.h:1331
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
unsigned int uint32
Definition: c.h:358
ExprState * repeatable
Definition: execnodes.h:1355
NextSampleBlock_function NextSampleBlock
Definition: tsmapi.h:73
#define ereport(elevel, rest)
Definition: elog.h:141
Datum hashfloat8(PG_FUNCTION_ARGS)
Definition: hashfunc.c:181
uintptr_t Datum
Definition: postgres.h:367
static void table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key, bool allow_strat, bool allow_sync, bool allow_pagemode)
Definition: tableam.h:855
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
struct TsmRoutine * tsmroutine
Definition: execnodes.h:1357
BeginSampleScan_function BeginSampleScan
Definition: tsmapi.h:72
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
void * arg
ScanState ss
Definition: execnodes.h:1353