Header And Logo

PostgreSQL
| The world's most advanced open source database.

nodeSubqueryscan.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeSubqueryscan.c
00004  *    Support routines for scanning subqueries (subselects in rangetable).
00005  *
00006  * This is just enough different from sublinks (nodeSubplan.c) to mean that
00007  * we need two sets of code.  Ought to look at trying to unify the cases.
00008  *
00009  *
00010  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00011  * Portions Copyright (c) 1994, Regents of the University of California
00012  *
00013  *
00014  * IDENTIFICATION
00015  *    src/backend/executor/nodeSubqueryscan.c
00016  *
00017  *-------------------------------------------------------------------------
00018  */
00019 /*
00020  * INTERFACE ROUTINES
00021  *      ExecSubqueryScan            scans a subquery.
00022  *      ExecSubqueryNext            retrieve next tuple in sequential order.
00023  *      ExecInitSubqueryScan        creates and initializes a subqueryscan node.
00024  *      ExecEndSubqueryScan         releases any storage allocated.
00025  *      ExecReScanSubqueryScan      rescans the relation
00026  *
00027  */
00028 #include "postgres.h"
00029 
00030 #include "executor/execdebug.h"
00031 #include "executor/nodeSubqueryscan.h"
00032 
00033 static TupleTableSlot *SubqueryNext(SubqueryScanState *node);
00034 
00035 /* ----------------------------------------------------------------
00036  *                      Scan Support
00037  * ----------------------------------------------------------------
00038  */
00039 /* ----------------------------------------------------------------
00040  *      SubqueryNext
00041  *
00042  *      This is a workhorse for ExecSubqueryScan
00043  * ----------------------------------------------------------------
00044  */
00045 static TupleTableSlot *
00046 SubqueryNext(SubqueryScanState *node)
00047 {
00048     TupleTableSlot *slot;
00049 
00050     /*
00051      * Get the next tuple from the sub-query.
00052      */
00053     slot = ExecProcNode(node->subplan);
00054 
00055     /*
00056      * We just return the subplan's result slot, rather than expending extra
00057      * cycles for ExecCopySlot().  (Our own ScanTupleSlot is used only for
00058      * EvalPlanQual rechecks.)
00059      */
00060     return slot;
00061 }
00062 
00063 /*
00064  * SubqueryRecheck -- access method routine to recheck a tuple in EvalPlanQual
00065  */
00066 static bool
00067 SubqueryRecheck(SubqueryScanState *node, TupleTableSlot *slot)
00068 {
00069     /* nothing to check */
00070     return true;
00071 }
00072 
00073 /* ----------------------------------------------------------------
00074  *      ExecSubqueryScan(node)
00075  *
00076  *      Scans the subquery sequentially and returns the next qualifying
00077  *      tuple.
00078  *      We call the ExecScan() routine and pass it the appropriate
00079  *      access method functions.
00080  * ----------------------------------------------------------------
00081  */
00082 TupleTableSlot *
00083 ExecSubqueryScan(SubqueryScanState *node)
00084 {
00085     return ExecScan(&node->ss,
00086                     (ExecScanAccessMtd) SubqueryNext,
00087                     (ExecScanRecheckMtd) SubqueryRecheck);
00088 }
00089 
00090 /* ----------------------------------------------------------------
00091  *      ExecInitSubqueryScan
00092  * ----------------------------------------------------------------
00093  */
00094 SubqueryScanState *
00095 ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
00096 {
00097     SubqueryScanState *subquerystate;
00098 
00099     /* check for unsupported flags */
00100     Assert(!(eflags & EXEC_FLAG_MARK));
00101 
00102     /* SubqueryScan should not have any "normal" children */
00103     Assert(outerPlan(node) == NULL);
00104     Assert(innerPlan(node) == NULL);
00105 
00106     /*
00107      * create state structure
00108      */
00109     subquerystate = makeNode(SubqueryScanState);
00110     subquerystate->ss.ps.plan = (Plan *) node;
00111     subquerystate->ss.ps.state = estate;
00112 
00113     /*
00114      * Miscellaneous initialization
00115      *
00116      * create expression context for node
00117      */
00118     ExecAssignExprContext(estate, &subquerystate->ss.ps);
00119 
00120     /*
00121      * initialize child expressions
00122      */
00123     subquerystate->ss.ps.targetlist = (List *)
00124         ExecInitExpr((Expr *) node->scan.plan.targetlist,
00125                      (PlanState *) subquerystate);
00126     subquerystate->ss.ps.qual = (List *)
00127         ExecInitExpr((Expr *) node->scan.plan.qual,
00128                      (PlanState *) subquerystate);
00129 
00130     /*
00131      * tuple table initialization
00132      */
00133     ExecInitResultTupleSlot(estate, &subquerystate->ss.ps);
00134     ExecInitScanTupleSlot(estate, &subquerystate->ss);
00135 
00136     /*
00137      * initialize subquery
00138      */
00139     subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
00140 
00141     subquerystate->ss.ps.ps_TupFromTlist = false;
00142 
00143     /*
00144      * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo)
00145      */
00146     ExecAssignScanType(&subquerystate->ss,
00147                        ExecGetResultType(subquerystate->subplan));
00148 
00149     /*
00150      * Initialize result tuple type and projection info.
00151      */
00152     ExecAssignResultTypeFromTL(&subquerystate->ss.ps);
00153     ExecAssignScanProjectionInfo(&subquerystate->ss);
00154 
00155     return subquerystate;
00156 }
00157 
00158 /* ----------------------------------------------------------------
00159  *      ExecEndSubqueryScan
00160  *
00161  *      frees any storage allocated through C routines.
00162  * ----------------------------------------------------------------
00163  */
00164 void
00165 ExecEndSubqueryScan(SubqueryScanState *node)
00166 {
00167     /*
00168      * Free the exprcontext
00169      */
00170     ExecFreeExprContext(&node->ss.ps);
00171 
00172     /*
00173      * clean out the upper tuple table
00174      */
00175     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00176     ExecClearTuple(node->ss.ss_ScanTupleSlot);
00177 
00178     /*
00179      * close down subquery
00180      */
00181     ExecEndNode(node->subplan);
00182 }
00183 
00184 /* ----------------------------------------------------------------
00185  *      ExecReScanSubqueryScan
00186  *
00187  *      Rescans the relation.
00188  * ----------------------------------------------------------------
00189  */
00190 void
00191 ExecReScanSubqueryScan(SubqueryScanState *node)
00192 {
00193     ExecScanReScan(&node->ss);
00194 
00195     /*
00196      * ExecReScan doesn't know about my subplan, so I have to do
00197      * changed-parameter signaling myself.  This is just as well, because the
00198      * subplan has its own memory context in which its chgParam state lives.
00199      */
00200     if (node->ss.ps.chgParam != NULL)
00201         UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);
00202 
00203     /*
00204      * if chgParam of subnode is not null then plan will be re-scanned by
00205      * first ExecProcNode.
00206      */
00207     if (node->subplan->chgParam == NULL)
00208         ExecReScan(node->subplan);
00209 }