Header And Logo

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

nodeFunctionscan.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeFunctionscan.c
00004  *    Support routines for scanning RangeFunctions (functions in rangetable).
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/executor/nodeFunctionscan.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 /*
00016  * INTERFACE ROUTINES
00017  *      ExecFunctionScan        scans a function.
00018  *      ExecFunctionNext        retrieve next tuple in sequential order.
00019  *      ExecInitFunctionScan    creates and initializes a functionscan node.
00020  *      ExecEndFunctionScan     releases any storage allocated.
00021  *      ExecReScanFunctionScan  rescans the function
00022  */
00023 #include "postgres.h"
00024 
00025 #include "executor/nodeFunctionscan.h"
00026 #include "funcapi.h"
00027 #include "nodes/nodeFuncs.h"
00028 
00029 
00030 static TupleTableSlot *FunctionNext(FunctionScanState *node);
00031 
00032 /* ----------------------------------------------------------------
00033  *                      Scan Support
00034  * ----------------------------------------------------------------
00035  */
00036 /* ----------------------------------------------------------------
00037  *      FunctionNext
00038  *
00039  *      This is a workhorse for ExecFunctionScan
00040  * ----------------------------------------------------------------
00041  */
00042 static TupleTableSlot *
00043 FunctionNext(FunctionScanState *node)
00044 {
00045     TupleTableSlot *slot;
00046     EState     *estate;
00047     ScanDirection direction;
00048     Tuplestorestate *tuplestorestate;
00049 
00050     /*
00051      * get information from the estate and scan state
00052      */
00053     estate = node->ss.ps.state;
00054     direction = estate->es_direction;
00055 
00056     tuplestorestate = node->tuplestorestate;
00057 
00058     /*
00059      * If first time through, read all tuples from function and put them in a
00060      * tuplestore. Subsequent calls just fetch tuples from tuplestore.
00061      */
00062     if (tuplestorestate == NULL)
00063     {
00064         node->tuplestorestate = tuplestorestate =
00065             ExecMakeTableFunctionResult(node->funcexpr,
00066                                         node->ss.ps.ps_ExprContext,
00067                                         node->tupdesc,
00068                                         node->eflags & EXEC_FLAG_BACKWARD);
00069     }
00070 
00071     /*
00072      * Get the next tuple from tuplestore. Return NULL if no more tuples.
00073      */
00074     slot = node->ss.ss_ScanTupleSlot;
00075     (void) tuplestore_gettupleslot(tuplestorestate,
00076                                    ScanDirectionIsForward(direction),
00077                                    false,
00078                                    slot);
00079     return slot;
00080 }
00081 
00082 /*
00083  * FunctionRecheck -- access method routine to recheck a tuple in EvalPlanQual
00084  */
00085 static bool
00086 FunctionRecheck(FunctionScanState *node, TupleTableSlot *slot)
00087 {
00088     /* nothing to check */
00089     return true;
00090 }
00091 
00092 /* ----------------------------------------------------------------
00093  *      ExecFunctionScan(node)
00094  *
00095  *      Scans the function sequentially and returns the next qualifying
00096  *      tuple.
00097  *      We call the ExecScan() routine and pass it the appropriate
00098  *      access method functions.
00099  * ----------------------------------------------------------------
00100  */
00101 TupleTableSlot *
00102 ExecFunctionScan(FunctionScanState *node)
00103 {
00104     return ExecScan(&node->ss,
00105                     (ExecScanAccessMtd) FunctionNext,
00106                     (ExecScanRecheckMtd) FunctionRecheck);
00107 }
00108 
00109 /* ----------------------------------------------------------------
00110  *      ExecInitFunctionScan
00111  * ----------------------------------------------------------------
00112  */
00113 FunctionScanState *
00114 ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
00115 {
00116     FunctionScanState *scanstate;
00117     Oid         funcrettype;
00118     TypeFuncClass functypclass;
00119     TupleDesc   tupdesc = NULL;
00120 
00121     /* check for unsupported flags */
00122     Assert(!(eflags & EXEC_FLAG_MARK));
00123 
00124     /*
00125      * FunctionScan should not have any children.
00126      */
00127     Assert(outerPlan(node) == NULL);
00128     Assert(innerPlan(node) == NULL);
00129 
00130     /*
00131      * create new ScanState for node
00132      */
00133     scanstate = makeNode(FunctionScanState);
00134     scanstate->ss.ps.plan = (Plan *) node;
00135     scanstate->ss.ps.state = estate;
00136     scanstate->eflags = eflags;
00137 
00138     /*
00139      * Miscellaneous initialization
00140      *
00141      * create expression context for node
00142      */
00143     ExecAssignExprContext(estate, &scanstate->ss.ps);
00144 
00145     /*
00146      * tuple table initialization
00147      */
00148     ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
00149     ExecInitScanTupleSlot(estate, &scanstate->ss);
00150 
00151     /*
00152      * initialize child expressions
00153      */
00154     scanstate->ss.ps.targetlist = (List *)
00155         ExecInitExpr((Expr *) node->scan.plan.targetlist,
00156                      (PlanState *) scanstate);
00157     scanstate->ss.ps.qual = (List *)
00158         ExecInitExpr((Expr *) node->scan.plan.qual,
00159                      (PlanState *) scanstate);
00160 
00161     /*
00162      * Now determine if the function returns a simple or composite type, and
00163      * build an appropriate tupdesc.
00164      */
00165     functypclass = get_expr_result_type(node->funcexpr,
00166                                         &funcrettype,
00167                                         &tupdesc);
00168 
00169     if (functypclass == TYPEFUNC_COMPOSITE)
00170     {
00171         /* Composite data type, e.g. a table's row type */
00172         Assert(tupdesc);
00173         /* Must copy it out of typcache for safety */
00174         tupdesc = CreateTupleDescCopy(tupdesc);
00175     }
00176     else if (functypclass == TYPEFUNC_SCALAR)
00177     {
00178         /* Base data type, i.e. scalar */
00179         char       *attname = strVal(linitial(node->funccolnames));
00180 
00181         tupdesc = CreateTemplateTupleDesc(1, false);
00182         TupleDescInitEntry(tupdesc,
00183                            (AttrNumber) 1,
00184                            attname,
00185                            funcrettype,
00186                            -1,
00187                            0);
00188         TupleDescInitEntryCollation(tupdesc,
00189                                     (AttrNumber) 1,
00190                                     exprCollation(node->funcexpr));
00191     }
00192     else if (functypclass == TYPEFUNC_RECORD)
00193     {
00194         tupdesc = BuildDescFromLists(node->funccolnames,
00195                                      node->funccoltypes,
00196                                      node->funccoltypmods,
00197                                      node->funccolcollations);
00198     }
00199     else
00200     {
00201         /* crummy error message, but parser should have caught this */
00202         elog(ERROR, "function in FROM has unsupported return type");
00203     }
00204 
00205     /*
00206      * For RECORD results, make sure a typmod has been assigned.  (The
00207      * function should do this for itself, but let's cover things in case it
00208      * doesn't.)
00209      */
00210     BlessTupleDesc(tupdesc);
00211 
00212     scanstate->tupdesc = tupdesc;
00213     ExecAssignScanType(&scanstate->ss, tupdesc);
00214 
00215     /*
00216      * Other node-specific setup
00217      */
00218     scanstate->tuplestorestate = NULL;
00219     scanstate->funcexpr = ExecInitExpr((Expr *) node->funcexpr,
00220                                        (PlanState *) scanstate);
00221 
00222     scanstate->ss.ps.ps_TupFromTlist = false;
00223 
00224     /*
00225      * Initialize result tuple type and projection info.
00226      */
00227     ExecAssignResultTypeFromTL(&scanstate->ss.ps);
00228     ExecAssignScanProjectionInfo(&scanstate->ss);
00229 
00230     return scanstate;
00231 }
00232 
00233 /* ----------------------------------------------------------------
00234  *      ExecEndFunctionScan
00235  *
00236  *      frees any storage allocated through C routines.
00237  * ----------------------------------------------------------------
00238  */
00239 void
00240 ExecEndFunctionScan(FunctionScanState *node)
00241 {
00242     /*
00243      * Free the exprcontext
00244      */
00245     ExecFreeExprContext(&node->ss.ps);
00246 
00247     /*
00248      * clean out the tuple table
00249      */
00250     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00251     ExecClearTuple(node->ss.ss_ScanTupleSlot);
00252 
00253     /*
00254      * Release tuplestore resources
00255      */
00256     if (node->tuplestorestate != NULL)
00257         tuplestore_end(node->tuplestorestate);
00258     node->tuplestorestate = NULL;
00259 }
00260 
00261 /* ----------------------------------------------------------------
00262  *      ExecReScanFunctionScan
00263  *
00264  *      Rescans the relation.
00265  * ----------------------------------------------------------------
00266  */
00267 void
00268 ExecReScanFunctionScan(FunctionScanState *node)
00269 {
00270     ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00271 
00272     ExecScanReScan(&node->ss);
00273 
00274     /*
00275      * If we haven't materialized yet, just return.
00276      */
00277     if (!node->tuplestorestate)
00278         return;
00279 
00280     /*
00281      * Here we have a choice whether to drop the tuplestore (and recompute the
00282      * function outputs) or just rescan it.  We must recompute if the
00283      * expression contains parameters, else we rescan.  XXX maybe we should
00284      * recompute if the function is volatile?
00285      */
00286     if (node->ss.ps.chgParam != NULL)
00287     {
00288         tuplestore_end(node->tuplestorestate);
00289         node->tuplestorestate = NULL;
00290     }
00291     else
00292         tuplestore_rescan(node->tuplestorestate);
00293 }