Do not allow Unique nodes to be scanned backwards. The code claimed that it
[PostgreSQL.git] / src / backend / executor / execAmi.c
blob15580d31ac5910226ddc9284ed32c884812d5ca8
1 /*-------------------------------------------------------------------------
3 * execAmi.c
4 * miscellaneous executor access method routines
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * $PostgreSQL$
11 *-------------------------------------------------------------------------
13 #include "postgres.h"
15 #include "executor/execdebug.h"
16 #include "executor/instrument.h"
17 #include "executor/nodeAgg.h"
18 #include "executor/nodeAppend.h"
19 #include "executor/nodeBitmapAnd.h"
20 #include "executor/nodeBitmapHeapscan.h"
21 #include "executor/nodeBitmapIndexscan.h"
22 #include "executor/nodeBitmapOr.h"
23 #include "executor/nodeFunctionscan.h"
24 #include "executor/nodeGroup.h"
25 #include "executor/nodeGroup.h"
26 #include "executor/nodeHash.h"
27 #include "executor/nodeHashjoin.h"
28 #include "executor/nodeIndexscan.h"
29 #include "executor/nodeLimit.h"
30 #include "executor/nodeMaterial.h"
31 #include "executor/nodeMergejoin.h"
32 #include "executor/nodeNestloop.h"
33 #include "executor/nodeResult.h"
34 #include "executor/nodeSeqscan.h"
35 #include "executor/nodeSetOp.h"
36 #include "executor/nodeSort.h"
37 #include "executor/nodeSubplan.h"
38 #include "executor/nodeSubqueryscan.h"
39 #include "executor/nodeTidscan.h"
40 #include "executor/nodeUnique.h"
41 #include "executor/nodeValuesscan.h"
45 * ExecReScan
46 * Reset a plan node so that its output can be re-scanned.
48 * Note that if the plan node has parameters that have changed value,
49 * the output might be different from last time.
51 * The second parameter is currently only used to pass a NestLoop plan's
52 * econtext down to its inner child plan, in case that is an indexscan that
53 * needs access to variables of the current outer tuple. (The handling of
54 * this parameter is currently pretty inconsistent: some callers pass NULL
55 * and some pass down their parent's value; so don't rely on it in other
56 * situations. It'd probably be better to remove the whole thing and use
57 * the generalized parameter mechanism instead.)
59 void
60 ExecReScan(PlanState *node, ExprContext *exprCtxt)
62 /* If collecting timing stats, update them */
63 if (node->instrument)
64 InstrEndLoop(node->instrument);
67 * If we have changed parameters, propagate that info.
69 * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
70 * corresponding to the output param(s) that the InitPlan will update.
71 * Since we make only one pass over the list, that means that an InitPlan
72 * can depend on the output param(s) of a sibling InitPlan only if that
73 * sibling appears earlier in the list. This is workable for now given
74 * the limited ways in which one InitPlan could depend on another, but
75 * eventually we might need to work harder (or else make the planner
76 * enlarge the extParam/allParam sets to include the params of depended-on
77 * InitPlans).
79 if (node->chgParam != NULL)
81 ListCell *l;
83 foreach(l, node->initPlan)
85 SubPlanState *sstate = (SubPlanState *) lfirst(l);
86 PlanState *splan = sstate->planstate;
88 if (splan->plan->extParam != NULL) /* don't care about child
89 * local Params */
90 UpdateChangedParamSet(splan, node->chgParam);
91 if (splan->chgParam != NULL)
92 ExecReScanSetParamPlan(sstate, node);
94 foreach(l, node->subPlan)
96 SubPlanState *sstate = (SubPlanState *) lfirst(l);
97 PlanState *splan = sstate->planstate;
99 if (splan->plan->extParam != NULL)
100 UpdateChangedParamSet(splan, node->chgParam);
102 /* Well. Now set chgParam for left/right trees. */
103 if (node->lefttree != NULL)
104 UpdateChangedParamSet(node->lefttree, node->chgParam);
105 if (node->righttree != NULL)
106 UpdateChangedParamSet(node->righttree, node->chgParam);
109 /* Shut down any SRFs in the plan node's targetlist */
110 if (node->ps_ExprContext)
111 ReScanExprContext(node->ps_ExprContext);
113 /* And do node-type-specific processing */
114 switch (nodeTag(node))
116 case T_ResultState:
117 ExecReScanResult((ResultState *) node, exprCtxt);
118 break;
120 case T_AppendState:
121 ExecReScanAppend((AppendState *) node, exprCtxt);
122 break;
124 case T_BitmapAndState:
125 ExecReScanBitmapAnd((BitmapAndState *) node, exprCtxt);
126 break;
128 case T_BitmapOrState:
129 ExecReScanBitmapOr((BitmapOrState *) node, exprCtxt);
130 break;
132 case T_SeqScanState:
133 ExecSeqReScan((SeqScanState *) node, exprCtxt);
134 break;
136 case T_IndexScanState:
137 ExecIndexReScan((IndexScanState *) node, exprCtxt);
138 break;
140 case T_BitmapIndexScanState:
141 ExecBitmapIndexReScan((BitmapIndexScanState *) node, exprCtxt);
142 break;
144 case T_BitmapHeapScanState:
145 ExecBitmapHeapReScan((BitmapHeapScanState *) node, exprCtxt);
146 break;
148 case T_TidScanState:
149 ExecTidReScan((TidScanState *) node, exprCtxt);
150 break;
152 case T_SubqueryScanState:
153 ExecSubqueryReScan((SubqueryScanState *) node, exprCtxt);
154 break;
156 case T_FunctionScanState:
157 ExecFunctionReScan((FunctionScanState *) node, exprCtxt);
158 break;
160 case T_ValuesScanState:
161 ExecValuesReScan((ValuesScanState *) node, exprCtxt);
162 break;
164 case T_NestLoopState:
165 ExecReScanNestLoop((NestLoopState *) node, exprCtxt);
166 break;
168 case T_MergeJoinState:
169 ExecReScanMergeJoin((MergeJoinState *) node, exprCtxt);
170 break;
172 case T_HashJoinState:
173 ExecReScanHashJoin((HashJoinState *) node, exprCtxt);
174 break;
176 case T_MaterialState:
177 ExecMaterialReScan((MaterialState *) node, exprCtxt);
178 break;
180 case T_SortState:
181 ExecReScanSort((SortState *) node, exprCtxt);
182 break;
184 case T_GroupState:
185 ExecReScanGroup((GroupState *) node, exprCtxt);
186 break;
188 case T_AggState:
189 ExecReScanAgg((AggState *) node, exprCtxt);
190 break;
192 case T_UniqueState:
193 ExecReScanUnique((UniqueState *) node, exprCtxt);
194 break;
196 case T_HashState:
197 ExecReScanHash((HashState *) node, exprCtxt);
198 break;
200 case T_SetOpState:
201 ExecReScanSetOp((SetOpState *) node, exprCtxt);
202 break;
204 case T_LimitState:
205 ExecReScanLimit((LimitState *) node, exprCtxt);
206 break;
208 default:
209 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
210 break;
213 if (node->chgParam != NULL)
215 bms_free(node->chgParam);
216 node->chgParam = NULL;
221 * ExecMarkPos
223 * Marks the current scan position.
225 void
226 ExecMarkPos(PlanState *node)
228 switch (nodeTag(node))
230 case T_SeqScanState:
231 ExecSeqMarkPos((SeqScanState *) node);
232 break;
234 case T_IndexScanState:
235 ExecIndexMarkPos((IndexScanState *) node);
236 break;
238 case T_TidScanState:
239 ExecTidMarkPos((TidScanState *) node);
240 break;
242 case T_FunctionScanState:
243 ExecFunctionMarkPos((FunctionScanState *) node);
244 break;
246 case T_ValuesScanState:
247 ExecValuesMarkPos((ValuesScanState *) node);
248 break;
250 case T_MaterialState:
251 ExecMaterialMarkPos((MaterialState *) node);
252 break;
254 case T_SortState:
255 ExecSortMarkPos((SortState *) node);
256 break;
258 case T_ResultState:
259 ExecResultMarkPos((ResultState *) node);
260 break;
262 default:
263 /* don't make hard error unless caller asks to restore... */
264 elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
265 break;
270 * ExecRestrPos
272 * restores the scan position previously saved with ExecMarkPos()
274 * NOTE: the semantics of this are that the first ExecProcNode following
275 * the restore operation will yield the same tuple as the first one following
276 * the mark operation. It is unspecified what happens to the plan node's
277 * result TupleTableSlot. (In most cases the result slot is unchanged by
278 * a restore, but the node may choose to clear it or to load it with the
279 * restored-to tuple.) Hence the caller should discard any previously
280 * returned TupleTableSlot after doing a restore.
282 void
283 ExecRestrPos(PlanState *node)
285 switch (nodeTag(node))
287 case T_SeqScanState:
288 ExecSeqRestrPos((SeqScanState *) node);
289 break;
291 case T_IndexScanState:
292 ExecIndexRestrPos((IndexScanState *) node);
293 break;
295 case T_TidScanState:
296 ExecTidRestrPos((TidScanState *) node);
297 break;
299 case T_FunctionScanState:
300 ExecFunctionRestrPos((FunctionScanState *) node);
301 break;
303 case T_ValuesScanState:
304 ExecValuesRestrPos((ValuesScanState *) node);
305 break;
307 case T_MaterialState:
308 ExecMaterialRestrPos((MaterialState *) node);
309 break;
311 case T_SortState:
312 ExecSortRestrPos((SortState *) node);
313 break;
315 case T_ResultState:
316 ExecResultRestrPos((ResultState *) node);
317 break;
319 default:
320 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
321 break;
326 * ExecSupportsMarkRestore - does a plan type support mark/restore?
328 * XXX Ideally, all plan node types would support mark/restore, and this
329 * wouldn't be needed. For now, this had better match the routines above.
330 * But note the test is on Plan nodetype, not PlanState nodetype.
332 * (However, since the only present use of mark/restore is in mergejoin,
333 * there is no need to support mark/restore in any plan type that is not
334 * capable of generating ordered output. So the seqscan, tidscan,
335 * functionscan, and valuesscan support is actually useless code at present.)
337 bool
338 ExecSupportsMarkRestore(NodeTag plantype)
340 switch (plantype)
342 case T_SeqScan:
343 case T_IndexScan:
344 case T_TidScan:
345 case T_FunctionScan:
346 case T_ValuesScan:
347 case T_Material:
348 case T_Sort:
349 return true;
351 case T_Result:
354 * T_Result only supports mark/restore if it has a child plan that
355 * does, so we do not have enough information to give a really
356 * correct answer. However, for current uses it's enough to
357 * always say "false", because this routine is not asked about
358 * gating Result plans, only base-case Results.
360 return false;
362 default:
363 break;
366 return false;
370 * ExecSupportsBackwardScan - does a plan type support backwards scanning?
372 * Ideally, all plan types would support backwards scan, but that seems
373 * unlikely to happen soon. In some cases, a plan node passes the backwards
374 * scan down to its children, and so supports backwards scan only if its
375 * children do. Therefore, this routine must be passed a complete plan tree.
377 bool
378 ExecSupportsBackwardScan(Plan *node)
380 if (node == NULL)
381 return false;
383 switch (nodeTag(node))
385 case T_Result:
386 if (outerPlan(node) != NULL)
387 return ExecSupportsBackwardScan(outerPlan(node));
388 else
389 return false;
391 case T_Append:
393 ListCell *l;
395 foreach(l, ((Append *) node)->appendplans)
397 if (!ExecSupportsBackwardScan((Plan *) lfirst(l)))
398 return false;
400 return true;
403 case T_SeqScan:
404 case T_IndexScan:
405 case T_TidScan:
406 case T_FunctionScan:
407 case T_ValuesScan:
408 return true;
410 case T_SubqueryScan:
411 return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan);
413 case T_Material:
414 case T_Sort:
415 return true;
417 case T_Limit:
418 return ExecSupportsBackwardScan(outerPlan(node));
420 default:
421 return false;