]> granicus.if.org Git - postgresql/blobdiff - src/bin/pg_dump/pg_dumpall.c
Fix HAVE_OPTRESET to be HAVE_INT_OPTRESET. Typos spotted by Lorne Sunley.
[postgresql] / src / bin / pg_dump / pg_dumpall.c
index 872416b64f74f3311bfc218efb678d91e65c2277..d666d53376bf97b02e11825b0605b2f362a4254f 100644 (file)
@@ -2,11 +2,11 @@
  *
  * pg_dumpall
  *
- * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.35 2004/05/25 01:00:24 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.55 2004/11/27 18:51:06 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "strdup.h"
 #endif
 #include <errno.h>
+#include <time.h>
 
 #include "getopt_long.h"
 
-#ifndef HAVE_OPTRESET
+#ifndef HAVE_INT_OPTRESET
 int                    optreset;
 #endif
 
@@ -43,28 +44,32 @@ static const char *progname;
 
 static void help(void);
 
-static void dumpUsers(PGconn *conn);
+static void dumpUsers(PGconn *conn, bool initdbonly);
 static void dumpGroups(PGconn *conn);
+static void dumpTablespaces(PGconn *conn);
 static void dumpCreateDB(PGconn *conn);
 static void dumpDatabaseConfig(PGconn *conn, const char *dbname);
 static void dumpUserConfig(PGconn *conn, const char *username);
 static void makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name);
 static void dumpDatabases(PGconn *conn);
+static void dumpTimestamp(char *msg);
 
 static int     runPgDump(const char *dbname);
 static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
                                const char *pguser, bool require_password);
 static PGresult *executeQuery(PGconn *conn, const char *query);
 
-
-char       pg_dump_bin[MAXPGPATH];
+char           pg_dump_bin[MAXPGPATH];
 PQExpBuffer pgdumpopts;
 bool           output_clean = false;
 bool           skip_acls = false;
 bool           verbose = false;
 int                    server_version;
 
-
+/* flags for -X long options */
+int                    disable_dollar_quoting = 0;
+int                    disable_triggers = 0;
+int                    use_setsessauth = 0;
 
 int
 main(int argc, char *argv[])
@@ -77,7 +82,8 @@ main(int argc, char *argv[])
        bool            globals_only = false;
        bool            schema_only = false;
        PGconn     *conn;
-       int                     c, ret;
+       int                     c,
+                               ret;
 
        static struct option long_options[] = {
                {"data-only", no_argument, NULL, 'a'},
@@ -89,19 +95,30 @@ main(int argc, char *argv[])
                {"host", required_argument, NULL, 'h'},
                {"ignore-version", no_argument, NULL, 'i'},
                {"oids", no_argument, NULL, 'o'},
+               {"no-owner", no_argument, NULL, 'O'},
                {"port", required_argument, NULL, 'p'},
                {"password", no_argument, NULL, 'W'},
                {"schema-only", no_argument, NULL, 's'},
+               {"superuser", required_argument, NULL, 'S'},
                {"username", required_argument, NULL, 'U'},
                {"verbose", no_argument, NULL, 'v'},
                {"no-privileges", no_argument, NULL, 'x'},
                {"no-acl", no_argument, NULL, 'x'},
+
+               /*
+                * the following options don't have an equivalent short option
+                * letter, but are available as '-X long-name'
+                */
+               {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
+               {"disable-triggers", no_argument, &disable_triggers, 1},
+               {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
+
                {NULL, 0, NULL, 0}
        };
 
        int                     optindex;
 
-       set_pglocale(argv[0], "pg_dump");
+       set_pglocale_pgservice(argv[0], "pg_dump");
 
        progname = get_progname(argv[0]);
 
@@ -122,24 +139,30 @@ main(int argc, char *argv[])
        if ((ret = find_other_exec(argv[0], "pg_dump", PG_VERSIONSTR,
                                                           pg_dump_bin)) < 0)
        {
+               char full_path[MAXPGPATH];
+
+               if (find_my_exec(argv[0], full_path) < 0)
+                       StrNCpy(full_path, progname, MAXPGPATH);
+
                if (ret == -1)
                        fprintf(stderr,
-                                               _("The program \"pg_dump\" is needed by %s "
-                                               "but was not found in the same directory as \"%s\".\n"
-                                               "Check your installation.\n"),
-                                               progname, progname);
+                                       _("The program \"pg_dump\" is needed by %s "
+                                         "but was not found in the\n"
+                                         "same directory as \"%s\".\n"
+                                         "Check your installation.\n"),
+                                       progname, full_path);
                else
                        fprintf(stderr,
-                                               _("The program \"pg_dump\" was found by %s "
-                                               "but was not the same version as \"%s\".\n"
-                                               "Check your installation.\n"),
-                                               progname, progname);
+                                       _("The program \"pg_dump\" was found by \"%s\"\n"
+                                         "but was not the same version as %s.\n"
+                                         "Check your installation.\n"),
+                                       full_path, progname);
                exit(1);
        }
 
        pgdumpopts = createPQExpBuffer();
 
