Header And Logo

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

Functions

nodeFunctionscan.c File Reference

#include "postgres.h"
#include "executor/nodeFunctionscan.h"
#include "funcapi.h"
#include "nodes/nodeFuncs.h"
Include dependency graph for nodeFunctionscan.c:

Go to the source code of this file.

Functions

static TupleTableSlotFunctionNext (FunctionScanState *node)
static bool FunctionRecheck (FunctionScanState *node, TupleTableSlot *slot)
TupleTableSlotExecFunctionScan (FunctionScanState *node)
FunctionScanStateExecInitFunctionScan (FunctionScan *node, EState *estate, int eflags)
void ExecEndFunctionScan (FunctionScanState *node)
void ExecReScanFunctionScan (FunctionScanState *node)

Function Documentation

void ExecEndFunctionScan ( FunctionScanState node  ) 

Definition at line 240 of file nodeFunctionscan.c.

References ExecClearTuple(), ExecFreeExprContext(), NULL, ScanState::ps, PlanState::ps_ResultTupleSlot, FunctionScanState::ss, ScanState::ss_ScanTupleSlot, tuplestore_end(), and FunctionScanState::tuplestorestate.

Referenced by ExecEndNode().

{
    /*
     * Free the exprcontext
     */
    ExecFreeExprContext(&node->ss.ps);

    /*
     * clean out the tuple table
     */
    ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
    ExecClearTuple(node->ss.ss_ScanTupleSlot);

    /*
     * Release tuplestore resources
     */
    if (node->tuplestorestate != NULL)
        tuplestore_end(node->tuplestorestate);
    node->tuplestorestate = NULL;
}

TupleTableSlot* ExecFunctionScan ( FunctionScanState node  ) 
FunctionScanState* ExecInitFunctionScan ( FunctionScan node,
EState estate,
int  eflags 
)

Definition at line 114 of file nodeFunctionscan.c.

References Assert, BlessTupleDesc(), BuildDescFromLists(), CreateTemplateTupleDesc(), CreateTupleDescCopy(), FunctionScanState::eflags, elog, ERROR, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignResultTypeFromTL(), ExecAssignScanProjectionInfo(), ExecAssignScanType(), ExecInitExpr(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), exprCollation(), FunctionScan::funccolcollations, FunctionScan::funccolnames, FunctionScan::funccoltypes, FunctionScan::funccoltypmods, FunctionScanState::funcexpr, FunctionScan::funcexpr, get_expr_result_type(), innerPlan, linitial, makeNode, NULL, outerPlan, Scan::plan, PlanState::plan, ScanState::ps, PlanState::ps_TupFromTlist, Plan::qual, PlanState::qual, FunctionScan::scan, FunctionScanState::ss, PlanState::state, strVal, Plan::targetlist, PlanState::targetlist, FunctionScanState::tupdesc, TupleDescInitEntry(), TupleDescInitEntryCollation(), FunctionScanState::tuplestorestate, TYPEFUNC_COMPOSITE, TYPEFUNC_RECORD, and TYPEFUNC_SCALAR.

Referenced by ExecInitNode().

