Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0e1a507

Browse files
committed
Fix pg_dump to read-lock all tables to be dumped as soon as it's read
their names from pg_class. This considerably reduces the window wherein someone could DROP or ALTER a table that pg_dump is intending to dump. Not a perfect solution, but definitely an improvement. Per complaints from Marc Fournier; patch by Brent Verner with some kibitzing by Tom Lane.
1 parent 5c2d36c commit 0e1a507

File tree

3 files changed

+74
-21
lines changed

3 files changed

+74
-21
lines changed

src/bin/pg_dump/common.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.60 2001/10/25 05:49:52 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.61 2002/01/11 23:21:55 tgl Exp $
1212
*
1313
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
1414
*
@@ -309,7 +309,7 @@ dumpSchema(Archive *fout,
309309

310310
if (g_verbose)
311311
write_msg(NULL, "reading user-defined tables\n");
312-
tblinfo = getTables(&numTables, finfo, numFuncs);
312+
tblinfo = getTables(&numTables, finfo, numFuncs, tablename);
313313

314314
if (g_verbose)
315315
write_msg(NULL, "reading index information\n");

src/bin/pg_dump/pg_dump.c

+66-16
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*
2323
*
2424
* IDENTIFICATION
25-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.236 2001/10/28 06:25:58 momjian Exp $
25+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.237 2002/01/11 23:21:55 tgl Exp $
2626
*
2727
*-------------------------------------------------------------------------
2828
*/
@@ -2035,13 +2035,14 @@ getFuncs(int *numFuncs)
20352035
* numTables is set to the number of tables read in
20362036
*/
20372037
TableInfo *
2038-
getTables(int *numTables, FuncInfo *finfo, int numFuncs)
2038+
getTables(int *numTables, FuncInfo *finfo, int numFuncs, const char* tablename)
20392039
{
20402040
PGresult *res;
20412041
int ntups;
20422042
int i;
20432043
PQExpBuffer query = createPQExpBuffer();
20442044
PQExpBuffer delqry = createPQExpBuffer();
2045+
PQExpBuffer lockquery = createPQExpBuffer();
20452046
TableInfo *tblinfo;
20462047

20472048
int i_reloid;
@@ -2054,11 +2055,6 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
20542055
int i_relhasindex;
20552056
int i_relhasoids;
20562057

2057-
char relkindview[2];
2058-
2059-
relkindview[0] = RELKIND_VIEW;
2060-
relkindview[1] = '\0';
2061-
20622058
/*
20632059
* find all the user-defined tables (no indexes and no catalogs),
20642060
* ordering by oid is important so that we always process the parent
@@ -2129,6 +2125,17 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
21292125

21302126
*numTables = ntups;
21312127

2128+
/*
2129+
* First pass: extract data from result and lock tables. We do the
2130+
* locking before anything else, to minimize the window wherein a table
2131+
* could disappear under us.
2132+
*
2133+
* Note that we have to collect info about all tables here, even when
2134+
* dumping only one, because we don't know which tables might be
2135+
* inheritance ancestors of the target table. Possible future
2136+
* improvement: suppress later collection of schema info about tables
2137+
* that are determined not to be either targets or ancestors of targets.
2138+
*/
21322139
tblinfo = (TableInfo *) malloc(ntups * sizeof(TableInfo));
21332140

21342141
i_reloid = PQfnumber(res, "oid");
@@ -2146,17 +2153,63 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
21462153
tblinfo[i].oid = strdup(PQgetvalue(res, i, i_reloid));
21472154
tblinfo[i].relname = strdup(PQgetvalue(res, i, i_relname));
21482155
tblinfo[i].relacl = strdup(PQgetvalue(res, i, i_relacl));
2149-
tblinfo[i].sequence = (strcmp(PQgetvalue(res, i, i_relkind), "S") == 0);
2156+
tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
2157+
tblinfo[i].sequence = (tblinfo[i].relkind == RELKIND_SEQUENCE);
2158+
tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
2159+
tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
21502160
tblinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
21512161
tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
21522162
tblinfo[i].ntrig = atoi(PQgetvalue(res, i, i_reltriggers));
21532163

2164+
/*
2165+
* Read-lock target tables to make sure they aren't DROPPED or
2166+
* altered in schema before we get around to dumping them.
2167+
*
2168+
* If no target tablename was specified, lock all tables we see,
2169+
* otherwise lock only the specified table. (This is incomplete
2170+
* because we'll still try to collect schema info about all tables,
2171+
* and could possibly lose during that phase. But for the typical
2172+
* use where we're dumping all tables anyway, it matters not.)
2173+
*
2174+
* NOTE: it'd be kinda nice to lock views and sequences too, not
2175+
* only plain tables, but the backend doesn't presently allow that.
2176+
*/
2177+
if ((tblinfo[i].relkind == RELKIND_RELATION) &&
2178+
(tablename == NULL || strcmp(tblinfo[i].relname, tablename) == 0))
2179+
{
2180+
PGresult *lres;
2181+
2182+
resetPQExpBuffer(lockquery);
2183+
appendPQExpBuffer(lockquery,
2184+
"LOCK TABLE %s IN ACCESS SHARE MODE",
2185+
fmtId(tblinfo[i].relname, force_quotes));
2186+
lres = PQexec(g_conn,lockquery->data);
2187+
if (!lres || PQresultStatus(lres) != PGRES_COMMAND_OK)
2188+
{
2189+
write_msg(NULL, "Attempt to lock table \"%s\" failed. %s",
2190+
tblinfo[i].relname, PQerrorMessage(g_conn));
2191+
exit_nicely();
2192+
}
2193+
PQclear(lres);
2194+
}
2195+
}
2196+
2197+
PQclear(res);
2198+
res = NULL;
2199+
2200+
/*
2201+
* Second pass: pick up additional information about each table,
2202+
* as required.
2203+
*/
2204+
for (i = 0; i < *numTables; i++)
2205+
{
2206+
/* Emit notice if join for owner failed */
21542207
if (strlen(tblinfo[i].usename) == 0)
21552208
write_msg(NULL, "WARNING: owner of table \"%s\" appears to be invalid\n",
21562209
tblinfo[i].relname);
21572210

2158-
/* Get view definition */
2159-
if (strcmp(PQgetvalue(res, i, i_relkind), relkindview) == 0)
2211+
/* Get definition if it's a view */
2212+
if (tblinfo[i].relkind == RELKIND_VIEW)
21602213
{
21612214
PGresult *res2;
21622215

@@ -2208,6 +2261,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
22082261
tblinfo[i].relname);
22092262
exit_nicely();
22102263
}
2264+
PQclear(res2);
22112265
}
22122266
else
22132267
tblinfo[i].viewdef = NULL;
@@ -2291,7 +2345,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
22912345
tblinfo[i].check_expr = NULL;
22922346

