#include "postgres.h"
#include "executor/nodeFunctionscan.h"
#include "funcapi.h"
#include "nodes/nodeFuncs.h"
Go to the source code of this file.
Functions | |
static TupleTableSlot * | FunctionNext (FunctionScanState *node) |
static bool | FunctionRecheck (FunctionScanState *node, TupleTableSlot *slot) |
TupleTableSlot * | ExecFunctionScan (FunctionScanState *node) |
FunctionScanState * | ExecInitFunctionScan (FunctionScan *node, EState *estate, int eflags) |
void | ExecEndFunctionScan (FunctionScanState *node) |
void | ExecReScanFunctionScan (FunctionScanState *node) |
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 | ) |
Definition at line 102 of file nodeFunctionscan.c.
References ExecScan(), FunctionNext(), FunctionRecheck(), and FunctionScanState::ss.
Referenced by ExecProcNode().
{ return ExecScan(&node->ss, (ExecScanAccessMtd) FunctionNext, (ExecScanRecheckMtd) FunctionRecheck); }
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; }