88 *
99 *
1010 * 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 $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -61,7 +61,7 @@ typedef struct
6161{
6262Oid * argtypes ;/* resolved types of arguments */
6363Oid rettype ;/* actual return type */
64- int typlen ;/* length of the return type */
64+ int16 typlen ;/* length of the return type */
6565bool typbyval ;/* true if return type is pass by value */
6666bool returnsTuple ;/* true if returning whole tuple result */
6767bool shutdown_reg ;/* true if registered shutdown callback */
@@ -151,12 +151,9 @@ init_sql_fcache(FmgrInfo *finfo)
151151Oid foid = finfo -> fn_oid ;
152152Oid rettype ;
153153HeapTuple procedureTuple ;
154- HeapTuple typeTuple ;
155154Form_pg_proc procedureStruct ;
156- Form_pg_type typeStruct ;
157155SQLFunctionCachePtr fcache ;
158156Oid * argOidVect ;
159- bool haspolyarg ;
160157char * src ;
161158int nargs ;
162159List * queryTree_list ;
@@ -193,35 +190,17 @@ init_sql_fcache(FmgrInfo *finfo)
193190
194191fcache -> rettype = rettype ;
195192
193+ /* Fetch the typlen and byval info for the result type */
194+ get_typlenbyval (rettype ,& fcache -> typlen ,& fcache -> typbyval );
195+
196196/* Remember if function is STABLE/IMMUTABLE */
197197fcache -> readonly_func =
198198(procedureStruct -> provolatile != PROVOLATILE_VOLATILE );
199199
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-
218200/*
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.
221202 */
222203nargs = procedureStruct -> pronargs ;
223- haspolyarg = false;
224-
225204if (nargs > 0 )
226205{
227206int argnum ;
@@ -244,14 +223,16 @@ init_sql_fcache(FmgrInfo *finfo)
244223errmsg ("could not determine actual type of argument declared %s" ,
245224format_type_be (argOidVect [argnum ]))));
246225argOidVect [argnum ]= argtype ;
247- haspolyarg = true;
248226}
249227}
250228}
251229else
252230argOidVect = NULL ;
253231fcache -> argtypes = argOidVect ;
254232
233+ /*
234+ * Parse and rewrite the queries in the function text.
235+ */
255236tmp = SysCacheGetAttr (PROCOID ,
256237procedureTuple ,
257238Anum_pg_proc_prosrc ,
@@ -263,32 +244,32 @@ init_sql_fcache(FmgrInfo *finfo)
263244queryTree_list = pg_parse_and_rewrite (src ,argOidVect ,nargs );
264245
265246/*
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.
268252 *
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
272255 * 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 .
274257 *
275258 * In the returnsTuple case, check_sql_fn_retval will also construct a
276259 * JunkFilter we can use to coerce the returned rowtype to the desired
277260 * form.
278261 */
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 );
284266
285267/* Finally, plan the queries */
286268fcache -> func_state = init_execution_state (queryTree_list ,
287269fcache -> readonly_func );
288270
289271pfree (src );
290272
291- ReleaseSysCache (typeTuple );
292273ReleaseSysCache (procedureTuple );
293274
294275finfo -> fn_extra = (void * )fcache ;
@@ -858,11 +839,10 @@ ShutdownSQLFunction(Datum arg)
858839 * the final query in the function. We do some ad-hoc type checking here
859840 * to be sure that the user is returning the type he claims.
860841 *
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.)
866846 *
867847 * The return value is true if the function returns the entire tuple result
868848 * of its final SELECT, and false otherwise. Note that because we allow