1 /*-------------------------------------------------------------------------
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
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/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/nodeRecursiveunion.h"
34 #include "executor/nodeResult.h"
35 #include "executor/nodeSeqscan.h"
36 #include "executor/nodeSetOp.h"
37 #include "executor/nodeSort.h"
38 #include "executor/nodeSubplan.h"
39 #include "executor/nodeSubqueryscan.h"
40 #include "executor/nodeTidscan.h"
41 #include "executor/nodeUnique.h"
42 #include "executor/nodeValuesscan.h"
43 #include "executor/nodeCtescan.h"
44 #include "executor/nodeWorktablescan.h"
45 #include "nodes/nodeFuncs.h"
46 #include "utils/syscache.h"
49 static bool TargetListSupportsBackwardScan(List
*targetlist
);
50 static bool IndexSupportsBackwardScan(Oid indexid
);
55 * Reset a plan node so that its output can be re-scanned.
57 * Note that if the plan node has parameters that have changed value,
58 * the output might be different from last time.
60 * The second parameter is currently only used to pass a NestLoop plan's
61 * econtext down to its inner child plan, in case that is an indexscan that
62 * needs access to variables of the current outer tuple. (The handling of
63 * this parameter is currently pretty inconsistent: some callers pass NULL
64 * and some pass down their parent's value; so don't rely on it in other
65 * situations. It'd probably be better to remove the whole thing and use
66 * the generalized parameter mechanism instead.)
69 ExecReScan(PlanState
*node
, ExprContext
*exprCtxt
)
71 /* If collecting timing stats, update them */
73 InstrEndLoop(node
->instrument
);
76 * If we have changed parameters, propagate that info.
78 * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
79 * corresponding to the output param(s) that the InitPlan will update.
80 * Since we make only one pass over the list, that means that an InitPlan
81 * can depend on the output param(s) of a sibling InitPlan only if that
82 * sibling appears earlier in the list. This is workable for now given
83 * the limited ways in which one InitPlan could depend on another, but
84 * eventually we might need to work harder (or else make the planner
85 * enlarge the extParam/allParam sets to include the params of depended-on
88 if (node
->chgParam
!= NULL
)
92 foreach(l
, node
->initPlan
)
94 SubPlanState
*sstate
= (SubPlanState
*) lfirst(l
);
95 PlanState
*splan
= sstate
->planstate
;
97 if (splan
->plan
->extParam
!= NULL
) /* don't care about child
99 UpdateChangedParamSet(splan
, node
->chgParam
);
100 if (splan
->chgParam
!= NULL
)
101 ExecReScanSetParamPlan(sstate
, node
);
103 foreach(l
, node
->subPlan
)
105 SubPlanState
*sstate
= (SubPlanState
*) lfirst(l
);
106 PlanState
*splan
= sstate
->planstate
;
108 if (splan
->plan
->extParam
!= NULL
)
109 UpdateChangedParamSet(splan
, node
->chgParam
);
111 /* Well. Now set chgParam for left/right trees. */
112 if (node
->lefttree
!= NULL
)
113 UpdateChangedParamSet(node
->lefttree
, node
->chgParam
);
114 if (node
->righttree
!= NULL
)
115 UpdateChangedParamSet(node
->righttree
, node
->chgParam
);
118 /* Shut down any SRFs in the plan node's targetlist */
119 if (node
->ps_ExprContext
)
120 ReScanExprContext(node
->ps_ExprContext
);
122 /* And do node-type-specific processing */
123 switch (nodeTag(node
))
126 ExecReScanResult((ResultState
*) node
, exprCtxt
);
130 ExecReScanAppend((AppendState
*) node
, exprCtxt
);
133 case T_RecursiveUnionState
:
134 ExecRecursiveUnionReScan((RecursiveUnionState
*) node
, exprCtxt
);
137 case T_BitmapAndState
:
138 ExecReScanBitmapAnd((BitmapAndState
*) node
, exprCtxt
);
141 case T_BitmapOrState
:
142 ExecReScanBitmapOr((BitmapOrState
*) node
, exprCtxt
);
146 ExecSeqReScan((SeqScanState
*) node
, exprCtxt
);
149 case T_IndexScanState
:
150 ExecIndexReScan((IndexScanState
*) node
, exprCtxt
);
153 case T_BitmapIndexScanState
:
154 ExecBitmapIndexReScan((BitmapIndexScanState
*) node
, exprCtxt
);
157 case T_BitmapHeapScanState
:
158 ExecBitmapHeapReScan((BitmapHeapScanState
*) node
, exprCtxt
);
162 ExecTidReScan((TidScanState
*) node
, exprCtxt
);
165 case T_SubqueryScanState
:
166 ExecSubqueryReScan((SubqueryScanState
*) node
, exprCtxt
);
169 case T_FunctionScanState
:
170 ExecFunctionReScan((FunctionScanState
*) node
, exprCtxt
);
173 case T_ValuesScanState
:
174 ExecValuesReScan((ValuesScanState
*) node
, exprCtxt
);
178 ExecCteScanReScan((CteScanState
*) node
, exprCtxt
);
181 case T_WorkTableScanState
:
182 ExecWorkTableScanReScan((WorkTableScanState
*) node
, exprCtxt
);
185 case T_NestLoopState
:
186 ExecReScanNestLoop((NestLoopState
*) node
, exprCtxt
);
189 case T_MergeJoinState
:
190 ExecReScanMergeJoin((MergeJoinState
*) node
, exprCtxt
);
193 case T_HashJoinState
:
194 ExecReScanHashJoin((HashJoinState
*) node
, exprCtxt
);
197 case T_MaterialState
:
198 ExecMaterialReScan((MaterialState
*) node
, exprCtxt
);
202 ExecReScanSort((SortState
*) node
, exprCtxt
);
206 ExecReScanGroup((GroupState
*) node
, exprCtxt
);
210 ExecReScanAgg((AggState
*) node
, exprCtxt
);
214 ExecReScanUnique((UniqueState
*) node
, exprCtxt
);
218 ExecReScanHash((HashState
*) node
, exprCtxt
);
222 ExecReScanSetOp((SetOpState
*) node
, exprCtxt
);
226 ExecReScanLimit((LimitState
*) node
, exprCtxt
);
230 elog(ERROR
, "unrecognized node type: %d", (int) nodeTag(node
));
234 if (node
->chgParam
!= NULL
)
236 bms_free(node
->chgParam
);
237 node
->chgParam
= NULL
;
244 * Marks the current scan position.
247 ExecMarkPos(PlanState
*node
)
249 switch (nodeTag(node
))
252 ExecSeqMarkPos((SeqScanState
*) node
);
255 case T_IndexScanState
:
256 ExecIndexMarkPos((IndexScanState
*) node
);
260 ExecTidMarkPos((TidScanState
*) node
);
263 case T_ValuesScanState
:
264 ExecValuesMarkPos((ValuesScanState
*) node
);
267 case T_MaterialState
:
268 ExecMaterialMarkPos((MaterialState
*) node
);
272 ExecSortMarkPos((SortState
*) node
);
276 ExecResultMarkPos((ResultState
*) node
);
280 /* don't make hard error unless caller asks to restore... */
281 elog(DEBUG2
, "unrecognized node type: %d", (int) nodeTag(node
));
289 * restores the scan position previously saved with ExecMarkPos()
291 * NOTE: the semantics of this are that the first ExecProcNode following
292 * the restore operation will yield the same tuple as the first one following
293 * the mark operation. It is unspecified what happens to the plan node's
294 * result TupleTableSlot. (In most cases the result slot is unchanged by
295 * a restore, but the node may choose to clear it or to load it with the
296 * restored-to tuple.) Hence the caller should discard any previously
297 * returned TupleTableSlot after doing a restore.
300 ExecRestrPos(PlanState
*node
)
302 switch (nodeTag(node
))
305 ExecSeqRestrPos((SeqScanState
*) node
);
308 case T_IndexScanState
:
309 ExecIndexRestrPos((IndexScanState
*) node
);
313 ExecTidRestrPos((TidScanState
*) node
);
316 case T_ValuesScanState
:
317 ExecValuesRestrPos((ValuesScanState
*) node
);
320 case T_MaterialState
:
321 ExecMaterialRestrPos((MaterialState
*) node
);
325 ExecSortRestrPos((SortState
*) node
);
329 ExecResultRestrPos((ResultState
*) node
);
333 elog(ERROR
, "unrecognized node type: %d", (int) nodeTag(node
));
339 * ExecSupportsMarkRestore - does a plan type support mark/restore?
341 * XXX Ideally, all plan node types would support mark/restore, and this
342 * wouldn't be needed. For now, this had better match the routines above.
343 * But note the test is on Plan nodetype, not PlanState nodetype.
345 * (However, since the only present use of mark/restore is in mergejoin,
346 * there is no need to support mark/restore in any plan type that is not
347 * capable of generating ordered output. So the seqscan, tidscan,
348 * and valuesscan support is actually useless code at present.)
351 ExecSupportsMarkRestore(NodeTag plantype
)
366 * T_Result only supports mark/restore if it has a child plan that
367 * does, so we do not have enough information to give a really
368 * correct answer. However, for current uses it's enough to
369 * always say "false", because this routine is not asked about
370 * gating Result plans, only base-case Results.
382 * ExecSupportsBackwardScan - does a plan type support backwards scanning?
384 * Ideally, all plan types would support backwards scan, but that seems
385 * unlikely to happen soon. In some cases, a plan node passes the backwards
386 * scan down to its children, and so supports backwards scan only if its
387 * children do. Therefore, this routine must be passed a complete plan tree.
390 ExecSupportsBackwardScan(Plan
*node
)
395 switch (nodeTag(node
))
398 if (outerPlan(node
) != NULL
)
399 return ExecSupportsBackwardScan(outerPlan(node
)) &&
400 TargetListSupportsBackwardScan(node
->targetlist
);
408 foreach(l
, ((Append
*) node
)->appendplans
)
410 if (!ExecSupportsBackwardScan((Plan
*) lfirst(l
)))
413 /* need not check tlist because Append doesn't evaluate it */
422 return TargetListSupportsBackwardScan(node
->targetlist
);
425 return IndexSupportsBackwardScan(((IndexScan
*) node
)->indexid
) &&
426 TargetListSupportsBackwardScan(node
->targetlist
);
429 return ExecSupportsBackwardScan(((SubqueryScan
*) node
)->subplan
) &&
430 TargetListSupportsBackwardScan(node
->targetlist
);
434 /* these don't evaluate tlist */
438 /* doesn't evaluate tlist */
439 return ExecSupportsBackwardScan(outerPlan(node
));
447 * If the tlist contains set-returning functions, we can't support backward
448 * scan, because the TupFromTlist code is direction-ignorant.
451 TargetListSupportsBackwardScan(List
*targetlist
)
453 if (expression_returns_set((Node
*) targetlist
))
459 * An IndexScan node supports backward scan only if the index's AM does.
462 IndexSupportsBackwardScan(Oid indexid
)
467 Form_pg_class idxrelrec
;
470 /* Fetch the pg_class tuple of the index relation */
471 ht_idxrel
= SearchSysCache(RELOID
,
472 ObjectIdGetDatum(indexid
),
474 if (!HeapTupleIsValid(ht_idxrel
))
475 elog(ERROR
, "cache lookup failed for relation %u", indexid
);
476 idxrelrec
= (Form_pg_class
) GETSTRUCT(ht_idxrel
);
478 /* Fetch the pg_am tuple of the index' access method */
479 ht_am
= SearchSysCache(AMOID
,
480 ObjectIdGetDatum(idxrelrec
->relam
),
482 if (!HeapTupleIsValid(ht_am
))
483 elog(ERROR
, "cache lookup failed for access method %u",
485 amrec
= (Form_pg_am
) GETSTRUCT(ht_am
);
487 result
= amrec
->amcanbackward
;
489 ReleaseSysCache(ht_idxrel
);
490 ReleaseSysCache(ht_am
);