-       while ((c = getopt_long(argc, argv, "acdDgh:iop:sU:vWx", long_options, &optindex)) != -1)
+       while ((c = getopt_long(argc, argv, "acdDgh:ioOp:sS:U:vWxX:", long_options, &optindex)) != -1)
        {
                switch (c)
                {
@@ -163,17 +186,32 @@ main(int argc, char *argv[])
 
                        case 'h':
                                pghost = optarg;
+#ifndef WIN32
                                appendPQExpBuffer(pgdumpopts, " -h '%s'", pghost);
+#else
+                                appendPQExpBuffer(pgdumpopts, " -h \"%s\"", pghost);
+#endif
+
                                break;
 
+
+
                        case 'i':
                        case 'o':
                                appendPQExpBuffer(pgdumpopts, " -%c", c);
                                break;
 
+                       case 'O':
+                               appendPQExpBuffer(pgdumpopts, " -O");
+                               break;
+
                        case 'p':
                                pgport = optarg;
+#ifndef WIN32
                                appendPQExpBuffer(pgdumpopts, " -p '%s'", pgport);
+#else
+                                appendPQExpBuffer(pgdumpopts, " -p \"%s\"", pgport);
+#endif
                                break;
 
                        case 's':
@@ -181,9 +219,21 @@ main(int argc, char *argv[])
                                appendPQExpBuffer(pgdumpopts, " -s");
                                break;
 
+                       case 'S':
+#ifndef WIN32
+                               appendPQExpBuffer(pgdumpopts, " -S '%s'", optarg);
+#else
+                                appendPQExpBuffer(pgdumpopts, " -S \"%s\"", optarg);
+#endif
+                               break;
+
                        case 'U':
                                pguser = optarg;
+#ifndef WIN32
                                appendPQExpBuffer(pgdumpopts, " -U '%s'", pguser);
+#else
+                                appendPQExpBuffer(pgdumpopts, " -U \"%s\"", pguser);
+#endif
                                break;
 
                        case 'v':
@@ -201,12 +251,40 @@ main(int argc, char *argv[])
                                appendPQExpBuffer(pgdumpopts, " -x");
                                break;
 
+                       case 'X':
+                               if (strcmp(optarg, "disable-dollar-quoting") == 0)
+                                       appendPQExpBuffer(pgdumpopts, " -X disable-dollar-quoting");
+                               else if (strcmp(optarg, "disable-triggers") == 0)
+                                       appendPQExpBuffer(pgdumpopts, " -X disable-triggers");
+                               else if (strcmp(optarg, "use-set-session-authorization") == 0)
+                                        /* no-op, still allowed for compatibility */ ;
+                               else
+                               {
+                                       fprintf(stderr,
+                                                       _("%s: invalid -X option -- %s\n"),
+                                                       progname, optarg);
+                                       fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+                                       exit(1);
+                               }
+                               break;
+
+                       case 0:
+                               break;
+
                        default:
                                fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
                                exit(1);
                }
        }
 
