diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/executor/functions.c | 74 | ||||
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 24 |
2 files changed, 35 insertions, 63 deletions
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index d08955163e9..9f3a85dbf85 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.91.4.2 2006/10/12 17:02:34 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.91.4.3 2007/02/02 00:03:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -62,7 +62,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 */ @@ -152,12 +152,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; @@ -194,35 +191,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; @@ -245,7 +224,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; } } } @@ -253,6 +231,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, @@ -264,24 +245,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 + * 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(rettype, - get_typtype(rettype), - queryTree_list, - &fcache->junkFilter); + fcache->returnsTuple = check_sql_fn_retval(rettype, + get_typtype(rettype), + queryTree_list, + &fcache->junkFilter); /* Finally, plan the queries */ fcache->func_state = init_execution_state(queryTree_list, @@ -289,7 +271,6 @@ init_sql_fcache(FmgrInfo *finfo) pfree(src); - ReleaseSysCache(typeTuple); ReleaseSysCache(procedureTuple); finfo->fn_extra = (void *) fcache; @@ -862,11 +843,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 diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 2c1b43266f8..66b6df85dff 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.186.4.4 2005/04/14 21:44:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.186.4.5 2007/02/02 00:03:44 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -2138,7 +2138,6 @@ inline_function(Oid funcid, Oid result_type, List *args, eval_const_expressions_context *context) { Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple); - bool polymorphic = false; Oid argtypes[FUNC_MAX_ARGS]; char *src; Datum tmp; @@ -2179,15 +2178,10 @@ inline_function(Oid funcid, Oid result_type, List *args, if (argtypes[i] == ANYARRAYOID || argtypes[i] == ANYELEMENTOID) { - polymorphic = true; argtypes[i] = exprType((Node *) list_nth(args, i)); } } - if (funcform->prorettype == ANYARRAYOID || - funcform->prorettype == ANYELEMENTOID) - polymorphic = true; - /* * Setup error traceback support for ereport(). This is so that we * can finger the function that bad information came from. @@ -2260,16 +2254,14 @@ inline_function(Oid funcid, Oid result_type, List *args, newexpr = (Node *) ((TargetEntry *) linitial(querytree->targetList))->expr; /* - * If the function has any arguments declared as polymorphic types, - * then it wasn't type-checked at definition time; must do so now. - * (This will raise an error if wrong, but that's okay since the - * function would fail at runtime anyway. Note we do not try this - * until we have verified that no rewriting was needed; that's - * probably not important, but let's be careful.) + * Make sure the function (still) returns what it's declared to. This will + * raise an error if wrong, but that's okay since the function would fail + * at runtime anyway. Note we do not try this until we have verified that + * no rewriting was needed; that's probably not important, but let's be + * careful. */ - if (polymorphic) - (void) check_sql_fn_retval(result_type, get_typtype(result_type), - querytree_list, NULL); + (void) check_sql_fn_retval(result_type, get_typtype(result_type), + querytree_list, NULL); /* * Additional validity checks on the expression. It mustn't return a |