]> granicus.if.org Git - postgresql/blobdiff - src/bin/pg_dump/pg_dumpall.c
Update copyrights to 2003.
[postgresql] / src / bin / pg_dump / pg_dumpall.c
index 4421d13e060f0dc3aa7f79bbbe25e8c0fdbd196c..9be39ecb759c783bc177fc6dd66f50a8e63c44e8 100644 (file)
@@ -2,11 +2,11 @@
  *
  * pg_dumpall
  *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.13 2003/01/16 15:27:59 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.26 2003/08/04 02:40:09 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,7 +27,7 @@
 
 #ifndef HAVE_GETOPT_LONG
 #include "getopt_long.h"
-int optreset;
+int                    optreset;
 #endif
 
 #include "dumputils.h"
@@ -60,6 +60,7 @@ static char *findPgDump(const char *argv0);
 char      *pgdumploc;
 PQExpBuffer pgdumpopts;
 bool           output_clean = false;
+bool           skip_acls = false;
 bool           verbose = false;
 int                    server_version;
 
@@ -72,22 +73,29 @@ main(int argc, char *argv[])
        char       *pgport = NULL;
        char       *pguser = NULL;
        bool            force_password = false;
+       bool            data_only = false;
        bool            globals_only = false;
+       bool            schema_only = false;
        PGconn     *conn;
        int                     c;
 
        static struct option long_options[] = {
+               {"data-only", no_argument, NULL, 'a'},
                {"clean", no_argument, NULL, 'c'},
                {"inserts", no_argument, NULL, 'd'},
                {"attribute-inserts", no_argument, NULL, 'D'},
                {"column-inserts", no_argument, NULL, 'D'},
+               {"globals-only", no_argument, NULL, 'g'},
                {"host", required_argument, NULL, 'h'},
                {"ignore-version", no_argument, NULL, 'i'},
                {"oids", no_argument, NULL, 'o'},
                {"port", required_argument, NULL, 'p'},
                {"password", no_argument, NULL, 'W'},
+               {"schema-only", no_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'},
                {NULL, 0, NULL, 0}
        };
 
@@ -99,10 +107,7 @@ main(int argc, char *argv[])
        textdomain("pg_dump");
 #endif
 
-       if (!strrchr(argv[0], '/'))
-               progname = argv[0];
-       else
-               progname = strrchr(argv[0], '/') + 1;
+       progname = get_progname(argv[0]);
 
        if (argc > 1)
        {
@@ -121,10 +126,15 @@ main(int argc, char *argv[])
        pgdumploc = findPgDump(argv[0]);
        pgdumpopts = createPQExpBuffer();
 
-       while ((c = getopt_long(argc, argv, "cdDgh:iop:U:vW", long_options, &optindex)) != -1)
+       while ((c = getopt_long(argc, argv, "acdDgh:iop:sU:vWx", long_options, &optindex)) != -1)
        {
                switch (c)
                {
+                       case 'a':
+                               data_only = true;
+                               appendPQExpBuffer(pgdumpopts, " -a");
+                               break;
+
                        case 'c':
                                output_clean = true;
                                break;
@@ -153,6 +163,11 @@ main(int argc, char *argv[])
                                appendPQExpBuffer(pgdumpopts, " -p '%s'", pgport);
                                break;
 
+                       case 's':
+                               schema_only = true;
+                               appendPQExpBuffer(pgdumpopts, " -s");
+                               break;
+
                        case 'U':
                                pguser = optarg;
                                appendPQExpBuffer(pgdumpopts, " -U '%s'", pguser);
@@ -168,18 +183,23 @@ main(int argc, char *argv[])
                                appendPQExpBuffer(pgdumpopts, " -W");
                                break;
 
+                       case 'x':
+                               skip_acls = true;
+                               appendPQExpBuffer(pgdumpopts, " -x");
+                               break;
+
                        default:
-                               fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
+                               fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
                                exit(1);
                }
        }
 
        if (optind < argc)
        {
-               fprintf(stderr,
-                               _("%s: too many command line options (first is '%s')\n"
-                                 "Try '%s --help' for more information.\n"),
-                               progname, argv[optind], progname);
+               fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
+                               progname, argv[optind]);
+               fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+                               progname);
                exit(1);
        }
 
@@ -191,16 +211,19 @@ main(int argc, char *argv[])
        printf("--\n\n");
        printf("\\connect \"template1\"\n\n");
 
-       dumpUsers(conn);
-       dumpGroups(conn);
-
-       if (globals_only)
-               goto end;
+       if (!data_only)
+       {
+               dumpUsers(conn);
+               dumpGroups(conn);
+       }
 
-       dumpCreateDB(conn);
-       dumpDatabases(conn);
+       if (!globals_only)
+       {
+               if (!data_only)
+                       dumpCreateDB(conn);
+               dumpDatabases(conn);
+       }
 
-end:
        PQfinish(conn);
        exit(0);
 }
