aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/functions.c')
-rw-r--r--src/backend/executor/functions.c68
1 files changed, 54 insertions, 14 deletions
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index a0e0919fd0b..e0ab9e92d50 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.66 2003/06/12 17:29:26 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.67 2003/07/01 00:04:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,6 +24,7 @@
#include "tcop/tcopprot.h"
#include "tcop/utility.h"
#include "utils/builtins.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -76,7 +77,8 @@ typedef SQLFunctionCache *SQLFunctionCachePtr;
/* non-export function prototypes */
static execution_state *init_execution_state(char *src,
- Oid *argOidVect, int nargs);
+ Oid *argOidVect, int nargs,
+ Oid rettype, bool haspolyarg);
static void init_sql_fcache(FmgrInfo *finfo);
static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
static TupleTableSlot *postquel_getnext(execution_state *es);
@@ -90,7 +92,8 @@ static void ShutdownSQLFunction(Datum arg);
static execution_state *
-init_execution_state(char *src, Oid *argOidVect, int nargs)
+init_execution_state(char *src, Oid *argOidVect, int nargs,
+ Oid rettype, bool haspolyarg)
{
execution_state *firstes;
execution_state *preves;
@@ -99,6 +102,13 @@ init_execution_state(char *src, Oid *argOidVect, int nargs)
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.
+ */
+ if (haspolyarg)
+ check_sql_fn_retval(rettype, get_typtype(rettype), queryTree_list);
+
firstes = NULL;
preves = NULL;
@@ -133,17 +143,21 @@ static void
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;
Datum tmp;
bool isNull;
+ fcache = (SQLFunctionCachePtr) palloc0(sizeof(SQLFunctionCache));
+
/*
* get the procedure tuple corresponding to the given function Oid
*/
@@ -153,30 +167,37 @@ init_sql_fcache(FmgrInfo *finfo)
if (!HeapTupleIsValid(procedureTuple))
elog(ERROR, "init_sql_fcache: Cache lookup failed for procedure %u",
foid);
-
procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
/*
- * get the return type from the procedure tuple
+ * get the result type from the procedure tuple, and check for
+ * polymorphic result type; if so, find out the actual result type.
*/
+ rettype = procedureStruct->prorettype;
+
+ if (rettype == ANYARRAYOID || rettype == ANYELEMENTOID)
+ {
+ rettype = get_fn_expr_rettype(finfo);
+ if (rettype == InvalidOid)
+ elog(ERROR, "could not determine actual result type for function declared %s",
+ format_type_be(procedureStruct->prorettype));
+ }
+
+ /* Now look up the actual result type */
typeTuple = SearchSysCache(TYPEOID,
- ObjectIdGetDatum(procedureStruct->prorettype),
+ ObjectIdGetDatum(rettype),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "init_sql_fcache: Cache lookup failed for type %u",
- procedureStruct->prorettype);
-
+ rettype);
typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
- fcache = (SQLFunctionCachePtr) palloc0(sizeof(SQLFunctionCache));
-
/*
* get the type length and by-value flag from the type tuple
*/
fcache->typlen = typeStruct->typlen;
- if (typeStruct->typtype != 'c' &&
- procedureStruct->prorettype != RECORDOID)
+ if (typeStruct->typtype != 'c' && rettype != RECORDOID)
{
/* The return type is not a composite type, so just use byval */
fcache->typbyval = typeStruct->typbyval;
@@ -205,17 +226,35 @@ init_sql_fcache(FmgrInfo *finfo)
fcache->funcSlot = NULL;
/*
- * Parse and plan the queries. We need the argument info to pass
+ * Parse and plan the queries. We need the argument type info to pass
* to the parser.
*/
nargs = procedureStruct->pronargs;
+ haspolyarg = false;
if (nargs > 0)
{
+ int argnum;
+
argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
memcpy(argOidVect,
procedureStruct->proargtypes,
nargs * sizeof(Oid));
+ /* Resolve any polymorphic argument types */
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+ Oid argtype = argOidVect[argnum];
+
+ if (argtype == ANYARRAYOID || argtype == ANYELEMENTOID)
+ {
+ argtype = get_fn_expr_argtype(finfo, argnum);
+ if (argtype == InvalidOid)
+ elog(ERROR, "could not determine actual type of argument declared %s",
+ format_type_be(argOidVect[argnum]));
+ argOidVect[argnum] = argtype;
+ haspolyarg = true;
+ }
+ }
}
else
argOidVect = (Oid *) NULL;
@@ -229,7 +268,8 @@ init_sql_fcache(FmgrInfo *finfo)
foid);
src = DatumGetCString(DirectFunctionCall1(textout, tmp));
- fcache->func_state = init_execution_state(src, argOidVect, nargs);
+ fcache->func_state = init_execution_state(src, argOidVect, nargs,
+ rettype, haspolyarg);
pfree(src);