Teach pg_dump about OUT parameters.
authorTom Lane
Fri, 1 Apr 2005 18:35:41 +0000 (18:35 +0000)
committerTom Lane
Fri, 1 Apr 2005 18:35:41 +0000 (18:35 +0000)
src/bin/pg_dump/pg_dump.c

index f4e7c6e5f1f0eacc475edc0821449084048adbc3..92ab99d01add5c1fec27b503206ddf89ebda21c3 100644 (file)
@@ -12,7 +12,7 @@
  * by PostgreSQL
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.404 2005/03/14 18:57:33 tgl Exp $
+ *   $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.405 2005/04/01 18:35:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -150,8 +150,11 @@ static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
 static void getDependencies(void);
 static void getDomainConstraints(TypeInfo *tinfo);
 static void getTableData(TableInfo *tblinfo, int numTables, bool oids);
-static char *format_function_signature(FuncInfo *finfo, char **argnames,
-                         bool honor_quotes);
+static char *format_function_arguments(FuncInfo *finfo, int nallargs,
+                         char **allargtypes,
+                         char **argmodes,
+                         char **argnames);
+static char *format_function_signature(FuncInfo *finfo, bool honor_quotes);
 static const char *convertRegProcReference(const char *proc);
 static const char *convertOperatorReference(const char *opr);
 static Oid findLastBuiltinOid_V71(const char *);
@@ -5060,38 +5063,63 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 }
 
 /*
- * format_function_signature: generate function name and argument list
+ * format_function_arguments: generate function name and argument list
  *
  * The argument type names are qualified if needed.  The function name
  * is never qualified.
  *
- * argnames may be NULL if no names are available.
+ * Any or all of allargtypes, argmodes, argnames may be NULL.
  */
 static char *