+       /* Add long options to the pg_dump argument list */
+       if (disable_dollar_quoting)
+               appendPQExpBuffer(pgdumpopts, " -X disable-dollar-quoting");
+       if (disable_triggers)
+               appendPQExpBuffer(pgdumpopts, " -X disable-triggers");
+       if (use_setsessauth)
+               appendPQExpBuffer(pgdumpopts, " -X use-set-session-authorization");
+
        if (optind < argc)
        {
                fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
@@ -219,29 +297,33 @@ main(int argc, char *argv[])
 
        conn = connectDatabase("template1", pghost, pgport, pguser, force_password);
 
-       printf("--\n");
-       printf("-- PostgreSQL database cluster dump\n");
-       printf("--\n\n");
+       printf("--\n-- PostgreSQL database cluster dump\n--\n\n");
+       if (verbose)
+               dumpTimestamp("Started on");
+
        printf("\\connect \"template1\"\n\n");
 
        if (!data_only)
        {
-               dumpUsers(conn);
+               /* Dump all users excluding the initdb user */
+               dumpUsers(conn, false);
                dumpGroups(conn);
+               if (server_version >= 80000)
+                       dumpTablespaces(conn);
+               if (!globals_only)
+                       dumpCreateDB(conn);
+               /* Dump alter command for initdb user */
+               dumpUsers(conn, true);
        }
 
        if (!globals_only)
-       {
-               if (!data_only)
-                       dumpCreateDB(conn);
                dumpDatabases(conn);
-       }
 
        PQfinish(conn);
 
-       printf("--\n");
-       printf("-- PostgreSQL database cluster dump complete\n");
-       printf("--\n\n");
+       if (verbose)
+               dumpTimestamp("Completed on");
+       printf("--\n-- PostgreSQL database cluster dump complete\n--\n\n");
 
        exit(0);
 }
@@ -255,20 +337,29 @@ help(void)
        printf(_("Usage:\n"));
        printf(_("  %s [OPTION]...\n"), progname);
 
-       printf(_("\nOptions:\n"));
+       printf(_("\nGeneral options:\n"));
+       printf(_("  -i, --ignore-version     proceed even when server version mismatches\n"
+                        "                           pg_dumpall version\n"));
+       printf(_("  --help                   show this help, then exit\n"));
+       printf(_("  --version                output version information, then exit\n"));
+       printf(_("\nOptions controlling the output content:\n"));
        printf(_("  -a, --data-only          dump only the data, not the schema\n"));
        printf(_("  -c, --clean              clean (drop) databases prior to create\n"));
        printf(_("  -d, --inserts            dump data as INSERT, rather than COPY, commands\n"));
        printf(_("  -D, --column-inserts     dump data as INSERT commands with column names\n"));
        printf(_("  -g, --globals-only       dump only global objects, no databases\n"));
-       printf(_("  -i, --ignore-version     proceed even when server version mismatches\n"
-                        "                           pg_dumpall version\n"));
-       printf(_("  -s, --schema-only        dump only the schema, no data\n"));
        printf(_("  -o, --oids               include OIDs in dump\n"));
-       printf(_("  -v, --verbose            verbose mode\n"));
+       printf(_("  -O, --no-owner           do not output commands to set object ownership\n"));
+       printf(_("  -s, --schema-only        dump only the schema, no data\n"));
+       printf(_("  -S, --superuser=NAME     specify the superuser user name to use in the dump\n"));
        printf(_("  -x, --no-privileges      do not dump privileges (grant/revoke)\n"));
-       printf(_("  --help                   show this help, then exit\n"));
-       printf(_("  --version                output version information, then exit\n"));
+       printf(_("  -X disable-dollar-quoting, --disable-dollar-quoting\n"
+                        "                           disable dollar quoting, use SQL standard quoting\n"));
+       printf(_("  -X disable-triggers, --disable-triggers\n"
+                        "                           disable triggers during data-only restore\n"));
+       printf(_("  -X use-set-session-authorization, --use-set-session-authorization\n"
+                        "                           use SESSION AUTHORIZATION commands instead of\n"
+                        "                           OWNER TO commands\n"));
 
        printf(_("\nConnection options:\n"));
        printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
@@ -283,39 +374,57 @@ help(void)
 
 
 /*
- * Dump users (but not the user created by initdb).
+ * Dump users
+ * Is able to dump all non initdb users or just the initdb user.
  */
 static void
-dumpUsers(PGconn *conn)
+dumpUsers(PGconn *conn, bool initdbonly)
 {
        PGresult   *res;
        int                     i;
 
-       printf("--\n-- Users\n--\n\n");
-       printf("DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');\n\n");
-
        if (server_version >= 70100)
                res = executeQuery(conn,
                                                "SELECT usename, usesysid, passwd, usecreatedb, "
-                                                  "usesuper, valuntil "
-                                                  "FROM pg_shadow "
-                                                  "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0')");
+                                                  "usesuper, valuntil, "
+                                                  "(usesysid = (SELECT datdba FROM pg_database WHERE datname = 'template0')) AS clusterowner "
+                                                  "FROM pg_shadow");
        else
                res = executeQuery(conn,
                                                "SELECT usename, usesysid, passwd, usecreatedb, "
-                                                  "usesuper, valuntil "
-                                                  "FROM pg_shadow "
-                                                  "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template1')");
+                                                  "usesuper, valuntil, "
+                                                  "(usesysid = (SELECT datdba FROM pg_database WHERE datname = 'template1')) AS clusterowner "
+                                                  "FROM pg_shadow");
+
+       if (PQntuples(res) > 0 || (!initdbonly && output_clean))
+               printf("--\n-- Users\n--\n\n");
+       if (!initdbonly && output_clean)
+               printf("DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');\n\n");
 
        for (i = 0; i < PQntuples(res); i++)
        {
-               PQExpBuffer buf = createPQExpBuffer();
                const char *username;
+               bool            clusterowner;
+               PQExpBuffer buf = createPQExpBuffer();
 
                username = PQgetvalue(res, i, 0);
-               appendPQExpBuffer(buf, "CREATE USER %s WITH SYSID %s",
-                                                 fmtId(username),
-                                                 PQgetvalue(res, i, 1));
+               clusterowner = (strcmp(PQgetvalue(res, i, 6), "t") == 0);
+
+               /* Check which pass we're on */
+               if ((initdbonly && !clusterowner) || (!initdbonly && clusterowner))
+                       continue;
+
+               /*
+                * Dump ALTER USER for the cluster owner and CREATE USER for all
+                * other users
+                */
+               if (!clusterowner)
+                       appendPQExpBuffer(buf, "CREATE USER %s WITH SYSID %s",
+                                                         fmtId(username),
+                                                         PQgetvalue(res, i, 1));
+               else
+                       appendPQExpBuffer(buf, "ALTER USER %s WITH",
+                                                         fmtId(username));
 
                if (!PQgetisnull(res, i, 2))
                {
@@ -361,11 +470,13 @@ dumpGroups(PGconn *conn)
        PGresult   *res;
        int                     i;
 
-       printf("--\n-- Groups\n--\n\n");
-       printf("DELETE FROM pg_group;\n\n");
-
        res = executeQuery(conn, "SELECT groname, grosysid, grolist FROM pg_group");
 
+       if (PQntuples(res) > 0 || output_clean)
+               printf("--\n-- Groups\n--\n\n");
+       if (output_clean)
+               printf("DELETE FROM pg_group;\n\n");
+
        for (i = 0; i < PQntuples(res); i++)
        {
                PQExpBuffer buf = createPQExpBuffer();
@@ -408,7 +519,69 @@ dumpGroups(PGconn *conn)
        printf("\n\n");
 }
 
+/*
+ * Dump tablespaces.
+ */
+static void
+dumpTablespaces(PGconn *conn)
+{
+       PGresult   *res;
+       int                     i;
+
+       /*
+        * Get all tablespaces except built-in ones (which we assume are named
+        * pg_xxx)
+        */
+       res = executeQuery(conn, "SELECT spcname, "
+                                        "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
+                                          "spclocation, spcacl "
+                                          "FROM pg_catalog.pg_tablespace "
+                                          "WHERE spcname NOT LIKE 'pg\\_%'");
+
+       if (PQntuples(res) > 0)
+               printf("--\n-- Tablespaces\n--\n\n");
+
+       for (i = 0; i < PQntuples(res); i++)
+       {
+               PQExpBuffer buf = createPQExpBuffer();
+               char       *spcname = PQgetvalue(res, i, 0);
+               char       *spcowner = PQgetvalue(res, i, 1);
+               char       *spclocation = PQgetvalue(res, i, 2);
+               char       *spcacl = PQgetvalue(res, i, 3);
+               char       *fspcname;
+
+               /* needed for buildACLCommands() */
+               fspcname = strdup(fmtId(spcname));
+
+               if (output_clean)
+                       appendPQExpBuffer(buf, "DROP TABLESPACE %s;\n", fspcname);
+
+               appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
+               appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
+
+               appendPQExpBuffer(buf, " LOCATION ");
+               appendStringLiteral(buf, spclocation, true);
+               appendPQExpBuffer(buf, ";\n");
+
+               if (!skip_acls &&
+                       !buildACLCommands(fspcname, "TABLESPACE", spcacl, spcowner,
+                                                         server_version, buf))
+               {
+                       fprintf(stderr, _("%s: could not parse ACL list (%s) for tablespace \"%s\"\n"),
+                                       progname, spcacl, fspcname);
+                       PQfinish(conn);
+                       exit(1);
+               }
 
+               printf("%s", buf->data);
+
+               free(fspcname);
+               destroyPQExpBuffer(buf);
+       }
+
+       PQclear(res);
+       printf("\n\n");
+}
 
 /*
  * Dump commands to create each database.
@@ -429,12 +602,22 @@ dumpCreateDB(PGconn *conn)
 
        printf("--\n-- Database creation\n--\n\n");
 
-       if (server_version >= 70300)
+       if (server_version >= 80000)
                res = executeQuery(conn,
                                                   "SELECT datname, "
                                                   "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
                                                   "pg_encoding_to_char(d.encoding), "
-                                                  "datistemplate, datpath, datacl "
+                                                  "datistemplate, datacl, "
+                                                  "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
+               "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
+                                                  "WHERE datallowconn ORDER BY 1");
+       else if (server_version >= 70300)
+               res = executeQuery(conn,
+                                                  "SELECT datname, "
+                                                  "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
+                                                  "pg_encoding_to_char(d.encoding), "
+                                                  "datistemplate, datacl, "
+                                                  "'pg_default' AS dattablespace "
                "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
                                                   "WHERE datallowconn ORDER BY 1");
        else if (server_version >= 70100)
@@ -444,16 +627,13 @@ dumpCreateDB(PGconn *conn)
                                "(select usename from pg_shadow where usesysid=datdba), "
                                                   "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
                                                   "pg_encoding_to_char(d.encoding), "
-                                                  "datistemplate, datpath, '' as datacl "
+                                                  "datistemplate, '' as datacl, "
+                                                  "'pg_default' AS dattablespace "
                                                   "FROM pg_database d "
                                                   "WHERE datallowconn ORDER BY 1");
        else
        {
                /*
-                * In 7.0, datpath is either the same as datname, or the user-given
-                * location with "/" and the datname appended.  We must strip this
-                * junk off to produce a correct LOCATION value.
-                *
                 * Note: 7.0 fails to cope with sub-select in COALESCE, so just
                 * deal with getting a NULL by not printing any OWNER clause.
                 */
@@ -462,10 +642,8 @@ dumpCreateDB(PGconn *conn)
                                "(select usename from pg_shadow where usesysid=datdba), "
                                                   "pg_encoding_to_char(d.encoding), "
                                                   "'f' as datistemplate, "
-                                                  "CASE WHEN length(datpath) > length(datname) THEN "
-                                                  "substr(datpath,1,length(datpath)-length(datname)-1) "
-                                                  "ELSE '' END as datpath, "
-                                                  "'' as datacl "
+                                                  "'' as datacl, "
+                                                  "'pg_default' AS dattablespace "
                                                   "FROM pg_database d "
                                                   "ORDER BY 1");
        }
