Commit a8e0dff1 authored by Tom Lane's avatar Tom Lane

Teach pg_dump about OUT parameters.

parent d1dcaed4
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * 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, ...@@ -150,8 +150,11 @@ static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
static void getDependencies(void); static void getDependencies(void);
static void getDomainConstraints(TypeInfo *tinfo); static void getDomainConstraints(TypeInfo *tinfo);
static void getTableData(TableInfo *tblinfo, int numTables, bool oids); static void getTableData(TableInfo *tblinfo, int numTables, bool oids);
static char *format_function_signature(FuncInfo *finfo, char **argnames, static char *format_function_arguments(FuncInfo *finfo, int nallargs,
bool honor_quotes); 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 *convertRegProcReference(const char *proc);
static const char *convertOperatorReference(const char *opr); static const char *convertOperatorReference(const char *opr);
static Oid findLastBuiltinOid_V71(const char *); static Oid findLastBuiltinOid_V71(const char *);
...@@ -5060,38 +5063,63 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang) ...@@ -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 * The argument type names are qualified if needed. The function name
* is never qualified. * is never qualified.
* *
* argnames may be NULL if no names are available. * Any or all of allargtypes, argmodes, argnames may be NULL.
*/ */
static char * static char *
format_function_signature(FuncInfo *finfo, char **argnames, format_function_arguments(FuncInfo *finfo, int nallargs,
bool honor_quotes) char **allargtypes,
char **argmodes,
char **argnames)
{ {
PQExpBufferData fn; PQExpBufferData fn;
int j; int j;
initPQExpBuffer(&fn); initPQExpBuffer(&fn);
if (honor_quotes) appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name)); for (j = 0; j < nallargs; j++)
else
appendPQExpBuffer(&fn, "%s(", finfo->dobj.name);
for (j = 0; j < finfo->nargs; j++)
{ {
Oid typid;
char *typname; 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; argname = argnames ? argnames[j] : (char *) NULL;
if (argname && argname[0] == '\0') if (argname && argname[0] == '\0')
argname = NULL; argname = NULL;
appendPQExpBuffer(&fn, "%s%s%s%s", appendPQExpBuffer(&fn, "%s%s%s%s%s",
(j > 0) ? ", " : "", (j > 0) ? ", " : "",
argmode,
argname ? fmtId(argname) : "", argname ? fmtId(argname) : "",
argname ? " " : "", argname ? " " : "",
typname); typname);
...@@ -5101,6 +5129,42 @@ format_function_signature(FuncInfo *finfo, char **argnames, ...@@ -5101,6 +5129,42 @@ format_function_signature(FuncInfo *finfo, char **argnames,
return fn.data; 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: * dumpFunc:
...@@ -5120,13 +5184,18 @@ dumpFunc(Archive *fout, FuncInfo *finfo) ...@@ -5120,13 +5184,18 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
char *proretset; char *proretset;
char *prosrc; char *prosrc;
char *probin; char *probin;
char *proallargtypes;
char *proargmodes;
char *proargnames; char *proargnames;
char *provolatile; char *provolatile;
char *proisstrict; char *proisstrict;
char *prosecdef; char *prosecdef;
char *lanname; char *lanname;
char *rettypename; char *rettypename;
char **argnamearray = NULL; int nallargs;
char **allargtypes = NULL;
char **argmodes = NULL;
char **argnames = NULL;
/* Dump only funcs in dumpable namespaces */ /* Dump only funcs in dumpable namespaces */
if (!finfo->dobj.namespace->dump || dataOnly) if (!finfo->dobj.namespace->dump || dataOnly)
...@@ -5141,10 +5210,23 @@ dumpFunc(Archive *fout, FuncInfo *finfo) ...@@ -5141,10 +5210,23 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
selectSourceSchema(finfo->dobj.namespace->dobj.name); selectSourceSchema(finfo->dobj.namespace->dobj.name);
/* Fetch function-specific details */ /* 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, appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, " "SELECT proretset, prosrc, probin, "
"null::text as proallargtypes, "
"null::text as proargmodes, "
"proargnames, " "proargnames, "
"provolatile, proisstrict, prosecdef, " "provolatile, proisstrict, prosecdef, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname " "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
...@@ -5156,6 +5238,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) ...@@ -5156,6 +5238,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
{ {
appendPQExpBuffer(query, appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, " "SELECT proretset, prosrc, probin, "
"null::text as proallargtypes, "
"null::text as proargmodes, "
"null::text as proargnames, " "null::text as proargnames, "
"provolatile, proisstrict, prosecdef, " "provolatile, proisstrict, prosecdef, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname " "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
...@@ -5167,6 +5251,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) ...@@ -5167,6 +5251,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
{ {
appendPQExpBuffer(query, appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, " "SELECT proretset, prosrc, probin, "
"null::text as proallargtypes, "
"null::text as proargmodes, "
"null::text as proargnames, " "null::text as proargnames, "
"case when proiscachable then 'i' else 'v' end as provolatile, " "case when proiscachable then 'i' else 'v' end as provolatile, "
"proisstrict, " "proisstrict, "
...@@ -5180,6 +5266,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) ...@@ -5180,6 +5266,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
{ {
appendPQExpBuffer(query, appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, " "SELECT proretset, prosrc, probin, "
"null::text as proallargtypes, "
"null::text as proargmodes, "
"null::text as proargnames, " "null::text as proargnames, "
"case when proiscachable then 'i' else 'v' end as provolatile, " "case when proiscachable then 'i' else 'v' end as provolatile, "
"'f'::boolean as proisstrict, " "'f'::boolean as proisstrict, "
...@@ -5205,6 +5293,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) ...@@ -5205,6 +5293,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset")); proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset"));
prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc")); prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
probin = PQgetvalue(res, 0, PQfnumber(res, "probin")); 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")); proargnames = PQgetvalue(res, 0, PQfnumber(res, "proargnames"));
provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile")); provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict")); proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
...@@ -5246,22 +5336,55 @@ dumpFunc(Archive *fout, FuncInfo *finfo) ...@@ -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) if (proargnames && *proargnames)
{ {
int nitems = 0; int nitems = 0;
if (!parsePGArray(proargnames, &argnamearray, &nitems) || if (!parsePGArray(proargnames, &argnames, &nitems) ||
nitems != finfo->nargs) nitems != nallargs)
{ {
write_msg(NULL, "WARNING: could not parse proargnames array\n"); write_msg(NULL, "WARNING: could not parse proargnames array\n");
if (argnamearray) if (argnames)
free(argnamearray); free(argnames);
argnamearray = NULL; argnames = NULL;
} }
} }
funcsig = format_function_signature(finfo, argnamearray, true); funcsig = format_function_arguments(finfo, nallargs, allargtypes,
funcsig_tag = format_function_signature(finfo, NULL, false); argmodes, argnames);
funcsig_tag = format_function_signature(finfo, false);
/* /*
* DROP must be fully qualified in case same name appears in * DROP must be fully qualified in case same name appears in
...@@ -5333,8 +5456,12 @@ dumpFunc(Archive *fout, FuncInfo *finfo) ...@@ -5333,8 +5456,12 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
destroyPQExpBuffer(asPart); destroyPQExpBuffer(asPart);
free(funcsig); free(funcsig);
free(funcsig_tag); free(funcsig_tag);
if (argnamearray) if (allargtypes)
free(argnamearray); free(allargtypes);
if (argmodes)
free(argmodes);
if (argnames)
free(argnames);
} }
...@@ -5432,7 +5559,7 @@ dumpCast(Archive *fout, CastInfo *cast) ...@@ -5432,7 +5559,7 @@ dumpCast(Archive *fout, CastInfo *cast)
appendPQExpBuffer(defqry, "WITH FUNCTION %s.", appendPQExpBuffer(defqry, "WITH FUNCTION %s.",
fmtId(funcInfo->dobj.namespace->dobj.name)); fmtId(funcInfo->dobj.namespace->dobj.name));
appendPQExpBuffer(defqry, "%s", appendPQExpBuffer(defqry, "%s",
format_function_signature(funcInfo, NULL, true)); format_function_signature(funcInfo, true));
} }
if (cast->castcontext == 'a') if (cast->castcontext == 'a')
...@@ -6380,8 +6507,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -6380,8 +6507,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
free(aggsig); free(aggsig);
free(aggsig_tag); free(aggsig_tag);
aggsig = format_function_signature(&agginfo->aggfn, NULL, true); aggsig = format_function_signature(&agginfo->aggfn, true);
aggsig_tag = format_function_signature(&agginfo->aggfn, NULL, false); aggsig_tag = format_function_signature(&agginfo->aggfn, false);
dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId, dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
"FUNCTION", "FUNCTION",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment