8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.109 2007/01/05 22:19:27 momjian Exp $
11
+ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.110 2007/02/02 00:02:55 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -61,7 +61,7 @@ typedef struct
61
61
{
62
62
Oid * argtypes ; /* resolved types of arguments */
63
63
Oid rettype ; /* actual return type */
64
- int typlen ; /* length of the return type */
64
+ int16 typlen ; /* length of the return type */
65
65
bool typbyval ; /* true if return type is pass by value */
66
66
bool returnsTuple ; /* true if returning whole tuple result */
67
67
bool shutdown_reg ; /* true if registered shutdown callback */
@@ -151,12 +151,9 @@ init_sql_fcache(FmgrInfo *finfo)
151
151
Oid foid = finfo -> fn_oid ;
152
152
Oid rettype ;
153
153
HeapTuple procedureTuple ;
154
- HeapTuple typeTuple ;
155
154
Form_pg_proc procedureStruct ;
156
- Form_pg_type typeStruct ;
157
155
SQLFunctionCachePtr fcache ;
158
156
Oid * argOidVect ;
159
- bool haspolyarg ;
160
157
char * src ;
161
158
int nargs ;
162
159
List * queryTree_list ;
@@ -193,35 +190,17 @@ init_sql_fcache(FmgrInfo *finfo)
193
190
194
191
fcache -> rettype = rettype ;
195
192
193
+ /* Fetch the typlen and byval info for the result type */
194
+ get_typlenbyval (rettype , & fcache -> typlen , & fcache -> typbyval );
195
+
196
196
/* Remember if function is STABLE/IMMUTABLE */
197
197
fcache -> readonly_func =
198
198
(procedureStruct -> provolatile != PROVOLATILE_VOLATILE );
199
199
200
- /* Now look up the actual result type */
201
- typeTuple = SearchSysCache (TYPEOID ,
202
- ObjectIdGetDatum (rettype ),
203
- 0 , 0 , 0 );
204
- if (!HeapTupleIsValid (typeTuple ))
205
- elog (ERROR , "cache lookup failed for type %u" , rettype );
206
- typeStruct = (Form_pg_type ) GETSTRUCT (typeTuple );
207
-
208
- /*
209
- * get the type length and by-value flag from the type tuple; also do a
210
- * preliminary check for returnsTuple (this may prove inaccurate, see
211
- * below).
212
- */
213
- fcache -> typlen = typeStruct -> typlen ;
214
- fcache -> typbyval = typeStruct -> typbyval ;
215
- fcache -> returnsTuple = (typeStruct -> typtype == 'c' ||
216
- rettype == RECORDOID );
217
-
218
200
/*
219
- * Parse and rewrite the queries. We need the argument type info to pass
220
- * to the parser.
201
+ * We need the actual argument types to pass to the parser.
221
202
*/
222
203
nargs = procedureStruct -> pronargs ;
223
- haspolyarg = false;
224
-
225
204
if (nargs > 0 )
226
205
{
227
206
int argnum ;
@@ -244,14 +223,16 @@ init_sql_fcache(FmgrInfo *finfo)
244
223
errmsg ("could not determine actual type of argument declared %s" ,
245
224
format_type_be (argOidVect [argnum ]))));
246
225
argOidVect [argnum ] = argtype ;
247
- haspolyarg = true;
248
226
}
249
227
}
250
228
}
251
229
else
252
230
argOidVect = NULL ;
253
231
fcache -> argtypes = argOidVect ;
254
232
233
+ /*
234
+ * Parse and rewrite the queries in the function text.
235
+ */
255
236
tmp = SysCacheGetAttr (PROCOID ,
256
237
procedureTuple ,
257
238
Anum_pg_proc_prosrc ,
@@ -263,32 +244,32 @@ init_sql_fcache(FmgrInfo *finfo)
263
244
queryTree_list = pg_parse_and_rewrite (src , argOidVect , nargs );
264
245
265
246
/*
266
- * If the function has any arguments declared as polymorphic types, then
267
- * it wasn't type-checked at definition time; must do so now.
247
+ * Check that the function returns the type it claims to. Although
248
+ * in simple cases this was already done when the function was defined,
249
+ * we have to recheck because database objects used in the function's
250
+ * queries might have changed type. We'd have to do it anyway if the
251
+ * function had any polymorphic arguments.
268
252
*
269
- * Also, force a type-check if the declared return type is a rowtype; we
270
- * need to find out whether we are actually returning the whole tuple
271
- * result, or just regurgitating a rowtype expression result. In the
253
+ * Note: we set fcache->returnsTuple according to whether we are
254
+ * returning the whole tuple result or just a single column. In the
272
255
* latter case we clear returnsTuple because we need not act different
273
- * from the scalar result case.
256
+ * from the scalar result case, even if it's a rowtype column .
274
257
*
275
258
* In the returnsTuple case, check_sql_fn_retval will also construct a
276
259
* JunkFilter we can use to coerce the returned rowtype to the desired
277
260
* form.
278
261
*/
279
- if (haspolyarg || fcache -> returnsTuple )
280
- fcache -> returnsTuple = check_sql_fn_retval (foid ,
281
- rettype ,
282
- queryTree_list ,
283
- & fcache -> junkFilter );
262
+ fcache -> returnsTuple = check_sql_fn_retval (foid ,
263
+ rettype ,
264
+ queryTree_list ,
265
+ & fcache -> junkFilter );
284
266
285
267
/* Finally, plan the queries */
286
268
fcache -> func_state = init_execution_state (queryTree_list ,
287
269
fcache -> readonly_func );
288
270
289
271
pfree (src );
290
272
291
- ReleaseSysCache (typeTuple );
292
273
ReleaseSysCache (procedureTuple );
293
274
294
275
finfo -> fn_extra = (void * ) fcache ;
@@ -858,11 +839,10 @@ ShutdownSQLFunction(Datum arg)
858
839
* the final query in the function. We do some ad-hoc type checking here
859
840
* to be sure that the user is returning the type he claims.
860
841
*
861
- * This is normally applied during function definition, but in the case
862
- * of a function with polymorphic arguments, we instead apply it during
863
- * function execution startup. The rettype is then the actual resolved
864
- * output type of the function, rather than the declared type. (Therefore,
865
- * we should never see ANYARRAY or ANYELEMENT as rettype.)
842
+ * For a polymorphic function the passed rettype must be the actual resolved
843
+ * output type of the function; we should never see ANYARRAY or ANYELEMENT
844
+ * as rettype. (This means we can't check the type during function definition
845
+ * of a polymorphic function.)
866
846
*
867
847
* The return value is true if the function returns the entire tuple result
868
848
* of its final SELECT, and false otherwise. Note that because we allow
0 commit comments