@@ -477,8 +655,8 @@ dumpCreateDB(PGconn *conn)
                char       *dbowner = PQgetvalue(res, i, 1);
                char       *dbencoding = PQgetvalue(res, i, 2);
                char       *dbistemplate = PQgetvalue(res, i, 3);
-               char       *dbpath = PQgetvalue(res, i, 4);
-               char       *dbacl = PQgetvalue(res, i, 5);
+               char       *dbacl = PQgetvalue(res, i, 4);
+               char       *dbtablespace = PQgetvalue(res, i, 5);
                char       *fdbname;
 
                if (strcmp(dbname, "template1") == 0)
@@ -493,20 +671,21 @@ dumpCreateDB(PGconn *conn)
                        appendPQExpBuffer(buf, "DROP DATABASE %s;\n", fdbname);
 
                appendPQExpBuffer(buf, "CREATE DATABASE %s", fdbname);
+
+               appendPQExpBuffer(buf, " WITH TEMPLATE = template0");
+
                if (strlen(dbowner) != 0)
-                       appendPQExpBuffer(buf, " WITH OWNER = %s",
+                       appendPQExpBuffer(buf, " OWNER = %s",
                                                          fmtId(dbowner));
-               appendPQExpBuffer(buf, " TEMPLATE = template0");
-
-               if (strlen(dbpath) != 0)
-               {
-                       appendPQExpBuffer(buf, " LOCATION = ");
-                       appendStringLiteral(buf, dbpath, true);
-               }
 
                appendPQExpBuffer(buf, " ENCODING = ");
                appendStringLiteral(buf, dbencoding, true);
 
+               /* Output tablespace if it isn't default */
+               if (strcmp(dbtablespace, "pg_default") != 0)
+                       appendPQExpBuffer(buf, " TABLESPACE = %s",
+                                                         fmtId(dbtablespace));
+
                appendPQExpBuffer(buf, ";\n");
 
                if (strcmp(dbistemplate, "t") == 0)
@@ -630,7 +809,16 @@ makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name
        *pos = 0;
        appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name));
        appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine));
