1 /*-------------------------------------------------------------------------
4 * miscellaneous executor access method routines
6 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * src/backend/executor/execAmi.c
11 *-------------------------------------------------------------------------
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/nodeCtescan.h"
24 #include "executor/nodeForeignscan.h"
25 #include "executor/nodeFunctionscan.h"
26 #include "executor/nodeGroup.h"
27 #include "executor/nodeGroup.h"
28 #include "executor/nodeHash.h"
29 #include "executor/nodeHashjoin.h"
30 #include "executor/nodeIndexscan.h"
31 #include "executor/nodeLimit.h"
32 #include "executor/nodeLockRows.h"
33 #include "executor/nodeMaterial.h"
34 #include "executor/nodeMergeAppend.h"
35 #include "executor/nodeMergejoin.h"
36 #include "executor/nodeModifyTable.h"
37 #include "executor/nodeNestloop.h"
38 #include "executor/nodeRecursiveunion.h"
39 #include "executor/nodeResult.h"
40 #include "executor/nodeSeqscan.h"
41 #include "executor/nodeSetOp.h"
42 #include "executor/nodeSort.h"
43 #include "executor/nodeSubplan.h"
44 #include "executor/nodeSubqueryscan.h"
45 #include "executor/nodeTidscan.h"
46 #include "executor/nodeUnique.h"
47 #include "executor/nodeValuesscan.h"
48 #include "executor/nodeWindowAgg.h"
49 #include "executor/nodeWorktablescan.h"
50 #include "nodes/nodeFuncs.h"
51 #include "utils/syscache.h"
54 static bool TargetListSupportsBackwardScan(List *targetlist);
55 static bool IndexSupportsBackwardScan(Oid indexid);
60 * Reset a plan node so that its output can be re-scanned.
62 * Note that if the plan node has parameters that have changed value,
63 * the output might be different from last time.
66 ExecReScan(PlanState *node)
68 /* If collecting timing stats, update them */
70 InstrEndLoop(node->instrument);
73 * If we have changed parameters, propagate that info.
75 * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
76 * corresponding to the output param(s) that the InitPlan will update.
77 * Since we make only one pass over the list, that means that an InitPlan
78 * can depend on the output param(s) of a sibling InitPlan only if that
79 * sibling appears earlier in the list. This is workable for now given
80 * the limited ways in which one InitPlan could depend on another, but
81 * eventually we might need to work harder (or else make the planner
82 * enlarge the extParam/allParam sets to include the params of depended-on
85 if (node->chgParam != NULL)
89 foreach(l, node->initPlan)
91 SubPlanState *sstate = (SubPlanState *) lfirst(l);
92 PlanState *splan = sstate->planstate;
94 if (splan->plan->extParam != NULL) /* don't care about child
96 UpdateChangedParamSet(splan, node->chgParam);
97 if (splan->chgParam != NULL)
98 ExecReScanSetParamPlan(sstate, node);
100 foreach(l, node->subPlan)
102 SubPlanState *sstate = (SubPlanState *) lfirst(l);
103 PlanState *splan = sstate->planstate;
105 if (splan->plan->extParam != NULL)
106 UpdateChangedParamSet(splan, node->chgParam);
108 /* Well. Now set chgParam for left/right trees. */
109 if (node->lefttree != NULL)
110 UpdateChangedParamSet(node->lefttree, node->chgParam);
111 if (node->righttree != NULL)
112 UpdateChangedParamSet(node->righttree, node->chgParam);
115 /* Shut down any SRFs in the plan node's targetlist */
116 if (node->ps_ExprContext)
117 ReScanExprContext(node->ps_ExprContext);
119 /* And do node-type-specific processing */
120 switch (nodeTag(node))
123 ExecReScanResult((ResultState *) node);
126 case T_ModifyTableState:
127 ExecReScanModifyTable((ModifyTableState *) node);
131 ExecReScanAppend((AppendState *) node);
134 case T_MergeAppendState:
135 ExecReScanMergeAppend((MergeAppendState *) node);
138 case T_RecursiveUnionState:
139 ExecReScanRecursiveUnion((RecursiveUnionState *) node);
142 case T_BitmapAndState:
143 ExecReScanBitmapAnd((BitmapAndState *) node);
146 case T_BitmapOrState:
147 ExecReScanBitmapOr((BitmapOrState *) node);
151 ExecReScanSeqScan((SeqScanState *) node);
154 case T_IndexScanState:
155 ExecReScanIndexScan((IndexScanState *) node);
158 case T_BitmapIndexScanState:
159 ExecReScanBitmapIndexScan((BitmapIndexScanState *) node);
162 case T_BitmapHeapScanState:
163 ExecReScanBitmapHeapScan((BitmapHeapScanState *) node);
167 ExecReScanTidScan((TidScanState *) node);
170 case T_SubqueryScanState:
171 ExecReScanSubqueryScan((SubqueryScanState *) node);
174 case T_FunctionScanState:
175 ExecReScanFunctionScan((FunctionScanState *) node);
178 case T_ValuesScanState:
179 ExecReScanValuesScan((ValuesScanState *) node);
183 ExecReScanCteScan((CteScanState *) node);
186 case T_WorkTableScanState:
187 ExecReScanWorkTableScan((WorkTableScanState *) node);
190 case T_ForeignScanState:
191 ExecReScanForeignScan((ForeignScanState *) node);
194 case T_NestLoopState:
195 ExecReScanNestLoop((NestLoopState *) node);
198 case T_MergeJoinState:
199 ExecReScanMergeJoin((MergeJoinState *) node);
202 case T_HashJoinState:
203 ExecReScanHashJoin((HashJoinState *) node);
206 case T_MaterialState:
207 ExecReScanMaterial((MaterialState *) node);
211 ExecReScanSort((SortState *) node);
215 ExecReScanGroup((GroupState *) node);
219 ExecReScanAgg((AggState *) node);
222 case T_WindowAggState:
223 ExecReScanWindowAgg((WindowAggState *) node);
227 ExecReScanUnique((UniqueState *) node);
231 ExecReScanHash((HashState *) node);
235 ExecReScanSetOp((SetOpState *) node);
238 case T_LockRowsState:
239 ExecReScanLockRows((LockRowsState *) node);
243 ExecReScanLimit((LimitState *) node);
247 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
251 if (node->chgParam != NULL)
253 bms_free(node->chgParam);
254 node->chgParam = NULL;
261 * Marks the current scan position.
264 ExecMarkPos(PlanState *node)
266 switch (nodeTag(node))
269 ExecSeqMarkPos((SeqScanState *) node);
272 case T_IndexScanState:
273 ExecIndexMarkPos((IndexScanState *) node);
277 ExecTidMarkPos((TidScanState *) node);
280 case T_ValuesScanState:
281 ExecValuesMarkPos((ValuesScanState *) node);
284 case T_MaterialState:
285 ExecMaterialMarkPos((MaterialState *) node);
289 ExecSortMarkPos((SortState *) node);
293 ExecResultMarkPos((ResultState *) node);
297 /* don't make hard error unless caller asks to restore... */
298 elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
306 * restores the scan position previously saved with ExecMarkPos()
308 * NOTE: the semantics of this are that the first ExecProcNode following
309 * the restore operation will yield the same tuple as the first one following
310 * the mark operation. It is unspecified what happens to the plan node's
311 * result TupleTableSlot. (In most cases the result slot is unchanged by
312 * a restore, but the node may choose to clear it or to load it with the
313 * restored-to tuple.) Hence the caller should discard any previously
314 * returned TupleTableSlot after doing a restore.
317 ExecRestrPos(PlanState *node)
319 switch (nodeTag(node))
322 ExecSeqRestrPos((SeqScanState *) node);
325 case T_IndexScanState:
326 ExecIndexRestrPos((IndexScanState *) node);
330 ExecTidRestrPos((TidScanState *) node);
333 case T_ValuesScanState:
334 ExecValuesRestrPos((ValuesScanState *) node);
337 case T_MaterialState:
338 ExecMaterialRestrPos((MaterialState *) node);
342 ExecSortRestrPos((SortState *) node);
346 ExecResultRestrPos((ResultState *) node);
350 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
356 * ExecSupportsMarkRestore - does a plan type support mark/restore?
358 * XXX Ideally, all plan node types would support mark/restore, and this
359 * wouldn't be needed. For now, this had better match the routines above.
360 * But note the test is on Plan nodetype, not PlanState nodetype.
362 * (However, since the only present use of mark/restore is in mergejoin,
363 * there is no need to support mark/restore in any plan type that is not
364 * capable of generating ordered output. So the seqscan, tidscan,
365 * and valuesscan support is actually useless code at present.)
368 ExecSupportsMarkRestore(NodeTag plantype)
383 * T_Result only supports mark/restore if it has a child plan that
384 * does, so we do not have enough information to give a really
385 * correct answer. However, for current uses it's enough to
386 * always say "false", because this routine is not asked about
387 * gating Result plans, only base-case Results.
399 * ExecSupportsBackwardScan - does a plan type support backwards scanning?
401 * Ideally, all plan types would support backwards scan, but that seems
402 * unlikely to happen soon. In some cases, a plan node passes the backwards
403 * scan down to its children, and so supports backwards scan only if its
404 * children do. Therefore, this routine must be passed a complete plan tree.
407 ExecSupportsBackwardScan(Plan *node)
412 switch (nodeTag(node))
415 if (outerPlan(node) != NULL)
416 return ExecSupportsBackwardScan(outerPlan(node)) &&
417 TargetListSupportsBackwardScan(node->targetlist);
425 foreach(l, ((Append *) node)->appendplans)
427 if (!ExecSupportsBackwardScan((Plan *) lfirst(l)))
430 /* need not check tlist because Append doesn't evaluate it */
439 return TargetListSupportsBackwardScan(node->targetlist);
442 return IndexSupportsBackwardScan(((IndexScan *) node)->indexid) &&
443 TargetListSupportsBackwardScan(node->targetlist);
446 return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan) &&
447 TargetListSupportsBackwardScan(node->targetlist);
451 /* these don't evaluate tlist */
456 /* these don't evaluate tlist */
457 return ExecSupportsBackwardScan(outerPlan(node));
465 * If the tlist contains set-returning functions, we can't support backward
466 * scan, because the TupFromTlist code is direction-ignorant.
469 TargetListSupportsBackwardScan(List *targetlist)
471 if (expression_returns_set((Node *) targetlist))
477 * An IndexScan node supports backward scan only if the index's AM does.
480 IndexSupportsBackwardScan(Oid indexid)
485 Form_pg_class idxrelrec;
488 /* Fetch the pg_class tuple of the index relation */
489 ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexid));
490 if (!HeapTupleIsValid(ht_idxrel))
491 elog(ERROR, "cache lookup failed for relation %u", indexid);
492 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
494 /* Fetch the pg_am tuple of the index' access method */
495 ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
496 if (!HeapTupleIsValid(ht_am))
497 elog(ERROR, "cache lookup failed for access method %u",
499 amrec = (Form_pg_am) GETSTRUCT(ht_am);
501 result = amrec->amcanbackward;
503 ReleaseSysCache(ht_idxrel);
504 ReleaseSysCache(ht_am);
510 * ExecMaterializesOutput - does a plan type materialize its output?
512 * Returns true if the plan node type is one that automatically materializes
513 * its output (typically by keeping it in a tuplestore). For such plans,
514 * a rescan without any parameter change will have zero startup cost and
515 * very low per-tuple cost.
518 ExecMaterializesOutput(NodeTag plantype)
525 case T_WorkTableScan: