Disallow empty passwords in LDAP authentication, the same way
[PostgreSQL.git] / src / backend / executor / nodeFunctionscan.c
blob6913e9c98221f99022d7c50cfc1d375e203cc787
1 /*-------------------------------------------------------------------------
3 * nodeFunctionscan.c
4 * Support routines for scanning RangeFunctions (functions in rangetable).
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
16 * INTERFACE ROUTINES
17 * ExecFunctionScan scans a function.
18 * ExecFunctionNext retrieve next tuple in sequential order.
19 * ExecInitFunctionScan creates and initializes a functionscan node.
20 * ExecEndFunctionScan releases any storage allocated.
21 * ExecFunctionReScan rescans the function
23 #include "postgres.h"
25 #include "executor/nodeFunctionscan.h"
26 #include "funcapi.h"
27 #include "utils/builtins.h"
30 static TupleTableSlot *FunctionNext(FunctionScanState *node);
32 /* ----------------------------------------------------------------
33 * Scan Support
34 * ----------------------------------------------------------------
36 /* ----------------------------------------------------------------
37 * FunctionNext
39 * This is a workhorse for ExecFunctionScan
40 * ----------------------------------------------------------------
42 static TupleTableSlot *
43 FunctionNext(FunctionScanState *node)
45 TupleTableSlot *slot;
46 EState *estate;
47 ScanDirection direction;
48 Tuplestorestate *tuplestorestate;
51 * get information from the estate and scan state
53 estate = node->ss.ps.state;
54 direction = estate->es_direction;
56 tuplestorestate = node->tuplestorestate;
59 * If first time through, read all tuples from function and put them in a
60 * tuplestore. Subsequent calls just fetch tuples from tuplestore.
62 if (tuplestorestate == NULL)
64 node->tuplestorestate = tuplestorestate =
65 ExecMakeTableFunctionResult(node->funcexpr,
66 node->ss.ps.ps_ExprContext,
67 node->tupdesc,
68 node->eflags & EXEC_FLAG_BACKWARD);
72 * Get the next tuple from tuplestore. Return NULL if no more tuples.
74 slot = node->ss.ss_ScanTupleSlot;
75 (void) tuplestore_gettupleslot(tuplestorestate,
76 ScanDirectionIsForward(direction),
77 false,
78 slot);
79 return slot;
82 /* ----------------------------------------------------------------
83 * ExecFunctionScan(node)
85 * Scans the function sequentially and returns the next qualifying
86 * tuple.
87 * It calls the ExecScan() routine and passes it the access method
88 * which retrieves tuples sequentially.
92 TupleTableSlot *
93 ExecFunctionScan(FunctionScanState *node)
96 * use FunctionNext as access method
98 return ExecScan(&node->ss, (ExecScanAccessMtd) FunctionNext);
101 /* ----------------------------------------------------------------
102 * ExecInitFunctionScan
103 * ----------------------------------------------------------------
105 FunctionScanState *
106 ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
108 FunctionScanState *scanstate;
109 Oid funcrettype;
110 TypeFuncClass functypclass;
111 TupleDesc tupdesc = NULL;
113 /* check for unsupported flags */
114 Assert(!(eflags & EXEC_FLAG_MARK));
117 * FunctionScan should not have any children.
119 Assert(outerPlan(node) == NULL);
120 Assert(innerPlan(node) == NULL);
123 * create new ScanState for node
125 scanstate = makeNode(FunctionScanState);
126 scanstate->ss.ps.plan = (Plan *) node;
127 scanstate->ss.ps.state = estate;
128 scanstate->eflags = eflags;
131 * Miscellaneous initialization
133 * create expression context for node
135 ExecAssignExprContext(estate, &scanstate->ss.ps);
137 #define FUNCTIONSCAN_NSLOTS 2
140 * tuple table initialization
142 ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
143 ExecInitScanTupleSlot(estate, &scanstate->ss);
146 * initialize child expressions
148 scanstate->ss.ps.targetlist = (List *)
149 ExecInitExpr((Expr *) node->scan.plan.targetlist,
150 (PlanState *) scanstate);
151 scanstate->ss.ps.qual = (List *)
152 ExecInitExpr((Expr *) node->scan.plan.qual,
153 (PlanState *) scanstate);
156 * Now determine if the function returns a simple or composite type, and
157 * build an appropriate tupdesc.
159 functypclass = get_expr_result_type(node->funcexpr,
160 &funcrettype,
161 &tupdesc);
163 if (functypclass == TYPEFUNC_COMPOSITE)
165 /* Composite data type, e.g. a table's row type */
166 Assert(tupdesc);
167 /* Must copy it out of typcache for safety */
168 tupdesc = CreateTupleDescCopy(tupdesc);
170 else if (functypclass == TYPEFUNC_SCALAR)
172 /* Base data type, i.e. scalar */
173 char *attname = strVal(linitial(node->funccolnames));
175 tupdesc = CreateTemplateTupleDesc(1, false);
176 TupleDescInitEntry(tupdesc,
177 (AttrNumber) 1,
178 attname,
179 funcrettype,
183 else if (functypclass == TYPEFUNC_RECORD)
185 tupdesc = BuildDescFromLists(node->funccolnames,
186 node->funccoltypes,
187 node->funccoltypmods);
189 else
191 /* crummy error message, but parser should have caught this */
192 elog(ERROR, "function in FROM has unsupported return type");
196 * For RECORD results, make sure a typmod has been assigned. (The
197 * function should do this for itself, but let's cover things in case it
198 * doesn't.)
200 BlessTupleDesc(tupdesc);
202 scanstate->tupdesc = tupdesc;
203 ExecAssignScanType(&scanstate->ss, tupdesc);
206 * Other node-specific setup
208 scanstate->tuplestorestate = NULL;
209 scanstate->funcexpr = ExecInitExpr((Expr *) node->funcexpr,
210 (PlanState *) scanstate);
212 scanstate->ss.ps.ps_TupFromTlist = false;
215 * Initialize result tuple type and projection info.
217 ExecAssignResultTypeFromTL(&scanstate->ss.ps);
218 ExecAssignScanProjectionInfo(&scanstate->ss);
220 return scanstate;
224 ExecCountSlotsFunctionScan(FunctionScan *node)
226 return ExecCountSlotsNode(outerPlan(node)) +
227 ExecCountSlotsNode(innerPlan(node)) +
228 FUNCTIONSCAN_NSLOTS;
231 /* ----------------------------------------------------------------
232 * ExecEndFunctionScan
234 * frees any storage allocated through C routines.
235 * ----------------------------------------------------------------
237 void
238 ExecEndFunctionScan(FunctionScanState *node)
241 * Free the exprcontext
243 ExecFreeExprContext(&node->ss.ps);
246 * clean out the tuple table
248 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
249 ExecClearTuple(node->ss.ss_ScanTupleSlot);
252 * Release tuplestore resources
254 if (node->tuplestorestate != NULL)
255 tuplestore_end(node->tuplestorestate);
256 node->tuplestorestate = NULL;
259 /* ----------------------------------------------------------------
260 * ExecFunctionReScan
262 * Rescans the relation.
263 * ----------------------------------------------------------------
265 void
266 ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt)
268 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
269 node->ss.ps.ps_TupFromTlist = false;
272 * If we haven't materialized yet, just return.
274 if (!node->tuplestorestate)
275 return;
278 * Here we have a choice whether to drop the tuplestore (and recompute the
279 * function outputs) or just rescan it. We must recompute if the
280 * expression contains parameters, else we rescan. XXX maybe we should
281 * recompute if the function is volatile?
283 if (node->ss.ps.chgParam != NULL)
285 tuplestore_end(node->tuplestorestate);
286 node->tuplestorestate = NULL;
288 else
289 tuplestore_rescan(node->tuplestorestate);