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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy