From a8e0dff10117bf8227394e6db61e606f9eea9164 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 1 Apr 2005 18:35:41 +0000 Subject: [PATCH] Teach pg_dump about OUT parameters. --- src/bin/pg_dump/pg_dump.c | 185 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 156 insertions(+), 29 deletions(-) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index f4e7c6e5f1..92ab99d01a 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -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", -- 2.11.0