* nodeSamplescan.c
* Support routines for sample scans of relations (table sampling).
*
- * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
#include "postgres.h"
#include "access/hash.h"
+#include "access/heapam.h"
#include "access/relscan.h"
#include "access/tsmapi.h"
#include "executor/executor.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/predicate.h"
+#include "utils/builtins.h"
#include "utils/rel.h"
-#include "utils/tqual.h"
-static void InitScanRelation(SampleScanState *node, EState *estate, int eflags);
static TupleTableSlot *SampleNext(SampleScanState *node);
static void tablesample_init(SampleScanState *scanstate);
static HeapTuple tablesample_getnext(SampleScanState *scanstate);
slot = node->ss.ss_ScanTupleSlot;
if (tuple)
- ExecStoreTuple(tuple, /* tuple to store */
- slot, /* slot to store in */
- node->ss.ss_currentScanDesc->rs_cbuf, /* tuple's buffer */
- false); /* don't pfree this pointer */
+ ExecStoreBufferHeapTuple(tuple, /* tuple to store */
+ slot, /* slot to store in */
+ node->ss.ss_currentScanDesc->rs_cbuf); /* tuple's buffer */
else
ExecClearTuple(slot);
* access method functions.
* ----------------------------------------------------------------
*/
-TupleTableSlot *
-ExecSampleScan(SampleScanState *node)
+static TupleTableSlot *
+ExecSampleScan(PlanState *pstate)
{
- return ExecScan((ScanState *) node,
+ SampleScanState *node = castNode(SampleScanState, pstate);
+
+ return ExecScan(&node->ss,
(ExecScanAccessMtd) SampleNext,
(ExecScanRecheckMtd) SampleRecheck);
}
-/* ----------------------------------------------------------------
- * InitScanRelation
- *
- * Set up to access the scan relation.
- * ----------------------------------------------------------------
- */
-static void
-InitScanRelation(SampleScanState *node, EState *estate, int eflags)
-{
- Relation currentRelation;
-
- /*
- * get the relation object id from the relid'th entry in the range table,
- * open that relation and acquire appropriate lock on it.
- */
- currentRelation = ExecOpenScanRelation(estate,
- ((SampleScan *) node->ss.ps.plan)->scan.scanrelid,
- eflags);
-
- node->ss.ss_currentRelation = currentRelation;
-
- /* we won't set up the HeapScanDesc till later */
- node->ss.ss_currentScanDesc = NULL;
-
- /* and report the scan tuple slot's rowtype */
- ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
-}
-
-
/* ----------------------------------------------------------------
* ExecInitSampleScan
* ----------------------------------------------------------------
scanstate = makeNode(SampleScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecSampleScan;
/*
* Miscellaneous initialization
ExecAssignExprContext(estate, &scanstate->ss.ps);
/*
- * initialize child expressions
+ * open the scan relation
*/
- scanstate->ss.ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->scan.plan.targetlist,
- (PlanState *) scanstate);
- scanstate->ss.ps.qual = (List *)
- ExecInitExpr((Expr *) node->scan.plan.qual,
- (PlanState *) scanstate);
-
- scanstate->args = (List *)
- ExecInitExpr((Expr *) tsc->args,
- (PlanState *) scanstate);
- scanstate->repeatable =
- ExecInitExpr(tsc->repeatable,
- (PlanState *) scanstate);
+ scanstate->ss.ss_currentRelation =
+ ExecOpenScanRelation(estate,
+ node->scan.scanrelid,
+ eflags);
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
- ExecInitScanTupleSlot(estate, &scanstate->ss);
+ /* we won't set up the HeapScanDesc till later */
+ scanstate->ss.ss_currentScanDesc = NULL;
+
+ /* and create slot with appropriate rowtype */
+ ExecInitScanTupleSlot(estate, &scanstate->ss,
+ RelationGetDescr(scanstate->ss.ss_currentRelation),
+ &TTSOpsBufferHeapTuple);
/*
- * initialize scan relation
+ * Initialize result type and projection.
*/
- InitScanRelation(scanstate, estate, eflags);
-
- scanstate->ss.ps.ps_TupFromTlist = false;
+ ExecInitResultTypeTL(&scanstate->ss.ps);
+ ExecAssignScanProjectionInfo(&scanstate->ss);
/*
- * Initialize result tuple type and projection info.
+ * initialize child expressions
*/
- ExecAssignResultTypeFromTL(&scanstate->ss.ps);
- ExecAssignScanProjectionInfo(&scanstate->ss);
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+
+ scanstate->args = ExecInitExprList(tsc->args, (PlanState *) scanstate);
+ scanstate->repeatable =
+ ExecInitExpr(tsc->repeatable, (PlanState *) scanstate);
/*
* If we don't have a REPEATABLE clause, select a random seed. We want to
/*
* clean out the tuple table
*/
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
*/
if (node->ss.ss_currentScanDesc)
heap_endscan(node->ss.ss_currentScanDesc);
-
- /*
- * close the heap relation.
- */
- ExecCloseScanRelation(node->ss.ss_currentRelation);
}
/* ----------------------------------------------------------------
params[i] = ExecEvalExprSwitchContext(argstate,
econtext,
- &isnull,
- NULL);
+ &isnull);
if (isnull)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
{
datum = ExecEvalExprSwitchContext(scanstate->repeatable,
econtext,
- &isnull,
- NULL);
+ &isnull);
if (isnull)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLESAMPLE_REPEAT),
- errmsg("TABLESAMPLE REPEATABLE parameter cannot be null")));
+ errmsg("TABLESAMPLE REPEATABLE parameter cannot be null")));
/*
* The REPEATABLE parameter has been coerced to float8 by the parser.
else
{
/* continue from previously returned page/tuple */
- blockno = scan->rs_cblock; /* current page */
+ blockno = scan->rs_cblock; /* current page */
}
/*