@@ -215,19 +238,22 @@ help(void)
        printf(_("  %s [OPTION]...\n"), progname);
 
        printf(_("\nOptions:\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(_("  -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(_("\nConnection options:\n"));
-       printf(_("  -h, --host=HOSTNAME      database server host name\n"));
+       printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
        printf(_("  -p, --port=PORT          database server port number\n"));
        printf(_("  -U, --username=NAME      connect as specified database user\n"));
        printf(_("  -W, --password           force password prompt (should happen automatically)\n"));
@@ -250,10 +276,18 @@ dumpUsers(PGconn *conn)
        printf("--\n-- Users\n--\n\n");
        printf("DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');\n\n");
 
-       res = executeQuery(conn,
-                                          "SELECT usename, usesysid, passwd, usecreatedb, usesuper, CAST(valuntil AS timestamp) "
-                                          "FROM pg_shadow "
-                                          "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');");
+       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')");
+       else
+               res = executeQuery(conn,
+                                               "SELECT usename, usesysid, passwd, usecreatedb, "
+                                                  "usesuper, valuntil "
+                                                  "FROM pg_shadow "
+                                                  "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template1')");
 
        for (i = 0; i < PQntuples(res); i++)
        {
@@ -282,7 +316,8 @@ dumpUsers(PGconn *conn)
                        appendPQExpBuffer(buf, " NOCREATEUSER");
 
                if (!PQgetisnull(res, i, 5))
-                       appendPQExpBuffer(buf, " VALID UNTIL '%s'", PQgetvalue(res, i, 5));
+                       appendPQExpBuffer(buf, " VALID UNTIL '%s'",
+                                                         PQgetvalue(res, i, 5));
 
                appendPQExpBuffer(buf, ";\n");
 
@@ -311,7 +346,7 @@ dumpGroups(PGconn *conn)
        printf("--\n-- Groups\n--\n\n");
        printf("DELETE FROM pg_group;\n\n");
 
-       res = executeQuery(conn, "SELECT groname, grosysid, grolist FROM pg_group;");
+       res = executeQuery(conn, "SELECT groname, grosysid, grolist FROM pg_group");
 
        for (i = 0; i < PQntuples(res); i++)
        {
@@ -325,7 +360,7 @@ dumpGroups(PGconn *conn)
 
                val = strdup(PQgetvalue(res, i, 2));
                tok = strtok(val, ",{}");
-               do
+               while (tok)
                {
                        PGresult   *res2;
                        PQExpBuffer buf2 = createPQExpBuffer();
@@ -345,7 +380,7 @@ dumpGroups(PGconn *conn)
 
                        tok = strtok(NULL, "{},");
                }
-               while (tok);
+               free(val);
 
                printf("%s", buf->data);
                destroyPQExpBuffer(buf);
@@ -376,11 +411,38 @@ dumpCreateDB(PGconn *conn)
 
        printf("--\n-- Database creation\n--\n\n");
 
-       /*
-        * Basically this query returns: dbname, dbowner, encoding,
-        * istemplate, dbpath
-        */
-       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 FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) WHERE datallowconn ORDER BY 1;");
+       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, datpath, datacl "
+               "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
+                                                  "WHERE datallowconn ORDER BY 1");
+       else if (server_version >= 70100)
+               res = executeQuery(conn,
+                                                  "SELECT datname, "
+                                                  "coalesce("
+                               "(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 "
+                                                  "FROM pg_database d "
+                                                  "WHERE datallowconn ORDER BY 1");
+       else
+       {
+               /*
+                * Note: 7.0 fails to cope with sub-select in COALESCE, so just
+                * deal with getting a NULL by not printing any OWNER clause.
+                */
+               res = executeQuery(conn,
+                                                  "SELECT datname, "
+                               "(select usename from pg_shadow where usesysid=datdba), "
+                                                  "pg_encoding_to_char(d.encoding), "
+                                                  "'f' as datistemplate, datpath, '' as datacl "
+                                                  "FROM pg_database d "
+                                                  "ORDER BY 1");
+       }
 
        for (i = 0; i < PQntuples(res); i++)
        {
@@ -390,19 +452,27 @@ dumpCreateDB(PGconn *conn)
                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       *fdbname;
 
                if (strcmp(dbname, "template1") == 0)
                        continue;
 
                buf = createPQExpBuffer();
 
+               /* needed for buildACLCommands() */
+               fdbname = strdup(fmtId(dbname));
+
                if (output_clean)
-                       appendPQExpBuffer(buf, "DROP DATABASE %s;\n", fmtId(dbname));
+                       appendPQExpBuffer(buf, "DROP DATABASE %s;\n", fdbname);
 
-               appendPQExpBuffer(buf, "CREATE DATABASE %s", fmtId(dbname));
-               appendPQExpBuffer(buf, " WITH OWNER = %s TEMPLATE = template0", fmtId(dbowner));
+               appendPQExpBuffer(buf, "CREATE DATABASE %s", fdbname);
+               if (strlen(dbowner) != 0)
+                       appendPQExpBuffer(buf, " WITH OWNER = %s",
+                                                         fmtId(dbowner));
+               appendPQExpBuffer(buf, " TEMPLATE = template0");
 
-               if (strcmp(dbpath, "") != 0)
+               if (strlen(dbpath) != 0)
                {
                        appendPQExpBuffer(buf, " LOCATION = ");
                        appendStringLiteral(buf, dbpath, true);
@@ -419,8 +489,20 @@ dumpCreateDB(PGconn *conn)
                        appendStringLiteral(buf, dbname, true);
                        appendPQExpBuffer(buf, ";\n");
                }
+
+               if (!skip_acls &&
+                       !buildACLCommands(fdbname, "DATABASE", dbacl, dbowner,
+                                                         server_version, buf))
+               {
+                       fprintf(stderr, _("%s: could not parse ACL list (%s) for database \"%s\"\n"),
+                                       progname, dbacl, fdbname);
+                       PQfinish(conn);
+                       exit(1);
+               }
+
                printf("%s", buf->data);
                destroyPQExpBuffer(buf);
+               free(fdbname);
 
                if (server_version >= 70300)
                        dumpDatabaseConfig(conn, dbname);
@@ -541,7 +623,11 @@ dumpDatabases(PGconn *conn)
        PGresult   *res;
        int                     i;
 
-       res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;");
+       if (server_version >= 70100)
+               res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1");
+       else
+               res = executeQuery(conn, "SELECT datname FROM pg_database ORDER BY 1");
+
        for (i = 0; i < PQntuples(res); i++)
        {
                int                     ret;
@@ -551,11 +637,11 @@ dumpDatabases(PGconn *conn)
                if (verbose)
                        fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
 
-               printf("\\connect %s\n", fmtId(dbname));
+               printf("\\connect %s\n\n", fmtId(dbname));
                ret = runPgDump(dbname);
                if (ret != 0)
                {
-                       fprintf(stderr, _("%s: pg_dump failed on %s, exiting\n"), progname, dbname);
+                       fprintf(stderr, _("%s: pg_dump failed on database \"%s\", exiting\n"), progname, dbname);
                        exit(1);
                }
        }
@@ -590,7 +676,7 @@ runPgDump(const char *dbname)
        appendPQExpBufferChar(cmd, '\'');
 
        if (verbose)
-               fprintf(stderr, _("%s: running %s\n"), progname, cmd->data);
+               fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data);
 
        fflush(stdout);
        fflush(stderr);
@@ -615,7 +701,7 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
        PGconn     *conn;
        char       *password = NULL;
        bool            need_pass = false;
-       PGresult   *res;
+       const char *remoteversion_str;
 
        if (require_password)
                password = simple_prompt("Password: ", 100, false);
@@ -631,7 +717,7 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
 
                if (!conn)
                {
-                       fprintf(stderr, _("%s: could not connect to database %s\n"),
+                       fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
                                        progname, dbname);
                        exit(1);
                }
@@ -654,28 +740,24 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
        /* check to see that the backend connection was successfully made */
        if (PQstatus(conn) == CONNECTION_BAD)
        {
-               fprintf(stderr, _("%s: could not connect to database %s: %s\n"),
+               fprintf(stderr, _("%s: could not connect to database \"%s\": %s\n"),
                                progname, dbname, PQerrorMessage(conn));
                exit(1);
        }
 
-       res = executeQuery(conn, "SELECT version();");
-       if (PQntuples(res) != 1)
+       remoteversion_str = PQparameterStatus(conn, "server_version");
+       if (!remoteversion_str)
        {
                fprintf(stderr, _("%s: could not get server version\n"), progname);
                exit(1);
        }
-       else
+       server_version = parse_version(remoteversion_str);
+       if (server_version < 0)
        {
-               char *val = PQgetvalue(res, 0, 0);
-               server_version = parse_version(val + strcspn(val, "0123456789"));
-               if (server_version < 0)
-               {
-                       fprintf(stderr, _("%s: could not parse server version \"%s\"\n"), progname, val);
-                       exit(1);
-               }
+               fprintf(stderr, _("%s: could not parse server version \"%s\"\n"),
+                               progname, remoteversion_str);
+               exit(1);
        }
-       PQclear(res);
 
        return conn;
 }
@@ -690,6 +772,9 @@ executeQuery(PGconn *conn, const char *query)
 {
        PGresult   *res;
 
+       if (verbose)
+               fprintf(stderr, _("%s: executing %s\n"), progname, query);
+
        res = PQexec(conn, query);
        if (!res ||
                PQresultStatus(res) != PGRES_TUPLES_OK)
@@ -719,7 +804,7 @@ findPgDump(const char *argv0)
                return result;
 
        cmd = createPQExpBuffer();
-       last = strrchr(argv0, '/');
+       last = last_path_separator(argv0);
 
        if (!last)
                appendPQExpBuffer(cmd, "pg_dump");