1 /*-------------------------------------------------------------------------
3 * nodeNamedtuplestorescan.c
4 * routines to handle NamedTuplestoreScan 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/nodeNamedtuplestorescan.c
13 *-------------------------------------------------------------------------
18 #include "executor/executor.h"
19 #include "executor/nodeNamedtuplestorescan.h"
20 #include "utils/queryenvironment.h"
22 static TupleTableSlot
*NamedTuplestoreScanNext(NamedTuplestoreScanState
*node
);
24 /* ----------------------------------------------------------------
25 * NamedTuplestoreScanNext
27 * This is a workhorse for ExecNamedTuplestoreScan
28 * ----------------------------------------------------------------
30 static TupleTableSlot
*
31 NamedTuplestoreScanNext(NamedTuplestoreScanState
*node
)
35 /* We intentionally do not support backward scan. */
36 Assert(ScanDirectionIsForward(node
->ss
.ps
.state
->es_direction
));
39 * Get the next tuple from tuplestore. Return NULL if no more tuples.
41 slot
= node
->ss
.ss_ScanTupleSlot
;
42 tuplestore_select_read_pointer(node
->relation
, node
->readptr
);
43 (void) tuplestore_gettupleslot(node
->relation
, true, false, slot
);
48 * NamedTuplestoreScanRecheck -- access method routine to recheck a tuple in
52 NamedTuplestoreScanRecheck(NamedTuplestoreScanState
*node
, TupleTableSlot
*slot
)
54 /* nothing to check */
58 /* ----------------------------------------------------------------
59 * ExecNamedTuplestoreScan(node)
61 * Scans the CTE sequentially and returns the next qualifying tuple.
62 * We call the ExecScan() routine and pass it the appropriate
63 * access method functions.
64 * ----------------------------------------------------------------
66 static TupleTableSlot
*
67 ExecNamedTuplestoreScan(PlanState
*pstate
)
69 NamedTuplestoreScanState
*node
= castNode(NamedTuplestoreScanState
, pstate
);
71 return ExecScan(&node
->ss
,
72 (ExecScanAccessMtd
) NamedTuplestoreScanNext
,
73 (ExecScanRecheckMtd
) NamedTuplestoreScanRecheck
);
77 /* ----------------------------------------------------------------
78 * ExecInitNamedTuplestoreScan
79 * ----------------------------------------------------------------
81 NamedTuplestoreScanState
*
82 ExecInitNamedTuplestoreScan(NamedTuplestoreScan
*node
, EState
*estate
, int eflags
)
84 NamedTuplestoreScanState
*scanstate
;
85 EphemeralNamedRelation enr
;
87 /* check for unsupported flags */
88 Assert(!(eflags
& (EXEC_FLAG_BACKWARD
| EXEC_FLAG_MARK
)));
91 * NamedTuplestoreScan should not have any children.
93 Assert(outerPlan(node
) == NULL
);
94 Assert(innerPlan(node
) == NULL
);
97 * create new NamedTuplestoreScanState for node
99 scanstate
= makeNode(NamedTuplestoreScanState
);
100 scanstate
->ss
.ps
.plan
= (Plan
*) node
;
101 scanstate
->ss
.ps
.state
= estate
;
102 scanstate
->ss
.ps
.ExecProcNode
= ExecNamedTuplestoreScan
;
104 enr
= get_ENR(estate
->es_queryEnv
, node
->enrname
);
106 elog(ERROR
, "executor could not find named tuplestore \"%s\"",
109 Assert(enr
->reldata
);
110 scanstate
->relation
= (Tuplestorestate
*) enr
->reldata
;
111 scanstate
->tupdesc
= ENRMetadataGetTupDesc(&(enr
->md
));
113 tuplestore_alloc_read_pointer(scanstate
->relation
, EXEC_FLAG_REWIND
);
116 * The new read pointer copies its position from read pointer 0, which
117 * could be anywhere, so explicitly rewind it.
119 tuplestore_select_read_pointer(scanstate
->relation
, scanstate
->readptr
);
120 tuplestore_rescan(scanstate
->relation
);
123 * XXX: Should we add a function to free that read pointer when done?
125 * This was attempted, but it did not improve performance or memory usage
126 * in any tested cases.
130 * Miscellaneous initialization
132 * create expression context for node
134 ExecAssignExprContext(estate
, &scanstate
->ss
.ps
);
137 * The scan tuple type is specified for the tuplestore.
139 ExecInitScanTupleSlot(estate
, &scanstate
->ss
, scanstate
->tupdesc
,
140 &TTSOpsMinimalTuple
);
143 * Initialize result type and projection.
145 ExecInitResultTypeTL(&scanstate
->ss
.ps
);
146 ExecAssignScanProjectionInfo(&scanstate
->ss
);
149 * initialize child expressions
151 scanstate
->ss
.ps
.qual
=
152 ExecInitQual(node
->scan
.plan
.qual
, (PlanState
*) scanstate
);
157 /* ----------------------------------------------------------------
158 * ExecReScanNamedTuplestoreScan
160 * Rescans the relation.
161 * ----------------------------------------------------------------
164 ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState
*node
)
166 Tuplestorestate
*tuplestorestate
= node
->relation
;
168 if (node
->ss
.ps
.ps_ResultTupleSlot
)
169 ExecClearTuple(node
->ss
.ps
.ps_ResultTupleSlot
);
171 ExecScanReScan(&node
->ss
);
174 * Rewind my own pointer.
176 tuplestore_select_read_pointer(tuplestorestate
, node
->readptr
);
177 tuplestore_rescan(tuplestorestate
);