* execAmi.c
* miscellaneous executor access method routines
*
- * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.84 2005/05/15 21:19:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.99 2008/10/04 21:56:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include "access/genam.h"
-#include "access/heapam.h"
-#include "catalog/heap.h"
#include "executor/execdebug.h"
#include "executor/instrument.h"
#include "executor/nodeAgg.h"
#include "executor/nodeMaterial.h"
#include "executor/nodeMergejoin.h"
#include "executor/nodeNestloop.h"
+#include "executor/nodeRecursiveunion.h"
#include "executor/nodeResult.h"
#include "executor/nodeSeqscan.h"
#include "executor/nodeSetOp.h"
#include "executor/nodeSubqueryscan.h"
#include "executor/nodeTidscan.h"
#include "executor/nodeUnique.h"
+#include "executor/nodeValuesscan.h"
+#include "executor/nodeCtescan.h"
+#include "executor/nodeWorktablescan.h"
/*
if (node->instrument)
InstrEndLoop(node->instrument);
- /* If we have changed parameters, propagate that info */
+ /*
+ * If we have changed parameters, propagate that info.
+ *
+ * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
+ * corresponding to the output param(s) that the InitPlan will update.
+ * Since we make only one pass over the list, that means that an InitPlan
+ * can depend on the output param(s) of a sibling InitPlan only if that
+ * sibling appears earlier in the list. This is workable for now given
+ * the limited ways in which one InitPlan could depend on another, but
+ * eventually we might need to work harder (or else make the planner
+ * enlarge the extParam/allParam sets to include the params of depended-on
+ * InitPlans).
+ */
if (node->chgParam != NULL)
{
ListCell *l;
ExecReScanAppend((AppendState *) node, exprCtxt);
break;
+ case T_RecursiveUnionState:
+ ExecRecursiveUnionReScan((RecursiveUnionState *) node, exprCtxt);
+ break;
+
case T_BitmapAndState:
ExecReScanBitmapAnd((BitmapAndState *) node, exprCtxt);
break;
ExecFunctionReScan((FunctionScanState *) node, exprCtxt);
break;
+ case T_ValuesScanState:
+ ExecValuesReScan((ValuesScanState *) node, exprCtxt);
+ break;
+
+ case T_CteScanState:
+ ExecCteScanReScan((CteScanState *) node, exprCtxt);
+ break;
+
+ case T_WorkTableScanState:
+ ExecWorkTableScanReScan((WorkTableScanState *) node, exprCtxt);
+ break;
+
case T_NestLoopState:
ExecReScanNestLoop((NestLoopState *) node, exprCtxt);
break;
ExecTidMarkPos((TidScanState *) node);
break;
- case T_FunctionScanState:
- ExecFunctionMarkPos((FunctionScanState *) node);
+ case T_ValuesScanState:
+ ExecValuesMarkPos((ValuesScanState *) node);
break;
case T_MaterialState:
ExecSortMarkPos((SortState *) node);
break;
+ case T_ResultState:
+ ExecResultMarkPos((ResultState *) node);
+ break;
+
default:
/* don't make hard error unless caller asks to restore... */
elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
*
* NOTE: the semantics of this are that the first ExecProcNode following
* the restore operation will yield the same tuple as the first one following
- * the mark operation. It is unspecified what happens to the plan node's
+ * the mark operation. It is unspecified what happens to the plan node's
* result TupleTableSlot. (In most cases the result slot is unchanged by
* a restore, but the node may choose to clear it or to load it with the
- * restored-to tuple.) Hence the caller should discard any previously
+ * restored-to tuple.) Hence the caller should discard any previously
* returned TupleTableSlot after doing a restore.
*/
void
ExecTidRestrPos((TidScanState *) node);
break;
- case T_FunctionScanState:
- ExecFunctionRestrPos((FunctionScanState *) node);
+ case T_ValuesScanState:
+ ExecValuesRestrPos((ValuesScanState *) node);
break;
case T_MaterialState:
ExecSortRestrPos((SortState *) node);
break;
+ case T_ResultState:
+ ExecResultRestrPos((ResultState *) node);
+ break;
+
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
break;
*
* (However, since the only present use of mark/restore is in mergejoin,
* there is no need to support mark/restore in any plan type that is not
- * capable of generating ordered output. So the seqscan, tidscan, and
- * functionscan support is actually useless code at present.)
+ * capable of generating ordered output. So the seqscan, tidscan,
+ * and valuesscan support is actually useless code at present.)
*/
bool
ExecSupportsMarkRestore(NodeTag plantype)
case T_SeqScan:
case T_IndexScan:
case T_TidScan:
- case T_FunctionScan:
+ case T_ValuesScan:
case T_Material:
case T_Sort:
return true;
+ case T_Result:
+
+ /*
+ * T_Result only supports mark/restore if it has a child plan that
+ * does, so we do not have enough information to give a really
+ * correct answer. However, for current uses it's enough to
+ * always say "false", because this routine is not asked about
+ * gating Result plans, only base-case Results.
+ */
+ return false;
+
default:
break;
}
case T_IndexScan:
case T_TidScan:
case T_FunctionScan:
+ case T_ValuesScan:
+ case T_CteScan:
+ case T_WorkTableScan:
return true;
case T_SubqueryScan:
case T_Sort:
return true;
- case T_Unique:
- return ExecSupportsBackwardScan(outerPlan(node));
-
case T_Limit:
return ExecSupportsBackwardScan(outerPlan(node));
return false;
}
}
-
-/*
- * ExecMayReturnRawTuples
- * Check whether a plan tree may return "raw" disk tuples (that is,
- * pointers to original data in disk buffers, as opposed to temporary
- * tuples constructed by projection steps). In the case of Append,
- * some subplans may return raw tuples and others projected tuples;
- * we return "true" if any of the returned tuples could be raw.
- *
- * This must be passed an already-initialized planstate tree, because we
- * need to look at the results of ExecAssignScanProjectionInfo().
- */
-bool
-ExecMayReturnRawTuples(PlanState *node)
-{
- /*
- * At a table scan node, we check whether ExecAssignScanProjectionInfo
- * decided to do projection or not. Most non-scan nodes always
- * project and so we can return "false" immediately. For nodes that
- * don't project but just pass up input tuples, we have to recursively
- * examine the input plan node.
- *
- * Note: Hash and Material are listed here because they sometimes return
- * an original input tuple, not a copy. But Sort and SetOp never
- * return an original tuple, so they can be treated like projecting
- * nodes.
- */
- switch (nodeTag(node))
- {
- /* Table scan nodes */
- case T_SeqScanState:
- case T_IndexScanState:
- case T_BitmapHeapScanState:
- case T_TidScanState:
- case T_SubqueryScanState:
- case T_FunctionScanState:
- if (node->ps_ProjInfo == NULL)
- return true;
- break;
-
- /* Non-projecting nodes */
- case T_HashState:
- case T_MaterialState:
- case T_UniqueState:
- case T_LimitState:
- return ExecMayReturnRawTuples(node->lefttree);
-
- case T_AppendState:
- {
- AppendState *appendstate = (AppendState *) node;
- int j;
-
- for (j = 0; j < appendstate->as_nplans; j++)
- {
- if (ExecMayReturnRawTuples(appendstate->appendplans[j]))
- return true;
- }
- break;
- }
-
- /* All projecting node types come here */
- default:
- break;
- }
- return false;
-}