-       appendStringLiteral(buf, pos + 1, false);
+
+       /*
+        * Some GUC variable names are 'LIST' type and hence must not be
+        * quoted.
+        */
+       if (strcasecmp(mine, "DateStyle") == 0
+               || strcasecmp(mine, "search_path") == 0)
+               appendPQExpBuffer(buf, "%s", pos + 1);
+       else
+               appendStringLiteral(buf, pos + 1, false);
        appendPQExpBuffer(buf, ";\n");
 
        printf("%s", buf->data);
@@ -687,18 +875,39 @@ runPgDump(const char *dbname)
        const char *p;
        int                     ret;
 
-       appendPQExpBuffer(cmd, "\"%s\" %s -Fp '", pg_dump_bin, pgdumpopts->data);
+       /*
+        * Win32 has to use double-quotes for args, rather than single quotes.
+        * Strangely enough, this is the only place we pass a database name on
+        * the command line, except template1 that doesn't need quoting.
+        */
+#ifndef WIN32
+       appendPQExpBuffer(cmd, "%s\"%s\" %s -Fp '", SYSTEMQUOTE, pg_dump_bin,
+#else
+       appendPQExpBuffer(cmd, "%s\"%s\" %s -Fp \"", SYSTEMQUOTE, pg_dump_bin,
+#endif
+                                         pgdumpopts->data);
 
        /* Shell quoting is not quite like SQL quoting, so can't use fmtId */
        for (p = dbname; *p; p++)
        {
+#ifndef WIN32
                if (*p == '\'')
                        appendPQExpBuffer(cmd, "'\"'\"'");
+#else
+               if (*p == '"')
+                       appendPQExpBuffer(cmd, "\\\"");
+#endif
                else
                        appendPQExpBufferChar(cmd, *p);
        }
 
+#ifndef WIN32
        appendPQExpBufferChar(cmd, '\'');
+#else
+       appendPQExpBufferChar(cmd, '"');
+#endif
+
+       appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE);
 
        if (verbose)
                fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data);
@@ -748,7 +957,7 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
                }
 
                if (PQstatus(conn) == CONNECTION_BAD &&
-                       strcmp(PQerrorMessage(conn), "fe_sendauth: no password supplied\n") == 0 &&
+                       strcmp(PQerrorMessage(conn), PQnoPasswordSupplied) == 0 &&
                        !feof(stdin))
                {
                        PQfinish(conn);
@@ -812,3 +1021,17 @@ executeQuery(PGconn *conn, const char *query)
 
        return res;
 }
+
+
+/*
+ * dumpTimestamp
+ */
+static void
+dumpTimestamp(char *msg)
+{
+       char            buf[256];
+       time_t          now = time(NULL);
+
+       if (strftime(buf, 256, "%Y-%m-%d %H:%M:%S %Z", localtime(&now)) != 0)
+               printf("-- %s %s\n\n", msg, buf);
+}