aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/pg_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_dump/pg_dump.c')
-rw-r--r--src/bin/pg_dump/pg_dump.c82
1 files changed, 66 insertions, 16 deletions
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 5c2c9045559..8fb0812dd6b 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.236 2001/10/28 06:25:58 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.237 2002/01/11 23:21:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2035,13 +2035,14 @@ getFuncs(int *numFuncs)
* numTables is set to the number of tables read in
*/
TableInfo *
-getTables(int *numTables, FuncInfo *finfo, int numFuncs)
+getTables(int *numTables, FuncInfo *finfo, int numFuncs, const char* tablename)
{
PGresult *res;
int ntups;
int i;
PQExpBuffer query = createPQExpBuffer();
PQExpBuffer delqry = createPQExpBuffer();
+ PQExpBuffer lockquery = createPQExpBuffer();
TableInfo *tblinfo;
int i_reloid;
@@ -2054,11 +2055,6 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
int i_relhasindex;
int i_relhasoids;
- char relkindview[2];
-
- relkindview[0] = RELKIND_VIEW;
- relkindview[1] = '\0';
-
/*
* find all the user-defined tables (no indexes and no catalogs),
* ordering by oid is important so that we always process the parent
@@ -2129,6 +2125,17 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
*numTables = ntups;
+ /*
+ * First pass: extract data from result and lock tables. We do the
+ * locking before anything else, to minimize the window wherein a table
+ * could disappear under us.
+ *
+ * Note that we have to collect info about all tables here, even when
+ * dumping only one, because we don't know which tables might be
+ * inheritance ancestors of the target table. Possible future
+ * improvement: suppress later collection of schema info about tables
+ * that are determined not to be either targets or ancestors of targets.
+ */
tblinfo = (TableInfo *) malloc(ntups * sizeof(TableInfo));
i_reloid = PQfnumber(res, "oid");
@@ -2146,17 +2153,63 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
tblinfo[i].oid = strdup(PQgetvalue(res, i, i_reloid));
tblinfo[i].relname = strdup(PQgetvalue(res, i, i_relname));
tblinfo[i].relacl = strdup(PQgetvalue(res, i, i_relacl));
- tblinfo[i].sequence = (strcmp(PQgetvalue(res, i, i_relkind), "S") == 0);
+ tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
+ tblinfo[i].sequence = (tblinfo[i].relkind == RELKIND_SEQUENCE);
+ tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
+ tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
tblinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
tblinfo[i].ntrig = atoi(PQgetvalue(res, i, i_reltriggers));
+ /*
+ * Read-lock target tables to make sure they aren't DROPPED or
+ * altered in schema before we get around to dumping them.
+ *
+ * If no target tablename was specified, lock all tables we see,
+ * otherwise lock only the specified table. (This is incomplete
+ * because we'll still try to collect schema info about all tables,
+ * and could possibly lose during that phase. But for the typical
+ * use where we're dumping all tables anyway, it matters not.)
+ *
+ * NOTE: it'd be kinda nice to lock views and sequences too, not
+ * only plain tables, but the backend doesn't presently allow that.
+ */
+ if ((tblinfo[i].relkind == RELKIND_RELATION) &&
+ (tablename == NULL || strcmp(tblinfo[i].relname, tablename) == 0))
+ {
+ PGresult *lres;
+
+ resetPQExpBuffer(lockquery);
+ appendPQExpBuffer(lockquery,
+ "LOCK TABLE %s IN ACCESS SHARE MODE",
+ fmtId(tblinfo[i].relname, force_quotes));
+ lres = PQexec(g_conn,lockquery->data);
+ if (!lres || PQresultStatus(lres) != PGRES_COMMAND_OK)
+ {
+ write_msg(NULL, "Attempt to lock table \"%s\" failed. %s",
+ tblinfo[i].relname, PQerrorMessage(g_conn));
+ exit_nicely();
+ }
+ PQclear(lres);
+ }
+ }
+
+ PQclear(res);
+ res = NULL;
+
+ /*
+ * Second pass: pick up additional information about each table,
+ * as required.
+ */
+ for (i = 0; i < *numTables; i++)
+ {
+ /* Emit notice if join for owner failed */
if (strlen(tblinfo[i].usename) == 0)
write_msg(NULL, "WARNING: owner of table \"%s\" appears to be invalid\n",
tblinfo[i].relname);
- /* Get view definition */
- if (strcmp(PQgetvalue(res, i, i_relkind), relkindview) == 0)
+ /* Get definition if it's a view */
+ if (tblinfo[i].relkind == RELKIND_VIEW)
{
PGresult *res2;
@@ -2208,6 +2261,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
tblinfo[i].relname);
exit_nicely();
}
+ PQclear(res2);
}
else
tblinfo[i].viewdef = NULL;
@@ -2291,7 +2345,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
tblinfo[i].check_expr = NULL;
/* Get primary key */
- if (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0)
+ if (tblinfo[i].hasindex)
{
PGresult *res2;
@@ -2323,9 +2377,6 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
else
tblinfo[i].pkIndexOid = NULL;
- /* Has it got OIDs? */
- tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
-
/* Get primary key name (if primary key exist) */
if (tblinfo[i].pkIndexOid != NULL)
{
@@ -2643,10 +2694,9 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
}
- PQclear(res);
-
destroyPQExpBuffer(query);
destroyPQExpBuffer(delqry);
+ destroyPQExpBuffer(lockquery);
return tblinfo;
}