{
    FunctionScanState *scanstate;
    Oid         funcrettype;
    TypeFuncClass functypclass;
    TupleDesc   tupdesc = NULL;

    /* check for unsupported flags */
    Assert(!(eflags & EXEC_FLAG_MARK));

    /*
     * FunctionScan should not have any children.
     */
    Assert(outerPlan(node) == NULL);
    Assert(innerPlan(node) == NULL);

    /*
     * create new ScanState for node
     */
    scanstate = makeNode(FunctionScanState);
    scanstate->ss.ps.plan = (Plan *) node;
    scanstate->ss.ps.state = estate;
    scanstate->eflags = eflags;

    /*
     * Miscellaneous initialization
     *
     * create expression context for node
     */
    ExecAssignExprContext(estate, &scanstate->ss.ps);

    /*
     * tuple table initialization
     */
    ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
    ExecInitScanTupleSlot(estate, &scanstate->ss);

    /*
     * initialize child expressions
     */
    scanstate->ss.ps.targetlist = (List *)
        ExecInitExpr((Expr *) node->scan.plan.targetlist,
                     (PlanState *) scanstate);
    scanstate->ss.ps.qual = (List *)
        ExecInitExpr((Expr *) node->scan.plan.qual,
                     (PlanState *) scanstate);

    /*
     * Now determine if the function returns a simple or composite type, and
     * build an appropriate tupdesc.
     */
    functypclass = get_expr_result_type(node->funcexpr,
                                        &funcrettype,
                                        &tupdesc);

    if (functypclass == TYPEFUNC_COMPOSITE)
    {
        /* Composite data type, e.g. a table's row type */
        Assert(tupdesc);
        /* Must copy it out of typcache for safety */
        tupdesc = CreateTupleDescCopy(tupdesc);
    }
    else if (functypclass == TYPEFUNC_SCALAR)
    {
        /* Base data type, i.e. scalar */
        char       *attname = strVal(linitial(node->funccolnames));

        tupdesc = CreateTemplateTupleDesc(1, false);
        TupleDescInitEntry(tupdesc,
                           (AttrNumber) 1,
                           attname,
                           funcrettype,
                           -1,
                           0);
        TupleDescInitEntryCollation(tupdesc,
                                    (AttrNumber) 1,
                                    exprCollation(node->funcexpr));
    }
    else if (functypclass == TYPEFUNC_RECORD)
    {
        tupdesc = BuildDescFromLists(node->funccolnames,
                                     node->funccoltypes,
                                     node->funccoltypmods,
                                     node->funccolcollations);
    }
    else
    {
        /* crummy error message, but parser should have caught this */
        elog(ERROR, "function in FROM has unsupported return type");
    }

    /*
     * For RECORD results, make sure a typmod has been assigned.  (The
     * function should do this for itself, but let's cover things in case it
     * doesn't.)
     */
    BlessTupleDesc(tupdesc);

    scanstate->tupdesc = tupdesc;
    ExecAssignScanType(&scanstate->ss, tupdesc);

    /*
     * Other node-specific setup
     */
    scanstate->tuplestorestate = NULL;
    scanstate->funcexpr = ExecInitExpr((Expr *) node->funcexpr,
                                       (PlanState *) scanstate);

    scanstate->ss.ps.ps_TupFromTlist = false;

    /*
     * Initialize result tuple type and projection info.
     */
    ExecAssignResultTypeFromTL(&scanstate->ss.ps);
    ExecAssignScanProjectionInfo(&scanstate->ss);

    return scanstate;
}

void ExecReScanFunctionScan ( FunctionScanState node  ) 

Definition at line 268 of file nodeFunctionscan.c.

References PlanState::chgParam, ExecClearTuple(), ExecScanReScan(), NULL, ScanState::ps, PlanState::ps_ResultTupleSlot, FunctionScanState::ss, tuplestore_end(), tuplestore_rescan(), and FunctionScanState::tuplestorestate.

Referenced by ExecReScan().

{
    ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);

    ExecScanReScan(&node->ss);

    /*
     * If we haven't materialized yet, just return.
     */
    if (!node->tuplestorestate)
        return;

    /*
     * Here we have a choice whether to drop the tuplestore (and recompute the
     * function outputs) or just rescan it.  We must recompute if the
     * expression contains parameters, else we rescan.  XXX maybe we should
     * recompute if the function is volatile?
     */
    if (node->ss.ps.chgParam != NULL)
    {
        tuplestore_end(node->tuplestorestate);
        node->tuplestorestate = NULL;
    }
    else
        tuplestore_rescan(node->tuplestorestate);
}

static TupleTableSlot * FunctionNext ( FunctionScanState node  )  [static]

Definition at line 43 of file nodeFunctionscan.c.

References FunctionScanState::eflags, EState::es_direction, EXEC_FLAG_BACKWARD, ExecMakeTableFunctionResult(), FunctionScanState::funcexpr, NULL, ScanState::ps, PlanState::ps_ExprContext, ScanDirectionIsForward, FunctionScanState::ss, ScanState::ss_ScanTupleSlot, PlanState::state, FunctionScanState::tupdesc, tuplestore_gettupleslot(), and FunctionScanState::tuplestorestate.

Referenced by ExecFunctionScan().

{
    TupleTableSlot *slot;
    EState     *estate;
    ScanDirection direction;
    Tuplestorestate *tuplestorestate;

    /*
     * get information from the estate and scan state
     */
    estate = node->ss.ps.state;
    direction = estate->es_direction;

    tuplestorestate = node->tuplestorestate;

    /*
     * If first time through, read all tuples from function and put them in a
     * tuplestore. Subsequent calls just fetch tuples from tuplestore.
     */
    if (tuplestorestate == NULL)
    {
        node->tuplestorestate = tuplestorestate =
            ExecMakeTableFunctionResult(node->funcexpr,
                                        node->ss.ps.ps_ExprContext,
                                        node->tupdesc,
                                        node->eflags & EXEC_FLAG_BACKWARD);
    }

    /*
     * Get the next tuple from tuplestore. Return NULL if no more tuples.
     */
    slot = node->ss.ss_ScanTupleSlot;
    (void) tuplestore_gettupleslot(tuplestorestate,
                                   ScanDirectionIsForward(direction),
                                   false,
                                   slot);
    return slot;
}

static bool FunctionRecheck ( FunctionScanState node,
TupleTableSlot slot 
) [static]

Definition at line 86 of file nodeFunctionscan.c.

Referenced by ExecFunctionScan().

{
    /* nothing to check */
    return true;
}