Skip to content

Commit 92bd532

Browse files
committed
- Added --create, --no-owner, --superuser, --no-reconnect (pg_dump & pg_restore)
- Added code to dump 'Create Schema' statement (pg_dump) - Don't bother to disable/enable triggers if we don't have a superuser (pg_restore) - Cleaned up code for reconnecting to database. - Force a reconnect as superuser before enabling/disabling triggers. - Added & Removed --throttle (pg_dump) - Fixed minor bug in language dumping code: expbuffres were not being reset. - Fixed version number initialization in _allocAH (pg_backup_archiver.c) - Added second connection when restoring BLOBs to allow temp. table to survive (db reconnection causes temp tables to be lost).
1 parent 7d0c418 commit 92bd532

File tree

8 files changed

+569
-101
lines changed

8 files changed

+569
-101
lines changed

src/bin/pg_dump/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
# Copyright (c) 1994, Regents of the University of California
66
#
7-
# $Header: /cvsroot/pgsql/src/bin/pg_dump/Makefile,v 1.21 2000/07/24 06:24:26 pjw Exp $
7+
# $Header: /cvsroot/pgsql/src/bin/pg_dump/Makefile,v 1.22 2000/08/01 15:51:44 pjw Exp $
88
#
99
#-------------------------------------------------------------------------
1010

src/bin/pg_dump/pg_backup.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,22 @@
2020
*
2121
* Initial version.
2222
*
23+
*
24+
* Modifications - 28-Jul-2000 - pjw@rhyme.com.au (1.45)
25+
*
26+
* Added --create, --no-owner, --superuser, --no-reconnect (pg_dump & pg_restore)
27+
* Added code to dump 'Create Schema' statement (pg_dump)
28+
* Don't bother to disable/enable triggers if we don't have a superuser (pg_restore)
29+
* Cleaned up code for reconnecting to database.
30+
* Force a reconnect as superuser before enabling/disabling triggers.
31+
*
32+
* Modifications - 31-Jul-2000 - pjw@rhyme.com.au (1.46, 1.47)
33+
* Added & Removed --throttle (pg_dump)
34+
* Fixed minor bug in language dumping code: expbuffres were not being reset.
35+
* Fixed version number initialization in _allocAH (pg_backup_archiver.c)
36+
* Added second connection when restoring BLOBs to allow temp. table to survive
37+
* (db reconnection causes temp tables to be lost).
38+
*
2339
*-------------------------------------------------------------------------
2440
*/
2541

