1/*-------------------------------------------------------------------------
4 * routines to handle WorkTableScan nodes.
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/executor/nodeWorktablescan.c
13 *-------------------------------------------------------------------------
23/* ----------------------------------------------------------------
26 * This is a workhorse for ExecWorkTableScan
27 * ----------------------------------------------------------------
36 * get information from the estate and scan state
38 * Note: we intentionally do not support backward scan. Although it would
39 * take only a couple more lines here, it would force nodeRecursiveunion.c
40 * to create the tuplestore with backward scan enabled, which has a
41 * performance cost. In practice backward scan is never useful for a
42 * worktable plan node, since it cannot appear high enough in the plan
43 * tree of a scrollable cursor to be exposed to a backward-scan
44 * requirement. So it's not worth expending effort to support it.
46 * Note: we are also assuming that this node is the only reader of the
47 * worktable. Therefore, we don't need a private read pointer for the
48 * tuplestore, nor do we need to tell tuplestore_gettupleslot to copy.
55 * Get the next tuple from tuplestore. Return NULL if no more tuples.
63 * WorkTableScanRecheck -- access method routine to recheck a tuple in EvalPlanQual
68 /* nothing to check */
72/* ----------------------------------------------------------------
73 * ExecWorkTableScan(node)
75 * Scans the worktable sequentially and returns the next qualifying tuple.
76 * We call the ExecScan() routine and pass it the appropriate
77 * access method functions.
78 * ----------------------------------------------------------------
86 * On the first call, find the ancestor RecursiveUnion's state via the
87 * Param slot reserved for it. (We can't do this during node init because
88 * there are corner cases where we'll get the init call before the
89 * RecursiveUnion does.)
97 param = &(estate->es_param_exec_vals[
plan->wtParam]);
98 Assert(param->execPlan == NULL);
104 * The scan tuple type (ie, the rowtype we expect to find in the work
105 * table) is the same as the result rowtype of the ancestor
106 * RecursiveUnion node. Note this depends on the assumption that
107 * RecursiveUnion doesn't allow projection.
113 * Now we can initialize the projection info. This must be completed
114 * before we can call ExecScan().
125/* ----------------------------------------------------------------
126 * ExecInitWorkTableScan
127 * ----------------------------------------------------------------
134 /* check for unsupported flags */
138 * WorkTableScan should not have any children.
144 * create new WorkTableScanState for node
150 scanstate->
rustate = NULL;
/* we'll set this later */
153 * Miscellaneous initialization
155 * create expression context for node
160 * tuple table initialization
164 /* signal that return type is not yet known */
171 * initialize child expressions
177 * Do not yet initialize projection info, see ExecWorkTableScan() for
184/* ----------------------------------------------------------------
185 * ExecReScanWorkTableScan
187 * Rescans the relation.
188 * ----------------------------------------------------------------
198 /* No need (or way) to rescan if ExecWorkTableScan not called yet */
ExprState * ExecInitQual(List *qual, PlanState *parent)
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
void ExecAssignScanProjectionInfo(ScanState *node)
void ExecScanReScan(ScanState *node)
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
void ExecInitResultTypeTL(PlanState *planstate)
const TupleTableSlotOps TTSOpsMinimalTuple
TupleDesc ExecGetResultType(PlanState *planstate)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
#define EXEC_FLAG_BACKWARD
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Assert(PointerIsAligned(start, uint64))
static TupleTableSlot * ExecWorkTableScan(PlanState *pstate)
WorkTableScanState * ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
static TupleTableSlot * WorkTableScanNext(WorkTableScanState *node)
void ExecReScanWorkTableScan(WorkTableScanState *node)
static bool WorkTableScanRecheck(WorkTableScanState *node, TupleTableSlot *slot)
#define castNode(_type_, nodeptr)
static Pointer DatumGetPointer(Datum X)
#define ScanDirectionIsForward(direction)
ScanDirection es_direction
TupleTableSlot * ps_ResultTupleSlot
ExecProcNodeMtd ExecProcNode
Tuplestorestate * working_table
TupleTableSlot * ss_ScanTupleSlot
RecursiveUnionState * rustate
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
void tuplestore_rescan(Tuplestorestate *state)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)