]> granicus.if.org Git - postgresql/commitdiff
Fix pg_dumpall with database names containing =
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 20 Feb 2013 15:08:54 +0000 (17:08 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 20 Feb 2013 15:08:54 +0000 (17:08 +0200)
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.

src/bin/pg_dump/pg_dumpall.c

index 9afbab4b07b2a180acb6d8833090657846625287..a6e6a0fa9aad4adb43d6749083d69fe8b65b15f9 100644 (file)
@@ -50,6 +50,7 @@ static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
 static void dumpDatabases(PGconn *conn);
 static void dumpTimestamp(char *msg);
 static void doShellQuoting(PQExpBuffer buf, const char *str);
+static void doConnStrQuoting(PQExpBuffer buf, const char *str);
 
 static int     runPgDump(const char *dbname);
 static void buildShSecLabels(PGconn *conn, const char *catalog_name,
@@ -1629,6 +1630,7 @@ dumpDatabases(PGconn *conn)
 static int
 runPgDump(const char *dbname)
 {
+       PQExpBuffer connstr = createPQExpBuffer();
        PQExpBuffer cmd = createPQExpBuffer();
        int                     ret;
 
@@ -1644,7 +1646,17 @@ runPgDump(const char *dbname)
        else
                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);
 
@@ -1657,6 +1669,7 @@ runPgDump(const char *dbname)
        ret = system(cmd->data);
 
        destroyPQExpBuffer(cmd);
+       destroyPQExpBuffer(connstr);
 
        return ret;
 }
@@ -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,
  * with suitable shell-style quoting.