mirror of
https://github.com/postgres/postgres.git
synced 2025-05-23 00:02:38 -04:00
pg_dump -z has gotten rather thoroughly broken in the last couple
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
This commit is contained in:
parent
b41468dad2
commit
916710fc91
@ -21,7 +21,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* 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 *AddAcl(char *s, const char *add);
|
||||||
static char *GetPrivledges(char *s);
|
static char *GetPrivledges(char *s);
|
||||||
static ACL *ParseACL(const char *acls, int *count);
|
static ACL *ParseACL(const char *acls, int *count);
|
||||||
|
static void becomeUser(FILE *fout, const char *username);
|
||||||
|
|
||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind,
|
extern int optind,
|
||||||
@ -110,6 +111,7 @@ int dumpData; /* dump data using proper insert strings */
|
|||||||
int attrNames; /* put attr names into insert strings */
|
int attrNames; /* put attr names into insert strings */
|
||||||
int schemaOnly;
|
int schemaOnly;
|
||||||
int dataOnly;
|
int dataOnly;
|
||||||
|
int aclsOption;
|
||||||
|
|
||||||
char g_opaque_type[10]; /* name for the opaque type */
|
char g_opaque_type[10]; /* name for the opaque type */
|
||||||
|
|
||||||
@ -141,12 +143,12 @@ usage(const char *progname)
|
|||||||
"\t -s \t\t dump out only the schema, no data\n");
|
"\t -s \t\t dump out only the schema, no data\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\t -t table \t\t dump for this table only\n");
|
"\t -t table \t\t dump for this table only\n");
|
||||||
|
fprintf(stderr,
|
||||||
|
"\t -u \t\t use password authentication\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\t -v \t\t verbose\n");
|
"\t -v \t\t verbose\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\t -z \t\t dump ACLs (grant/revoke)\n");
|
"\t -z \t\t dump ACLs (grant/revoke)\n");
|
||||||
fprintf(stderr,
|
|
||||||
"\t -u \t\t use password authentication\n");
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\nIf dbname is not supplied, then the DATABASE environment "
|
"\nIf dbname is not supplied, then the DATABASE environment "
|
||||||
"variable value is used.\n");
|
"variable value is used.\n");
|
||||||
@ -435,7 +437,7 @@ dumpClasses(const TableInfo tblinfo[], const int numTables, FILE *fout,
|
|||||||
if (g_verbose)
|
if (g_verbose)
|
||||||
fprintf(stderr, "%s dumping out schema of sequence '%s' %s\n",
|
fprintf(stderr, "%s dumping out schema of sequence '%s' %s\n",
|
||||||
g_comment_start, tblinfo[i].relname, g_comment_end);
|
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]);
|
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",
|
fprintf(stderr, "%s dumping out the contents of Table '%s' %s\n",
|
||||||
g_comment_start, classname, g_comment_end);
|
g_comment_start, classname, g_comment_end);
|
||||||
|
|
||||||
|
becomeUser(fout, tblinfo[i].usename);
|
||||||
|
|
||||||
if (!dumpData)
|
if (!dumpData)
|
||||||
dumpClasses_nodumpData(fout, classname, oids);
|
dumpClasses_nodumpData(fout, classname, oids);
|
||||||
else
|
else
|
||||||
@ -534,8 +538,7 @@ main(int argc, char **argv)
|
|||||||
const char *pghost = NULL;
|
const char *pghost = NULL;
|
||||||
const char *pgport = NULL;
|
const char *pgport = NULL;
|
||||||
char *tablename = NULL;
|
char *tablename = NULL;
|
||||||
int oids = 0,
|
int oids = 0;
|
||||||
acls = 0;
|
|
||||||
TableInfo *tblinfo;
|
TableInfo *tblinfo;
|
||||||
int numTables;
|
int numTables;
|
||||||
char connect_string[512] = "";
|
char connect_string[512] = "";
|
||||||
@ -598,8 +601,8 @@ main(int argc, char **argv)
|
|||||||
case 'v': /* verbose */
|
case 'v': /* verbose */
|
||||||
g_verbose = true;
|
g_verbose = true;
|
||||||
break;
|
break;
|
||||||
case 'z': /* Dump oids */
|
case 'z': /* Dump ACLs and table ownership info */
|
||||||
acls = 1;
|
aclsOption = 1;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
use_password = 1;
|
use_password = 1;
|
||||||
@ -657,11 +660,11 @@ main(int argc, char **argv)
|
|||||||
strcat(connect_string, tmp_string);
|
strcat(connect_string, tmp_string);
|
||||||
sprintf(tmp_string, "password=%s ", password);
|
sprintf(tmp_string, "password=%s ", password);
|
||||||
strcat(connect_string, tmp_string);
|
strcat(connect_string, tmp_string);
|
||||||
bzero(tmp_string, sizeof(tmp_string));
|
MemSet(tmp_string, 0, sizeof(tmp_string));
|
||||||
bzero(password, sizeof(password));
|
MemSet(password, 0, sizeof(password));
|
||||||
}
|
}
|
||||||
g_conn = PQconnectdb(connect_string);
|
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 */
|
/* check to see that the backend connection was successfully made */
|
||||||
if (PQstatus(g_conn) == CONNECTION_BAD)
|
if (PQstatus(g_conn) == CONNECTION_BAD)
|
||||||
{
|
{
|
||||||
@ -679,10 +682,10 @@ main(int argc, char **argv)
|
|||||||
if (g_verbose)
|
if (g_verbose)
|
||||||
fprintf(stderr, "%s last builtin oid is %d %s\n",
|
fprintf(stderr, "%s last builtin oid is %d %s\n",
|
||||||
g_comment_start, g_last_builtin_oid, g_comment_end);
|
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
|
else
|
||||||
tblinfo = dumpSchema(NULL, &numTables, tablename, acls);
|
tblinfo = dumpSchema(NULL, &numTables, tablename, aclsOption);
|
||||||
|
|
||||||
if (!schemaOnly)
|
if (!schemaOnly)
|
||||||
dumpClasses(tblinfo, numTables, g_fout, tablename, oids);
|
dumpClasses(tblinfo, numTables, g_fout, tablename, oids);
|
||||||
@ -1961,7 +1964,7 @@ dumpTypes(FILE *fout, FuncInfo *finfo, int numFuncs,
|
|||||||
if (funcInd != -1)
|
if (funcInd != -1)
|
||||||
dumpOneFunc(fout, finfo, funcInd, tinfo, numTypes);
|
dumpOneFunc(fout, finfo, funcInd, tinfo, numTypes);
|
||||||
|
|
||||||
fprintf(fout, "\\connect - %s\n", tinfo[i].usename);
|
becomeUser(fout, tinfo[i].usename);
|
||||||
|
|
||||||
sprintf(q,
|
sprintf(q,
|
||||||
"CREATE TYPE \"%s\" "
|
"CREATE TYPE \"%s\" "
|
||||||
@ -2028,7 +2031,7 @@ dumpOneFunc(FILE *fout, FuncInfo *finfo, int i,
|
|||||||
else
|
else
|
||||||
finfo[i].dumped = 1;
|
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);
|
sprintf(q, "CREATE FUNCTION \"%s\" (", finfo[i].proname);
|
||||||
for (j = 0; j < finfo[i].nargs; j++)
|
for (j = 0; j < finfo[i].nargs; j++)
|
||||||
@ -2143,7 +2146,7 @@ dumpOprs(FILE *fout, OprInfo *oprinfo, int numOperators,
|
|||||||
oprinfo[i].oprlsortop));
|
oprinfo[i].oprlsortop));
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fout, "\\connect - %s\n", oprinfo[i].usename);
|
becomeUser(fout, oprinfo[i].usename);
|
||||||
|
|
||||||
sprintf(q,
|
sprintf(q,
|
||||||
"CREATE OPERATOR %s "
|
"CREATE OPERATOR %s "
|
||||||
@ -2238,7 +2241,7 @@ dumpAggs(FILE *fout, AggInfo *agginfo, int numAggs,
|
|||||||
else
|
else
|
||||||
comma2[0] = '\0';
|
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",
|
sprintf(q, "CREATE AGGREGATE %s ( %s %s%s %s%s %s );\n",
|
||||||
agginfo[i].aggname,
|
agginfo[i].aggname,
|
||||||
@ -2349,7 +2352,7 @@ ParseACL(const char *acls, int *count)
|
|||||||
s = strdup(acls);
|
s = strdup(acls);
|
||||||
|
|
||||||
/* Setup up public */
|
/* Setup up public */
|
||||||
ParsedAcl[0].user = strdup("Public");
|
ParsedAcl[0].user = NULL; /* indicates PUBLIC */
|
||||||
tok = strtok(s, ",");
|
tok = strtok(s, ",");
|
||||||
ParsedAcl[0].privledges = GetPrivledges(strchr(tok, '='));
|
ParsedAcl[0].privledges = GetPrivledges(strchr(tok, '='));
|
||||||
|
|
||||||
@ -2397,18 +2400,25 @@ dumpACL(FILE *fout, TableInfo tbinfo)
|
|||||||
|
|
||||||
/* Revoke Default permissions for PUBLIC */
|
/* Revoke Default permissions for PUBLIC */
|
||||||
fprintf(fout,
|
fprintf(fout,
|
||||||
"REVOKE ALL on '%s' from PUBLIC;\n",
|
"REVOKE ALL on \"%s\" from PUBLIC;\n",
|
||||||
tbinfo.relname);
|
tbinfo.relname);
|
||||||
|
|
||||||
for (k = 0; k < l; k++)
|
for (k = 0; k < l; k++)
|
||||||
{
|
{
|
||||||
if (ACLlist[k].privledges != (char *) NULL)
|
if (ACLlist[k].privledges != (char *) NULL)
|
||||||
|
{
|
||||||
|
if (ACLlist[k].user == (char *) NULL)
|
||||||
|
fprintf(fout,
|
||||||
|
"GRANT %s on \"%s\" to PUBLIC;\n",
|
||||||
|
ACLlist[k].privledges, tbinfo.relname);
|
||||||
|
else
|
||||||
fprintf(fout,
|
fprintf(fout,
|
||||||
"GRANT %s on \"%s\" to \"%s\";\n",
|
"GRANT %s on \"%s\" to \"%s\";\n",
|
||||||
ACLlist[k].privledges, tbinfo.relname,
|
ACLlist[k].privledges, tbinfo.relname,
|
||||||
ACLlist[k].user);
|
ACLlist[k].user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2437,7 +2447,7 @@ dumpTables(FILE *fout, TableInfo *tblinfo, int numTables,
|
|||||||
continue;
|
continue;
|
||||||
if (!tablename || (!strcmp(tblinfo[i].relname, tablename)))
|
if (!tablename || (!strcmp(tblinfo[i].relname, tablename)))
|
||||||
{
|
{
|
||||||
fprintf(fout, "\\connect - %s\n", tblinfo[i].usename);
|
becomeUser(fout, tblinfo[i].usename);
|
||||||
dumpSequence(fout, tblinfo[i]);
|
dumpSequence(fout, tblinfo[i]);
|
||||||
if (acls)
|
if (acls)
|
||||||
dumpACL(fout, tblinfo[i]);
|
dumpACL(fout, tblinfo[i]);
|
||||||
@ -2459,7 +2469,7 @@ dumpTables(FILE *fout, TableInfo *tblinfo, int numTables,
|
|||||||
parentRels = tblinfo[i].parentRels;
|
parentRels = tblinfo[i].parentRels;
|
||||||
numParents = tblinfo[i].numParents;
|
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));
|
sprintf(q, "CREATE TABLE \"%s\" (", fmtId(tblinfo[i].relname));
|
||||||
actual_atts = 0;
|
actual_atts = 0;
|
||||||
@ -2954,8 +2964,30 @@ dumpTriggers(FILE *fout, const char *tablename,
|
|||||||
continue;
|
continue;
|
||||||
for (j = 0; j < tblinfo[i].ntrig; j++)
|
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);
|
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;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
.\" This is -*-nroff-*-
|
.\" This is -*-nroff-*-
|
||||||
.\" XXX standard disclaimer belongs here....
|
.\" 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 $
|
.\" $Header: /cvsroot/pgsql/src/man/Attic/pg_dump.1,v 1.12 1998/07/19 05:24:51 momjian Exp $
|
||||||
.TH PG_DUMP UNIX 1/20/96 PostgreSQL PostgreSQL
|
.TH PG_DUMP UNIX 7/15/98 PostgreSQL PostgreSQL
|
||||||
.SH NAME
|
.SH NAME
|
||||||
pg_dump - dumps out a Postgres database into a script file
|
pg_dump - dumps out a Postgres database into a script file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -36,23 +36,27 @@ port]
|
|||||||
.BR "-t"
|
.BR "-t"
|
||||||
table]
|
table]
|
||||||
[\c
|
[\c
|
||||||
|
.BR "-u"
|
||||||
|
]
|
||||||
|
[\c
|
||||||
.BR "-v"
|
.BR "-v"
|
||||||
]
|
]
|
||||||
[\c
|
[\c
|
||||||
.BR "-u"]
|
.BR "-z"
|
||||||
|
]
|
||||||
dbname
|
dbname
|
||||||
.in -5n
|
.in -5n
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.IR "pg_dump"
|
.IR "pg_dump"
|
||||||
is a utility for dumping out a
|
is a utility for dumping out a
|
||||||
Postgres database into a script file containing query commands. The script
|
Postgres database into a script file containing query commands. The script
|
||||||
files are in a 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.
|
even on other machines and other architectures.
|
||||||
.IR "pg_dump"
|
.IR "pg_dump"
|
||||||
will produce the queries necessary to re-generate all
|
will produce the queries necessary to re-generate all
|
||||||
user-defined types, functions, tables, indices, aggregates, and
|
user-defined types, functions, tables, indices, aggregates, and
|
||||||
operators. In addition, all the data is copied out in ASCII format so
|
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.
|
for textual editing.
|
||||||
.PP
|
.PP
|
||||||
.IR "pg_dump"
|
.IR "pg_dump"
|
||||||
@ -92,10 +96,13 @@ Dump out only the schema, no data
|
|||||||
Dump for this table only
|
Dump for this table only
|
||||||
.TP
|
.TP
|
||||||
.BR "-u"
|
.BR "-u"
|
||||||
Use password authentication. Prompts for username and password.
|
Use password authentication. Prompts for username and password
|
||||||
.TP
|
.TP
|
||||||
.BR "-v" ""
|
.BR "-v" ""
|
||||||
Specifies verbose mode
|
Specifies verbose mode
|
||||||
|
.TP
|
||||||
|
.BR "-z" ""
|
||||||
|
Include ACLs (grant/revoke commands) and table ownership information
|
||||||
.PP
|
.PP
|
||||||
If dbname is not supplied, then the DATABASE environment variable value is used.
|
If dbname is not supplied, then the DATABASE environment variable value is used.
|
||||||
.SH "CAVEATS AND LIMITATIONS"
|
.SH "CAVEATS AND LIMITATIONS"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user