@@ -53,6 +69,10 @@ typedef struct _Archive {
5369
typedef int (*DataDumperPtr)(Archive* AH, char* oid, void* userArg);
5470

5571
typedef struct _restoreOptions {
72+
int create; /* Issue commands to create the database */
73+
int noOwner; /* Don't reconnect to database to match original object owner */
74+
int noReconnect; /* Don't reconnect to database under any cirsumstances */
75+
char *superuser; /* Username to use as superuser */
5676
int dataOnly;
5777
int dropSchema;
5878
char *filename;
@@ -84,9 +104,9 @@ typedef struct _restoreOptions {
84104
int ignoreVersion;
85105
int requirePassword;
86106

87-
int *idWanted;
88-
int limitToList;
89-
int compression;
107+
int *idWanted;
108+
int limitToList;
109+
int compression;
90110

91111
} RestoreOptions;
92112

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 158 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
*
1919
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
2020
*
21-
* Initial version.
21+
* Initial version.
22+
*
23+
* Modifications - 31-Jul-2000 - pjw@rhyme.com.au (1.46, 1.47)
24+
* Fixed version number initialization in _allocAH (pg_backup_archiver.c)
2225
*
2326
*-------------------------------------------------------------------------
2427
*/
@@ -43,7 +46,9 @@ static int _tocSortCompareByIDNum(const void *p1, const void *p2);
4346
static ArchiveHandle* _allocAH(const char* FileSpec, const ArchiveFormat fmt,
4447
int compression, ArchiveMode mode);
4548
static int _printTocEntry(ArchiveHandle* AH, TocEntry* te, RestoreOptions *ropt);
46-
static void _reconnectAsOwner(ArchiveHandle* AH, TocEntry* te);
49+
50+
static void _reconnectAsOwner(ArchiveHandle* AH, const char *dbname, TocEntry* te);
51+
static void _reconnectAsUser(ArchiveHandle* AH, const char *dbname, char *user);
4752

4853
static int _tocEntryRequired(TocEntry* te, RestoreOptions *ropt);
4954
static void _disableTriggers(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
@@ -58,7 +63,7 @@ static char *progname = "Archiver";
5863
static void _die_horribly(ArchiveHandle *AH, const char *fmt, va_list ap);
5964

6065
static int _canRestoreBlobs(ArchiveHandle *AH);
61-
66+
static int _restoringToDB(ArchiveHandle *AH);
6267

6368
/*
6469
* Wrapper functions.
@@ -110,6 +115,9 @@ void RestoreArchive(Archive* AHX, RestoreOptions *ropt)
110115

111116
AH->ropt = ropt;
112117

118+
if (ropt->create && ropt->noReconnect)
119+
die_horribly(AH, "%s: --create and --no-reconnect are incompatible options\n",progname);
120+
113121
/*
114122
* If we're using a DB connection, then connect it.
115123
*/
@@ -121,8 +129,25 @@ void RestoreArchive(Archive* AHX, RestoreOptions *ropt)
121129

122130
ConnectDatabase(AHX, ropt->dbname, ropt->pghost, ropt->pgport,
123131
ropt->requirePassword, ropt->ignoreVersion);
132+
133+
/*
134+
* If no superuser was specified then see if the current user will do...
135+
*/
136+
if (!ropt->superuser)
137+
{
138+
if (UserIsSuperuser(AH, ConnectedUser(AH)))
139+
ropt->superuser = strdup(ConnectedUser(AH));
140+
}
141+
124142
}
125143

144+
if (!ropt->superuser)
145+
fprintf(stderr, "\n%s: ******** WARNING ******** \n"
146+
" Data restoration may fail since any defined triggers\n"
147+
" can not be disabled (no superuser username specified).\n"
148+
" This is only a problem for restoration into a database\n"
149+
" with triggers already defined.\n\n", progname);
150+
126151
/*
127152
* Setup the output file if necessary.
128153
*/
@@ -155,16 +180,20 @@ void RestoreArchive(Archive* AHX, RestoreOptions *ropt)
155180
/* Work out what, if anything, we want from this entry */
156181
reqs = _tocEntryRequired(te, ropt);
157182

158-
/* Reconnect if necessary */
159-
if (reqs != 0)
160-
{
161-
_reconnectAsOwner(AH, te);
162-
}
163-
164183
if ( (reqs & 1) != 0) /* We want the schema */
165184
{
185+
/* Reconnect if necessary */
186+
_reconnectAsOwner(AH, "-", te);
187+
166188
ahlog(AH, 1, "Creating %s %s\n", te->desc, te->name);
167189
_printTocEntry(AH, te, ropt);
190+
191+
/* If we created a DB, connect to it... */
192+
if (strcmp(te->desc,"DATABASE") == 0)
193+
{
194+
ahlog(AH, 1, "Connecting to new DB '%s' as %s\n",te->name, te->owner);
195+
_reconnectAsUser(AH, te->name, te->owner);
196+
}
168197
}
169198

170199
/*
@@ -176,8 +205,6 @@ void RestoreArchive(Archive* AHX, RestoreOptions *ropt)
176205
die_horribly(AH, "%s: Unable to restore data from a compressed archive\n", progname);
177206
#endif
178207

179-
ahlog(AH, 1, "Restoring data for %s \n", te->name);
180-
181208
ahprintf(AH, "--\n-- Data for TOC Entry ID %d (OID %s) %s %s\n--\n\n",
182209
te->id, te->oid, te->desc, te->name);
183210

@@ -197,6 +224,10 @@ void RestoreArchive(Archive* AHX, RestoreOptions *ropt)
197224

198225
_disableTriggers(AH, te, ropt);
199226

227+
/* Reconnect if necessary (_disableTriggers may have reconnected) */
228+
_reconnectAsOwner(AH, "-", te);
229+
230+
ahlog(AH, 1, "Restoring data for %s \n", te->name);
200231

201232
/* If we have a copy statement, use it. As of V1.3, these are separate
202233
* to allow easy import from withing a database connection. Pre 1.3
@@ -256,6 +287,12 @@ void RestoreArchive(Archive* AHX, RestoreOptions *ropt)
256287
{
257288
PQfinish(AH->connection);
258289
AH->connection = NULL;
290+
291+
if (AH->blobConnection)
292+
{
293+
PQfinish(AH->blobConnection);
294+
AH->blobConnection = NULL;
295+
}
259296
}
260297
}
261298

@@ -274,19 +311,89 @@ RestoreOptions* NewRestoreOptions(void)
274311
return opts;
275312
}
276313

277-
static int _canRestoreBlobs(ArchiveHandle *AH)
314+
static int _restoringToDB(ArchiveHandle *AH)
278315
{
279316
return (AH->ropt->useDB && AH->connection);
280317
}
281318

319+
static int _canRestoreBlobs(ArchiveHandle *AH)
320+
{
321+
return _restoringToDB(AH);
322+
}
323+
282324
static void _disableTriggers(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
283325
{
326+
char *oldUser = NULL;
327+
328+
/* Can't do much if we're connected & don't have a superuser */
329+
if (_restoringToDB(AH) && !ropt->superuser)
330+
return;
331+
332+
/*
333+
* Reconnect as superuser if possible, since they are the only ones
334+
* who can update pg_class...
335+
*/
336+
if (ropt->superuser)
337+
{
338+
/* If we're not allowing changes for ownership, then remember the user
339+
* so we can change it back here. Otherwise, let _reconnectAsOwner
340+
* do what it has to do.
341+
*/
342+
if (ropt->noOwner)
343+
oldUser = strdup(ConnectedUser(AH));
344+
_reconnectAsUser(AH, "-", ropt->superuser);
345+
}
346+
347+
ahlog(AH, 1, "Disabling triggers\n");
348+
349+
/*
350+
* Disable them. This is a hack. Needs to be done via an appropriate 'SET'
351+
* command when one is available.
352+
*/
284353
ahprintf(AH, "-- Disable triggers\n");
285354
ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = 0 WHERE \"relname\" !~ '^pg_';\n\n");
355+
356+
/*
357+
* Restore the user connection from the start of this procedure
358+
* if _reconnectAsOwner is disabled.
359+
*/
360+
if (ropt->noOwner && oldUser)
361+
{
362+
_reconnectAsUser(AH, "-", oldUser);
363+
free(oldUser);
364+
}
286365
}
287366

