diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:19:15 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:19:15 +0000 |
commit | 6eb9c5a5657d1fe77b55cc261450f3538d35a94d (patch) | |
tree | 657d8194422a5daccecfd42d654b8a245ef7b4c8 /src/backend/executor/nodeWorktablescan.c | |
parent | Initial commit. (diff) | |
download | postgresql-13-6eb9c5a5657d1fe77b55cc261450f3538d35a94d.tar.xz postgresql-13-6eb9c5a5657d1fe77b55cc261450f3538d35a94d.zip |
Adding upstream version 13.4.upstream/13.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/backend/executor/nodeWorktablescan.c')
-rw-r--r-- | src/backend/executor/nodeWorktablescan.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c new file mode 100644 index 0000000..e8f5caf --- /dev/null +++ b/src/backend/executor/nodeWorktablescan.c @@ -0,0 +1,223 @@ +/*------------------------------------------------------------------------- + * + * nodeWorktablescan.c + * routines to handle WorkTableScan nodes. + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/executor/nodeWorktablescan.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "executor/execdebug.h" +#include "executor/nodeWorktablescan.h" + +static TupleTableSlot *WorkTableScanNext(WorkTableScanState *node); + +/* ---------------------------------------------------------------- + * WorkTableScanNext + * + * This is a workhorse for ExecWorkTableScan + * ---------------------------------------------------------------- + */ +static TupleTableSlot * +WorkTableScanNext(WorkTableScanState *node) +{ + TupleTableSlot *slot; + Tuplestorestate *tuplestorestate; + + /* + * get information from the estate and scan state + * + * Note: we intentionally do not support backward scan. Although it would + * take only a couple more lines here, it would force nodeRecursiveunion.c + * to create the tuplestore with backward scan enabled, which has a + * performance cost. In practice backward scan is never useful for a + * worktable plan node, since it cannot appear high enough in the plan + * tree of a scrollable cursor to be exposed to a backward-scan + * requirement. So it's not worth expending effort to support it. + * + * Note: we are also assuming that this node is the only reader of the + * worktable. Therefore, we don't need a private read pointer for the + * tuplestore, nor do we need to tell tuplestore_gettupleslot to copy. + */ + Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction)); + + tuplestorestate = node->rustate->working_table; + + /* + * Get the next tuple from tuplestore. Return NULL if no more tuples. + */ + slot = node->ss.ss_ScanTupleSlot; + (void) tuplestore_gettupleslot(tuplestorestate, true, false, slot); + return slot; +} + +/* + * WorkTableScanRecheck -- access method routine to recheck a tuple in EvalPlanQual + */ +static bool +WorkTableScanRecheck(WorkTableScanState *node, TupleTableSlot *slot) +{ + /* nothing to check */ + return true; +} + +/* ---------------------------------------------------------------- + * ExecWorkTableScan(node) + * + * Scans the worktable sequentially and returns the next qualifying tuple. + * We call the ExecScan() routine and pass it the appropriate + * access method functions. + * ---------------------------------------------------------------- + */ +static TupleTableSlot * +ExecWorkTableScan(PlanState *pstate) +{ + WorkTableScanState *node = castNode(WorkTableScanState, pstate); + + /* + * On the first call, find the ancestor RecursiveUnion's state via the + * Param slot reserved for it. (We can't do this during node init because + * there are corner cases where we'll get the init call before the + * RecursiveUnion does.) + */ + if (node->rustate == NULL) + { + WorkTableScan *plan = (WorkTableScan *) node->ss.ps.plan; + EState *estate = node->ss.ps.state; + ParamExecData *param; + + param = &(estate->es_param_exec_vals[plan->wtParam]); + Assert(param->execPlan == NULL); + Assert(!param->isnull); + node->rustate = castNode(RecursiveUnionState, DatumGetPointer(param->value)); + Assert(node->rustate); + + /* + * The scan tuple type (ie, the rowtype we expect to find in the work + * table) is the same as the result rowtype of the ancestor + * RecursiveUnion node. Note this depends on the assumption that + * RecursiveUnion doesn't allow projection. + */ + ExecAssignScanType(&node->ss, + ExecGetResultType(&node->rustate->ps)); + + /* + * Now we can initialize the projection info. This must be completed + * before we can call ExecScan(). + */ + ExecAssignScanProjectionInfo(&node->ss); + } + + return ExecScan(&node->ss, + (ExecScanAccessMtd) WorkTableScanNext, + (ExecScanRecheckMtd) WorkTableScanRecheck); +} + + +/* ---------------------------------------------------------------- + * ExecInitWorkTableScan + * ---------------------------------------------------------------- + */ +WorkTableScanState * +ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags) +{ + WorkTableScanState *scanstate; + + /* check for unsupported flags */ + Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); + + /* + * WorkTableScan should not have any children. + */ + Assert(outerPlan(node) == NULL); + Assert(innerPlan(node) == NULL); + + /* + * create new WorkTableScanState for node + */ + scanstate = makeNode(WorkTableScanState); + scanstate->ss.ps.plan = (Plan *) node; + scanstate->ss.ps.state = estate; + scanstate->ss.ps.ExecProcNode = ExecWorkTableScan; + scanstate->rustate = NULL; /* we'll set this later */ + + /* + * Miscellaneous initialization + * + * create expression context for node + */ + ExecAssignExprContext(estate, &scanstate->ss.ps); + + /* + * tuple table initialization + */ + ExecInitResultTypeTL(&scanstate->ss.ps); + + /* signal that return type is not yet known */ + scanstate->ss.ps.resultopsset = true; + scanstate->ss.ps.resultopsfixed = false; + + ExecInitScanTupleSlot(estate, &scanstate->ss, NULL, &TTSOpsMinimalTuple); + + /* + * initialize child expressions + */ + scanstate->ss.ps.qual = + ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate); + + /* + * Do not yet initialize projection info, see ExecWorkTableScan() for + * details. + */ + + return scanstate; +} + +/* ---------------------------------------------------------------- + * ExecEndWorkTableScan + * + * frees any storage allocated through C routines. + * ---------------------------------------------------------------- + */ +void +ExecEndWorkTableScan(WorkTableScanState *node) +{ + /* + * Free exprcontext + */ + ExecFreeExprContext(&node->ss.ps); + + /* + * clean out the tuple table + */ + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + ExecClearTuple(node->ss.ss_ScanTupleSlot); +} + +/* ---------------------------------------------------------------- + * ExecReScanWorkTableScan + * + * Rescans the relation. + * ---------------------------------------------------------------- + */ +void +ExecReScanWorkTableScan(WorkTableScanState *node) +{ + if (node->ss.ps.ps_ResultTupleSlot) + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + + ExecScanReScan(&node->ss); + + /* No need (or way) to rescan if ExecWorkTableScan not called yet */ + if (node->rustate) + tuplestore_rescan(node->rustate->working_table); +} |