diff options
Diffstat (limited to 'src/backend/executor/nodeFunctionscan.c')
-rw-r--r-- | src/backend/executor/nodeFunctionscan.c | 469 |
1 files changed, 0 insertions, 469 deletions
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c deleted file mode 100644 index 3645a188334..00000000000 --- a/src/backend/executor/nodeFunctionscan.c +++ /dev/null @@ -1,469 +0,0 @@ -/*------------------------------------------------------------------------- - * - * nodeFunctionscan.c - * Support routines for scanning RangeFunctions (functions in rangetable). - * - * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.2 2002/06/20 20:29:28 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -/* - * INTERFACE ROUTINES - * ExecFunctionScan scans a function. - * ExecFunctionNext retrieve next tuple in sequential order. - * ExecInitFunctionScan creates and initializes a functionscan node. - * ExecEndFunctionScan releases any storage allocated. - * ExecFunctionReScan rescans the function - */ -#include "postgres.h" - -#include "miscadmin.h" -#include "access/heapam.h" -#include "catalog/pg_type.h" -#include "executor/execdebug.h" -#include "executor/execdefs.h" -#include "executor/execdesc.h" -#include "executor/nodeFunctionscan.h" -#include "parser/parsetree.h" -#include "parser/parse_expr.h" -#include "parser/parse_type.h" -#include "storage/lmgr.h" -#include "tcop/pquery.h" -#include "utils/lsyscache.h" -#include "utils/syscache.h" -#include "utils/tuplestore.h" - -static TupleTableSlot *FunctionNext(FunctionScan *node); -static TupleTableSlot *function_getonetuple(TupleTableSlot *slot, - Node *expr, - ExprContext *econtext, - TupleDesc tupdesc, - bool returnsTuple, - bool *isNull, - ExprDoneCond *isDone); -static FunctionMode get_functionmode(Node *expr); - -/* ---------------------------------------------------------------- - * Scan Support - * ---------------------------------------------------------------- - */ -/* ---------------------------------------------------------------- - * FunctionNext - * - * This is a workhorse for ExecFunctionScan - * ---------------------------------------------------------------- - */ -static TupleTableSlot * -FunctionNext(FunctionScan *node) -{ - TupleTableSlot *slot; - Node *expr; - ExprContext *econtext; - TupleDesc tupdesc; - EState *estate; - ScanDirection direction; - Tuplestorestate *tuplestorestate; - FunctionScanState *scanstate; - bool should_free; - HeapTuple heapTuple; - - /* - * get information from the estate and scan state - */ - scanstate = (FunctionScanState *) node->scan.scanstate; - estate = node->scan.plan.state; - direction = estate->es_direction; - econtext = scanstate->csstate.cstate.cs_ExprContext; - - tuplestorestate = scanstate->tuplestorestate; - tupdesc = scanstate->tupdesc; - expr = scanstate->funcexpr; - - /* - * If first time through, read all tuples from function and pass them to - * tuplestore.c. Subsequent calls just fetch tuples from tuplestore. - */ - if (tuplestorestate == NULL) - { - /* - * Initialize tuplestore module. - */ - tuplestorestate = tuplestore_begin_heap(true, /* randomAccess */ - SortMem); - - scanstate->tuplestorestate = (void *) tuplestorestate; - - /* - * Compute all the function tuples and pass to tuplestore. - */ - for (;;) - { - bool isNull; - ExprDoneCond isDone; - - isNull = false; - isDone = ExprSingleResult; - slot = function_getonetuple(scanstate->csstate.css_ScanTupleSlot, - expr, econtext, tupdesc, - scanstate->returnsTuple, - &isNull, &isDone); - if (TupIsNull(slot)) - break; - - tuplestore_puttuple(tuplestorestate, (void *) slot->val); - ExecClearTuple(slot); - - if (isDone != ExprMultipleResult) - break; - } - - /* - * Complete the store. - */ - tuplestore_donestoring(tuplestorestate); - } - - /* - * Get the next tuple from tuplestore. Return NULL if no more tuples. - */ - slot = scanstate->csstate.css_ScanTupleSlot; - heapTuple = tuplestore_getheaptuple(tuplestorestate, - ScanDirectionIsForward(direction), - &should_free); - - return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free); -} - -/* ---------------------------------------------------------------- - * ExecFunctionScan(node) - * - * Scans the Function sequentially and returns the next qualifying - * tuple. - * It calls the ExecScan() routine and passes it the access method - * which retrieve tuples sequentially. - * - */ - -TupleTableSlot * -ExecFunctionScan(FunctionScan *node) -{ - /* - * use FunctionNext as access method - */ - return ExecScan(&node->scan, (ExecScanAccessMtd) FunctionNext); -} - -/* ---------------------------------------------------------------- - * ExecInitFunctionScan - * ---------------------------------------------------------------- - */ -bool -ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) -{ - FunctionScanState *scanstate; - RangeTblEntry *rte; - Oid funcrettype; - Oid funcrelid; - TupleDesc tupdesc; - - /* - * FunctionScan should not have any children. - */ - Assert(outerPlan((Plan *) node) == NULL); - Assert(innerPlan((Plan *) node) == NULL); - - /* - * assign the node's execution state - */ - node->scan.plan.state = estate; - - /* - * create new ScanState for node - */ - scanstate = makeNode(FunctionScanState); - node->scan.scanstate = &scanstate->csstate; - - /* - * Miscellaneous initialization - * - * create expression context for node - */ - ExecAssignExprContext(estate, &scanstate->csstate.cstate); - -#define FUNCTIONSCAN_NSLOTS 2 - - /* - * tuple table initialization - */ - ExecInitResultTupleSlot(estate, &scanstate->csstate.cstate); - ExecInitScanTupleSlot(estate, &scanstate->csstate); - - /* - * get info about function - */ - rte = rt_fetch(node->scan.scanrelid, estate->es_range_table); - Assert(rte->rtekind == RTE_FUNCTION); - funcrettype = exprType(rte->funcexpr); - funcrelid = typeidTypeRelid(funcrettype); - - /* - * Build a suitable tupledesc representing the output rows - */ - if (OidIsValid(funcrelid)) - { - /* - * Composite data type, i.e. a table's row type - * Same as ordinary relation RTE - */ - Relation rel; - - rel = relation_open(funcrelid, AccessShareLock); - tupdesc = CreateTupleDescCopy(RelationGetDescr(rel)); - relation_close(rel, AccessShareLock); - scanstate->returnsTuple = true; - } - else - { - /* - * Must be a base data type, i.e. scalar - */ - char *attname = strVal(lfirst(rte->eref->colnames)); - - tupdesc = CreateTemplateTupleDesc(1); - TupleDescInitEntry(tupdesc, - (AttrNumber) 1, - attname, - funcrettype, - -1, - 0, - false); - scanstate->returnsTuple = false; - } - scanstate->tupdesc = tupdesc; - ExecSetSlotDescriptor(scanstate->csstate.css_ScanTupleSlot, - tupdesc, false); - - /* - * Other node-specific setup - */ - scanstate->tuplestorestate = NULL; - scanstate->funcexpr = rte->funcexpr; - - scanstate->functionmode = get_functionmode(rte->funcexpr); - - scanstate->csstate.cstate.cs_TupFromTlist = false; - - /* - * initialize tuple type - */ - ExecAssignResultTypeFromTL((Plan *) node, &scanstate->csstate.cstate); - ExecAssignProjectionInfo((Plan *) node, &scanstate->csstate.cstate); - - return TRUE; -} - -int -ExecCountSlotsFunctionScan(FunctionScan *node) -{ - return ExecCountSlotsNode(outerPlan(node)) + - ExecCountSlotsNode(innerPlan(node)) + - FUNCTIONSCAN_NSLOTS; -} - -/* ---------------------------------------------------------------- - * ExecEndFunctionScan - * - * frees any storage allocated through C routines. - * ---------------------------------------------------------------- - */ -void -ExecEndFunctionScan(FunctionScan *node) -{ - FunctionScanState *scanstate; - EState *estate; - - /* - * get information from node - */ - scanstate = (FunctionScanState *) node->scan.scanstate; - estate = node->scan.plan.state; - - /* - * Free the projection info and the scan attribute info - * - * Note: we don't ExecFreeResultType(scanstate) because the rule manager - * depends on the tupType returned by ExecMain(). So for now, this is - * freed at end-transaction time. -cim 6/2/91 - */ - ExecFreeProjectionInfo(&scanstate->csstate.cstate); - ExecFreeExprContext(&scanstate->csstate.cstate); - - /* - * clean out the tuple table - */ - ExecClearTuple(scanstate->csstate.cstate.cs_ResultTupleSlot); - ExecClearTuple(scanstate->csstate.css_ScanTupleSlot); - - /* - * Release tuplestore resources - */ - if (scanstate->tuplestorestate != NULL) - tuplestore_end((Tuplestorestate *) scanstate->tuplestorestate); - scanstate->tuplestorestate = NULL; -} - -/* ---------------------------------------------------------------- - * ExecFunctionMarkPos - * - * Calls tuplestore to save the current position in the stored file. - * ---------------------------------------------------------------- - */ -void -ExecFunctionMarkPos(FunctionScan *node) -{ - FunctionScanState *scanstate; - - scanstate = (FunctionScanState *) node->scan.scanstate; - - /* - * if we haven't materialized yet, just return. - */ - if (!scanstate->tuplestorestate) - return; - - tuplestore_markpos((Tuplestorestate *) scanstate->tuplestorestate); -} - -/* ---------------------------------------------------------------- - * ExecFunctionRestrPos - * - * Calls tuplestore to restore the last saved file position. - * ---------------------------------------------------------------- - */ -void -ExecFunctionRestrPos(FunctionScan *node) -{ - FunctionScanState *scanstate; - - scanstate = (FunctionScanState *) node->scan.scanstate; - - /* - * if we haven't materialized yet, just return. - */ - if (!scanstate->tuplestorestate) - return; - - tuplestore_restorepos((Tuplestorestate *) scanstate->tuplestorestate); -} - -/* ---------------------------------------------------------------- - * ExecFunctionReScan - * - * Rescans the relation. - * ---------------------------------------------------------------- - */ -void -ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent) -{ - FunctionScanState *scanstate; - - /* - * get information from node - */ - scanstate = (FunctionScanState *) node->scan.scanstate; - - ExecClearTuple(scanstate->csstate.cstate.cs_ResultTupleSlot); - - /* - * If we haven't materialized yet, just return. - */ - if (!scanstate->tuplestorestate) - return; - - /* - * Here we have a choice whether to drop the tuplestore (and recompute - * the function outputs) or just rescan it. This should depend on - * whether the function expression contains parameters and/or is - * marked volatile. FIXME soon. - */ - if (node->scan.plan.chgParam != NULL) - { - tuplestore_end((Tuplestorestate *) scanstate->tuplestorestate); - scanstate->tuplestorestate = NULL; - } - else - tuplestore_rescan((Tuplestorestate *) scanstate->tuplestorestate); -} - -/* - * Run the underlying function to get the next tuple - */ -static TupleTableSlot * -function_getonetuple(TupleTableSlot *slot, - Node *expr, - ExprContext *econtext, - TupleDesc tupdesc, - bool returnsTuple, - bool *isNull, - ExprDoneCond *isDone) -{ - HeapTuple tuple; - Datum retDatum; - char nullflag; - - /* - * get the next Datum from the function - */ - retDatum = ExecEvalExprSwitchContext(expr, econtext, isNull, isDone); - - /* - * check to see if we're really done - */ - if (*isDone == ExprEndResult) - slot = NULL; - else - { - if (returnsTuple) - { - /* - * Composite data type, i.e. a table's row type - * function returns pointer to tts?? - */ - slot = (TupleTableSlot *) retDatum; - } - else - { - /* - * Must be a base data type, i.e. scalar - * turn it into a tuple - */ - nullflag = *isNull ? 'n' : ' '; - tuple = heap_formtuple(tupdesc, &retDatum, &nullflag); - - /* - * save the tuple in the scan tuple slot and return the slot. - */ - slot = ExecStoreTuple(tuple, /* tuple to store */ - slot, /* slot to store in */ - InvalidBuffer, /* buffer associated with - * this tuple */ - true); /* pfree this pointer */ - } - } - - return slot; -} - -static FunctionMode -get_functionmode(Node *expr) -{ - /* - * for the moment, hardwire this - */ - return PM_REPEATEDCALL; -} |