22932347
/* Get primary key */
2294-
if (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0)
2348+
if (tblinfo[i].hasindex)
22952349
{
22962350
PGresult *res2;
22972351

@@ -2323,9 +2377,6 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
23232377
else
23242378
tblinfo[i].pkIndexOid = NULL;
23252379

2326-
/* Has it got OIDs? */
2327-
tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
2328-
23292380
/* Get primary key name (if primary key exist) */
23302381
if (tblinfo[i].pkIndexOid != NULL)
23312382
{
@@ -2643,10 +2694,9 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
26432694

26442695
}
26452696

2646-
PQclear(res);
2647-
26482697
destroyPQExpBuffer(query);
26492698
destroyPQExpBuffer(delqry);
2699+
destroyPQExpBuffer(lockquery);
26502700

26512701
return tblinfo;
26522702
}

src/bin/pg_dump/pg_dump.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: pg_dump.h,v 1.76 2001/11/05 17:46:30 momjian Exp $
9+
* $Id: pg_dump.h,v 1.77 2002/01/11 23:21:55 tgl Exp $
1010
*
1111
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
1212
*
@@ -96,7 +96,9 @@ typedef struct _tableInfo
9696
* constructed manually from rules, and
9797
* rule may ref things created after the
9898
* base table was created. */
99-
bool sequence;
99+
char relkind;
100+
bool sequence; /* this is redundant with relkind... */
101+
bool hasindex; /* does it have any indexes? */
100102
bool hasoids; /* does it have OIDs? */
101103
int numatts; /* number of attributes */
102104
int *inhAttrs; /* an array of flags, one for each
@@ -254,7 +256,8 @@ extern void clearOprInfo(OprInfo *, int);
254256
extern void clearTypeInfo(TypeInfo *, int);
255257

256258
extern OprInfo *getOperators(int *numOperators);
257-
extern TableInfo *getTables(int *numTables, FuncInfo *finfo, int numFuncs);
259+
extern TableInfo *getTables(int *numTables, FuncInfo *finfo, int numFuncs,
260+
const char* tablename);
258261
extern InhInfo *getInherits(int *numInherits);
259262
extern void getTableAttrs(TableInfo *tbinfo, int numTables);
260263
extern IndInfo *getIndexes(int *numIndexes);

0 commit comments

Comments
 (0)