OSDN Git Service

Support function parameter names in plpgsql. This is the last of
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 7 Jan 2004 06:20:02 +0000 (06:20 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 7 Jan 2004 06:20:02 +0000 (06:20 +0000)
Dennis Bjorklund's original patch for function parameter names, but
there's still plenty left to do (documentation for instance...)

src/pl/plpgsql/src/pl_comp.c

index bcd8a14..b74e07e 100644 (file)
@@ -3,7 +3,7 @@
  *                       procedural language
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.71 2004/01/06 23:55:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.72 2004/01/07 06:20:02 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -54,6 +54,7 @@
 #include "parser/gramparse.h"
 #include "parser/parse_type.h"
 #include "tcop/tcopprot.h"
+#include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/syscache.h"
 
@@ -102,6 +103,7 @@ static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
                   HeapTuple procTup,
                   PLpgSQL_func_hashkey *hashkey);
 static void plpgsql_compile_error_callback(void *arg);
+static char **fetchArgNames(HeapTuple procTup, int nargs);
 static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
 static void compute_function_hashkey(FunctionCallInfo fcinfo,
                                                 Form_pg_proc procStruct,
@@ -248,6 +250,7 @@ do_compile(FunctionCallInfo fcinfo,
        ErrorContextCallback plerrcontext;
        int                     parse_rc;
        Oid                     rettypeid;
+       char      **argnames;
 
        /*
         * Setup the scanner input and error info.      We assume that this
@@ -408,12 +411,16 @@ do_compile(FunctionCallInfo fcinfo,
                        /*
                         * Create the variables for the procedure's parameters
                         */
+                       argnames = fetchArgNames(procTup, procStruct->pronargs);
+
                        for (i = 0; i < procStruct->pronargs; i++)
                        {
                                char            buf[32];
                                Oid                     argtypeid;
+                               PLpgSQL_datum *argdatum;
+                               int                     argitemtype;
 
-                               /* name for variable */
+                               /* Create $n name for variable */
                                snprintf(buf, sizeof(buf), "$%d", i + 1);
 
                                /*
@@ -424,7 +431,7 @@ do_compile(FunctionCallInfo fcinfo,
                                argtypeid = hashkey->argtypes[i];
 
                                /*
-                                * Get the parameters type
+                                * Get the parameter type
                                 */
                                typeTup = SearchSysCache(TYPEOID,
                                                                                 ObjectIdGetDatum(argtypeid),
@@ -448,14 +455,10 @@ do_compile(FunctionCallInfo fcinfo,
                                         * that type
                                         */
                                        row = plpgsql_build_rowtype(typeStruct->typrelid);
-
                                        row->refname = strdup(buf);
 
-                                       plpgsql_adddatum((PLpgSQL_datum *) row);
-                                       plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, row->rowno,
-                                                                          row->refname);
-
-                                       arg_varnos[i] = row->rowno;
+                                       argdatum = (PLpgSQL_datum *) row;
+                                       argitemtype = PLPGSQL_NSTYPE_ROW;
                                }
                                else
                                {
@@ -473,12 +476,22 @@ do_compile(FunctionCallInfo fcinfo,
                                        var->notnull = false;
                                        var->default_val = NULL;
 
-                                       plpgsql_adddatum((PLpgSQL_datum *) var);
-                                       plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno,
-                                                                          var->refname);
-
-                                       arg_varnos[i] = var->varno;
+                                       argdatum = (PLpgSQL_datum *) var;
+                                       argitemtype = PLPGSQL_NSTYPE_VAR;
                                }
+
+                               /* Add it to datum list, and remember datum number */
+                               plpgsql_adddatum(argdatum);
+                               arg_varnos[i] = argdatum->dno;
+
+                               /* Add to namespace under the $n name */
+                               plpgsql_ns_additem(argitemtype, argdatum->dno, buf);
+
+                               /* If there's a name for the argument, make an alias */
+                               if (argnames && argnames[i] && argnames[i][0])
+                                       plpgsql_ns_additem(argitemtype, argdatum->dno,
+                                                                          argnames[i]);
+
                                ReleaseSysCache(typeTup);
                        }
                        break;
@@ -730,6 +743,44 @@ plpgsql_compile_error_callback(void *arg)
 }
 
 
+/*
+ * Fetch the argument names, if any, from the proargnames field of the
+ * pg_proc tuple.  Results are palloc'd.
+ */
+static char **
+fetchArgNames(HeapTuple procTup, int nargs)
+{
+       Datum           argnamesDatum;
+       bool            isNull;
+       Datum      *elems;
+       int                     nelems;
+       char      **result;
+       int                     i;
+
+       if (nargs == 0)
+               return NULL;
+
+       argnamesDatum = SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_proargnames,
+                                                                       &isNull);
+       if (isNull)
+               return NULL;
+
+       deconstruct_array(DatumGetArrayTypeP(argnamesDatum),
+                                         TEXTOID, -1, false, 'i',
+                                         &elems, &nelems);
+
+       if (nelems != nargs)            /* should not happen */
+               elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
+
+       result = (char **) palloc(sizeof(char *) * nargs);
+
+       for (i=0; i < nargs; i++)
+               result[i] = DatumGetCString(DirectFunctionCall1(textout, elems[i]));
+
+       return result;
+}
+
+
 /* ----------
  * plpgsql_parse_word          The scanner calls this to postparse
  *                             any single word not found by a