Commit 599dba4a authored by Tom Lane's avatar Tom Lane

Fix several problems in pg_dump's handling of SQL/MED objects, notably failure

to dump a PUBLIC user mapping correctly, as per bug #5560 from Shigeru Hanada.
Use the pg_user_mappings view rather than trying to access pg_user_mapping
directly, so that the code doesn't fail when run by a non-superuser.  And
clean up some minor carelessness such as unsafe usage of fmtId().

Back-patch to 8.4 where this code was added.
parent d494e685
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
* http://archives.postgresql.org/pgsql-bugs/2010-02/msg00187.php * http://archives.postgresql.org/pgsql-bugs/2010-02/msg00187.php
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.581 2010/07/06 19:18:59 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.582 2010/07/14 21:21:08 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -173,7 +173,7 @@ static void dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo); ...@@ -173,7 +173,7 @@ static void dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo);
static void dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo); static void dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo);
static void dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo); static void dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo);
static void dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo); static void dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo);
static void dumpUserMappings(Archive *fout, const char *target, static void dumpUserMappings(Archive *fout,
const char *servername, const char *namespace, const char *servername, const char *namespace,
const char *owner, CatalogId catalogId, DumpId dumpId); const char *owner, CatalogId catalogId, DumpId dumpId);
static void dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo); static void dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo);
...@@ -10138,6 +10138,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo) ...@@ -10138,6 +10138,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
query = createPQExpBuffer(); query = createPQExpBuffer();
/* look up the foreign-data wrapper */ /* look up the foreign-data wrapper */
selectSourceSchema("pg_catalog");
appendPQExpBuffer(query, "SELECT fdwname " appendPQExpBuffer(query, "SELECT fdwname "
"FROM pg_foreign_data_wrapper w " "FROM pg_foreign_data_wrapper w "
"WHERE w.oid = '%u'", "WHERE w.oid = '%u'",
...@@ -10198,9 +10199,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo) ...@@ -10198,9 +10199,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
free(namecopy); free(namecopy);
/* Dump user mappings */ /* Dump user mappings */
resetPQExpBuffer(q); dumpUserMappings(fout,
appendPQExpBuffer(q, "SERVER %s", fmtId(srvinfo->dobj.name));
dumpUserMappings(fout, q->data,
srvinfo->dobj.name, NULL, srvinfo->dobj.name, NULL,
srvinfo->rolname, srvinfo->rolname,
srvinfo->dobj.catId, srvinfo->dobj.dumpId); srvinfo->dobj.catId, srvinfo->dobj.dumpId);
...@@ -10217,7 +10216,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo) ...@@ -10217,7 +10216,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
* for the server. * for the server.
*/ */
static void static void
dumpUserMappings(Archive *fout, const char *target, dumpUserMappings(Archive *fout,
const char *servername, const char *namespace, const char *servername, const char *namespace,
const char *owner, const char *owner,
CatalogId catalogId, DumpId dumpId) CatalogId catalogId, DumpId dumpId)
...@@ -10228,7 +10227,7 @@ dumpUserMappings(Archive *fout, const char *target, ...@@ -10228,7 +10227,7 @@ dumpUserMappings(Archive *fout, const char *target,
PQExpBuffer tag; PQExpBuffer tag;
PGresult *res; PGresult *res;
int ntups; int ntups;
int i_umuser; int i_usename;
int i_umoptions; int i_umoptions;
int i; int i;
...@@ -10237,31 +10236,40 @@ dumpUserMappings(Archive *fout, const char *target, ...@@ -10237,31 +10236,40 @@ dumpUserMappings(Archive *fout, const char *target,
delq = createPQExpBuffer(); delq = createPQExpBuffer();
query = createPQExpBuffer(); query = createPQExpBuffer();
/*
* We read from the publicly accessible view pg_user_mappings, so as not
* to fail if run by a non-superuser. Note that the view will show
* umoptions as null if the user hasn't got privileges for the associated
* server; this means that pg_dump will dump such a mapping, but with no
* OPTIONS clause. A possible alternative is to skip such mappings
* altogether, but it's not clear that that's an improvement.
*/
selectSourceSchema("pg_catalog");
appendPQExpBuffer(query, appendPQExpBuffer(query,
"SELECT (%s umuser) AS umuser, " "SELECT usename, "
"array_to_string(ARRAY(SELECT option_name || ' ' || quote_literal(option_value) FROM pg_options_to_table(umoptions)), ', ') AS umoptions\n" "array_to_string(ARRAY(SELECT option_name || ' ' || quote_literal(option_value) FROM pg_options_to_table(umoptions)), ', ') AS umoptions\n"
"FROM pg_user_mapping " "FROM pg_user_mappings "
"WHERE umserver=%u", "WHERE srvid = %u",
username_subquery,
catalogId.oid); catalogId.oid);
res = PQexec(g_conn, query->data); res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK); check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res); ntups = PQntuples(res);
i_umuser = PQfnumber(res, "umuser"); i_usename = PQfnumber(res, "usename");
i_umoptions = PQfnumber(res, "umoptions"); i_umoptions = PQfnumber(res, "umoptions");
for (i = 0; i < ntups; i++) for (i = 0; i < ntups; i++)
{ {
char *umuser; char *usename;
char *umoptions; char *umoptions;
umuser = PQgetvalue(res, i, i_umuser); usename = PQgetvalue(res, i, i_usename);
umoptions = PQgetvalue(res, i, i_umoptions); umoptions = PQgetvalue(res, i, i_umoptions);
resetPQExpBuffer(q); resetPQExpBuffer(q);
appendPQExpBuffer(q, "CREATE USER MAPPING FOR %s", fmtId(umuser)); appendPQExpBuffer(q, "CREATE USER MAPPING FOR %s", fmtId(usename));
appendPQExpBuffer(q, " SERVER %s", fmtId(servername)); appendPQExpBuffer(q, " SERVER %s", fmtId(servername));
if (umoptions && strlen(umoptions) > 0) if (umoptions && strlen(umoptions) > 0)
...@@ -10270,10 +10278,12 @@ dumpUserMappings(Archive *fout, const char *target, ...@@ -10270,10 +10278,12 @@ dumpUserMappings(Archive *fout, const char *target,
appendPQExpBuffer(q, ";\n"); appendPQExpBuffer(q, ";\n");
resetPQExpBuffer(delq); resetPQExpBuffer(delq);
appendPQExpBuffer(delq, "DROP USER MAPPING FOR %s SERVER %s;\n", fmtId(umuser), fmtId(servername)); appendPQExpBuffer(delq, "DROP USER MAPPING FOR %s", fmtId(usename));
appendPQExpBuffer(delq, " SERVER %s;\n", fmtId(servername));
resetPQExpBuffer(tag); resetPQExpBuffer(tag);
appendPQExpBuffer(tag, "USER MAPPING %s %s", fmtId(umuser), target); appendPQExpBuffer(tag, "USER MAPPING %s SERVER %s",
usename, servername);
ArchiveEntry(fout, nilCatalogId, createDumpId(), ArchiveEntry(fout, nilCatalogId, createDumpId(),
tag->data, tag->data,
......
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