* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.10 2003/11/29 19:52:05 pgsql Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.11 2004/01/07 00:44:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#define supports_grant_options(version) ((version) >= 70400)
-static bool parseAclArray(const char *acls, char ***itemarray, int *nitems);
static bool parseAclItem(const char *item, const char *type, const char *name,
int remoteVersion,
PQExpBuffer grantee, PQExpBuffer grantor,
}
+/*
+ * Deconstruct the text representation of a 1-dimensional Postgres array
+ * into individual items.
+ *
+ * On success, returns true and sets *itemarray and *nitems to describe
+ * an array of individual strings. On parse failure, returns false;
+ * *itemarray may exist or be NULL.
+ *
+ * NOTE: free'ing itemarray is sufficient to deallocate the working storage.
+ */
+bool
+parsePGArray(const char *atext, char ***itemarray, int *nitems)
+{
+ int inputlen;
+ char **items;
+ char *strings;
+ int curitem;
+
+ /*
+ * We expect input in the form of "{item,item,item}" where any item is
+ * either raw data, or surrounded by double quotes (in which case
+ * embedded characters including backslashes and quotes are
+ * backslashed).
+ *
+ * We build the result as an array of pointers followed by the actual
+ * string data, all in one malloc block for convenience of
+ * deallocation. The worst-case storage need is not more than one
+ * pointer and one character for each input character (consider
+ * "{,,,,,,,,,,}").
+ */
+ *itemarray = NULL;
+ *nitems = 0;
+ inputlen = strlen(atext);
+ if (inputlen < 2 || atext[0] != '{' || atext[inputlen - 1] != '}')
+ return false; /* bad input */
+ items = (char **) malloc(inputlen * (sizeof(char *) + sizeof(char)));
+ if (items == NULL)
+ return false; /* out of memory */
+ *itemarray = items;
+ strings = (char *) (items + inputlen);
+
+ atext++; /* advance over initial '{' */
+ curitem = 0;
+ while (*atext != '}')
+ {
+ if (*atext == '\0')
+ return false; /* premature end of string */
+ items[curitem] = strings;
+ while (*atext != '}' && *atext != ',')
+ {
+ if (*atext == '\0')
+ return false; /* premature end of string */
+ if (*atext != '"')
+ *strings++ = *atext++; /* copy unquoted data */
+ else
+ {
+ /* process quoted substring */
+ atext++;
+ while (*atext != '"')
+ {
+ if (*atext == '\0')
+ return false; /* premature end of string */
+ if (*atext == '\\')
+ {
+ atext++;
+ if (*atext == '\0')
+ return false; /* premature end of string */
+ }
+ *strings++ = *atext++; /* copy quoted data */
+ }
+ atext++;
+ }
+ }
+ *strings++ = '\0';
+ if (*atext == ',')
+ atext++;
+ curitem++;
+ }
+ if (atext[1] != '\0')
+ return false; /* bogus syntax (embedded '}') */
+ *nitems = curitem;
+ return true;
+}
+
+
/*
* Build GRANT/REVOKE command(s) for an object.
*
if (strlen(acls) == 0)
return true; /* object has default permissions */
- if (!parseAclArray(acls, &aclitems, &naclitems))
+ if (!parsePGArray(acls, &aclitems, &naclitems))
{
if (aclitems)
free(aclitems);
return true;
}
-/*
- * Deconstruct an ACL array (or actually any 1-dimensional Postgres array)
- * into individual items.
- *
- * On success, returns true and sets *itemarray and *nitems to describe
- * an array of individual strings. On parse failure, returns false;
- * *itemarray may exist or be NULL.
- *
- * NOTE: free'ing itemarray is sufficient to deallocate the working storage.
- */
-static bool
-parseAclArray(const char *acls, char ***itemarray, int *nitems)
-{
- int inputlen;
- char **items;
- char *strings;
- int curitem;
-
- /*
- * We expect input in the form of "{item,item,item}" where any item is
- * either raw data, or surrounded by double quotes (in which case
- * embedded characters including backslashes and quotes are
- * backslashed).
- *
- * We build the result as an array of pointers followed by the actual
- * string data, all in one malloc block for convenience of
- * deallocation. The worst-case storage need is not more than one
- * pointer and one character for each input character (consider
- * "{,,,,,,,,,,}").
- */
- *itemarray = NULL;
- *nitems = 0;
- inputlen = strlen(acls);
- if (inputlen < 2 || acls[0] != '{' || acls[inputlen - 1] != '}')
- return false; /* bad input */
- items = (char **) malloc(inputlen * (sizeof(char *) + sizeof(char)));
- if (items == NULL)
- return false; /* out of memory */
- *itemarray = items;
- strings = (char *) (items + inputlen);
-
- acls++; /* advance over initial '{' */
- curitem = 0;
- while (*acls != '}')
- {
- if (*acls == '\0')
- return false; /* premature end of string */
- items[curitem] = strings;
- while (*acls != '}' && *acls != ',')
- {
- if (*acls == '\0')
- return false; /* premature end of string */
- if (*acls != '"')
- *strings++ = *acls++; /* copy unquoted data */
- else
- {
- /* process quoted substring */
- acls++;
- while (*acls != '"')
- {
- if (*acls == '\0')
- return false; /* premature end of string */
- if (*acls == '\\')
- {
- acls++;
- if (*acls == '\0')
- return false; /* premature end of string */
- }
- *strings++ = *acls++; /* copy quoted data */
- }
- acls++;
- }
- }
- *strings++ = '\0';
- if (*acls == ',')
- acls++;
- curitem++;
- }
- if (acls[1] != '\0')
- return false; /* bogus syntax (embedded '}') */
- *nitems = curitem;
- return true;
-}
-
/*
* This will parse an aclitem string, having the general form
* username=privilegecodes/grantor
* by PostgreSQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.361 2003/12/19 14:21:56 petere Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.362 2004/01/07 00:44:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
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, bool honor_quotes);
+static char *format_function_signature(FuncInfo *finfo, char **argnames,
+ bool honor_quotes);
static const char *convertRegProcReference(const char *proc);
static const char *convertOperatorReference(const char *opr);
static Oid findLastBuiltinOid_V71(const char *);
*
* The argument type names are qualified if needed. The function name
* is never qualified.
+ *
+ * argnames may be NULL if no names are available.
*/
static char *
-format_function_signature(FuncInfo *finfo, bool honor_quotes)
+format_function_signature(FuncInfo *finfo, char **argnames,
+ bool honor_quotes)
{
PQExpBufferData fn;
int j;
for (j = 0; j < finfo->nargs; j++)
{
char *typname;
+ char *argname;
typname = getFormattedTypeName(finfo->argtypes[j], zeroAsOpaque);
- appendPQExpBuffer(&fn, "%s%s",
+
+ argname = argnames ? argnames[j] : (char *) NULL;
+ if (argname && argname[0] == '\0')
+ argname = NULL;
+
+ appendPQExpBuffer(&fn, "%s%s%s%s",
(j > 0) ? ", " : "",
+ argname ? fmtId(argname) : "",
+ argname ? " " : "",
typname);
free(typname);
}
char *proretset;
char *prosrc;
char *probin;
+ char *proargnames;
char *provolatile;
char *proisstrict;
char *prosecdef;
char *lanname;
char *rettypename;
+ char **argnamearray = NULL;
/* Dump only funcs in dumpable namespaces */
if (!finfo->pronamespace->dump || dataOnly)
selectSourceSchema(finfo->pronamespace->nspname);
/* Fetch function-specific details */
- if (g_fout->remoteVersion >= 70300)
+ if (g_fout->remoteVersion >= 70500)
{
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
+ "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 >= 70300)
+ {
+ appendPQExpBuffer(query,
+ "SELECT proretset, prosrc, probin, "
+ "null::text as proargnames, "
"provolatile, proisstrict, prosecdef, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
"FROM pg_catalog.pg_proc "
{
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
+ "null::text as proargnames, "
"case when proiscachable then 'i' else 'v' end as provolatile, "
"proisstrict, "
"'f'::boolean as prosecdef, "
{
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
+ "null::text as proargnames, "
"case when proiscachable then 'i' else 'v' end as provolatile, "
"'f'::boolean as proisstrict, "
"'f'::boolean as prosecdef, "
proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset"));
prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
probin = PQgetvalue(res, 0, PQfnumber(res, "probin"));
+ proargnames = PQgetvalue(res, 0, PQfnumber(res, "proargnames"));
provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
}
}
- funcsig = format_function_signature(finfo, true);
- funcsig_tag = format_function_signature(finfo, false);
+ if (proargnames && *proargnames)
+ {
+ int nitems = 0;
+
+ if (!parsePGArray(proargnames, &argnamearray, &nitems) ||
+ nitems != finfo->nargs)
+ {
+ write_msg(NULL, "WARNING: could not parse proargnames array\n");
+ if (argnamearray)
+ free(argnamearray);
+ argnamearray = NULL;
+ }
+ }
+
+ funcsig = format_function_signature(finfo, argnamearray, true);
+ funcsig_tag = format_function_signature(finfo, NULL, false);
/*
* DROP must be fully qualified in case same name appears in
destroyPQExpBuffer(asPart);
free(funcsig);
free(funcsig_tag);
+ if (argnamearray)
+ free(argnamearray);
}
appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
else
appendPQExpBuffer(defqry, "WITH FUNCTION %s",
- format_function_signature(funcInfo, true));
+ format_function_signature(funcInfo, NULL, true));
if (cast->castcontext == 'a')
appendPQExpBuffer(defqry, " AS ASSIGNMENT");
free(aggsig);
free(aggsig_tag);
- aggsig = format_function_signature(&agginfo->aggfn, true);
- aggsig_tag = format_function_signature(&agginfo->aggfn, false);
+ aggsig = format_function_signature(&agginfo->aggfn, NULL, true);
+ aggsig_tag = format_function_signature(&agginfo->aggfn, NULL, false);
dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
"FUNCTION",