]> granicus.if.org Git - postgresql/commitdiff
Move plpgsql's fetchArgInfo() into funcapi.c, and rename to
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 28 Dec 2005 18:11:25 +0000 (18:11 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 28 Dec 2005 18:11:25 +0000 (18:11 +0000)
get_func_arg_info() for consistency with other names there.
This code will probably be useful to other PLs when they start to
support OUT parameters, so better to have it in the main backend.
Also, fix plpgsql validator to detect bogus OUT parameters even when
check_function_bodies is off.

src/backend/utils/fmgr/funcapi.c
src/include/funcapi.h
src/pl/plpgsql/src/pl_comp.c
src/pl/plpgsql/src/pl_handler.c

index b545928d9b9536711f50330c784a8a0d41ea9937..b450b2ee546dd5facaeddab4b1088a9c4d9f79a6 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 2002-2005, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.27 2005/11/17 22:14:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.28 2005/12/28 18:11:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -628,6 +628,109 @@ get_type_func_class(Oid typid)
 }
 
 
+/*
+ * get_func_arg_info
+ *
+ * Fetch info about the argument types, names, and IN/OUT modes from the
+ * pg_proc tuple.  Return value is the total number of arguments.
+ * Other results are palloc'd.  *p_argtypes is always filled in, but
+ * *p_argnames and *p_argmodes will be set NULL in the default cases
+ * (no names, and all IN arguments, respectively).
+ *
+ * Note that this function simply fetches what is in the pg_proc tuple;
+ * it doesn't do any interpretation of polymorphic types.
+ */
+int
+get_func_arg_info(HeapTuple procTup,
+                                 Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
+{
+       Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
+       Datum           proallargtypes;
+       Datum           proargmodes;
+       Datum           proargnames;
+       bool            isNull;
+       ArrayType  *arr;
+       int                     numargs;
+       Datum      *elems;
+       int                     nelems;
+       int                     i;
+
+       /* First discover the total number of parameters and get their types */
+       proallargtypes = SysCacheGetAttr(PROCOID, procTup,
+                                                                        Anum_pg_proc_proallargtypes,
+                                                                        &isNull);
+       if (!isNull)
+       {
+               /*
+                * We expect the arrays to be 1-D arrays of the right types; verify
+                * that.  For the OID and char arrays, we don't need to use
+                * deconstruct_array() since the array data is just going to look like
+                * a C array of values.
+                */
+               arr = DatumGetArrayTypeP(proallargtypes);               /* ensure not toasted */
+               numargs = ARR_DIMS(arr)[0];
+               if (ARR_NDIM(arr) != 1 ||
+                       numargs < 0 ||
+                       ARR_HASNULL(arr) ||
+                       ARR_ELEMTYPE(arr) != OIDOID)
+                       elog(ERROR, "proallargtypes is not a 1-D Oid array");
+               Assert(numargs >= procStruct->pronargs);
+               *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
+               memcpy(*p_argtypes, ARR_DATA_PTR(arr),
+                          numargs * sizeof(Oid));
+       }
+       else
+       {
+               /* If no proallargtypes, use proargtypes */
+               numargs = procStruct->proargtypes.dim1;
+               Assert(numargs == procStruct->pronargs);
+               *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
+               memcpy(*p_argtypes, procStruct->proargtypes.values,
+                          numargs * sizeof(Oid));
+       }
+
+       /* Get argument names, if available */
+       proargnames = SysCacheGetAttr(PROCOID, procTup,
+                                                                 Anum_pg_proc_proargnames,
+                                                                 &isNull);
+       if (isNull)
+               *p_argnames = NULL;
+       else
+       {
+               deconstruct_array(DatumGetArrayTypeP(proargnames),
+                                                 TEXTOID, -1, false, 'i',
+                                                 &elems, NULL, &nelems);
+               if (nelems != numargs)  /* should not happen */
+                       elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
+               *p_argnames = (char **) palloc(sizeof(char *) * numargs);
+               for (i = 0; i < numargs; i++)
+                       (*p_argnames)[i] = DatumGetCString(DirectFunctionCall1(textout,
+                                                                                                                                  elems[i]));
+       }
+
+       /* Get argument modes, if available */
+       proargmodes = SysCacheGetAttr(PROCOID, procTup,
+                                                                 Anum_pg_proc_proargmodes,
+                                                                 &isNull);
+       if (isNull)
+               *p_argmodes = NULL;
+       else
+       {
+               arr = DatumGetArrayTypeP(proargmodes);  /* ensure not toasted */
+               if (ARR_NDIM(arr) != 1 ||
+                       ARR_DIMS(arr)[0] != numargs ||
+                       ARR_HASNULL(arr) ||
+                       ARR_ELEMTYPE(arr) != CHAROID)
+                       elog(ERROR, "proargmodes is not a 1-D char array");
+               *p_argmodes = (char *) palloc(numargs * sizeof(char));
+               memcpy(*p_argmodes, ARR_DATA_PTR(arr),
+                          numargs * sizeof(char));
+       }
+
+       return numargs;
+}
+
+
 /*
  * get_func_result_name
  *
index 1f455d3eeaf6ed490e0fde974a8c9e8e31fb7df5..ccc61dfbf08cd14a511ecfbc1403944f414bc294 100644 (file)
@@ -9,7 +9,7 @@
  *
  * Copyright (c) 2002-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/funcapi.h,v 1.21 2005/11/22 18:17:29 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/funcapi.h,v 1.22 2005/12/28 18:11:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -165,12 +165,16 @@ extern TypeFuncClass get_func_result_type(Oid functionId,
                                         Oid *resultTypeId,
                                         TupleDesc *resultTupleDesc);
 
-extern char *get_func_result_name(Oid functionId);
-
 extern bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes,
                                                         char *argmodes,
                                                         Node *call_expr);
 
+extern int     get_func_arg_info(HeapTuple procTup,
+                                                         Oid **p_argtypes, char ***p_argnames,
+                                                         char **p_argmodes);
+
+extern char *get_func_result_name(Oid functionId);
+
 extern TupleDesc build_function_result_tupdesc_d(Datum proallargtypes,
                                                                Datum proargmodes,
                                                                Datum proargnames);
index b89f975981c7d9a1f7d2275caa676b5bae4a00f3..d9fa1f0e422bb141a54d9ba0a13d265ba7669856 100644 (file)
@@ -3,7 +3,7 @@
  *                       procedural language
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.97 2005/12/09 17:08:49 tgl Exp $
+ *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.98 2005/12/28 18:11:25 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -123,9 +123,6 @@ static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
                   HeapTuple procTup,
                   PLpgSQL_func_hashkey *hashkey,
                   bool forValidator);
-static int fetchArgInfo(HeapTuple procTup,
-                        Oid **p_argtypes, char ***p_argnames,
-                        char **p_argmodes);
 static PLpgSQL_row *build_row_from_class(Oid classOid);
 static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
 static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
@@ -358,7 +355,8 @@ do_compile(FunctionCallInfo fcinfo,
                         */
                        MemoryContextSwitchTo(compile_tmp_cxt);
 
-                       numargs = fetchArgInfo(procTup, &argtypes, &argnames, &argmodes);
+                       numargs = get_func_arg_info(procTup,
+                                                                               &argtypes, &argnames, &argmodes);
 
                        plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
                                                                                                 fcinfo->flinfo->fn_expr,
@@ -751,102 +749,6 @@ plpgsql_compile_error_callback(void *arg)
 }
 
 
-/*
- * Fetch info about the argument types, names, and IN/OUT modes from the
- * pg_proc tuple.  Return value is the number of arguments.
- * Other results are palloc'd.
- */
-static int
-fetchArgInfo(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames,
-                        char **p_argmodes)
-{
-       Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
-       Datum           proallargtypes;
-       Datum           proargmodes;
-       Datum           proargnames;
-       bool            isNull;
-       ArrayType  *arr;
-       int                     numargs;
-       Datum      *elems;
-       int                     nelems;
-       int                     i;
-
-       /* First discover the total number of parameters and get their types */
-       proallargtypes = SysCacheGetAttr(PROCOID, procTup,
-                                                                        Anum_pg_proc_proallargtypes,
-                                                                        &isNull);
-       if (!isNull)
-       {
-               /*
-                * We expect the arrays to be 1-D arrays of the right types; verify
-                * that.  For the OID and char arrays, we don't need to use
-                * deconstruct_array() since the array data is just going to look like
-                * a C array of values.
-                */
-               arr = DatumGetArrayTypeP(proallargtypes);               /* ensure not toasted */
-               numargs = ARR_DIMS(arr)[0];
-               if (ARR_NDIM(arr) != 1 ||
-                       numargs < 0 ||
-                       ARR_HASNULL(arr) ||
-                       ARR_ELEMTYPE(arr) != OIDOID)
-                       elog(ERROR, "proallargtypes is not a 1-D Oid array");
-               Assert(numargs >= procStruct->pronargs);
-               *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
-               memcpy(*p_argtypes, ARR_DATA_PTR(arr),
-                          numargs * sizeof(Oid));
-       }
-       else
-       {
-               /* If no proallargtypes, use proargtypes */
-               numargs = procStruct->proargtypes.dim1;
-               Assert(numargs == procStruct->pronargs);
-               *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
-               memcpy(*p_argtypes, procStruct->proargtypes.values,
-                          numargs * sizeof(Oid));
-       }
-
-       /* Get argument names, if available */
-       proargnames = SysCacheGetAttr(PROCOID, procTup,
-                                                                 Anum_pg_proc_proargnames,
-                                                                 &isNull);
-       if (isNull)
-               *p_argnames = NULL;
-       else
-       {
-               deconstruct_array(DatumGetArrayTypeP(proargnames),
-                                                 TEXTOID, -1, false, 'i',
-                                                 &elems, NULL, &nelems);
-               if (nelems != numargs)  /* should not happen */
-                       elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
-               *p_argnames = (char **) palloc(sizeof(char *) * numargs);
-               for (i = 0; i < numargs; i++)
-                       (*p_argnames)[i] = DatumGetCString(DirectFunctionCall1(textout,
-                                                                                                                                  elems[i]));
-       }
-
-       /* Get argument modes, if available */
-       proargmodes = SysCacheGetAttr(PROCOID, procTup,
-                                                                 Anum_pg_proc_proargmodes,
-                                                                 &isNull);
-       if (isNull)
-               *p_argmodes = NULL;
-       else
-       {
-               arr = DatumGetArrayTypeP(proargmodes);  /* ensure not toasted */
-               if (ARR_NDIM(arr) != 1 ||
-                       ARR_DIMS(arr)[0] != numargs ||
-                       ARR_HASNULL(arr) ||
-                       ARR_ELEMTYPE(arr) != CHAROID)
-                       elog(ERROR, "proargmodes is not a 1-D char array");
-               *p_argmodes = (char *) palloc(numargs * sizeof(char));
-               memcpy(*p_argmodes, ARR_DATA_PTR(arr),
-                          numargs * sizeof(char));
-       }
-
-       return numargs;
-}
-
-
 /* ----------
  * plpgsql_parse_word          The scanner calls this to postparse
  *                             any single word not found by a
index 69d128e8698316a812423c2160816914fbba0558..59e6acc7893a2722e5c5f603989ab95cef283860 100644 (file)
@@ -3,7 +3,7 @@
  *                       procedural language
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.26 2005/10/15 02:49:50 momjian Exp $
+ *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.27 2005/12/28 18:11:25 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -41,6 +41,7 @@
 #include "access/heapam.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
+#include "funcapi.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
@@ -147,9 +148,11 @@ plpgsql_validator(PG_FUNCTION_ARGS)
        HeapTuple       tuple;
        Form_pg_proc proc;
        char            functyptype;
+       int                     numargs;
+       Oid                *argtypes;
+       char      **argnames;
+       char       *argmodes;
        bool            istrigger = false;
-       bool            haspolyresult;
-       bool            haspolyarg;
        int                     i;
 
        /* perform initialization */
