X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=src%2Fbackend%2Fexecutor%2FexecAmi.c;h=1de3f5a778efedac7a6daf329a19ba53039f579e;hb=44d5be0e5308e951c0c5dc522b4bcacf2bcbc476;hp=c2cb4b68835118f17700e96c7ca910b05eb8a1a4;hpb=2ef172a2a4d8c093c0f2d4d580d5aab1ca8dcffe;p=postgresql diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index c2cb4b6883..1de3f5a778 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -3,18 +3,15 @@ * 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" @@ -33,6 +30,7 @@ #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" @@ -41,6 +39,9 @@ #include "executor/nodeSubqueryscan.h" #include "executor/nodeTidscan.h" #include "executor/nodeUnique.h" +#include "executor/nodeValuesscan.h" +#include "executor/nodeCtescan.h" +#include "executor/nodeWorktablescan.h" /* @@ -65,7 +66,19 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt) 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; @@ -111,6 +124,10 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt) ExecReScanAppend((AppendState *) node, exprCtxt); break; + case T_RecursiveUnionState: + ExecRecursiveUnionReScan((RecursiveUnionState *) node, exprCtxt); + break; + case T_BitmapAndState: ExecReScanBitmapAnd((BitmapAndState *) node, exprCtxt); break; @@ -147,6 +164,18 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt) 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; @@ -225,8 +254,8 @@ ExecMarkPos(PlanState *node) ExecTidMarkPos((TidScanState *) node); break; - case T_FunctionScanState: - ExecFunctionMarkPos((FunctionScanState *) node); + case T_ValuesScanState: + ExecValuesMarkPos((ValuesScanState *) node); break; case T_MaterialState: @@ -237,6 +266,10 @@ ExecMarkPos(PlanState *node) 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)); @@ -251,10 +284,10 @@ ExecMarkPos(PlanState *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 @@ -274,8 +307,8 @@ ExecRestrPos(PlanState *node) ExecTidRestrPos((TidScanState *) node); break; - case T_FunctionScanState: - ExecFunctionRestrPos((FunctionScanState *) node); + case T_ValuesScanState: + ExecValuesRestrPos((ValuesScanState *) node); break; case T_MaterialState: @@ -286,6 +319,10 @@ ExecRestrPos(PlanState *node) ExecSortRestrPos((SortState *) node); break; + case T_ResultState: + ExecResultRestrPos((ResultState *) node); + break; + default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); break; @@ -301,8 +338,8 @@ ExecRestrPos(PlanState *node) * * (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) @@ -312,11 +349,22 @@ 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; } @@ -362,6 +410,9 @@ ExecSupportsBackwardScan(Plan *node) case T_IndexScan: case T_TidScan: case T_FunctionScan: + case T_ValuesScan: + case T_CteScan: + case T_WorkTableScan: return true; case T_SubqueryScan: @@ -371,9 +422,6 @@ ExecSupportsBackwardScan(Plan *node) case T_Sort: return true; - case T_Unique: - return ExecSupportsBackwardScan(outerPlan(node)); - case T_Limit: return ExecSupportsBackwardScan(outerPlan(node)); @@ -381,69 +429,3 @@ ExecSupportsBackwardScan(Plan *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; -}