-format_function_signature(FuncInfo *finfo, char **argnames,
-                         bool honor_quotes)
+format_function_arguments(FuncInfo *finfo, int nallargs,
+                         char **allargtypes,
+                         char **argmodes,
+                         char **argnames)
 {
    PQExpBufferData fn;
    int         j;
 
    initPQExpBuffer(&fn);
-   if (honor_quotes)
-       appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
-   else
-       appendPQExpBuffer(&fn, "%s(", finfo->dobj.name);
-   for (j = 0; j < finfo->nargs; j++)
+   appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
+   for (j = 0; j < nallargs; j++)
    {
+       Oid         typid;
        char       *typname;
-       char       *argname;
+       const char *argmode;
+       const char *argname;
 
-       typname = getFormattedTypeName(finfo->argtypes[j], zeroAsOpaque);
+       typid = allargtypes ? atooid(allargtypes[j]) : finfo->argtypes[j];
+       typname = getFormattedTypeName(typid, zeroAsOpaque);
+
+       if (argmodes)
+       {
+           switch (argmodes[j][0])
+           {
+               case 'i':
+                   argmode = "";
+                   break;
+               case 'o':
+                   argmode = "OUT ";
+                   break;
+               case 'b':
+                   argmode = "INOUT ";
+                   break;
+               default:
+                   write_msg(NULL, "WARNING: bogus value in proargmodes array\n");
+                   argmode = "";
+                   break;
+           }
+       }
+       else
+           argmode = "";
 
        argname = argnames ? argnames[j] : (char *) NULL;
        if (argname && argname[0] == '\0')
            argname = NULL;
 
-       appendPQExpBuffer(&fn, "%s%s%s%s",
+       appendPQExpBuffer(&fn, "%s%s%s%s%s",
                          (j > 0) ? ", " : "",
+                         argmode,
                          argname ? fmtId(argname) : "",
                          argname ? " " : "",
                          typname);
@@ -5101,6 +5129,42 @@ format_function_signature(FuncInfo *finfo, char **argnames,
    return fn.data;
 }
 
+/*
+ * format_function_signature: generate function name and argument list
+ *
+ * This is like format_function_arguments except that only a minimal
+ * list of input argument types is generated; this is sufficient to
+ * reference the function, but not to define it.
+ *
+ * If honor_quotes is false then the function name is never quoted.
+ * This is appropriate for use in TOC tags, but not in SQL commands.
+ */
+static char *
+format_function_signature(FuncInfo *finfo, bool honor_quotes)
+{
+   PQExpBufferData fn;
+   int         j;
+
+   initPQExpBuffer(&fn);
+   if (honor_quotes)
+       appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
+   else
+       appendPQExpBuffer(&fn, "%s(", finfo->dobj.name);
+   for (j = 0; j < finfo->nargs; j++)
+   {
+       char       *typname;
+
+       typname = getFormattedTypeName(finfo->argtypes[j], zeroAsOpaque);
+
+       appendPQExpBuffer(&fn, "%s%s",
+                         (j > 0) ? ", " : "",
+                         typname);
+       free(typname);
+   }
+   appendPQExpBuffer(&fn, ")");
+   return fn.data;
+}
+
 
 /*
  * dumpFunc:
@@ -5120,13 +5184,18 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
    char       *proretset;
    char       *prosrc;
    char       *probin;
+   char       *proallargtypes;
+   char       *proargmodes;
    char       *proargnames;
    char       *provolatile;
    char       *proisstrict;
    char       *prosecdef;
    char       *lanname;
    char       *rettypename;
-   char      **argnamearray = NULL;
+   int         nallargs;
+   char      **allargtypes = NULL;
+   char      **argmodes = NULL;
+   char      **argnames = NULL;
 
    /* Dump only funcs in dumpable namespaces */
    if (!finfo->dobj.namespace->dump || dataOnly)
@@ -5141,10 +5210,23 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
    selectSourceSchema(finfo->dobj.namespace->dobj.name);
 
    /* Fetch function-specific details */
-   if (g_fout->remoteVersion >= 80000)
+   if (g_fout->remoteVersion >= 80100)
+   {
+       appendPQExpBuffer(query,
+                         "SELECT proretset, prosrc, probin, "
+                         "proallargtypes, proargmodes, proargnames, "
+                         "provolatile, proisstrict, prosecdef, "
+                         "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
+                         "FROM pg_catalog.pg_proc "
+                         "WHERE oid = '%u'::pg_catalog.oid",
+                         finfo->dobj.catId.oid);
+   }
+   else if (g_fout->remoteVersion >= 80000)
    {
        appendPQExpBuffer(query,
                          "SELECT proretset, prosrc, probin, "
+                         "null::text as proallargtypes, "
+                         "null::text as proargmodes, "
                          "proargnames, "
                          "provolatile, proisstrict, prosecdef, "
                          "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
@@ -5156,6 +5238,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
    {
        appendPQExpBuffer(query,
                          "SELECT proretset, prosrc, probin, "
+                         "null::text as proallargtypes, "
+                         "null::text as proargmodes, "
                          "null::text as proargnames, "
                          "provolatile, proisstrict, prosecdef, "
                          "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
@@ -5167,6 +5251,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
    {
        appendPQExpBuffer(query,
                          "SELECT proretset, prosrc, probin, "
+                         "null::text as proallargtypes, "
+                         "null::text as proargmodes, "
                          "null::text as proargnames, "
         "case when proiscachable then 'i' else 'v' end as provolatile, "
                          "proisstrict, "
@@ -5180,6 +5266,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
    {
        appendPQExpBuffer(query,
                          "SELECT proretset, prosrc, probin, "
+                         "null::text as proallargtypes, "
+                         "null::text as proargmodes, "
                          "null::text as proargnames, "
         "case when proiscachable then 'i' else 'v' end as provolatile, "
                          "'f'::boolean as proisstrict, "
@@ -5205,6 +5293,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
    proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset"));
    prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
    probin = PQgetvalue(res, 0, PQfnumber(res, "probin"));
+   proallargtypes = PQgetvalue(res, 0, PQfnumber(res, "proallargtypes"));
+   proargmodes = PQgetvalue(res, 0, PQfnumber(res, "proargmodes"));
    proargnames = PQgetvalue(res, 0, PQfnumber(res, "proargnames"));
    provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
    proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
@@ -5246,22 +5336,55 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        }
    }
 
+   nallargs = finfo->nargs;    /* unless we learn different from allargs */
+
+   if (proallargtypes && *proallargtypes)
+   {
+       int         nitems = 0;
+
+       if (!parsePGArray(proallargtypes, &allargtypes, &nitems) ||
+           nitems < finfo->nargs)
+       {
+           write_msg(NULL, "WARNING: could not parse proallargtypes array\n");
+           if (allargtypes)
+               free(allargtypes);
+           allargtypes = NULL;
+       }
+       else
+           nallargs = nitems;
+   }
+
+   if (proargmodes && *proargmodes)
+   {
+       int         nitems = 0;
+
+       if (!parsePGArray(proargmodes, &argmodes, &nitems) ||
+           nitems != nallargs)
+       {
+           write_msg(NULL, "WARNING: could not parse proargmodes array\n");
+           if (argmodes)
+               free(argmodes);
+           argmodes = NULL;
+       }
+   }
+
    if (proargnames && *proargnames)
    {
        int         nitems = 0;
 
-       if (!parsePGArray(proargnames, &argnamearray, &nitems) ||
-           nitems != finfo->nargs)
+       if (!parsePGArray(proargnames, &argnames, &nitems) ||
+           nitems != nallargs)
        {
            write_msg(NULL, "WARNING: could not parse proargnames array\n");
-           if (argnamearray)
-               free(argnamearray);
-           argnamearray = NULL;
+           if (argnames)
+               free(argnames);
+           argnames = NULL;
        }
    }
 
-   funcsig = format_function_signature(finfo, argnamearray, true);
-   funcsig_tag = format_function_signature(finfo, NULL, false);
+   funcsig = format_function_arguments(finfo, nallargs, allargtypes,
+                                       argmodes, argnames);
+   funcsig_tag = format_function_signature(finfo, false);
 
    /*
     * DROP must be fully qualified in case same name appears in
@@ -5333,8 +5456,12 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
    destroyPQExpBuffer(asPart);
    free(funcsig);
    free(funcsig_tag);
-   if (argnamearray)
-       free(argnamearray);
+   if (allargtypes)
+       free(allargtypes);
+   if (argmodes)
+       free(argmodes);
+   if (argnames)
+       free(argnames);
 }
 
 
@@ -5432,7 +5559,7 @@ dumpCast(Archive *fout, CastInfo *cast)
        appendPQExpBuffer(defqry, "WITH FUNCTION %s.",
                          fmtId(funcInfo->dobj.namespace->dobj.name));
        appendPQExpBuffer(defqry, "%s",
-                       format_function_signature(funcInfo, NULL, true));
+                         format_function_signature(funcInfo, true));
    }
 
    if (cast->castcontext == 'a')
@@ -6380,8 +6507,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
    free(aggsig);
    free(aggsig_tag);
 
-   aggsig = format_function_signature(&agginfo->aggfn, NULL, true);
-   aggsig_tag = format_function_signature(&agginfo->aggfn, NULL, false);
+   aggsig = format_function_signature(&agginfo->aggfn, true);
+   aggsig_tag = format_function_signature(&agginfo->aggfn, false);
 
    dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
            "FUNCTION",