@@ -173,32 +176,30 @@ plpgsql_validator(PG_FUNCTION_ARGS)
                if (proc->prorettype == TRIGGEROID ||
                        (proc->prorettype == OPAQUEOID && proc->pronargs == 0))
                        istrigger = true;
-               else if (proc->prorettype == ANYARRAYOID ||
-                                proc->prorettype == ANYELEMENTOID)
-                       haspolyresult = true;
                else if (proc->prorettype != RECORDOID &&
-                                proc->prorettype != VOIDOID)
+                                proc->prorettype != VOIDOID &&
+                                proc->prorettype != ANYARRAYOID &&
+                                proc->prorettype != ANYELEMENTOID)
                        ereport(ERROR,
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                         errmsg("plpgsql functions cannot return type %s",
                                                        format_type_be(proc->prorettype))));
        }
 
-       /* Disallow pseudotypes in arguments */
+       /* Disallow pseudotypes in arguments (either IN or OUT) */
        /* except for ANYARRAY or ANYELEMENT */
-       haspolyarg = false;
-       for (i = 0; i < proc->pronargs; i++)
+       numargs = get_func_arg_info(tuple,
+                                                               &argtypes, &argnames, &argmodes);
+       for (i = 0; i < numargs; i++)
        {
-               if (get_typtype(proc->proargtypes.values[i]) == 'p')
+               if (get_typtype(argtypes[i]) == 'p')
                {
-                       if (proc->proargtypes.values[i] == ANYARRAYOID ||
-                               proc->proargtypes.values[i] == ANYELEMENTOID)
-                               haspolyarg = true;
-                       else
+                       if (argtypes[i] != ANYARRAYOID &&
+                               argtypes[i] != ANYELEMENTOID)
                                ereport(ERROR,
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                                 errmsg("plpgsql functions cannot take type %s",
-                                                         format_type_be(proc->proargtypes.values[i]))));
+                                                         format_type_be(argtypes[i]))));
                }
        }