Fix xslt_process() to ensure that it inserts a NULL terminator after the
[PostgreSQL.git] / src / backend / executor / nodeWorktablescan.c
blob22f060c238cb6413731ec8e8943fd52c03df1cc9
1 /*-------------------------------------------------------------------------
3 * nodeWorktablescan.c
4 * routines to handle WorkTableScan nodes.
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
16 #include "postgres.h"
18 #include "executor/execdebug.h"
19 #include "executor/nodeWorktablescan.h"
21 static TupleTableSlot *WorkTableScanNext(WorkTableScanState *node);
23 /* ----------------------------------------------------------------
24 * WorkTableScanNext
26 * This is a workhorse for ExecWorkTableScan
27 * ----------------------------------------------------------------
29 static TupleTableSlot *
30 WorkTableScanNext(WorkTableScanState *node)
32 TupleTableSlot *slot;
33 EState *estate;
34 Tuplestorestate *tuplestorestate;
37 * get information from the estate and scan state
39 * Note: we intentionally do not support backward scan. Although it would
40 * take only a couple more lines here, it would force nodeRecursiveunion.c
41 * to create the tuplestore with backward scan enabled, which has a
42 * performance cost. In practice backward scan is never useful for a
43 * worktable plan node, since it cannot appear high enough in the plan
44 * tree of a scrollable cursor to be exposed to a backward-scan
45 * requirement. So it's not worth expending effort to support it.
47 * Note: we are also assuming that this node is the only reader of the
48 * worktable. Therefore, we don't need a private read pointer for the
49 * tuplestore, nor do we need to tell tuplestore_gettupleslot to copy.
51 estate = node->ss.ps.state;
52 Assert(ScanDirectionIsForward(estate->es_direction));
54 tuplestorestate = node->rustate->working_table;
57 * Get the next tuple from tuplestore. Return NULL if no more tuples.
59 slot = node->ss.ss_ScanTupleSlot;
60 (void) tuplestore_gettupleslot(tuplestorestate, true, false, slot);
61 return slot;
64 /* ----------------------------------------------------------------
65 * ExecWorkTableScan(node)
67 * Scans the worktable sequentially and returns the next qualifying tuple.
68 * It calls the ExecScan() routine and passes it the access method
69 * which retrieves tuples sequentially.
70 * ----------------------------------------------------------------
72 TupleTableSlot *
73 ExecWorkTableScan(WorkTableScanState *node)
76 * On the first call, find the ancestor RecursiveUnion's state via the
77 * Param slot reserved for it. (We can't do this during node init because
78 * there are corner cases where we'll get the init call before the
79 * RecursiveUnion does.)
81 if (node->rustate == NULL)
83 WorkTableScan *plan = (WorkTableScan *) node->ss.ps.plan;
84 EState *estate = node->ss.ps.state;
85 ParamExecData *param;
87 param = &(estate->es_param_exec_vals[plan->wtParam]);
88 Assert(param->execPlan == NULL);
89 Assert(!param->isnull);
90 node->rustate = (RecursiveUnionState *) DatumGetPointer(param->value);
91 Assert(node->rustate && IsA(node->rustate, RecursiveUnionState));
94 * The scan tuple type (ie, the rowtype we expect to find in the work
95 * table) is the same as the result rowtype of the ancestor
96 * RecursiveUnion node. Note this depends on the assumption that
97 * RecursiveUnion doesn't allow projection.
99 ExecAssignScanType(&node->ss,
100 ExecGetResultType(&node->rustate->ps));
103 * Now we can initialize the projection info. This must be completed
104 * before we can call ExecScan().
106 ExecAssignScanProjectionInfo(&node->ss);
110 * use WorkTableScanNext as access method
112 return ExecScan(&node->ss, (ExecScanAccessMtd) WorkTableScanNext);
116 /* ----------------------------------------------------------------
117 * ExecInitWorkTableScan
118 * ----------------------------------------------------------------
120 WorkTableScanState *
121 ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
123 WorkTableScanState *scanstate;
125 /* check for unsupported flags */
126 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
129 * WorkTableScan should not have any children.
131 Assert(outerPlan(node) == NULL);
132 Assert(innerPlan(node) == NULL);
135 * create new WorkTableScanState for node
137 scanstate = makeNode(WorkTableScanState);
138 scanstate->ss.ps.plan = (Plan *) node;
139 scanstate->ss.ps.state = estate;
140 scanstate->rustate = NULL; /* we'll set this later */
143 * Miscellaneous initialization
145 * create expression context for node
147 ExecAssignExprContext(estate, &scanstate->ss.ps);
150 * initialize child expressions
152 scanstate->ss.ps.targetlist = (List *)
153 ExecInitExpr((Expr *) node->scan.plan.targetlist,
154 (PlanState *) scanstate);
155 scanstate->ss.ps.qual = (List *)
156 ExecInitExpr((Expr *) node->scan.plan.qual,
157 (PlanState *) scanstate);
159 #define WORKTABLESCAN_NSLOTS 2
162 * tuple table initialization
164 ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
165 ExecInitScanTupleSlot(estate, &scanstate->ss);
168 * Initialize result tuple type, but not yet projection info.
170 ExecAssignResultTypeFromTL(&scanstate->ss.ps);
172 scanstate->ss.ps.ps_TupFromTlist = false;
174 return scanstate;
178 ExecCountSlotsWorkTableScan(WorkTableScan *node)
180 return ExecCountSlotsNode(outerPlan(node)) +
181 ExecCountSlotsNode(innerPlan(node)) +
182 WORKTABLESCAN_NSLOTS;
185 /* ----------------------------------------------------------------
186 * ExecEndWorkTableScan
188 * frees any storage allocated through C routines.
189 * ----------------------------------------------------------------
191 void
192 ExecEndWorkTableScan(WorkTableScanState *node)
195 * Free exprcontext
197 ExecFreeExprContext(&node->ss.ps);
200 * clean out the tuple table
202 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
203 ExecClearTuple(node->ss.ss_ScanTupleSlot);
206 /* ----------------------------------------------------------------
207 * ExecWorkTableScanReScan
209 * Rescans the relation.
210 * ----------------------------------------------------------------
212 void
213 ExecWorkTableScanReScan(WorkTableScanState *node, ExprContext *exprCtxt)
215 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
216 node->ss.ps.ps_TupFromTlist = false;
218 /* No need (or way) to rescan if ExecWorkTableScan not called yet */
219 if (node->rustate)
220 tuplestore_rescan(node->rustate->working_table);