288367
static void _enableTriggers(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
289368
{
369+
char *oldUser = NULL;
370+
371+
/* Can't do much if we're connected & don't have a superuser */
372+
if (_restoringToDB(AH) && !ropt->superuser)
373+
return;
374+
375+
/*
376+
* Reconnect as superuser if possible, since they are the only ones
377+
* who can update pg_class...
378+
*/
379+
if (ropt->superuser)
380+
{
381+
/* If we're not allowing changes for ownership, then remember the user
382+
* so we can change it back here. Otherwise, let _reconnectAsOwner
383+
* do what it has to do
384+
*/
385+
if (ropt->noOwner)
386+
oldUser = strdup(ConnectedUser(AH));
387+
388+
_reconnectAsUser(AH, "-", ropt->superuser);
389+
}
390+
391+
ahlog(AH, 1, "Enabling triggers\n");
392+
393+
/*
394+
* Enable them. This is a hack. Needs to be done via an appropriate 'SET'
395+
* command when one is available.
396+
*/
290397
ahprintf(AH, "-- Enable triggers\n");
291398
ahprintf(AH, "BEGIN TRANSACTION;\n");
292399
ahprintf(AH, "CREATE TEMP TABLE \"tr\" (\"tmp_relname\" name, \"tmp_reltriggers\" smallint);\n");
@@ -298,8 +405,17 @@ static void _enableTriggers(ArchiveHandle *AH, TocEntry *te, RestoreOptions *rop
298405
"\"pg_class\".\"relname\" = TMP.\"tmp_relname\";\n");
299406
ahprintf(AH, "DROP TABLE \"tr\";\n");
300407
ahprintf(AH, "COMMIT TRANSACTION;\n\n");
301-
}
302408

409+
/*
410+
* Restore the user connection from the start of this procedure
411+
* if _reconnectAsOwner is disabled.
412+
*/
413+
if (ropt->noOwner && oldUser)
414+
{
415+
_reconnectAsUser(AH, "-", oldUser);
416+
free(oldUser);
417+
}
418+
}
303419

