Commit f435cd1d authored by Heikki Linnakangas's avatar Heikki Linnakangas

Fix pg_dumpall with database names containing =

If a database name contained a '=' character, pg_dumpall failed. The problem
was in the way pg_dumpall passes the database name to pg_dump on the
command line. If it contained a '=' character, pg_dump would interpret it
as a libpq connection string instead of a plain database name.

To fix, pass the database name to pg_dump as a connection string,
"dbname=foo", with the database name escaped if necessary.

Back-patch to all supported branches.
parent 2930c056
...@@ -50,6 +50,7 @@ static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem, ...@@ -50,6 +50,7 @@ static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
static void dumpDatabases(PGconn *conn); static void dumpDatabases(PGconn *conn);
static void dumpTimestamp(char *msg); static void dumpTimestamp(char *msg);
static void doShellQuoting(PQExpBuffer buf, const char *str); static void doShellQuoting(PQExpBuffer buf, const char *str);
static void doConnStrQuoting(PQExpBuffer buf, const char *str);
static int runPgDump(const char *dbname); static int runPgDump(const char *dbname);
static void buildShSecLabels(PGconn *conn, const char *catalog_name, static void buildShSecLabels(PGconn *conn, const char *catalog_name,
...@@ -1629,6 +1630,7 @@ dumpDatabases(PGconn *conn) ...@@ -1629,6 +1630,7 @@ dumpDatabases(PGconn *conn)
static int static int
runPgDump(const char *dbname) runPgDump(const char *dbname)
{ {
PQExpBuffer connstr = createPQExpBuffer();
PQExpBuffer cmd = createPQExpBuffer(); PQExpBuffer cmd = createPQExpBuffer();
int ret; int ret;
...@@ -1644,7 +1646,17 @@ runPgDump(const char *dbname) ...@@ -1644,7 +1646,17 @@ runPgDump(const char *dbname)
else else
appendPQExpBuffer(cmd, " -Fp "); appendPQExpBuffer(cmd, " -Fp ");
doShellQuoting(cmd, dbname); /*
* Construct a connection string from the database name, like
* dbname='<database name>'. pg_dump would usually also accept the
* database name as is, but if it contains any = characters, it would
* incorrectly treat it as a connection string.
*/
appendPQExpBuffer(connstr, "dbname='");
doConnStrQuoting(connstr, dbname);
appendPQExpBuffer(connstr, "'");
doShellQuoting(cmd, connstr->data);
appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE); appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE);
...@@ -1657,6 +1669,7 @@ runPgDump(const char *dbname) ...@@ -1657,6 +1669,7 @@ runPgDump(const char *dbname)
ret = system(cmd->data); ret = system(cmd->data);
destroyPQExpBuffer(cmd); destroyPQExpBuffer(cmd);
destroyPQExpBuffer(connstr);
return ret; return ret;
} }
...@@ -1896,6 +1909,25 @@ dumpTimestamp(char *msg) ...@@ -1896,6 +1909,25 @@ dumpTimestamp(char *msg)
} }
/*
* Append the given string to the buffer, with suitable quoting for passing
* the string as a value, in a keyword/pair value in a libpq connection
* string
*/
static void
doConnStrQuoting(PQExpBuffer buf, const char *str)
{
while (*str)
{
/* ' and \ must be escaped by to \' and \\ */
if (*str == '\'' || *str == '\\')
appendPQExpBufferChar(buf, '\\');
appendPQExpBufferChar(buf, *str);
str++;
}
}
/* /*
* Append the given string to the shell command being built in the buffer, * Append the given string to the shell command being built in the buffer,
* with suitable shell-style quoting. * with suitable shell-style quoting.
......
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