OSDN Git Service

pg_dump -z has gotten rather thoroughly broken in the last couple
authorBruce Momjian <bruce@momjian.us>
Sun, 19 Jul 1998 05:24:51 +0000 (05:24 +0000)
committerBruce Momjian <bruce@momjian.us>
Sun, 19 Jul 1998 05:24:51 +0000 (05:24 +0000)
of days --- it was emitting stuff like
REVOKE ALL on 'table' from PUBLIC; GRANT ALL on "table" to
"Public"; neither of which work.  While I was at it I
cleaned up a few other things:

* \connect commands are issued only in -z mode.  In this way,
reloading a pg_dump script made without -z will generate a simple
database wholly owned by the invoking user, rather than a mishmash
of tables owned by various people but lacking in access rights.
(Analogy: cp versus cp -p.)

* \connect commands are issued just before COPY FROM stdin commands;
without this, reloading a database containing non-world-writable
tables tended to fail because the COPY was not necessarily attempted
as the table owner.

* Redundant \connect commands are suppressed (each one costs a
backend launch, so...).

* Man page updated (-z wasn't ever documented).

The first two items were discussed in a pgsql-hackers thread around
6 May 98 ("An item for the TODO list: pg_dump and multiple table
owners") but no one had bothered to deal with 'em yet.

regards, tom lane

src/bin/pg_dump/pg_dump.c
src/man/pg_dump.1

index 45e9a81..ad68b9f 100644 (file)
@@ -21,7 +21,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.77 1998/07/08 14:33:19 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.78 1998/07/19 05:24:49 momjian Exp $
  *
  * Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb
  *
@@ -95,6 +95,7 @@ static void setMaxOid(FILE *fout);
 static char *AddAcl(char *s, const char *add);
 static char *GetPrivledges(char *s);
 static ACL *ParseACL(const char *acls, int *count);
+static void becomeUser(FILE *fout, const char *username);
 
 extern char *optarg;
 extern int     optind,
@@ -110,6 +111,7 @@ int                 dumpData;                       /* dump data using proper insert strings */
 int                    attrNames;                      /* put attr names into insert strings */
 int                    schemaOnly;
 int                    dataOnly;
+int                    aclsOption;
 
 char           g_opaque_type[10];      /* name for the opaque type */
 
@@ -142,12 +144,12 @@ usage(const char *progname)
        fprintf(stderr,
                        "\t -t table    \t\t dump for this table only\n");
        fprintf(stderr,
+                       "\t -u          \t\t use password authentication\n");
+       fprintf(stderr,
                        "\t -v          \t\t verbose\n");
        fprintf(stderr,
                        "\t -z          \t\t dump ACLs (grant/revoke)\n");
        fprintf(stderr,
-                       "\t -u          \t\t use password authentication\n");
-       fprintf(stderr,
                        "\nIf dbname is not supplied, then the DATABASE environment "
                        "variable value is used.\n");
        fprintf(stderr, "\n");
@@ -435,7 +437,7 @@ dumpClasses(const TableInfo tblinfo[], const int numTables, FILE *fout,
                                if (g_verbose)
                                        fprintf(stderr, "%s dumping out schema of sequence '%s' %s\n",
                                         g_comment_start, tblinfo[i].relname, g_comment_end);
-                               fprintf(fout, "\\connect - %s\n", tblinfo[i].usename);
+                               becomeUser(fout, tblinfo[i].usename);
                                dumpSequence(fout, tblinfo[i]);
                        }
                }
@@ -458,6 +460,8 @@ dumpClasses(const TableInfo tblinfo[], const int numTables, FILE *fout,
                                fprintf(stderr, "%s dumping out the contents of Table '%s' %s\n",
                                                g_comment_start, classname, g_comment_end);
 
+                       becomeUser(fout, tblinfo[i].usename);
+
                        if (!dumpData)
                                dumpClasses_nodumpData(fout, classname, oids);
                        else
@@ -534,8 +538,7 @@ main(int argc, char **argv)
        const char *pghost = NULL;
        const char *pgport = NULL;
        char       *tablename = NULL;
-       int                     oids = 0,
-                               acls = 0;
+       int                     oids = 0;
        TableInfo  *tblinfo;
        int                     numTables;
        char            connect_string[512] = "";
@@ -598,8 +601,8 @@ main(int argc, char **argv)
                        case 'v':                       /* verbose */
                                g_verbose = true;
                                break;
-                       case 'z':                       /* Dump oids */
-                               acls = 1;
+                       case 'z':                       /* Dump ACLs and table ownership info */
+                               aclsOption = 1;
                                break;
                        case 'u':
                                use_password = 1;
@@ -657,11 +660,11 @@ main(int argc, char **argv)
                strcat(connect_string, tmp_string);
                sprintf(tmp_string, "password=%s ", password);
                strcat(connect_string, tmp_string);
-               bzero(tmp_string, sizeof(tmp_string));
-               bzero(password, sizeof(password));
+               MemSet(tmp_string, 0, sizeof(tmp_string));
+               MemSet(password, 0, sizeof(password));
        }
        g_conn = PQconnectdb(connect_string);
-       bzero(connect_string, sizeof(connect_string));
+       MemSet(connect_string, 0, sizeof(connect_string));
        /* check to see that the backend connection was successfully made */
        if (PQstatus(g_conn) == CONNECTION_BAD)
        {
@@ -679,10 +682,10 @@ main(int argc, char **argv)
                if (g_verbose)
                        fprintf(stderr, "%s last builtin oid is %d %s\n",
                                        g_comment_start, g_last_builtin_oid, g_comment_end);
-               tblinfo = dumpSchema(g_fout, &numTables, tablename, acls);
+               tblinfo = dumpSchema(g_fout, &numTables, tablename, aclsOption);
        }
        else
-               tblinfo = dumpSchema(NULL, &numTables, tablename, acls);
+               tblinfo = dumpSchema(NULL, &numTables, tablename, aclsOption);
 
        if (!schemaOnly)
                dumpClasses(tblinfo, numTables, g_fout, tablename, oids);
@@ -1961,7 +1964,7 @@ dumpTypes(FILE *fout, FuncInfo *finfo, int numFuncs,
                if (funcInd != -1)
                        dumpOneFunc(fout, finfo, funcInd, tinfo, numTypes);
 
-               fprintf(fout, "\\connect - %s\n", tinfo[i].usename);
+               becomeUser(fout, tinfo[i].usename);
 
                sprintf(q,
                                "CREATE TYPE \"%s\" "
@@ -2028,7 +2031,7 @@ dumpOneFunc(FILE *fout, FuncInfo *finfo, int i,
        else
                finfo[i].dumped = 1;
 
-       fprintf(fout, "\\connect - %s\n", finfo[i].usename);
+       becomeUser(fout, finfo[i].usename);
 
        sprintf(q, "CREATE FUNCTION \"%s\" (", finfo[i].proname);
        for (j = 0; j < finfo[i].nargs; j++)
@@ -2143,7 +2146,7 @@ dumpOprs(FILE *fout, OprInfo *oprinfo, int numOperators,
                                                                         oprinfo[i].oprlsortop));
                }
 
-               fprintf(fout, "\\connect - %s\n", oprinfo[i].usename);
+               becomeUser(fout, oprinfo[i].usename);
 
                sprintf(q,
                                "CREATE OPERATOR %s "
@@ -2238,7 +2241,7 @@ dumpAggs(FILE *fout, AggInfo *agginfo, int numAggs,
                else
                        comma2[0] = '\0';
 
-               fprintf(fout, "\\connect - %s\n", agginfo[i].usename);
+               becomeUser(fout, agginfo[i].usename);
 
                sprintf(q, "CREATE AGGREGATE %s ( %s %s%s %s%s %s );\n",
                                agginfo[i].aggname,
@@ -2349,7 +2352,7 @@ ParseACL(const char *acls, int *count)
        s = strdup(acls);
 
        /* Setup up public */
-       ParsedAcl[0].user = strdup("Public");
+       ParsedAcl[0].user = NULL;       /* indicates PUBLIC */
        tok = strtok(s, ",");
        ParsedAcl[0].privledges = GetPrivledges(strchr(tok, '='));
 
@@ -2397,16 +2400,23 @@ dumpACL(FILE *fout, TableInfo tbinfo)
 
        /* Revoke Default permissions for PUBLIC */
        fprintf(fout,
-                       "REVOKE ALL on '%s' from PUBLIC;\n",
+                       "REVOKE ALL on \"%s\" from PUBLIC;\n",
                        tbinfo.relname);
 
        for (k = 0; k < l; k++)
        {
                if (ACLlist[k].privledges != (char *) NULL)
-                       fprintf(fout,
-                                       "GRANT %s on \"%s\" to \"%s\";\n",
-                                       ACLlist[k].privledges, tbinfo.relname,
-                                       ACLlist[k].user);
+               {
+                       if (ACLlist[k].user == (char *) NULL)
+                               fprintf(fout,
+                                               "GRANT %s on \"%s\" to PUBLIC;\n",
+                                               ACLlist[k].privledges, tbinfo.relname);
+                       else
+                               fprintf(fout,
+                                               "GRANT %s on \"%s\" to \"%s\";\n",
+                                               ACLlist[k].privledges, tbinfo.relname,
+                                               ACLlist[k].user);
+               }
        }
 }
 
@@ -2437,7 +2447,7 @@ dumpTables(FILE *fout, TableInfo *tblinfo, int numTables,
                        continue;
                if (!tablename || (!strcmp(tblinfo[i].relname, tablename)))
                {
-                       fprintf(fout, "\\connect - %s\n", tblinfo[i].usename);
+                       becomeUser(fout, tblinfo[i].usename);
                        dumpSequence(fout, tblinfo[i]);
                        if (acls)
                                dumpACL(fout, tblinfo[i]);
@@ -2459,7 +2469,7 @@ dumpTables(FILE *fout, TableInfo *tblinfo, int numTables,
                        parentRels = tblinfo[i].parentRels;
                        numParents = tblinfo[i].numParents;
 
-                       fprintf(fout, "\\connect - %s\n", tblinfo[i].usename);
+                       becomeUser(fout, tblinfo[i].usename);
 
                        sprintf(q, "CREATE TABLE \"%s\" (", fmtId(tblinfo[i].relname));
                        actual_atts = 0;
@@ -2954,8 +2964,30 @@ dumpTriggers(FILE *fout, const char *tablename,
                        continue;
                for (j = 0; j < tblinfo[i].ntrig; j++)
                {
-                       fprintf(fout, "\\connect - %s\n", tblinfo[i].usename);
+                       becomeUser(fout, tblinfo[i].usename);
                        fputs(tblinfo[i].triggers[j], fout);
                }
        }
 }
+
+
+/* Issue a psql \connect command to become the specified user.
+ * We want to do this only if we are dumping ACLs,
+ * and only if the new username is different from the last one
+ * (to avoid the overhead of useless backend launches).
+ */
+
+static void becomeUser(FILE *fout, const char *username)
+{
+       static const char *lastusername = "";
+
+       if (! aclsOption)
+               return;
+
+       if (strcmp(lastusername, username) == 0)
+               return;
+
+       fprintf(fout, "\\connect - %s\n", username);
+
+       lastusername = username;
+}
index c34fe32..67f04e6 100644 (file)
@@ -1,7 +1,7 @@
 .\" This is -*-nroff-*-
 .\" XXX standard disclaimer belongs here....
-.\" $Header: /cvsroot/pgsql/src/man/Attic/pg_dump.1,v 1.11 1998/06/24 13:21:28 momjian Exp $
-.TH PG_DUMP UNIX 1/20/96 PostgreSQL PostgreSQL
+.\" $Header: /cvsroot/pgsql/src/man/Attic/pg_dump.1,v 1.12 1998/07/19 05:24:51 momjian Exp $
+.TH PG_DUMP UNIX 7/15/98 PostgreSQL PostgreSQL
 .SH NAME
 pg_dump - dumps out a Postgres database into a script file
 .SH SYNOPSIS
@@ -36,23 +36,27 @@ port]
 .BR "-t"
 table]
 [\c
+.BR "-u"
+]
+[\c
 .BR "-v"
 ]
 [\c
-.BR "-u"]
+.BR "-z"
+]
 dbname
 .in -5n
 .SH DESCRIPTION
 .IR "pg_dump"
 is a utility for dumping out a 
 Postgres database into a script file containing query commands.  The script
-files are in ASCII format and can be used to reconstruct the database,
+files are in ASCII format and can be used to reconstruct the database,
 even on other machines and other architectures.  
 .IR "pg_dump" 
 will produce the queries necessary to re-generate all
 user-defined types, functions, tables, indices, aggregates, and
 operators.  In addition, all the data is copied out in ASCII format so
-that it can be readily copied in again, as well, as imported into tools
+that it can be readily copied in again, as well as imported into tools
 for textual editing.
 .PP
 .IR "pg_dump" 
@@ -92,10 +96,13 @@ Dump out only the schema, no data
 Dump for this table only
 .TP
 .BR "-u"
-Use password authentication. Prompts for username and password.
+Use password authentication. Prompts for username and password
 .TP
 .BR "-v" ""
 Specifies verbose mode
+.TP
+.BR "-z" ""
+Include ACLs (grant/revoke commands) and table ownership information
 .PP
 If dbname is not supplied, then the DATABASE environment variable value is used.
 .SH "CAVEATS AND LIMITATIONS"