304420
/*
305421
* This is a routine that is part of the dumper interface, hence the 'Archive*' parameter.
@@ -394,6 +510,8 @@ void PrintTOCSummary(Archive* AHX, RestoreOptions *ropt)
394510
default:
395511
fmtName = "UNKNOWN";
396512
}
513+
514+
ahprintf(AH, "; Dump Version: %d.%d-%d\n", AH->vmaj, AH->vmin, AH->vrev);
397515
ahprintf(AH, "; Format: %s\n;\n", fmtName);
398516

399517
ahprintf(AH, ";\n; Selected TOC Entries:\n;\n");
@@ -456,14 +574,14 @@ void StartRestoreBlob(ArchiveHandle* AH, int oid)
456574
AH->createdBlobXref = 1;
457575
}
458576

577+
StartTransaction(AH);
578+
459579
loOid = lo_creat(AH->connection, INV_READ | INV_WRITE);
460580
if (loOid == 0)
461581
die_horribly(AH, "%s: unable to create BLOB\n", progname);
462582

463583
ahlog(AH, 1, "Restoring BLOB oid %d as %d\n", oid, loOid);
464584

465-
StartTransaction(AH);
466-
467585
InsertBlobXref(AH, oid, loOid);
468586

469587
AH->loFd = lo_open(AH->connection, loOid, INV_WRITE);
@@ -829,6 +947,8 @@ static void _die_horribly(ArchiveHandle *AH, const char *fmt, va_list ap)
829947
if (AH)
830948
if (AH->connection)
831949
PQfinish(AH->connection);
950+
if (AH->blobConnection)
951+
PQfinish(AH->blobConnection);
832952

833953
exit(1);
834954
}
@@ -1113,6 +1233,7 @@ static ArchiveHandle* _allocAH(const char* FileSpec, const ArchiveFormat fmt,
11131233

11141234
AH->vmaj = K_VERS_MAJOR;
11151235
AH->vmin = K_VERS_MINOR;
1236+
AH->vrev = K_VERS_REV;
11161237

11171238
AH->createDate = time(NULL);
11181239

@@ -1299,6 +1420,9 @@ static int _tocEntryRequired(TocEntry* te, RestoreOptions *ropt)
12991420
if (ropt->aclsSkip && strcmp(te->desc,"ACL") == 0)
13001421
return 0;
13011422

1423+
if (!ropt->create && strcmp(te->desc,"DATABASE") == 0)
1424+
return 0;
1425+
13021426
/* Check if tablename only is wanted */
13031427
if (ropt->selTypes)
13041428
{
@@ -1351,20 +1475,32 @@ static int _tocEntryRequired(TocEntry* te, RestoreOptions *ropt)
13511475
return res;
13521476
}
13531477

1354-
static void _reconnectAsOwner(ArchiveHandle* AH, TocEntry* te)
1478+
static void _reconnectAsUser(ArchiveHandle* AH, const char *dbname, char *user)
13551479
{
1356-
if (te->owner && strlen(te->owner) != 0 && strcmp(AH->currUser, te->owner) != 0) {
1480+
if (AH->ropt && AH->ropt->noReconnect)
1481+
return;
1482+
1483+
if (user && strlen(user) != 0
1484+
&& ( (strcmp(AH->currUser, user) != 0) || (strcmp(dbname,"-") != 0)))
1485+
{
13571486
if (RestoringToDB(AH))
13581487
{
1359-
ReconnectDatabase(AH, te->owner);
1360-
/* todo pjw - ???? fix for db connection... */
1488+
ReconnectDatabase(AH, dbname, user);
13611489
}
13621490
else
13631491
{
1364-
ahprintf(AH, "\\connect - %s\n", te->owner);
1492+
ahprintf(AH, "\\connect %s %s\n", dbname, user);
13651493
}
1366-
AH->currUser = te->owner;
1367-
}
1494+
AH->currUser = user;
1495+
}
1496+
}
1497+
1498+
static void _reconnectAsOwner(ArchiveHandle* AH, const char *dbname, TocEntry* te)
1499+
{
1500+
if (AH->ropt && AH->ropt->noOwner)
1501+
return;
1502+
1503+
_reconnectAsUser(AH, dbname, te->owner);
13681504
}
13691505

13701506
static int _printTocEntry(ArchiveHandle* AH, TocEntry* te, RestoreOptions *ropt)

0 commit comments

Comments
 (0)