]> granicus.if.org Git - postgresql/blobdiff - src/backend/executor/execAmi.c
Implement SQL-standard WITH clauses, including WITH RECURSIVE.
[postgresql] / src / backend / executor / execAmi.c
index c2cb4b68835118f17700e96c7ca910b05eb8a1a4..1de3f5a778efedac7a6daf329a19ba53039f579e 100644 (file)
@@ -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;
-}