diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/functions.c | 70 |
1 files changed, 25 insertions, 45 deletions
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 278960b4970..9dd97b79ffa 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.108 2006/10/12 17:02:24 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.108.2.1 2007/02/02 00:03:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -61,7 +61,7 @@ typedef struct { Oid *argtypes; /* resolved types of arguments */ Oid rettype; /* actual return type */ - int typlen; /* length of the return type */ + int16 typlen; /* length of the return type */ bool typbyval; /* true if return type is pass by value */ bool returnsTuple; /* true if returning whole tuple result */ bool shutdown_reg; /* true if registered shutdown callback */ @@ -151,12 +151,9 @@ init_sql_fcache(FmgrInfo *finfo) Oid foid = finfo->fn_oid; Oid rettype; HeapTuple procedureTuple; - HeapTuple typeTuple; Form_pg_proc procedureStruct; - Form_pg_type typeStruct; SQLFunctionCachePtr fcache; Oid *argOidVect; - bool haspolyarg; char *src; int nargs; List *queryTree_list; @@ -193,35 +190,17 @@ init_sql_fcache(FmgrInfo *finfo) fcache->rettype = rettype; + /* Fetch the typlen and byval info for the result type */ + get_typlenbyval(rettype, &fcache->typlen, &fcache->typbyval); + /* Remember if function is STABLE/IMMUTABLE */ fcache->readonly_func = (procedureStruct->provolatile != PROVOLATILE_VOLATILE); - /* Now look up the actual result type */ - typeTuple = SearchSysCache(TYPEOID, - ObjectIdGetDatum(rettype), - 0, 0, 0); - if (!HeapTupleIsValid(typeTuple)) - elog(ERROR, "cache lookup failed for type %u", rettype); - typeStruct = (Form_pg_type) GETSTRUCT(typeTuple); - - /* - * get the type length and by-value flag from the type tuple; also do a - * preliminary check for returnsTuple (this may prove inaccurate, see - * below). - */ - fcache->typlen = typeStruct->typlen; - fcache->typbyval = typeStruct->typbyval; - fcache->returnsTuple = (typeStruct->typtype == 'c' || - rettype == RECORDOID); - /* - * Parse and rewrite the queries. We need the argument type info to pass - * to the parser. + * We need the actual argument types to pass to the parser. */ nargs = procedureStruct->pronargs; - haspolyarg = false; - if (nargs > 0) { int argnum; @@ -244,7 +223,6 @@ init_sql_fcache(FmgrInfo *finfo) errmsg("could not determine actual type of argument declared %s", format_type_be(argOidVect[argnum])))); argOidVect[argnum] = argtype; - haspolyarg = true; } } } @@ -252,6 +230,9 @@ init_sql_fcache(FmgrInfo *finfo) argOidVect = NULL; fcache->argtypes = argOidVect; + /* + * Parse and rewrite the queries in the function text. + */ tmp = SysCacheGetAttr(PROCOID, procedureTuple, Anum_pg_proc_prosrc, @@ -263,24 +244,25 @@ init_sql_fcache(FmgrInfo *finfo) queryTree_list = pg_parse_and_rewrite(src, argOidVect, nargs); /* - * If the function has any arguments declared as polymorphic types, then - * it wasn't type-checked at definition time; must do so now. + * Check that the function returns the type it claims to. Although + * in simple cases this was already done when the function was defined, + * we have to recheck because database objects used in the function's + * queries might have changed type. We'd have to do it anyway if the + * function had any polymorphic arguments. * - * Also, force a type-check if the declared return type is a rowtype; we - * need to find out whether we are actually returning the whole tuple - * result, or just regurgitating a rowtype expression result. In the + * Note: we set fcache->returnsTuple according to whether we are + * returning the whole tuple result or just a single column. In the * latter case we clear returnsTuple because we need not act different - * from the scalar result case. + * from the scalar result case, even if it's a rowtype column. * * In the returnsTuple case, check_sql_fn_retval will also construct a * JunkFilter we can use to coerce the returned rowtype to the desired * form. */ - if (haspolyarg || fcache->returnsTuple) - fcache->returnsTuple = check_sql_fn_retval(foid, - rettype, - queryTree_list, - &fcache->junkFilter); + fcache->returnsTuple = check_sql_fn_retval(foid, + rettype, + queryTree_list, + &fcache->junkFilter); /* Finally, plan the queries */ fcache->func_state = init_execution_state(queryTree_list, @@ -288,7 +270,6 @@ init_sql_fcache(FmgrInfo *finfo) pfree(src); - ReleaseSysCache(typeTuple); ReleaseSysCache(procedureTuple); finfo->fn_extra = (void *) fcache; @@ -858,11 +839,10 @@ ShutdownSQLFunction(Datum arg) * the final query in the function. We do some ad-hoc type checking here * to be sure that the user is returning the type he claims. * - * This is normally applied during function definition, but in the case - * of a function with polymorphic arguments, we instead apply it during - * function execution startup. The rettype is then the actual resolved - * output type of the function, rather than the declared type. (Therefore, - * we should never see ANYARRAY or ANYELEMENT as rettype.) + * For a polymorphic function the passed rettype must be the actual resolved + * output type of the function; we should never see ANYARRAY or ANYELEMENT + * as rettype. (This means we can't check the type during function definition + * of a polymorphic function.) * * The return value is true if the function returns the entire tuple result * of its final SELECT, and false otherwise. Note that because we allow |