Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pg_backup_archiver.c
4 : *
5 : * Private implementation of the archiver routines.
6 : *
7 : * See the headers to pg_restore for more details.
8 : *
9 : * Copyright (c) 2000, Philip Warner
10 : * Rights are granted to use this software in any way so long
11 : * as this notice is not removed.
12 : *
13 : * The author is not responsible for loss or damages that may
14 : * result from its use.
15 : *
16 : *
17 : * IDENTIFICATION
18 : * src/bin/pg_dump/pg_backup_archiver.c
19 : *
20 : *-------------------------------------------------------------------------
21 : */
22 : #include "postgres_fe.h"
23 :
24 : #include <ctype.h>
25 : #include <fcntl.h>
26 : #include <unistd.h>
27 : #include <sys/stat.h>
28 : #include <sys/wait.h>
29 : #ifdef WIN32
30 : #include <io.h>
31 : #endif
32 :
33 : #include "common/string.h"
34 : #include "compress_io.h"
35 : #include "dumputils.h"
36 : #include "fe_utils/string_utils.h"
37 : #include "lib/stringinfo.h"
38 : #include "libpq/libpq-fs.h"
39 : #include "parallel.h"
40 : #include "pg_backup_archiver.h"
41 : #include "pg_backup_db.h"
42 : #include "pg_backup_utils.h"
43 :
44 : #define TEXT_DUMP_HEADER "--\n-- PostgreSQL database dump\n--\n\n"
45 : #define TEXT_DUMPALL_HEADER "--\n-- PostgreSQL database cluster dump\n--\n\n"
46 :
47 : /*
48 : * State for tracking TocEntrys that are ready to process during a parallel
49 : * restore. (This used to be a list, and we still call it that, though now
50 : * it's really an array so that we can apply qsort to it.)
51 : *
52 : * tes[] is sized large enough that we can't overrun it.
53 : * The valid entries are indexed first_te .. last_te inclusive.
54 : * We periodically sort the array to bring larger-by-dataLength entries to
55 : * the front; "sorted" is true if the valid entries are known sorted.
56 : */
57 : typedef struct _parallelReadyList
58 : {
59 : TocEntry **tes; /* Ready-to-dump TocEntrys */
60 : int first_te; /* index of first valid entry in tes[] */
61 : int last_te; /* index of last valid entry in tes[] */
62 : bool sorted; /* are valid entries currently sorted? */
63 : } ParallelReadyList;
64 :
65 :
66 : static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
67 : const pg_compress_specification compression_spec,
68 : bool dosync, ArchiveMode mode,
69 : SetupWorkerPtrType setupWorkerPtr);
70 : static void _getObjectDescription(PQExpBuffer buf, const TocEntry *te);
71 : static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData);
72 : static char *sanitize_line(const char *str, bool want_hyphen);
73 : static void _doSetFixedOutputState(ArchiveHandle *AH);
74 : static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
75 : static void _reconnectToDB(ArchiveHandle *AH, const char *dbname);
76 : static void _becomeUser(ArchiveHandle *AH, const char *user);
77 : static void _becomeOwner(ArchiveHandle *AH, TocEntry *te);
78 : static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
79 : static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
80 : static void _selectTableAccessMethod(ArchiveHandle *AH, const char *tableam);
81 : static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te);
82 : static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te);
83 : static void processSearchPathEntry(ArchiveHandle *AH, TocEntry *te);
84 : static int _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH);
85 : static RestorePass _tocEntryRestorePass(TocEntry *te);
86 : static bool _tocEntryIsACL(TocEntry *te);
87 : static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te);
88 : static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te);
89 : static bool is_load_via_partition_root(TocEntry *te);
90 : static void buildTocEntryArrays(ArchiveHandle *AH);
91 : static void _moveBefore(TocEntry *pos, TocEntry *te);
92 : static int _discoverArchiveFormat(ArchiveHandle *AH);
93 :
94 : static int RestoringToDB(ArchiveHandle *AH);
95 : static void dump_lo_buf(ArchiveHandle *AH);
96 : static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim);
97 : static void SetOutput(ArchiveHandle *AH, const char *filename,
98 : const pg_compress_specification compression_spec);
99 : static CompressFileHandle *SaveOutput(ArchiveHandle *AH);
100 : static void RestoreOutput(ArchiveHandle *AH, CompressFileHandle *savedOutput);
101 :
102 : static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel);
103 : static void restore_toc_entries_prefork(ArchiveHandle *AH,
104 : TocEntry *pending_list);
105 : static void restore_toc_entries_parallel(ArchiveHandle *AH,
106 : ParallelState *pstate,
107 : TocEntry *pending_list);
108 : static void restore_toc_entries_postfork(ArchiveHandle *AH,
109 : TocEntry *pending_list);
110 : static void pending_list_header_init(TocEntry *l);
111 : static void pending_list_append(TocEntry *l, TocEntry *te);
112 : static void pending_list_remove(TocEntry *te);
113 : static void ready_list_init(ParallelReadyList *ready_list, int tocCount);
114 : static void ready_list_free(ParallelReadyList *ready_list);
115 : static void ready_list_insert(ParallelReadyList *ready_list, TocEntry *te);
116 : static void ready_list_remove(ParallelReadyList *ready_list, int i);
117 : static void ready_list_sort(ParallelReadyList *ready_list);
118 : static int TocEntrySizeCompare(const void *p1, const void *p2);
119 : static void move_to_ready_list(TocEntry *pending_list,
120 : ParallelReadyList *ready_list,
121 : RestorePass pass);
122 : static TocEntry *pop_next_work_item(ParallelReadyList *ready_list,
123 : ParallelState *pstate);
124 : static void mark_dump_job_done(ArchiveHandle *AH,
125 : TocEntry *te,
126 : int status,
127 : void *callback_data);
128 : static void mark_restore_job_done(ArchiveHandle *AH,
129 : TocEntry *te,
130 : int status,
131 : void *callback_data);
132 : static void fix_dependencies(ArchiveHandle *AH);
133 : static bool has_lock_conflicts(TocEntry *te1, TocEntry *te2);
134 : static void repoint_table_dependencies(ArchiveHandle *AH);
135 : static void identify_locking_dependencies(ArchiveHandle *AH, TocEntry *te);
136 : static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te,
137 : ParallelReadyList *ready_list);
138 : static void mark_create_done(ArchiveHandle *AH, TocEntry *te);
139 : static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te);
140 :
141 : static void StrictNamesCheck(RestoreOptions *ropt);
142 :
143 :
3099 alvherre 144 ECB : /*
145 : * Allocate a new DumpOptions block containing all default values.
146 : */
147 : DumpOptions *
3099 alvherre 148 CBC 33 : NewDumpOptions(void)
3099 alvherre 149 ECB : {
3010 tgl 150 GIC 33 : DumpOptions *opts = (DumpOptions *) pg_malloc(sizeof(DumpOptions));
151 :
152 33 : InitDumpOptions(opts);
153 33 : return opts;
154 : }
155 :
3010 tgl 156 ECB : /*
157 : * Initialize a DumpOptions struct to all default values
158 : */
159 : void
3010 tgl 160 CBC 183 : InitDumpOptions(DumpOptions *opts)
3010 tgl 161 ECB : {
3010 tgl 162 CBC 183 : memset(opts, 0, sizeof(DumpOptions));
3099 alvherre 163 ECB : /* set any fields that shouldn't default to zeroes */
3099 alvherre 164 GIC 183 : opts->include_everything = true;
927 tgl 165 183 : opts->cparams.promptPassword = TRI_DEFAULT;
3099 alvherre 166 183 : opts->dumpSections = DUMP_UNSECTIONED;
167 183 : }
168 :
169 : /*
3099 alvherre 170 ECB : * Create a freshly allocated DumpOptions with options equivalent to those
171 : * found in the given RestoreOptions.
172 : */
173 : DumpOptions *
3099 alvherre 174 GIC 33 : dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
3099 alvherre 175 ECB : {
3099 alvherre 176 CBC 33 : DumpOptions *dopt = NewDumpOptions();
3099 alvherre 177 ECB :
178 : /* this is the inverse of what's at the end of pg_dump.c's main() */
927 tgl 179 CBC 33 : dopt->cparams.dbname = ropt->cparams.dbname ? pg_strdup(ropt->cparams.dbname) : NULL;
180 33 : dopt->cparams.pgport = ropt->cparams.pgport ? pg_strdup(ropt->cparams.pgport) : NULL;
181 33 : dopt->cparams.pghost = ropt->cparams.pghost ? pg_strdup(ropt->cparams.pghost) : NULL;
182 33 : dopt->cparams.username = ropt->cparams.username ? pg_strdup(ropt->cparams.username) : NULL;
183 33 : dopt->cparams.promptPassword = ropt->cparams.promptPassword;
3099 alvherre 184 33 : dopt->outputClean = ropt->dropSchema;
185 33 : dopt->dataOnly = ropt->dataOnly;
186 33 : dopt->schemaOnly = ropt->schemaOnly;
187 33 : dopt->if_exists = ropt->if_exists;
188 33 : dopt->column_inserts = ropt->column_inserts;
189 33 : dopt->dumpSections = ropt->dumpSections;
190 33 : dopt->aclsSkip = ropt->aclsSkip;
191 33 : dopt->outputSuperuser = ropt->superuser;
192 33 : dopt->outputCreateDB = ropt->createDB;
193 33 : dopt->outputNoOwner = ropt->noOwner;
447 michael 194 33 : dopt->outputNoTableAm = ropt->noTableAm;
3099 alvherre 195 33 : dopt->outputNoTablespaces = ropt->noTablespace;
196 33 : dopt->disable_triggers = ropt->disable_triggers;
197 33 : dopt->use_setsessauth = ropt->use_setsessauth;
198 33 : dopt->disable_dollar_quoting = ropt->disable_dollar_quoting;
199 33 : dopt->dump_inserts = ropt->dump_inserts;
1900 tgl 200 33 : dopt->no_comments = ropt->no_comments;
2158 peter_e 201 33 : dopt->no_publications = ropt->no_publications;
3099 alvherre 202 33 : dopt->no_security_labels = ropt->no_security_labels;
2161 peter_e 203 33 : dopt->no_subscriptions = ropt->no_subscriptions;
3099 alvherre 204 GIC 33 : dopt->lockWaitTimeout = ropt->lockWaitTimeout;
3099 alvherre 205 CBC 33 : dopt->include_everything = ropt->include_everything;
3099 alvherre 206 GIC 33 : dopt->enable_row_security = ropt->enable_row_security;
2420 peter_e 207 33 : dopt->sequence_data = ropt->sequence_data;
208 :
3099 alvherre 209 33 : return dopt;
210 : }
211 :
212 :
213 : /*
214 : * Wrapper functions.
215 : *
216 : * The objective is to make writing new formats and dumpers as simple
217 : * as possible, if necessary at the expense of extra function calls etc.
218 : *
219 : */
220 :
221 : /*
222 : * The dump worker setup needs lots of knowledge of the internals of pg_dump,
1031 michael 223 ECB : * so it's defined in pg_dump.c and passed into OpenArchive. The restore worker
224 : * setup doesn't need to know anything much, so it's defined here.
3668 andrew 225 : */
226 : static void
2643 tgl 227 CBC 10 : setupRestoreWorker(Archive *AHX)
3668 andrew 228 ECB : {
3668 andrew 229 GIC 10 : ArchiveHandle *AH = (ArchiveHandle *) AHX;
230 :
2040 peter_e 231 10 : AH->ReopenPtr(AH);
3668 andrew 232 10 : }
233 :
8314 bruce 234 ECB :
235 : /* Create a new archive */
236 : /* Public */
237 : Archive *
8053 bruce 238 GIC 133 : CreateArchive(const char *FileSpec, const ArchiveFormat fmt,
239 : const pg_compress_specification compression_spec,
240 : bool dosync, ArchiveMode mode,
2413 peter_e 241 ECB : SetupWorkerPtrType setupDumpWorker)
242 :
243 : {
128 michael 244 GNC 133 : ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression_spec,
245 : dosync, mode, setupDumpWorker);
246 :
8053 bruce 247 GIC 132 : return (Archive *) AH;
248 : }
249 :
8314 bruce 250 ECB : /* Open an existing archive */
251 : /* Public */
252 : Archive *
8053 bruce 253 CBC 31 : OpenArchive(const char *FileSpec, const ArchiveFormat fmt)
254 : {
255 : ArchiveHandle *AH;
128 michael 256 GNC 31 : pg_compress_specification compression_spec = {0};
257 :
258 31 : compression_spec.algorithm = PG_COMPRESSION_NONE;
259 31 : AH = _allocAH(FileSpec, fmt, compression_spec, true,
260 : archModeRead, setupRestoreWorker);
8053 bruce 261 ECB :
8053 bruce 262 GIC 31 : return (Archive *) AH;
263 : }
8314 bruce 264 ECB :
265 : /* Public */
266 : void
2643 tgl 267 GIC 148 : CloseArchive(Archive *AHX)
268 : {
8053 bruce 269 148 : ArchiveHandle *AH = (ArchiveHandle *) AHX;
8053 bruce 270 ECB :
2040 peter_e 271 GIC 148 : AH->ClosePtr(AH);
8314 bruce 272 ECB :
273 : /* Close the output */
45 tomas.vondra 274 GNC 148 : errno = 0;
17 275 148 : if (!EndCompressFileHandle(AH->OF))
366 tgl 276 UIC 0 : pg_fatal("could not close output file: %m");
8314 bruce 277 CBC 148 : }
278 :
279 : /* Public */
8053 bruce 280 ECB : void
2643 tgl 281 CBC 285 : SetArchiveOptions(Archive *AH, DumpOptions *dopt, RestoreOptions *ropt)
282 : {
283 : /* Caller can omit dump options, in which case we synthesize them */
284 285 : if (dopt == NULL && ropt != NULL)
285 33 : dopt = dumpOptionsFromRestoreOptions(ropt);
3967 tgl 286 ECB :
287 : /* Save options for later access */
2643 tgl 288 GIC 285 : AH->dopt = dopt;
3967 289 285 : AH->ropt = ropt;
2643 tgl 290 CBC 285 : }
291 :
2643 tgl 292 ECB : /* Public */
293 : void
2643 tgl 294 GIC 144 : ProcessArchiveRestoreOptions(Archive *AHX)
295 : {
296 144 : ArchiveHandle *AH = (ArchiveHandle *) AHX;
297 144 : RestoreOptions *ropt = AH->public.ropt;
2643 tgl 298 ECB : TocEntry *te;
299 : teSection curSection;
300 :
301 : /* Decide which TOC entries will be dumped/restored, and mark them */
3967 tgl 302 GIC 144 : curSection = SECTION_PRE_DATA;
303 26403 : for (te = AH->toc->next; te != AH->toc; te = te->next)
304 : {
305 : /*
306 : * When writing an archive, we also take this opportunity to check
3940 tgl 307 ECB : * that we have generated the entries in a sane order that respects
308 : * the section divisions. When reading, don't complain, since buggy
309 : * old versions of pg_dump might generate out-of-order archives.
310 : */
3940 tgl 311 CBC 26259 : if (AH->mode != archModeRead)
312 : {
313 21324 : switch (te->section)
3940 tgl 314 ECB : {
3940 tgl 315 CBC 2713 : case SECTION_NONE:
3940 tgl 316 EUB : /* ok to be anywhere */
3940 tgl 317 CBC 2713 : break;
318 10513 : case SECTION_PRE_DATA:
319 10513 : if (curSection != SECTION_PRE_DATA)
1469 peter 320 UBC 0 : pg_log_warning("archive items not in correct section order");
3940 tgl 321 CBC 10513 : break;
322 3475 : case SECTION_DATA:
3940 tgl 323 GIC 3475 : if (curSection == SECTION_POST_DATA)
1469 peter 324 LBC 0 : pg_log_warning("archive items not in correct section order");
3940 tgl 325 GBC 3475 : break;
326 4623 : case SECTION_POST_DATA:
327 : /* ok no matter which section we were in */
3940 tgl 328 GIC 4623 : break;
3940 tgl 329 UIC 0 : default:
366 330 0 : pg_fatal("unexpected section code %d",
331 : (int) te->section);
3940 tgl 332 ECB : break;
333 : }
334 : }
335 :
3967 tgl 336 GIC 26259 : if (te->section != SECTION_NONE)
337 22694 : curSection = te->section;
338 :
1900 tgl 339 CBC 26259 : te->reqs = _tocEntryRequired(te, curSection, AH);
3967 tgl 340 EUB : }
2764 teodor 341 ECB :
342 : /* Enforce strict names checking */
2764 teodor 343 GIC 144 : if (ropt->strict_names)
2764 teodor 344 UIC 0 : StrictNamesCheck(ropt);
3967 tgl 345 CBC 144 : }
346 :
3967 tgl 347 ECB : /* Public */
348 : void
3967 tgl 349 GIC 121 : RestoreArchive(Archive *AHX)
350 : {
351 121 : ArchiveHandle *AH = (ArchiveHandle *) AHX;
2643 352 121 : RestoreOptions *ropt = AH->public.ropt;
4242 tgl 353 ECB : bool parallel_mode;
354 : TocEntry *te;
355 : CompressFileHandle *sav;
356 :
6806 bruce 357 GIC 121 : AH->stage = STAGE_INITIALIZING;
8297 pjw 358 ECB :
4242 tgl 359 : /*
360 : * If we're going to do parallel restore, there are some restrictions.
361 : */
3668 andrew 362 CBC 121 : parallel_mode = (AH->public.numWorkers > 1 && ropt->useDB);
4242 tgl 363 GBC 121 : if (parallel_mode)
364 : {
365 : /* We haven't got round to making this work for all archive formats */
4242 tgl 366 CBC 4 : if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
366 tgl 367 UBC 0 : pg_fatal("parallel restore is not supported with this archive file format");
368 :
369 : /* Doesn't work if the archive represents dependencies as OIDs */
4242 tgl 370 GIC 4 : if (AH->version < K_VERS_1_8)
366 tgl 371 UIC 0 : pg_fatal("parallel restore is not supported with archives made by pre-8.0 pg_dump");
372 :
4242 tgl 373 ECB : /*
374 : * It's also not gonna work if we can't reopen the input file, so
375 : * let's try that immediately.
376 : */
2040 peter_e 377 GIC 4 : AH->ReopenPtr(AH);
378 : }
4242 tgl 379 ECB :
380 : /*
5179 andrew 381 : * Make sure we won't need (de)compression we haven't got
382 : */
45 tomas.vondra 383 GNC 121 : if (AH->PrintTocDataPtr != NULL)
5179 andrew 384 ECB : {
5179 andrew 385 CBC 14252 : for (te = AH->toc->next; te != AH->toc; te = te->next)
5179 andrew 386 EUB : {
3967 tgl 387 GIC 14202 : if (te->hadDumper && (te->reqs & REQ_DATA) != 0)
388 : {
45 tomas.vondra 389 GNC 71 : char *errmsg = supports_compression(AH->compression_spec);
390 71 : if (errmsg)
45 tomas.vondra 391 UNC 0 : pg_fatal("cannot restore from compressed archive (%s)",
392 : errmsg);
393 : else
45 tomas.vondra 394 GNC 71 : break;
395 : }
5179 andrew 396 ECB : }
397 : }
398 :
399 : /*
400 : * Prepare index arrays, so we can assume we have them throughout restore.
401 : * It's possible we already did this, though.
402 : */
3968 tgl 403 GIC 121 : if (AH->tocsByDumpId == NULL)
3968 tgl 404 CBC 119 : buildTocEntryArrays(AH);
3968 tgl 405 ECB :
406 : /*
407 : * If we're using a DB connection, then connect it.
408 : */
8297 pjw 409 GIC 121 : if (ropt->useDB)
8297 pjw 410 ECB : {
1469 peter 411 GIC 10 : pg_log_info("connecting to database for restore");
8297 pjw 412 CBC 10 : if (AH->version < K_VERS_1_3)
366 tgl 413 LBC 0 : pg_fatal("direct database connections are not supported in pre-1.3 archives");
8297 pjw 414 EUB :
415 : /*
416 : * We don't want to guess at whether the dump will successfully
417 : * restore; allow the attempt regardless of the version of the restore
418 : * target.
419 : */
3388 kgrittn 420 GIC 10 : AHX->minRemoteVersion = 0;
2370 tgl 421 CBC 10 : AHX->maxRemoteVersion = 9999999;
8019 pjw 422 ECB :
927 tgl 423 GIC 10 : ConnectDatabase(AHX, &ropt->cparams, false);
6797 bruce 424 ECB :
425 : /*
426 : * If we're talking to the DB directly, don't send comments since they
427 : * obscure SQL when displaying errors
428 : */
6806 bruce 429 GIC 10 : AH->noTocComments = 1;
8297 pjw 430 ECB : }
431 :
432 : /*
433 : * Work out if we have an implied data-only restore. This can happen if
434 : * the dump was data only or if the user has used a toc list to exclude
435 : * all of the schema data. All we do is look for schema entries - if none
436 : * are found then we set the dataOnly flag.
437 : *
438 : * We could scan for wanted TABLE entries, but that is not the same as
439 : * dataOnly. At this stage, it seems unnecessary (6-Mar-2001).
440 : */
8053 bruce 441 GIC 121 : if (!ropt->dataOnly)
8053 bruce 442 ECB : {
6385 bruce 443 GIC 115 : int impliedDataOnly = 1;
6648 tgl 444 ECB :
6648 tgl 445 GIC 969 : for (te = AH->toc->next; te != AH->toc; te = te->next)
8053 bruce 446 ECB : {
3967 tgl 447 GIC 952 : if ((te->reqs & REQ_SCHEMA) != 0)
8053 bruce 448 ECB : { /* It's schema, and it's wanted */
8069 pjw 449 GIC 98 : impliedDataOnly = 0;
8069 pjw 450 CBC 98 : break;
8069 pjw 451 ECB : }
452 : }
8069 pjw 453 GIC 115 : if (impliedDataOnly)
8069 pjw 454 ECB : {
8069 pjw 455 GIC 17 : ropt->dataOnly = impliedDataOnly;
1469 peter 456 CBC 17 : pg_log_info("implied data-only restore");
8069 pjw 457 ECB : }
458 : }
459 :
460 : /*
461 : * Setup the output file if necessary.
462 : */
4460 tgl 463 GIC 121 : sav = SaveOutput(AH);
128 michael 464 GNC 121 : if (ropt->filename || ropt->compression_spec.algorithm != PG_COMPRESSION_NONE)
465 101 : SetOutput(AH, ropt->filename, ropt->compression_spec);
8314 bruce 466 ECB :
7539 peter_e 467 GIC 121 : ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n");
7188 bruce 468 ECB :
3198 tgl 469 GIC 121 : if (AH->archiveRemoteVersion)
3198 tgl 470 CBC 121 : ahprintf(AH, "-- Dumped from database version %s\n",
3198 tgl 471 ECB : AH->archiveRemoteVersion);
3198 tgl 472 GIC 121 : if (AH->archiveDumpVersion)
3198 tgl 473 CBC 121 : ahprintf(AH, "-- Dumped by pg_dump version %s\n",
3198 tgl 474 ECB : AH->archiveDumpVersion);
475 :
3198 tgl 476 GIC 121 : ahprintf(AH, "\n");
3198 tgl 477 ECB :
4793 bruce 478 GIC 121 : if (AH->public.verbose)
6568 tgl 479 CBC 17 : dumpTimestamp(AH, "Started on", AH->createDate);
6568 tgl 480 ECB :
6264 tgl 481 GIC 121 : if (ropt->single_txn)
6263 tgl 482 ECB : {
6263 tgl 483 UIC 0 : if (AH->connection)
3099 alvherre 484 UBC 0 : StartTransaction(AHX);
6263 tgl 485 EUB : else
6263 tgl 486 UIC 0 : ahprintf(AH, "BEGIN;\n\n");
6263 tgl 487 EUB : }
488 :
489 : /*
490 : * Establish important parameter values right away.
491 : */
6984 tgl 492 GIC 121 : _doSetFixedOutputState(AH);
6984 tgl 493 ECB :
6806 bruce 494 GIC 121 : AH->stage = STAGE_PROCESSING;
6806 bruce 495 ECB :
496 : /*
497 : * Drop the items at the start, in reverse order
498 : */
8053 bruce 499 GIC 121 : if (ropt->dropSchema)
8053 bruce 500 ECB : {
6568 tgl 501 GIC 867 : for (te = AH->toc->prev; te != AH->toc; te = te->prev)
8053 bruce 502 ECB : {
6568 tgl 503 GIC 858 : AH->currentTE = te;
6568 tgl 504 ECB :
505 : /*
506 : * In createDB mode, issue a DROP *only* for the database as a
507 : * whole. Issuing drops against anything else would be wrong,
508 : * because at this point we're connected to the wrong database.
509 : * (The DATABASE PROPERTIES entry, if any, should be treated like
510 : * the DATABASE entry.)
511 : */
3823 tgl 512 GIC 858 : if (ropt->createDB)
3823 tgl 513 ECB : {
1903 tgl 514 GIC 299 : if (strcmp(te->desc, "DATABASE") != 0 &&
1903 tgl 515 CBC 295 : strcmp(te->desc, "DATABASE PROPERTIES") != 0)
3823 516 293 : continue;
3823 tgl 517 ECB : }
518 :
519 : /* Otherwise, drop anything that's selected and has a dropStmt */
3967 tgl 520 GIC 565 : if (((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0) && te->dropStmt)
7950 peter_e 521 ECB : {
1469 peter 522 GIC 260 : pg_log_info("dropping %s %s", te->desc, te->tag);
7639 tgl 523 ECB : /* Select owner and schema as necessary */
7138 tgl 524 GIC 260 : _becomeOwner(AH, te);
7639 tgl 525 CBC 260 : _selectOutputSchema(AH, te->namespace);
3324 alvherre 526 ECB :
527 : /*
528 : * Now emit the DROP command, if the object has one. Note we
529 : * don't necessarily emit it verbatim; at this point we add an
530 : * appropriate IF EXISTS clause, if the user requested it.
531 : */
3324 alvherre 532 GIC 260 : if (*te->dropStmt != '\0')
3324 alvherre 533 ECB : {
80 tgl 534 GIC 251 : if (!ropt->if_exists ||
80 tgl 535 CBC 123 : strncmp(te->dropStmt, "--", 2) == 0)
3324 alvherre 536 ECB : {
537 : /*
538 : * Without --if-exists, or if it's just a comment (as
539 : * happens for the public schema), print the dropStmt
540 : * as-is.
541 : */
3324 alvherre 542 GIC 129 : ahprintf(AH, "%s", te->dropStmt);
3324 alvherre 543 ECB : }
544 : else
545 : {
546 : /*
547 : * Inject an appropriate spelling of "if exists". For
548 : * large objects, we have a separate routine that
549 : * knows how to do it, without depending on
550 : * te->dropStmt; use that. For other objects we need
551 : * to parse the command.
552 : */
3113 alvherre 553 GIC 122 : if (strncmp(te->desc, "BLOB", 4) == 0)
3324 alvherre 554 ECB : {
125 peter 555 GNC 2 : DropLOIfExists(AH, te->catalogId.oid);
3324 alvherre 556 ECB : }
557 : else
558 : {
3113 alvherre 559 GIC 120 : char *dropStmt = pg_strdup(te->dropStmt);
2334 tgl 560 CBC 120 : char *dropStmtOrig = dropStmt;
3113 alvherre 561 120 : PQExpBuffer ftStmt = createPQExpBuffer();
3113 alvherre 562 ECB :
563 : /*
564 : * Need to inject IF EXISTS clause after ALTER
565 : * TABLE part in ALTER TABLE .. DROP statement
566 : */
3113 alvherre 567 GIC 120 : if (strncmp(dropStmt, "ALTER TABLE", 11) == 0)
3113 alvherre 568 ECB : {
1375 drowley 569 GIC 15 : appendPQExpBufferStr(ftStmt,
1375 drowley 570 ECB : "ALTER TABLE IF EXISTS");
3113 alvherre 571 GIC 15 : dropStmt = dropStmt + 11;
3113 alvherre 572 ECB : }
573 :
574 : /*
575 : * ALTER TABLE..ALTER COLUMN..DROP DEFAULT does
576 : * not support the IF EXISTS clause, and therefore
577 : * we simply emit the original command for DEFAULT
578 : * objects (modulo the adjustment made above).
579 : *
580 : * Likewise, don't mess with DATABASE PROPERTIES.
581 : *
582 : * If we used CREATE OR REPLACE VIEW as a means of
583 : * quasi-dropping an ON SELECT rule, that should
584 : * be emitted unchanged as well.
585 : *
586 : * For other object types, we need to extract the
587 : * first part of the DROP which includes the
588 : * object type. Most of the time this matches
589 : * te->desc, so search for that; however for the
590 : * different kinds of CONSTRAINTs, we know to
591 : * search for hardcoded "DROP CONSTRAINT" instead.
592 : */
2334 tgl 593 GIC 120 : if (strcmp(te->desc, "DEFAULT") == 0 ||
1903 tgl 594 CBC 117 : strcmp(te->desc, "DATABASE PROPERTIES") == 0 ||
2334 595 117 : strncmp(dropStmt, "CREATE OR REPLACE VIEW", 22) == 0)
2838 heikki.linnakangas 596 3 : appendPQExpBufferStr(ftStmt, dropStmt);
3324 alvherre 597 ECB : else
598 : {
599 : char buffer[40];
600 : char *mark;
601 :
3113 alvherre 602 GIC 117 : if (strcmp(te->desc, "CONSTRAINT") == 0 ||
2118 tgl 603 CBC 107 : strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2 alvherre 604 GNC 107 : strcmp(te->desc, "NOT NULL CONSTRAINT") == 0 ||
3113 alvherre 605 CBC 107 : strcmp(te->desc, "FK CONSTRAINT") == 0)
606 12 : strcpy(buffer, "DROP CONSTRAINT");
3113 alvherre 607 ECB : else
3113 alvherre 608 CBC 105 : snprintf(buffer, sizeof(buffer), "DROP %s",
609 : te->desc);
3324 alvherre 610 ECB :
3113 alvherre 611 GIC 117 : mark = strstr(dropStmt, buffer);
612 :
2334 tgl 613 CBC 117 : if (mark)
614 : {
615 117 : *mark = '\0';
2334 tgl 616 GIC 117 : appendPQExpBuffer(ftStmt, "%s%s IF EXISTS%s",
2334 tgl 617 ECB : dropStmt, buffer,
2334 tgl 618 CBC 117 : mark + strlen(buffer));
619 : }
2334 tgl 620 ECB : else
621 : {
622 : /* complain and emit unmodified command */
1469 peter 623 UIC 0 : pg_log_warning("could not find where to insert IF EXISTS in statement \"%s\"",
624 : dropStmtOrig);
2334 tgl 625 UBC 0 : appendPQExpBufferStr(ftStmt, dropStmt);
626 : }
3113 alvherre 627 EUB : }
628 :
3113 alvherre 629 GIC 120 : ahprintf(AH, "%s", ftStmt->data);
630 :
3113 alvherre 631 CBC 120 : destroyPQExpBuffer(ftStmt);
2334 tgl 632 GIC 120 : pg_free(dropStmtOrig);
3113 alvherre 633 ECB : }
3324 634 : }
635 : }
636 : }
637 : }
638 :
639 : /*
640 : * _selectOutputSchema may have set currSchema to reflect the effect
641 : * of a "SET search_path" command it emitted. However, by now we may
642 : * have dropped that schema; or it might not have existed in the first
643 : * place. In either case the effective value of search_path will not
644 : * be what we think. Forcibly reset currSchema so that we will
645 : * re-establish the search_path setting when needed (after creating
646 : * the schema).
647 : *
648 : * If we treated users as pg_dump'able objects then we'd need to reset
649 : * currUser here too.
650 : */
297 peter 651 GNC 9 : free(AH->currSchema);
5179 andrew 652 CBC 9 : AH->currSchema = NULL;
8053 bruce 653 ECB : }
654 :
4242 tgl 655 GIC 121 : if (parallel_mode)
3668 andrew 656 ECB : {
657 : /*
658 : * In parallel mode, turn control over to the parallel-restore logic.
659 : */
660 : ParallelState *pstate;
661 : TocEntry pending_list;
662 :
663 : /* The archive format module may need some setup for this */
1668 tgl 664 GIC 4 : if (AH->PrepParallelRestorePtr)
1668 tgl 665 CBC 4 : AH->PrepParallelRestorePtr(AH);
1668 tgl 666 ECB :
1668 tgl 667 GIC 4 : pending_list_header_init(&pending_list);
3668 andrew 668 ECB :
669 : /* This runs PRE_DATA items and then disconnects from the database */
2075 tgl 670 GIC 4 : restore_toc_entries_prefork(AH, &pending_list);
3668 andrew 671 CBC 4 : Assert(AH->connection == NULL);
3668 andrew 672 ECB :
673 : /* ParallelBackupStart() will actually fork the processes */
2643 tgl 674 GIC 4 : pstate = ParallelBackupStart(AH);
3668 andrew 675 CBC 4 : restore_toc_entries_parallel(AH, pstate, &pending_list);
676 4 : ParallelBackupEnd(AH, pstate);
3668 andrew 677 ECB :
678 : /* reconnect the leader and see if we missed something */
3668 andrew 679 GIC 4 : restore_toc_entries_postfork(AH, &pending_list);
3668 andrew 680 CBC 4 : Assert(AH->connection != NULL);
3668 andrew 681 ECB : }
682 : else
683 : {
684 : /*
685 : * In serial mode, process everything in three phases: normal items,
686 : * then ACLs, then post-ACL items. We might be able to skip one or
687 : * both extra phases in some cases, eg data-only restores.
688 : */
2075 tgl 689 GIC 117 : bool haveACL = false;
1126 tgl 690 CBC 117 : bool havePostACL = false;
2075 tgl 691 ECB :
5179 andrew 692 GIC 21630 : for (te = AH->toc->next; te != AH->toc; te = te->next)
2075 tgl 693 ECB : {
2075 tgl 694 GIC 21514 : if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) == 0)
2075 tgl 695 CBC 949 : continue; /* ignore if not to be dumped at all */
8314 bruce 696 ECB :
2075 tgl 697 GIC 20565 : switch (_tocEntryRestorePass(te))
2075 tgl 698 ECB : {
2075 tgl 699 GIC 18337 : case RESTORE_PASS_MAIN:
2075 tgl 700 CBC 18337 : (void) restore_toc_entry(AH, te, false);
701 18336 : break;
702 1964 : case RESTORE_PASS_ACL:
703 1964 : haveACL = true;
704 1964 : break;
1126 705 264 : case RESTORE_PASS_POST_ACL:
706 264 : havePostACL = true;
2075 707 264 : break;
2075 tgl 708 ECB : }
709 : }
710 :
2075 tgl 711 GIC 116 : if (haveACL)
6844 bruce 712 ECB : {
2075 tgl 713 GIC 20849 : for (te = AH->toc->next; te != AH->toc; te = te->next)
2075 tgl 714 ECB : {
2075 tgl 715 GIC 41024 : if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0 &&
2075 tgl 716 CBC 20241 : _tocEntryRestorePass(te) == RESTORE_PASS_ACL)
717 1964 : (void) restore_toc_entry(AH, te, false);
2075 tgl 718 ECB : }
719 : }
720 :
1126 tgl 721 GIC 116 : if (havePostACL)
2075 tgl 722 ECB : {
2075 tgl 723 GIC 18320 : for (te = AH->toc->next; te != AH->toc; te = te->next)
2075 tgl 724 ECB : {
2075 tgl 725 GIC 36230 : if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0 &&
1126 tgl 726 CBC 17950 : _tocEntryRestorePass(te) == RESTORE_PASS_POST_ACL)
2075 727 264 : (void) restore_toc_entry(AH, te, false);
2075 tgl 728 ECB : }
729 : }
730 : }
731 :
6264 tgl 732 GIC 120 : if (ropt->single_txn)
6263 tgl 733 ECB : {
6263 tgl 734 UIC 0 : if (AH->connection)
3099 alvherre 735 UBC 0 : CommitTransaction(AHX);
6263 tgl 736 EUB : else
6263 tgl 737 UIC 0 : ahprintf(AH, "COMMIT;\n\n");
6263 tgl 738 EUB : }
739 :
6568 tgl 740 GIC 120 : if (AH->public.verbose)
6568 tgl 741 CBC 17 : dumpTimestamp(AH, "Completed on", time(NULL));
6568 tgl 742 ECB :
6596 tgl 743 GIC 120 : ahprintf(AH, "--\n-- PostgreSQL database dump complete\n--\n\n");
6596 tgl 744 ECB :
745 : /*
746 : * Clean up & we're done.
747 : */
6806 bruce 748 GIC 120 : AH->stage = STAGE_FINALIZING;
6806 bruce 749 ECB :
128 michael 750 GNC 120 : if (ropt->filename || ropt->compression_spec.algorithm != PG_COMPRESSION_NONE)
4460 tgl 751 CBC 101 : RestoreOutput(AH, sav);
6976 tgl 752 ECB :
6976 tgl 753 GIC 120 : if (ropt->useDB)
4070 rhaas 754 CBC 10 : DisconnectDatabase(&AH->public);
8314 bruce 755 120 : }
8314 bruce 756 ECB :
757 : /*
758 : * Restore a single TOC item. Used in both parallel and non-parallel restore;
759 : * is_parallel is true if we are in a worker child process.
760 : *
761 : * Returns 0 normally, but WORKER_CREATE_DONE or WORKER_INHIBIT_DATA if
762 : * the parallel parent has to make the corresponding status update.
763 : */
764 : static int
2643 tgl 765 GIC 20661 : restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
5179 andrew 766 ECB : {
2643 tgl 767 GIC 20661 : RestoreOptions *ropt = AH->public.ropt;
3668 andrew 768 CBC 20661 : int status = WORKER_OK;
849 peter 769 ECB : int reqs;
770 : bool defnDumped;
771 :
5179 andrew 772 GIC 20661 : AH->currentTE = te;
5179 andrew 773 ECB :
774 : /* Dump any relevant dump warnings to stderr */
5179 andrew 775 GIC 20661 : if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0)
5179 andrew 776 ECB : {
5179 andrew 777 UIC 0 : if (!ropt->dataOnly && te->defn != NULL && strlen(te->defn) != 0)
1469 peter 778 UBC 0 : pg_log_warning("warning from original dump file: %s", te->defn);
5179 andrew 779 0 : else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0)
1469 peter 780 0 : pg_log_warning("warning from original dump file: %s", te->copyStmt);
5179 andrew 781 EUB : }
782 :
783 : /* Work out what, if anything, we want from this entry */
1900 tgl 784 GIC 20661 : reqs = te->reqs;
1900 tgl 785 ECB :
5179 andrew 786 GIC 20661 : defnDumped = false;
5179 andrew 787 ECB :
788 : /*
789 : * If it has a schema component that we want, then process that
790 : */
2075 tgl 791 GIC 20661 : if ((reqs & REQ_SCHEMA) != 0)
5179 andrew 792 ECB : {
793 : /* Show namespace in log message if available */
3148 heikki.linnakangas 794 GIC 17039 : if (te->namespace)
1469 peter 795 CBC 15867 : pg_log_info("creating %s \"%s.%s\"",
1469 peter 796 ECB : te->desc, te->namespace, te->tag);
797 : else
1469 peter 798 GIC 1172 : pg_log_info("creating %s \"%s\"",
1469 peter 799 ECB : te->desc, te->tag);
800 :
2075 tgl 801 GIC 17039 : _printTocEntry(AH, te, false);
5179 andrew 802 CBC 17039 : defnDumped = true;
5179 andrew 803 ECB :
5179 andrew 804 GIC 17039 : if (strcmp(te->desc, "TABLE") == 0)
5179 andrew 805 ECB : {
5179 andrew 806 GIC 4036 : if (AH->lastErrorTE == te)
5179 andrew 807 ECB : {
808 : /*
809 : * We failed to create the table. If
810 : * --no-data-for-failed-tables was given, mark the
811 : * corresponding TABLE DATA to be ignored.
812 : *
813 : * In the parallel case this must be done in the parent, so we
814 : * just set the return value.
815 : */
5179 andrew 816 UIC 0 : if (ropt->noDataForFailedTables)
5179 andrew 817 EUB : {
5179 andrew 818 UIC 0 : if (is_parallel)
3668 andrew 819 UBC 0 : status = WORKER_INHIBIT_DATA;
5179 andrew 820 EUB : else
5179 andrew 821 UIC 0 : inhibit_data_for_failed_table(AH, te);
5179 andrew 822 EUB : }
823 : }
824 : else
825 : {
826 : /*
827 : * We created the table successfully. Mark the corresponding
828 : * TABLE DATA for possible truncation.
829 : *
830 : * In the parallel case this must be done in the parent, so we
831 : * just set the return value.
832 : */
5179 andrew 833 GIC 4036 : if (is_parallel)
3668 andrew 834 LBC 0 : status = WORKER_CREATE_DONE;
5179 andrew 835 EUB : else
5179 andrew 836 GIC 4036 : mark_create_done(AH, te);
5179 andrew 837 ECB : }
838 : }
839 :
840 : /*
841 : * If we created a DB, connect to it. Also, if we changed DB
842 : * properties, reconnect to ensure that relevant GUC settings are
843 : * applied to our session.
844 : */
1902 tgl 845 GIC 17039 : if (strcmp(te->desc, "DATABASE") == 0 ||
1902 tgl 846 CBC 17005 : strcmp(te->desc, "DATABASE PROPERTIES") == 0)
5179 andrew 847 ECB : {
1469 peter 848 GIC 44 : pg_log_info("connecting to new database \"%s\"", te->tag);
5179 andrew 849 CBC 44 : _reconnectToDB(AH, te->tag);
5179 andrew 850 ECB : }
851 : }
852 :
853 : /*
854 : * If it has a data component that we want, then process that
855 : */
5179 andrew 856 GIC 20661 : if ((reqs & REQ_DATA) != 0)
5179 andrew 857 ECB : {
858 : /*
859 : * hadDumper will be set if there is genuine data component for this
860 : * node. Otherwise, we need to check the defn field for statements
861 : * that need to be executed in data-only restores.
862 : */
5179 andrew 863 GIC 3607 : if (te->hadDumper)
5179 andrew 864 ECB : {
865 : /*
866 : * If we can output the data, then restore it.
867 : */
2153 bruce 868 GIC 3106 : if (AH->PrintTocDataPtr != NULL)
5179 andrew 869 ECB : {
2075 tgl 870 GIC 3106 : _printTocEntry(AH, te, true);
5179 andrew 871 ECB :
5179 andrew 872 GIC 3106 : if (strcmp(te->desc, "BLOBS") == 0 ||
5179 andrew 873 CBC 3067 : strcmp(te->desc, "BLOB COMMENTS") == 0)
5179 andrew 874 ECB : {
1469 peter 875 GIC 39 : pg_log_info("processing %s", te->desc);
5179 andrew 876 ECB :
5179 andrew 877 GIC 39 : _selectOutputSchema(AH, "pg_catalog");
5179 andrew 878 ECB :
879 : /* Send BLOB COMMENTS data to ExecuteSimpleCommands() */
3223 tgl 880 GIC 39 : if (strcmp(te->desc, "BLOB COMMENTS") == 0)
3223 tgl 881 LBC 0 : AH->outputKind = OUTPUT_OTHERDATA;
3223 tgl 882 EUB :
2040 peter_e 883 GIC 39 : AH->PrintTocDataPtr(AH, te);
3223 tgl 884 ECB :
3223 tgl 885 GIC 39 : AH->outputKind = OUTPUT_SQLCMDS;
5179 andrew 886 ECB : }
887 : else
888 : {
889 : bool use_truncate;
890 :
2643 tgl 891 GIC 3067 : _disableTriggersIfNecessary(AH, te);
5179 andrew 892 ECB :
893 : /* Select owner and schema as necessary */
5179 andrew 894 GIC 3067 : _becomeOwner(AH, te);
5179 andrew 895 CBC 3067 : _selectOutputSchema(AH, te->namespace);
5179 andrew 896 ECB :
1469 peter 897 GIC 3067 : pg_log_info("processing data for table \"%s.%s\"",
1418 tgl 898 ECB : te->namespace, te->tag);
899 :
900 : /*
901 : * In parallel restore, if we created the table earlier in
902 : * this run (so that we know it is empty) and we are not
903 : * restoring a load-via-partition-root data item then we
904 : * wrap the COPY in a transaction and precede it with a
905 : * TRUNCATE. If wal_level is set to minimal this prevents
906 : * WAL-logging the COPY. This obtains a speedup similar
907 : * to that from using single_txn mode in non-parallel
908 : * restores.
909 : *
910 : * We mustn't do this for load-via-partition-root cases
911 : * because some data might get moved across partition
912 : * boundaries, risking deadlock and/or loss of previously
913 : * loaded data. (We assume that all partitions of a
914 : * partitioned table will be treated the same way.)
915 : */
23 tgl 916 GIC 3083 : use_truncate = is_parallel && te->created &&
23 tgl 917 CBC 16 : !is_load_via_partition_root(te);
23 tgl 918 ECB :
23 tgl 919 GIC 3067 : if (use_truncate)
5179 andrew 920 ECB : {
921 : /*
922 : * Parallel restore is always talking directly to a
923 : * server, so no need to see if we should issue BEGIN.
924 : */
3099 alvherre 925 GIC 10 : StartTransaction(&AH->public);
5179 andrew 926 ECB :
927 : /*
928 : * Issue TRUNCATE with ONLY so that child tables are
929 : * not wiped.
930 : */
481 tgl 931 GIC 10 : ahprintf(AH, "TRUNCATE TABLE ONLY %s;\n\n",
1696 tgl 932 CBC 10 : fmtQualifiedId(te->namespace, te->tag));
5179 andrew 933 ECB : }
934 :
935 : /*
936 : * If we have a copy statement, use it.
937 : */
5179 andrew 938 GIC 3067 : if (te->copyStmt && strlen(te->copyStmt) > 0)
5179 andrew 939 ECB : {
5179 andrew 940 GIC 3010 : ahprintf(AH, "%s", te->copyStmt);
4111 tgl 941 CBC 3010 : AH->outputKind = OUTPUT_COPYDATA;
5179 andrew 942 ECB : }
943 : else
4111 tgl 944 GIC 57 : AH->outputKind = OUTPUT_OTHERDATA;
5179 andrew 945 ECB :
2040 peter_e 946 GIC 3067 : AH->PrintTocDataPtr(AH, te);
5179 andrew 947 ECB :
948 : /*
949 : * Terminate COPY if needed.
950 : */
4111 tgl 951 GIC 6075 : if (AH->outputKind == OUTPUT_COPYDATA &&
4111 tgl 952 CBC 3009 : RestoringToDB(AH))
3099 alvherre 953 9 : EndDBCopyMode(&AH->public, te->tag);
4111 tgl 954 3066 : AH->outputKind = OUTPUT_SQLCMDS;
5179 andrew 955 ECB :
956 : /* close out the transaction started above */
23 tgl 957 GIC 3066 : if (use_truncate)
3099 alvherre 958 CBC 10 : CommitTransaction(&AH->public);
5179 andrew 959 ECB :
2643 tgl 960 GIC 3066 : _enableTriggersIfNecessary(AH, te);
5179 andrew 961 ECB : }
962 : }
963 : }
5179 andrew 964 GIC 501 : else if (!defnDumped)
5179 andrew 965 ECB : {
966 : /* If we haven't already dumped the defn part, do so now */
1469 peter 967 GIC 501 : pg_log_info("executing %s %s", te->desc, te->tag);
2075 tgl 968 CBC 501 : _printTocEntry(AH, te, false);
5179 andrew 969 ECB : }
970 : }
971 :
3668 andrew 972 GIC 20660 : if (AH->public.n_errors > 0 && status == WORKER_OK)
3668 andrew 973 LBC 0 : status = WORKER_IGNORED_ERRORS;
3668 andrew 974 EUB :
3668 andrew 975 GIC 20660 : return status;
5179 andrew 976 ECB : }
977 :
978 : /*
979 : * Allocate a new RestoreOptions block.
980 : * This is mainly so we can initialize it, but also for future expansion,
981 : */
982 : RestoreOptions *
8053 bruce 983 GIC 166 : NewRestoreOptions(void)
8314 bruce 984 ECB : {
985 : RestoreOptions *opts;
986 :
3841 tgl 987 GIC 166 : opts = (RestoreOptions *) pg_malloc0(sizeof(RestoreOptions));
8314 bruce 988 ECB :
989 : /* set any fields that shouldn't default to zeroes */
8314 bruce 990 GIC 166 : opts->format = archUnknown;
927 tgl 991 CBC 166 : opts->cparams.promptPassword = TRI_DEFAULT;
4132 andrew 992 166 : opts->dumpSections = DUMP_UNSECTIONED;
128 michael 993 GNC 166 : opts->compression_spec.algorithm = PG_COMPRESSION_NONE;
994 166 : opts->compression_spec.level = 0;
8314 bruce 995 ECB :
8314 bruce 996 CBC 166 : return opts;
8314 bruce 997 ECB : }
998 :
8053 999 : static void
2643 tgl 1000 GIC 3067 : _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te)
1001 : {
1002 3067 : RestoreOptions *ropt = AH->public.ropt;
2643 tgl 1003 ECB :
1004 : /* This hack is only needed in a data-only restore */
7639 tgl 1005 CBC 3067 : if (!ropt->dataOnly || !ropt->disable_triggers)
8286 pjw 1006 GIC 3043 : return;
1007 :
1469 peter 1008 CBC 24 : pg_log_info("disabling triggers for %s", te->tag);
6438 tgl 1009 ECB :
1010 : /*
7522 bruce 1011 : * Become superuser if possible, since they are the only ones who can
1012 : * disable constraint triggers. If -S was not given, assume the initial
1013 : * user identity is a superuser. (XXX would it be better to become the
1014 : * table owner?)
1015 : */
7138 tgl 1016 GIC 24 : _becomeUser(AH, ropt->superuser);
1017 :
1018 : /*
6438 tgl 1019 ECB : * Disable them.
1020 : */
6438 tgl 1021 GIC 24 : ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
1696 1022 24 : fmtQualifiedId(te->namespace, te->tag));
1023 : }
8314 bruce 1024 ECB :
8053 1025 : static void
2643 tgl 1026 GIC 3066 : _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te)
1027 : {
1028 3066 : RestoreOptions *ropt = AH->public.ropt;
2643 tgl 1029 ECB :
1030 : /* This hack is only needed in a data-only restore */
7639 tgl 1031 CBC 3066 : if (!ropt->dataOnly || !ropt->disable_triggers)
8286 pjw 1032 GIC 3042 : return;
1033 :
1469 peter 1034 CBC 24 : pg_log_info("enabling triggers for %s", te->tag);
6438 tgl 1035 ECB :
1036 : /*
7522 bruce 1037 : * Become superuser if possible, since they are the only ones who can
1038 : * disable constraint triggers. If -S was not given, assume the initial
1039 : * user identity is a superuser. (XXX would it be better to become the
1040 : * table owner?)
1041 : */
7138 tgl 1042 GIC 24 : _becomeUser(AH, ropt->superuser);
1043 :
1044 : /*
6438 tgl 1045 ECB : * Enable them.
1046 : */
6438 tgl 1047 GIC 24 : ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
1696 1048 24 : fmtQualifiedId(te->namespace, te->tag));
1049 : }
8314 bruce 1050 ECB :
23 tgl 1051 : /*
1052 : * Detect whether a TABLE DATA TOC item is performing "load via partition
1053 : * root", that is the target table is an ancestor partition rather than the
1054 : * table the TOC item is nominally for.
1055 : *
1056 : * In newer archive files this can be detected by checking for a special
1057 : * comment placed in te->defn. In older files we have to fall back to seeing
1058 : * if the COPY statement targets the named table or some other one. This
1059 : * will not work for data dumped as INSERT commands, so we could give a false
1060 : * negative in that case; fortunately, that's a rarely-used option.
1061 : */
1062 : static bool
23 tgl 1063 GIC 16 : is_load_via_partition_root(TocEntry *te)
1064 : {
1065 16 : if (te->defn &&
23 tgl 1066 CBC 6 : strncmp(te->defn, "-- load via partition root ", 27) == 0)
23 tgl 1067 GIC 6 : return true;
23 tgl 1068 CBC 10 : if (te->copyStmt && *te->copyStmt)
23 tgl 1069 ECB : {
23 tgl 1070 CBC 6 : PQExpBuffer copyStmt = createPQExpBuffer();
23 tgl 1071 ECB : bool result;
1072 :
1073 : /*
1074 : * Build the initial part of the COPY as it would appear if the
1075 : * nominal target table is the actual target. If we see anything
1076 : * else, it must be a load-via-partition-root case.
1077 : */
23 tgl 1078 GIC 6 : appendPQExpBuffer(copyStmt, "COPY %s ",
1079 6 : fmtQualifiedId(te->namespace, te->tag));
1080 6 : result = strncmp(te->copyStmt, copyStmt->data, copyStmt->len) != 0;
23 tgl 1081 CBC 6 : destroyPQExpBuffer(copyStmt);
1082 6 : return result;
23 tgl 1083 ECB : }
1084 : /* Assume it's not load-via-partition-root */
23 tgl 1085 CBC 4 : return false;
1086 : }
1087 :
8314 bruce 1088 ECB : /*
1089 : * This is a routine that is part of the dumper interface, hence the 'Archive*' parameter.
1090 : */
1091 :
1092 : /* Public */
1093 : void
7537 peter_e 1094 GIC 1716439 : WriteData(Archive *AHX, const void *data, size_t dLen)
1095 : {
8053 bruce 1096 1716439 : ArchiveHandle *AH = (ArchiveHandle *) AHX;
8314 bruce 1097 ECB :
8297 pjw 1098 GIC 1716439 : if (!AH->currToc)
366 tgl 1099 LBC 0 : pg_fatal("internal error -- WriteData cannot be called outside the context of a DataDumper routine");
1100 :
2040 peter_e 1101 CBC 1716439 : AH->WriteDataPtr(AH, data, dLen);
8314 bruce 1102 GBC 1716439 : }
1103 :
8314 bruce 1104 ECB : /*
8053 1105 : * Create a new TOC entry. The TOC was designed as a TOC, but is now the
1106 : * repository for all metadata. But the name has stuck.
1107 : *
1108 : * The new entry is added to the Archive's TOC list. Most callers can ignore
1109 : * the result value because nothing else need be done, but a few want to
1110 : * manipulate the TOC entry further.
1111 : */
1112 :
1113 : /* Public */
1114 : TocEntry *
1528 alvherre 1115 GIC 21324 : ArchiveEntry(Archive *AHX, CatalogId catalogId, DumpId dumpId,
1116 : ArchiveOpts *opts)
1117 : {
8053 bruce 1118 CBC 21324 : ArchiveHandle *AH = (ArchiveHandle *) AHX;
1119 : TocEntry *newToc;
1120 :
3841 tgl 1121 21324 : newToc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
1122 :
7064 tgl 1123 GIC 21324 : AH->tocCount++;
7064 tgl 1124 CBC 21324 : if (dumpId > AH->maxDumpId)
7064 tgl 1125 GIC 3626 : AH->maxDumpId = dumpId;
7064 tgl 1126 ECB :
8053 bruce 1127 CBC 21324 : newToc->prev = AH->toc->prev;
1128 21324 : newToc->next = AH->toc;
8053 bruce 1129 GIC 21324 : AH->toc->prev->next = newToc;
8053 bruce 1130 CBC 21324 : AH->toc->prev = newToc;
8053 bruce 1131 ECB :
7064 tgl 1132 CBC 21324 : newToc->catalogId = catalogId;
1133 21324 : newToc->dumpId = dumpId;
1528 alvherre 1134 GIC 21324 : newToc->section = opts->section;
8043 pjw 1135 ECB :
1528 alvherre 1136 CBC 21324 : newToc->tag = pg_strdup(opts->tag);
1137 21324 : newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
1528 alvherre 1138 GIC 21324 : newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
1495 andres 1139 CBC 21324 : newToc->tableam = opts->tableam ? pg_strdup(opts->tableam) : NULL;
1444 alvherre 1140 21324 : newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
1528 1141 21324 : newToc->desc = pg_strdup(opts->description);
1444 1142 21324 : newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
1143 21324 : newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
1528 1144 21324 : newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
8043 pjw 1145 ECB :
1528 alvherre 1146 CBC 21324 : if (opts->nDeps > 0)
7064 tgl 1147 ECB : {
1528 alvherre 1148 GIC 6569 : newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId));
1528 alvherre 1149 CBC 6569 : memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
1528 alvherre 1150 GIC 6569 : newToc->nDeps = opts->nDeps;
7064 tgl 1151 ECB : }
1152 : else
1153 : {
7064 tgl 1154 GIC 14755 : newToc->dependencies = NULL;
1155 14755 : newToc->nDeps = 0;
1156 : }
8043 pjw 1157 ECB :
1528 alvherre 1158 CBC 21324 : newToc->dataDumper = opts->dumpFn;
1528 alvherre 1159 GIC 21324 : newToc->dataDumperArg = opts->dumpArg;
1160 21324 : newToc->hadDumper = opts->dumpFn ? true : false;
8314 bruce 1161 ECB :
7064 tgl 1162 CBC 21324 : newToc->formatData = NULL;
1668 1163 21324 : newToc->dataLength = 0;
1164 :
2153 bruce 1165 21324 : if (AH->ArchiveEntryPtr != NULL)
2040 peter_e 1166 4931 : AH->ArchiveEntryPtr(AH, newToc);
1167 :
1668 tgl 1168 21324 : return newToc;
8314 bruce 1169 ECB : }
1170 :
1171 : /* Public */
1172 : void
2643 tgl 1173 GIC 5 : PrintTOCSummary(Archive *AHX)
1174 : {
8053 bruce 1175 5 : ArchiveHandle *AH = (ArchiveHandle *) AHX;
2643 tgl 1176 CBC 5 : RestoreOptions *ropt = AH->public.ropt;
1177 : TocEntry *te;
128 michael 1178 GNC 5 : pg_compress_specification out_compression_spec = {0};
3967 tgl 1179 ECB : teSection curSection;
1180 : CompressFileHandle *sav;
1181 : const char *fmtName;
3138 bruce 1182 : char stamp_str[64];
1183 :
1184 : /* TOC is always uncompressed */
128 michael 1185 GNC 5 : out_compression_spec.algorithm = PG_COMPRESSION_NONE;
1186 :
4460 tgl 1187 GIC 5 : sav = SaveOutput(AH);
8053 bruce 1188 5 : if (ropt->filename)
128 michael 1189 UNC 0 : SetOutput(AH, ropt->filename, out_compression_spec);
1190 :
3087 tgl 1191 GIC 5 : if (strftime(stamp_str, sizeof(stamp_str), PGDUMP_STRFTIME_FMT,
3087 tgl 1192 CBC 5 : localtime(&AH->createDate)) == 0)
3087 tgl 1193 UIC 0 : strcpy(stamp_str, "[unknown]");
3087 tgl 1194 ECB :
3138 bruce 1195 CBC 5 : ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
45 tomas.vondra 1196 GNC 10 : ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %s\n",
1528 alvherre 1197 GIC 5 : sanitize_line(AH->archdbname, false),
1198 : AH->tocCount,
1199 : get_compress_algorithm_name(AH->compression_spec.algorithm));
8297 pjw 1200 ECB :
8053 bruce 1201 GBC 5 : switch (AH->format)
1202 : {
8297 pjw 1203 CBC 4 : case archCustom:
1204 4 : fmtName = "CUSTOM";
1205 4 : break;
3584 fujii 1206 GIC 1 : case archDirectory:
1207 1 : fmtName = "DIRECTORY";
1208 1 : break;
8297 pjw 1209 LBC 0 : case archTar:
8297 pjw 1210 UIC 0 : fmtName = "TAR";
8297 pjw 1211 LBC 0 : break;
1212 0 : default:
1213 0 : fmtName = "UNKNOWN";
8297 pjw 1214 ECB : }
8286 1215 :
2357 peter_e 1216 CBC 5 : ahprintf(AH, "; Dump Version: %d.%d-%d\n",
2357 peter_e 1217 GBC 5 : ARCHIVE_MAJOR(AH->version), ARCHIVE_MINOR(AH->version), ARCHIVE_REV(AH->version));
7474 bruce 1218 5 : ahprintf(AH, "; Format: %s\n", fmtName);
7469 tgl 1219 5 : ahprintf(AH, "; Integer: %d bytes\n", (int) AH->intSize);
1220 5 : ahprintf(AH, "; Offset: %d bytes\n", (int) AH->offSize);
6728 1221 5 : if (AH->archiveRemoteVersion)
6728 tgl 1222 GIC 5 : ahprintf(AH, "; Dumped from database version: %s\n",
1223 : AH->archiveRemoteVersion);
6728 tgl 1224 CBC 5 : if (AH->archiveDumpVersion)
1225 5 : ahprintf(AH, "; Dumped by pg_dump version: %s\n",
6728 tgl 1226 ECB : AH->archiveDumpVersion);
8297 pjw 1227 :
7474 bruce 1228 CBC 5 : ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");
8314 bruce 1229 ECB :
3967 tgl 1230 CBC 5 : curSection = SECTION_PRE_DATA;
5179 andrew 1231 GIC 1310 : for (te = AH->toc->next; te != AH->toc; te = te->next)
8053 bruce 1232 ECB : {
3967 tgl 1233 CBC 1305 : if (te->section != SECTION_NONE)
3967 tgl 1234 GIC 950 : curSection = te->section;
1235 1305 : if (ropt->verbose ||
1900 tgl 1236 CBC 1305 : (_tocEntryRequired(te, curSection, AH) & (REQ_SCHEMA | REQ_DATA)) != 0)
1237 : {
2221 tgl 1238 ECB : char *sanitized_name;
1239 : char *sanitized_schema;
1240 : char *sanitized_owner;
1241 :
1242 : /*
1243 : */
1528 alvherre 1244 CBC 1280 : sanitized_name = sanitize_line(te->tag, false);
1528 alvherre 1245 GIC 1280 : sanitized_schema = sanitize_line(te->namespace, true);
1246 1280 : sanitized_owner = sanitize_line(te->owner, false);
1247 :
6757 tgl 1248 1280 : ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
1249 : te->catalogId.tableoid, te->catalogId.oid,
1250 : te->desc, sanitized_schema, sanitized_name,
1251 : sanitized_owner);
2221 tgl 1252 ECB :
2221 tgl 1253 CBC 1280 : free(sanitized_name);
1254 1280 : free(sanitized_schema);
2221 tgl 1255 GIC 1280 : free(sanitized_owner);
2221 tgl 1256 ECB : }
5179 andrew 1257 GIC 1305 : if (ropt->verbose && te->nDeps > 0)
1258 : {
1259 : int i;
1260 :
5179 andrew 1261 LBC 0 : ahprintf(AH, ";\tdepends on:");
1262 0 : for (i = 0; i < te->nDeps; i++)
1263 0 : ahprintf(AH, " %d", te->dependencies[i]);
5179 andrew 1264 UIC 0 : ahprintf(AH, "\n");
5179 andrew 1265 ECB : }
1266 : }
1267 :
1268 : /* Enforce strict names checking */
2764 teodor 1269 GBC 5 : if (ropt->strict_names)
2764 teodor 1270 UBC 0 : StrictNamesCheck(ropt);
2764 teodor 1271 EUB :
8053 bruce 1272 GBC 5 : if (ropt->filename)
4460 tgl 1273 UIC 0 : RestoreOutput(AH, sav);
8314 bruce 1274 GIC 5 : }
1275 :
1276 : /***********
1277 : * Large Object Archival
8297 pjw 1278 EUB : ***********/
1279 :
1280 : /* Called by a dumper to signal start of a LO */
8053 bruce 1281 : int
125 peter 1282 GNC 80 : StartLO(Archive *AHX, Oid oid)
1283 : {
8053 bruce 1284 GIC 80 : ArchiveHandle *AH = (ArchiveHandle *) AHX;
1285 :
125 peter 1286 GNC 80 : if (!AH->StartLOPtr)
366 tgl 1287 UIC 0 : pg_fatal("large-object output not supported in chosen format");
1288 :
125 peter 1289 GNC 80 : AH->StartLOPtr(AH, AH->currToc, oid);
8297 pjw 1290 ECB :
8053 bruce 1291 GIC 80 : return 1;
8297 pjw 1292 ECB : }
1293 :
1294 : /* Called by a dumper to signal end of a LO */
8053 bruce 1295 EUB : int
125 peter 1296 GNC 80 : EndLO(Archive *AHX, Oid oid)
8297 pjw 1297 ECB : {
8053 bruce 1298 GIC 80 : ArchiveHandle *AH = (ArchiveHandle *) AHX;
8297 pjw 1299 ECB :
125 peter 1300 GNC 80 : if (AH->EndLOPtr)
1301 80 : AH->EndLOPtr(AH, AH->currToc, oid);
1302 :
8053 bruce 1303 GIC 80 : return 1;
8297 pjw 1304 ECB : }
1305 :
1306 : /**********
1307 : * Large Object Restoration
1308 : **********/
1309 :
1310 : /*
1311 : * Called by a format handler before any LOs are restored
1312 : */
1313 : void
125 peter 1314 GNC 10 : StartRestoreLOs(ArchiveHandle *AH)
1315 : {
2643 tgl 1316 GIC 10 : RestoreOptions *ropt = AH->public.ropt;
1317 :
1318 10 : if (!ropt->single_txn)
1319 : {
6263 1320 10 : if (AH->connection)
3099 alvherre 1321 UIC 0 : StartTransaction(&AH->public);
6263 tgl 1322 ECB : else
6263 tgl 1323 GIC 10 : ahprintf(AH, "BEGIN;\n\n");
6263 tgl 1324 ECB : }
1325 :
125 peter 1326 GNC 10 : AH->loCount = 0;
8195 pjw 1327 GIC 10 : }
8195 pjw 1328 ECB :
8195 pjw 1329 EUB : /*
1330 : * Called by a format handler after all LOs are restored
8195 pjw 1331 ECB : */
1332 : void
125 peter 1333 GNC 10 : EndRestoreLOs(ArchiveHandle *AH)
8195 pjw 1334 ECB : {
2643 tgl 1335 CBC 10 : RestoreOptions *ropt = AH->public.ropt;
1336 :
2643 tgl 1337 GIC 10 : if (!ropt->single_txn)
1338 : {
6263 1339 10 : if (AH->connection)
3099 alvherre 1340 UIC 0 : CommitTransaction(&AH->public);
6263 tgl 1341 ECB : else
6263 tgl 1342 GIC 10 : ahprintf(AH, "COMMIT;\n\n");
6263 tgl 1343 ECB : }
1344 :
1469 peter 1345 CBC 10 : pg_log_info(ngettext("restored %d large object",
1346 : "restored %d large objects",
1347 : AH->loCount),
1348 : AH->loCount);
8195 pjw 1349 GIC 10 : }
8195 pjw 1350 ECB :
1351 :
1352 : /*
1353 : * Called by a format handler to initiate restoration of a LO
1354 : */
1355 : void
125 peter 1356 GNC 20 : StartRestoreLO(ArchiveHandle *AH, Oid oid, bool drop)
8297 pjw 1357 ECB : {
125 peter 1358 GNC 20 : bool old_lo_style = (AH->version < K_VERS_1_12);
1359 : Oid loOid;
1360 :
1361 20 : AH->loCount++;
1362 :
1363 : /* Initialize the LO Buffer */
7655 bruce 1364 CBC 20 : AH->lo_buf_used = 0;
1365 :
1469 peter 1366 20 : pg_log_info("restoring large object with OID %u", oid);
1367 :
1368 : /* With an old archive we must do drop and create logic here */
125 peter 1369 GNC 20 : if (old_lo_style && drop)
125 peter 1370 UNC 0 : DropLOIfExists(AH, oid);
1371 :
6501 tgl 1372 CBC 20 : if (AH->connection)
1373 : {
125 peter 1374 UNC 0 : if (old_lo_style)
1375 : {
4798 tgl 1376 UIC 0 : loOid = lo_create(AH->connection, oid);
4798 tgl 1377 LBC 0 : if (loOid == 0 || loOid != oid)
366 tgl 1378 UBC 0 : pg_fatal("could not create large object %u: %s",
1379 : oid, PQerrorMessage(AH->connection));
4798 tgl 1380 ECB : }
6501 tgl 1381 UIC 0 : AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
6501 tgl 1382 UBC 0 : if (AH->loFd == -1)
366 tgl 1383 UIC 0 : pg_fatal("could not open large object %u: %s",
366 tgl 1384 EUB : oid, PQerrorMessage(AH->connection));
6501 1385 : }
1386 : else
1387 : {
125 peter 1388 GNC 20 : if (old_lo_style)
4798 tgl 1389 UBC 0 : ahprintf(AH, "SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n",
4798 tgl 1390 EUB : oid, INV_WRITE);
1391 : else
4798 tgl 1392 GIC 20 : ahprintf(AH, "SELECT pg_catalog.lo_open('%u', %d);\n",
1393 : oid, INV_WRITE);
1394 : }
1395 :
125 peter 1396 GNC 20 : AH->writingLO = true;
8297 pjw 1397 GBC 20 : }
1398 :
1399 : void
125 peter 1400 GNC 20 : EndRestoreLO(ArchiveHandle *AH, Oid oid)
1401 : {
7620 tgl 1402 GIC 20 : if (AH->lo_buf_used > 0)
1403 : {
7620 tgl 1404 ECB : /* Write remaining bytes from the LO buffer */
6501 tgl 1405 CBC 10 : dump_lo_buf(AH);
1406 : }
1407 :
125 peter 1408 GNC 20 : AH->writingLO = false;
1409 :
6501 tgl 1410 CBC 20 : if (AH->connection)
1411 : {
6501 tgl 1412 UIC 0 : lo_close(AH->connection, AH->loFd);
6501 tgl 1413 LBC 0 : AH->loFd = -1;
1414 : }
1415 : else
6501 tgl 1416 ECB : {
5010 tgl 1417 GIC 20 : ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
8195 pjw 1418 ECB : }
8297 pjw 1419 GIC 20 : }
8297 pjw 1420 EUB :
8314 bruce 1421 : /***********
1422 : * Sorting and Reordering
1423 : ***********/
1424 :
8053 bruce 1425 ECB : void
2643 tgl 1426 UIC 0 : SortTocFromFile(Archive *AHX)
8314 bruce 1427 ECB : {
8053 bruce 1428 UIC 0 : ArchiveHandle *AH = (ArchiveHandle *) AHX;
2643 tgl 1429 0 : RestoreOptions *ropt = AH->public.ropt;
1430 : FILE *fh;
1431 : StringInfoData linebuf;
1432 :
1433 : /* Allocate space for the 'wanted' array, and init it */
1474 michael 1434 UBC 0 : ropt->idWanted = (bool *) pg_malloc0(sizeof(bool) * AH->maxDumpId);
1435 :
8053 bruce 1436 EUB : /* Setup the file */
8053 bruce 1437 UBC 0 : fh = fopen(ropt->tocFile, PG_BINARY_R);
8053 bruce 1438 UIC 0 : if (!fh)
366 tgl 1439 0 : pg_fatal("could not open TOC file \"%s\": %m", ropt->tocFile);
1440 :
929 1441 0 : initStringInfo(&linebuf);
929 tgl 1442 EUB :
929 tgl 1443 UIC 0 : while (pg_get_line_buf(fh, &linebuf))
1444 : {
4385 tgl 1445 EUB : char *cmnt;
1446 : char *endptr;
1447 : DumpId id;
1448 : TocEntry *te;
1449 :
1450 : /* Truncate line at comment, if any */
929 tgl 1451 UBC 0 : cmnt = strchr(linebuf.data, ';');
8053 bruce 1452 UIC 0 : if (cmnt != NULL)
1453 : {
1454 0 : cmnt[0] = '\0';
929 tgl 1455 0 : linebuf.len = cmnt - linebuf.data;
1456 : }
1457 :
1458 : /* Ignore if all blank */
929 tgl 1459 UBC 0 : if (strspn(linebuf.data, " \t\r\n") == linebuf.len)
8053 bruce 1460 0 : continue;
1461 :
6536 tgl 1462 EUB : /* Get an ID, check it's valid and not already seen */
929 tgl 1463 UBC 0 : id = strtol(linebuf.data, &endptr, 10);
929 tgl 1464 UIC 0 : if (endptr == linebuf.data || id <= 0 || id > AH->maxDumpId ||
6536 1465 0 : ropt->idWanted[id - 1])
1466 : {
929 tgl 1467 UBC 0 : pg_log_warning("line ignored: %s", linebuf.data);
8053 bruce 1468 0 : continue;
1469 : }
1470 :
8053 bruce 1471 EUB : /* Find TOC entry */
7064 tgl 1472 UBC 0 : te = getTocEntryByDumpId(AH, id);
8053 bruce 1473 0 : if (!te)
366 tgl 1474 UIC 0 : pg_fatal("could not find entry for ID %d",
366 tgl 1475 EUB : id);
8314 bruce 1476 :
1477 : /* Mark it wanted */
7064 tgl 1478 UIC 0 : ropt->idWanted[id - 1] = true;
1479 :
4614 tgl 1480 EUB : /*
1481 : * Move each item to the end of the list as it is selected, so that
1482 : * they are placed in the desired order. Any unwanted items will end
1483 : * up at the front of the list, which may seem unintuitive but it's
1484 : * what we need. In an ordinary serial restore that makes no
1485 : * difference, but in a parallel restore we need to mark unrestored
1486 : * items' dependencies as satisfied before we start examining
1487 : * restorable items. Otherwise they could have surprising
1488 : * side-effects on the order in which restorable items actually get
1489 : * restored.
1490 : */
957 peter 1491 UIC 0 : _moveBefore(AH->toc, te);
1492 : }
1493 :
929 tgl 1494 0 : pg_free(linebuf.data);
1495 :
8053 bruce 1496 0 : if (fclose(fh) != 0)
366 tgl 1497 0 : pg_fatal("could not close TOC file: %m");
8314 bruce 1498 0 : }
8314 bruce 1499 EUB :
1500 : /**********************
1501 : * Convenience functions that look like standard IO functions
1502 : * for writing data when in dump mode.
1503 : **********************/
1504 :
1505 : /* Public */
3261 1506 : void
8053 bruce 1507 GIC 21600 : archputs(const char *s, Archive *AH)
1508 : {
3261 1509 21600 : WriteData(AH, s, strlen(s));
8314 1510 21600 : }
1511 :
1512 : /* Public */
1513 : int
8053 1514 2985 : archprintf(Archive *AH, const char *fmt,...)
8314 bruce 1515 ECB : {
1656 tgl 1516 GIC 2985 : int save_errno = errno;
3454 tgl 1517 ECB : char *p;
3454 tgl 1518 CBC 2985 : size_t len = 128; /* initial assumption about buffer size */
1519 : size_t cnt;
1520 :
1521 : for (;;)
8314 bruce 1522 LBC 0 : {
1523 : va_list args;
3454 tgl 1524 ECB :
1525 : /* Allocate work buffer. */
3454 tgl 1526 CBC 2985 : p = (char *) pg_malloc(len);
1527 :
1528 : /* Try to format the data. */
1656 tgl 1529 GIC 2985 : errno = save_errno;
3454 tgl 1530 GBC 2985 : va_start(args, fmt);
3454 tgl 1531 GIC 2985 : cnt = pvsnprintf(p, len, fmt, args);
1532 2985 : va_end(args);
1533 :
3454 tgl 1534 CBC 2985 : if (cnt < len)
3454 tgl 1535 GIC 2985 : break; /* success */
1536 :
3454 tgl 1537 ECB : /* Release buffer and loop around to try again with larger len. */
3454 tgl 1538 LBC 0 : free(p);
1539 0 : len = cnt;
8053 bruce 1540 ECB : }
1541 :
8053 bruce 1542 CBC 2985 : WriteData(AH, p, cnt);
1543 2985 : free(p);
3454 tgl 1544 GIC 2985 : return (int) cnt;
1545 : }
8314 bruce 1546 EUB :
1547 :
1548 : /*******************************
1549 : * Stuff below here should be 'private' to the archiver routines
8314 bruce 1550 ECB : *******************************/
1551 :
4460 tgl 1552 : static void
128 michael 1553 GNC 101 : SetOutput(ArchiveHandle *AH, const char *filename,
1554 : const pg_compress_specification compression_spec)
1555 : {
1556 : CompressFileHandle *CFH;
1557 : const char *mode;
45 tomas.vondra 1558 101 : int fn = -1;
1559 :
8053 bruce 1560 GIC 101 : if (filename)
1561 : {
1466 alvherre 1562 101 : if (strcmp(filename, "-") == 0)
1466 alvherre 1563 UIC 0 : fn = fileno(stdout);
1564 : }
8053 bruce 1565 0 : else if (AH->FH)
1566 0 : fn = fileno(AH->FH);
8053 bruce 1567 LBC 0 : else if (AH->fSpec)
1568 : {
8053 bruce 1569 UIC 0 : filename = AH->fSpec;
8053 bruce 1570 ECB : }
8053 bruce 1571 EUB : else
8053 bruce 1572 UIC 0 : fn = fileno(stdout);
8053 bruce 1573 EUB :
45 tomas.vondra 1574 GNC 101 : if (AH->mode == archModeAppend)
1575 34 : mode = PG_BINARY_A;
1576 : else
1577 67 : mode = PG_BINARY_W;
7111 tgl 1578 ECB :
45 tomas.vondra 1579 GNC 101 : CFH = InitCompressFileHandle(compression_spec);
1580 :
17 1581 101 : if (!CFH->open_func(filename, fn, mode, CFH))
5642 tgl 1582 ECB : {
5642 tgl 1583 LBC 0 : if (filename)
366 tgl 1584 UBC 0 : pg_fatal("could not open output file \"%s\": %m", filename);
1585 : else
366 tgl 1586 LBC 0 : pg_fatal("could not open output file: %m");
5642 tgl 1587 ECB : }
1588 :
45 tomas.vondra 1589 GNC 101 : AH->OF = CFH;
4460 tgl 1590 GIC 101 : }
1591 :
1592 : static CompressFileHandle *
1593 126 : SaveOutput(ArchiveHandle *AH)
1594 : {
45 tomas.vondra 1595 GNC 126 : return (CompressFileHandle *) AH->OF;
8314 bruce 1596 ECB : }
1597 :
1598 : static void
45 tomas.vondra 1599 GNC 101 : RestoreOutput(ArchiveHandle *AH, CompressFileHandle *savedOutput)
8314 bruce 1600 ECB : {
45 tomas.vondra 1601 GNC 101 : errno = 0;
17 1602 101 : if (!EndCompressFileHandle(AH->OF))
366 tgl 1603 LBC 0 : pg_fatal("could not close output file: %m");
1604 :
45 tomas.vondra 1605 GNC 101 : AH->OF = savedOutput;
8314 bruce 1606 GIC 101 : }
1607 :
8314 bruce 1608 ECB :
1609 :
1610 : /*
1611 : * Print formatted text to the output file (usually stdout).
1612 : */
8053 1613 : int
8053 bruce 1614 CBC 111361 : ahprintf(ArchiveHandle *AH, const char *fmt,...)
1615 : {
1656 tgl 1616 GIC 111361 : int save_errno = errno;
1617 : char *p;
3454 1618 111361 : size_t len = 128; /* initial assumption about buffer size */
1619 : size_t cnt;
1620 :
3454 tgl 1621 ECB : for (;;)
8080 tgl 1622 GIC 6048 : {
3454 tgl 1623 ECB : va_list args;
1624 :
1625 : /* Allocate work buffer. */
3454 tgl 1626 GIC 117409 : p = (char *) pg_malloc(len);
1627 :
1628 : /* Try to format the data. */
1656 1629 117409 : errno = save_errno;
3454 1630 117409 : va_start(args, fmt);
1631 117409 : cnt = pvsnprintf(p, len, fmt, args);
3454 tgl 1632 CBC 117409 : va_end(args);
1633 :
1634 117409 : if (cnt < len)
3454 tgl 1635 GIC 111361 : break; /* success */
1636 :
1637 : /* Release buffer and loop around to try again with larger len. */
3454 tgl 1638 GBC 6048 : free(p);
1639 6048 : len = cnt;
1640 : }
1641 :
8053 bruce 1642 GIC 111361 : ahwrite(p, 1, cnt, AH);
1643 111361 : free(p);
3454 tgl 1644 GBC 111361 : return (int) cnt;
8314 bruce 1645 EUB : }
1646 :
1647 : /*
1648 : * Single place for logic which says 'We are restoring to a direct DB connection'.
1649 : */
6109 bruce 1650 ECB : static int
8053 bruce 1651 GIC 1805211 : RestoringToDB(ArchiveHandle *AH)
8294 pjw 1652 ECB : {
2643 tgl 1653 GIC 1805211 : RestoreOptions *ropt = AH->public.ropt;
1654 :
1655 1805211 : return (ropt && ropt->useDB && AH->connection);
1656 : }
1657 :
6501 tgl 1658 ECB : /*
1659 : * Dump the current contents of the LO data buffer while writing a LO
1660 : */
1661 : static void
6501 tgl 1662 CBC 10 : dump_lo_buf(ArchiveHandle *AH)
1663 : {
1664 10 : if (AH->connection)
6501 tgl 1665 ECB : {
1666 : int res;
1667 :
6501 tgl 1668 UIC 0 : res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
903 1669 0 : pg_log_debug(ngettext("wrote %zu byte of large object data (result = %d)",
1670 : "wrote %zu bytes of large object data (result = %d)",
1671 : AH->lo_buf_used),
1672 : AH->lo_buf_used, res);
1673 : /* We assume there are no short writes, only errors */
6501 1674 0 : if (res != AH->lo_buf_used)
903 tgl 1675 LBC 0 : warn_or_exit_horribly(AH, "could not write to large object: %s",
903 tgl 1676 UIC 0 : PQerrorMessage(AH->connection));
6501 tgl 1677 ECB : }
1678 : else
1679 : {
4996 tgl 1680 GIC 10 : PQExpBuffer buf = createPQExpBuffer();
6501 tgl 1681 ECB :
4996 tgl 1682 GIC 10 : appendByteaLiteralAHX(buf,
4996 tgl 1683 ECB : (const unsigned char *) AH->lo_buf,
1684 : AH->lo_buf_used,
4996 tgl 1685 EUB : AH);
1686 :
1687 : /* Hack: turn off writingLO so ahwrite doesn't recurse to here */
125 peter 1688 GNC 10 : AH->writingLO = false;
4996 tgl 1689 GBC 10 : ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
125 peter 1690 GNC 10 : AH->writingLO = true;
6501 tgl 1691 EUB :
4996 tgl 1692 GIC 10 : destroyPQExpBuffer(buf);
1693 : }
6501 tgl 1694 CBC 10 : AH->lo_buf_used = 0;
1695 10 : }
1696 :
6501 tgl 1697 ECB :
1698 : /*
4273 1699 : * Write buffer to the output file (usually stdout). This is used for
8053 bruce 1700 : * outputting 'restore' scripts etc. It is even possible for an archive
1701 : * format to create a custom output routine to 'fake' a restore if it
1702 : * wants to generate a script (see TAR output).
1703 : */
1704 : void
8053 bruce 1705 GIC 1803486 : ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
8314 bruce 1706 ECB : {
3260 bruce 1707 CBC 1803486 : int bytes_written = 0;
1708 :
125 peter 1709 GNC 1803486 : if (AH->writingLO)
8297 pjw 1710 ECB : {
6385 bruce 1711 GIC 16 : size_t remaining = size * nmemb;
6501 tgl 1712 ECB :
6501 tgl 1713 CBC 16 : while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1714 : {
6501 tgl 1715 UIC 0 : size_t avail = AH->lo_buf_size - AH->lo_buf_used;
6501 tgl 1716 ECB :
6501 tgl 1717 UBC 0 : memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
6501 tgl 1718 LBC 0 : ptr = (const void *) ((const char *) ptr + avail);
6501 tgl 1719 UIC 0 : remaining -= avail;
1720 0 : AH->lo_buf_used += avail;
1721 0 : dump_lo_buf(AH);
7537 peter_e 1722 EUB : }
1723 :
6501 tgl 1724 GIC 16 : memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1725 16 : AH->lo_buf_used += remaining;
6501 tgl 1726 EUB :
3261 bruce 1727 GIC 16 : bytes_written = size * nmemb;
1728 : }
8053 bruce 1729 GBC 1803470 : else if (AH->CustomOutPtr)
2153 bruce 1730 GIC 1614 : bytes_written = AH->CustomOutPtr(AH, ptr, size * nmemb);
3260 bruce 1731 EUB :
1732 : /*
1733 : * If we're doing a restore, and it's direct to DB, and we're connected
1734 : * then send it to the DB.
1735 : */
45 tomas.vondra 1736 GNC 1801856 : else if (RestoringToDB(AH))
1737 3603 : bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb);
8297 pjw 1738 EUB : else
45 tomas.vondra 1739 : {
45 tomas.vondra 1740 GNC 1798253 : CompressFileHandle *CFH = (CompressFileHandle *) AH->OF;
1741 :
17 1742 1798253 : if (CFH->write_func(ptr, size * nmemb, CFH))
1743 1798253 : bytes_written = size * nmemb;
45 tomas.vondra 1744 EUB : }
3261 bruce 1745 :
3261 bruce 1746 GBC 1803486 : if (bytes_written != size * nmemb)
3261 bruce 1747 UIC 0 : WRITE_ERROR_EXIT;
8053 bruce 1748 GBC 1803486 : }
1749 :
6926 bruce 1750 EUB : /* on some error, we may decide to go on... */
1751 : void
1469 peter 1752 UIC 0 : warn_or_exit_horribly(ArchiveHandle *AH, const char *fmt,...)
1753 : {
1754 : va_list ap;
1755 :
6797 bruce 1756 0 : switch (AH->stage)
1757 : {
6806 bruce 1758 EUB :
6806 bruce 1759 UBC 0 : case STAGE_NONE:
1760 : /* Do nothing special */
1761 0 : break;
6806 bruce 1762 EUB :
6806 bruce 1763 UBC 0 : case STAGE_INITIALIZING:
6797 bruce 1764 UIC 0 : if (AH->stage != AH->lastErrorStage)
366 tgl 1765 UBC 0 : pg_log_info("while INITIALIZING:");
6806 bruce 1766 0 : break;
1767 :
1768 0 : case STAGE_PROCESSING:
6797 1769 0 : if (AH->stage != AH->lastErrorStage)
366 tgl 1770 UIC 0 : pg_log_info("while PROCESSING TOC:");
6806 bruce 1771 0 : break;
1772 :
1773 0 : case STAGE_FINALIZING:
6797 1774 0 : if (AH->stage != AH->lastErrorStage)
366 tgl 1775 0 : pg_log_info("while FINALIZING:");
6806 bruce 1776 0 : break;
1777 : }
6797 1778 0 : if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE)
1779 : {
366 tgl 1780 0 : pg_log_info("from TOC entry %d; %u %u %s %s %s",
1781 : AH->currentTE->dumpId,
1782 : AH->currentTE->catalogId.tableoid,
1783 : AH->currentTE->catalogId.oid,
1784 : AH->currentTE->desc ? AH->currentTE->desc : "(no desc)",
1785 : AH->currentTE->tag ? AH->currentTE->tag : "(no tag)",
1786 : AH->currentTE->owner ? AH->currentTE->owner : "(no owner)");
1787 : }
6806 bruce 1788 0 : AH->lastErrorStage = AH->stage;
6806 bruce 1789 UBC 0 : AH->lastErrorTE = AH->currentTE;
1790 :
6926 bruce 1791 UIC 0 : va_start(ap, fmt);
366 tgl 1792 UBC 0 : pg_log_generic_v(PG_LOG_ERROR, PG_LOG_PRIMARY, fmt, ap);
4037 alvherre 1793 0 : va_end(ap);
1794 :
6806 bruce 1795 UIC 0 : if (AH->public.exit_on_error)
4037 alvherre 1796 UBC 0 : exit_nicely(1);
6926 bruce 1797 EUB : else
6926 bruce 1798 UBC 0 : AH->public.n_errors++;
1799 0 : }
8297 pjw 1800 EUB :
1801 : #ifdef NOT_USED
1802 :
1803 : static void
1804 : _moveAfter(ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
1805 : {
1806 : /* Unlink te from list */
1807 : te->prev->next = te->next;
1808 : te->next->prev = te->prev;
1809 :
1810 : /* and insert it after "pos" */
1811 : te->prev = pos;
1812 : te->next = pos->next;
1813 : pos->next->prev = te;
8053 bruce 1814 ECB : pos->next = te;
1815 : }
4614 tgl 1816 : #endif
1817 :
1818 : static void
957 peter 1819 LBC 0 : _moveBefore(TocEntry *pos, TocEntry *te)
8314 bruce 1820 ECB : {
1821 : /* Unlink te from list */
8053 bruce 1822 LBC 0 : te->prev->next = te->next;
8053 bruce 1823 UIC 0 : te->next->prev = te->prev;
1824 :
4614 tgl 1825 ECB : /* and insert it before "pos" */
8053 bruce 1826 UBC 0 : te->prev = pos->prev;
8053 bruce 1827 UIC 0 : te->next = pos;
1828 0 : pos->prev->next = te;
8053 bruce 1829 LBC 0 : pos->prev = te;
8314 bruce 1830 UIC 0 : }
1831 :
1832 : /*
1833 : * Build index arrays for the TOC list
1834 : *
1835 : * This should be invoked only after we have created or read in all the TOC
1836 : * items.
3968 tgl 1837 ECB : *
1838 : * The arrays are indexed by dump ID (so entry zero is unused). Note that the
3260 bruce 1839 : * array entries run only up to maxDumpId. We might see dependency dump IDs
1840 : * beyond that (if the dump was partial); so always check the array bound
1841 : * before trying to touch an array entry.
1842 : */
1843 : static void
3968 tgl 1844 GIC 139 : buildTocEntryArrays(ArchiveHandle *AH)
1845 : {
3968 tgl 1846 CBC 139 : DumpId maxDumpId = AH->maxDumpId;
8053 bruce 1847 EUB : TocEntry *te;
1848 :
3841 tgl 1849 CBC 139 : AH->tocsByDumpId = (TocEntry **) pg_malloc0((maxDumpId + 1) * sizeof(TocEntry *));
3841 tgl 1850 GIC 139 : AH->tableDataId = (DumpId *) pg_malloc0((maxDumpId + 1) * sizeof(DumpId));
1851 :
5179 andrew 1852 CBC 26360 : for (te = AH->toc->next; te != AH->toc; te = te->next)
1853 : {
1854 : /* this check is purely paranoia, maxDumpId should be correct */
3968 tgl 1855 26221 : if (te->dumpId <= 0 || te->dumpId > maxDumpId)
366 tgl 1856 UIC 0 : pg_fatal("bad dumpId");
1857 :
3968 tgl 1858 ECB : /* tocsByDumpId indexes all TOCs by their dump ID */
3968 tgl 1859 CBC 26221 : AH->tocsByDumpId[te->dumpId] = te;
1860 :
3968 tgl 1861 ECB : /*
1862 : * tableDataId provides the TABLE DATA item's dump ID for each TABLE
1863 : * TOC entry that has a DATA item. We compute this by reversing the
3968 tgl 1864 EUB : * TABLE DATA item's dependency, knowing that a TABLE DATA item has
1865 : * just one dependency and it is the TABLE item.
1866 : */
3968 tgl 1867 GIC 26221 : if (strcmp(te->desc, "TABLE DATA") == 0 && te->nDeps > 0)
3968 tgl 1868 ECB : {
3968 tgl 1869 GIC 3367 : DumpId tableId = te->dependencies[0];
3968 tgl 1870 ECB :
1871 : /*
1872 : * The TABLE item might not have been in the archive, if this was
1873 : * a data-only dump; but its dump ID should be less than its data
1874 : * item's dump ID, so there should be a place for it in the array.
1875 : */
3968 tgl 1876 GIC 3367 : if (tableId <= 0 || tableId > maxDumpId)
366 tgl 1877 UIC 0 : pg_fatal("bad table dumpId for TABLE DATA item");
1878 :
3968 tgl 1879 CBC 3367 : AH->tableDataId[tableId] = te->dumpId;
1880 : }
1881 : }
3968 tgl 1882 GIC 139 : }
1883 :
3668 andrew 1884 ECB : TocEntry *
3968 tgl 1885 GIC 10706 : getTocEntryByDumpId(ArchiveHandle *AH, DumpId id)
1886 : {
3968 tgl 1887 ECB : /* build index arrays if we didn't already */
3968 tgl 1888 GIC 10706 : if (AH->tocsByDumpId == NULL)
3968 tgl 1889 CBC 20 : buildTocEntryArrays(AH);
3968 tgl 1890 ECB :
3968 tgl 1891 GIC 10706 : if (id > 0 && id <= AH->maxDumpId)
3968 tgl 1892 CBC 10706 : return AH->tocsByDumpId[id];
1893 :
8053 bruce 1894 UIC 0 : return NULL;
1895 : }
8314 bruce 1896 ECB :
1897 : int
3967 tgl 1898 GIC 10538 : TocIDRequired(ArchiveHandle *AH, DumpId id)
1899 : {
7064 1900 10538 : TocEntry *te = getTocEntryByDumpId(AH, id);
1901 :
8053 bruce 1902 10538 : if (!te)
8053 bruce 1903 CBC 4916 : return 0;
1904 :
3967 tgl 1905 GIC 5622 : return te->reqs;
8314 bruce 1906 ECB : }
1907 :
1908 : size_t
5893 magnus 1909 GBC 6334 : WriteOffset(ArchiveHandle *AH, pgoff_t o, int wasSet)
1910 : {
7188 bruce 1911 EUB : int off;
7474 1912 :
1913 : /* Save the flag */
2040 peter_e 1914 GBC 6334 : AH->WriteBytePtr(AH, wasSet);
1915 :
1916 : /* Write out pgoff_t smallest byte first, prevents endian mismatch */
5893 magnus 1917 57006 : for (off = 0; off < sizeof(pgoff_t); off++)
7474 bruce 1918 EUB : {
2040 peter_e 1919 GIC 50672 : AH->WriteBytePtr(AH, o & 0xFF);
7474 bruce 1920 50672 : o >>= 8;
1921 : }
5893 magnus 1922 6334 : return sizeof(pgoff_t) + 1;
1923 : }
1924 :
1925 : int
5624 bruce 1926 4211 : ReadOffset(ArchiveHandle *AH, pgoff_t * o)
1927 : {
7188 bruce 1928 ECB : int i;
1929 : int off;
1930 : int offsetFlg;
1931 :
7474 1932 : /* Initialize to zero */
7474 bruce 1933 GIC 4211 : *o = 0;
1934 :
1935 : /* Check for old version */
7474 bruce 1936 CBC 4211 : if (AH->version < K_VERS_1_7)
1937 : {
7474 bruce 1938 EUB : /* Prior versions wrote offsets using WriteInt */
7474 bruce 1939 UBC 0 : i = ReadInt(AH);
1940 : /* -1 means not set */
7474 bruce 1941 UIC 0 : if (i < 0)
7188 1942 0 : return K_OFFSET_POS_NOT_SET;
7474 1943 0 : else if (i == 0)
7188 1944 0 : return K_OFFSET_NO_DATA;
7474 bruce 1945 ECB :
1946 : /* Cast to pgoff_t because it was written as an int. */
5893 magnus 1947 LBC 0 : *o = (pgoff_t) i;
7474 bruce 1948 0 : return K_OFFSET_POS_SET;
1949 : }
1950 :
7474 bruce 1951 EUB : /*
6385 1952 : * Read the flag indicating the state of the data pointer. Check if valid
1953 : * and die if not.
1954 : *
1955 : * This used to be handled by a negative or zero pointer, now we use an
6347 bruce 1956 ECB : * extra byte specifically for the state.
1957 : */
2040 peter_e 1958 GIC 4211 : offsetFlg = AH->ReadBytePtr(AH) & 0xFF;
1959 :
7474 bruce 1960 CBC 4211 : switch (offsetFlg)
1961 : {
7474 bruce 1962 GIC 4211 : case K_OFFSET_POS_NOT_SET:
1963 : case K_OFFSET_NO_DATA:
1964 : case K_OFFSET_POS_SET:
1965 :
7188 1966 4211 : break;
1967 :
7474 bruce 1968 UIC 0 : default:
366 tgl 1969 0 : pg_fatal("unexpected data offset flag %d", offsetFlg);
1970 : }
1971 :
1972 : /*
7474 bruce 1973 ECB : * Read the bytes
1974 : */
7474 bruce 1975 CBC 37899 : for (off = 0; off < AH->offSize; off++)
7474 bruce 1976 ECB : {
5893 magnus 1977 GIC 33688 : if (off < sizeof(pgoff_t))
2040 peter_e 1978 33688 : *o |= ((pgoff_t) (AH->ReadBytePtr(AH))) << (off * 8);
7474 bruce 1979 ECB : else
1980 : {
2040 peter_e 1981 LBC 0 : if (AH->ReadBytePtr(AH) != 0)
366 tgl 1982 UIC 0 : pg_fatal("file offset in dump file is too large");
7474 bruce 1983 ECB : }
1984 : }
1985 :
7474 bruce 1986 GIC 4211 : return offsetFlg;
7474 bruce 1987 ECB : }
1988 :
1989 : size_t
8053 bruce 1990 GIC 143787 : WriteInt(ArchiveHandle *AH, int i)
8314 bruce 1991 ECB : {
1992 : int b;
8053 1993 :
1994 : /*
1995 : * This is a bit yucky, but I don't want to make the binary format very
6385 1996 : * dependent on representation, and not knowing much about it, I write out
1997 : * a sign byte. If you change this, don't forget to change the file
1998 : * version #, and modify ReadInt to read the new format AS WELL AS the old
1999 : * formats.
2000 : */
8053 2001 :
2002 : /* SIGN byte */
8053 bruce 2003 CBC 143787 : if (i < 0)
2004 : {
2040 peter_e 2005 32269 : AH->WriteBytePtr(AH, 1);
8297 pjw 2006 32269 : i = -i;
8053 bruce 2007 ECB : }
2008 : else
2040 peter_e 2009 GIC 111518 : AH->WriteBytePtr(AH, 0);
2010 :
8053 bruce 2011 CBC 718935 : for (b = 0; b < AH->intSize; b++)
8053 bruce 2012 ECB : {
2040 peter_e 2013 GIC 575148 : AH->WriteBytePtr(AH, i & 0xFF);
7620 tgl 2014 CBC 575148 : i >>= 8;
2015 : }
2016 :
8053 bruce 2017 GIC 143787 : return AH->intSize + 1;
8314 bruce 2018 ECB : }
2019 :
2020 : int
8053 bruce 2021 GIC 111973 : ReadInt(ArchiveHandle *AH)
8314 bruce 2022 ECB : {
8053 bruce 2023 GIC 111973 : int res = 0;
8053 bruce 2024 ECB : int bv,
2025 : b;
8053 bruce 2026 CBC 111973 : int sign = 0; /* Default positive */
2027 111973 : int bitShift = 0;
8314 bruce 2028 ECB :
8053 bruce 2029 GIC 111973 : if (AH->version > K_VERS_1_0)
2030 : /* Read a sign byte */
2040 peter_e 2031 CBC 111973 : sign = AH->ReadBytePtr(AH);
2032 :
8053 bruce 2033 559865 : for (b = 0; b < AH->intSize; b++)
2034 : {
2040 peter_e 2035 GIC 447892 : bv = AH->ReadBytePtr(AH) & 0xFF;
8297 pjw 2036 447892 : if (bv != 0)
8297 pjw 2037 CBC 109296 : res = res + (bv << bitShift);
8297 pjw 2038 GIC 447892 : bitShift += 8;
2039 : }
2040 :
8053 bruce 2041 111973 : if (sign)
8053 bruce 2042 CBC 25809 : res = -res;
8314 bruce 2043 ECB :
8053 bruce 2044 CBC 111973 : return res;
2045 : }
2046 :
7537 peter_e 2047 ECB : size_t
8043 pjw 2048 CBC 118932 : WriteStr(ArchiveHandle *AH, const char *c)
2049 : {
7537 peter_e 2050 ECB : size_t res;
2051 :
8297 pjw 2052 GIC 118932 : if (c)
8297 pjw 2053 ECB : {
3260 bruce 2054 GIC 86663 : int len = strlen(c);
2055 :
3261 2056 86663 : res = WriteInt(AH, len);
2040 peter_e 2057 CBC 86663 : AH->WriteBufPtr(AH, c, len);
3261 bruce 2058 GIC 86663 : res += len;
2059 : }
2060 : else
8297 pjw 2061 32269 : res = WriteInt(AH, -1);
8297 pjw 2062 ECB :
8053 bruce 2063 GBC 118932 : return res;
2064 : }
8314 bruce 2065 ECB :
2066 : char *
8053 bruce 2067 GIC 92650 : ReadStr(ArchiveHandle *AH)
2068 : {
8053 bruce 2069 ECB : char *buf;
2070 : int l;
2071 :
8053 bruce 2072 GIC 92650 : l = ReadInt(AH);
5725 tgl 2073 92650 : if (l < 0)
8297 pjw 2074 CBC 25809 : buf = NULL;
2075 : else
8297 pjw 2076 ECB : {
4153 bruce 2077 GIC 66841 : buf = (char *) pg_malloc(l + 1);
2040 peter_e 2078 CBC 66841 : AH->ReadBufPtr(AH, (void *) buf, l);
2079 :
8297 pjw 2080 66841 : buf[l] = '\0';
8297 pjw 2081 ECB : }
8314 bruce 2082 :
8053 bruce 2083 CBC 92650 : return buf;
8314 bruce 2084 ECB : }
2085 :
2086 : static bool
45 tomas.vondra 2087 GNC 12 : _fileExistsInDirectory(const char *dir, const char *filename)
2088 : {
2089 : struct stat st;
2090 : char buf[MAXPGPATH];
2091 :
2092 12 : if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
45 tomas.vondra 2093 UNC 0 : pg_fatal("directory name too long: \"%s\"", dir);
2094 :
45 tomas.vondra 2095 GNC 12 : return (stat(buf, &st) == 0 && S_ISREG(st.st_mode));
2096 : }
2097 :
8158 tgl 2098 ECB : static int
8053 bruce 2099 GIC 27 : _discoverArchiveFormat(ArchiveHandle *AH)
2100 : {
2101 : FILE *fh;
8053 bruce 2102 ECB : char sig[6]; /* More than enough */
2103 : size_t cnt;
8053 bruce 2104 GIC 27 : int wantClose = 0;
2105 :
1469 peter 2106 27 : pg_log_debug("attempting to ascertain archive format");
2107 :
297 peter 2108 GNC 27 : free(AH->lookahead);
8297 pjw 2109 ECB :
738 tgl 2110 CBC 27 : AH->readHeader = 0;
8297 pjw 2111 27 : AH->lookaheadSize = 512;
3841 tgl 2112 GIC 27 : AH->lookahead = pg_malloc0(512);
8297 pjw 2113 GBC 27 : AH->lookaheadLen = 0;
2114 27 : AH->lookaheadPos = 0;
2115 :
8053 bruce 2116 GIC 27 : if (AH->fSpec)
8053 bruce 2117 EUB : {
4382 2118 : struct stat st;
2119 :
8297 pjw 2120 GIC 27 : wantClose = 1;
4459 heikki.linnakangas 2121 EUB :
2122 : /*
2123 : * Check if the specified archive is a directory. If so, check if
2124 : * there's a "toc.dat" (or "toc.dat.{gz,lz4,zst}") file in it.
2125 : */
4459 heikki.linnakangas 2126 GIC 27 : if (stat(AH->fSpec, &st) == 0 && S_ISDIR(st.st_mode))
2127 : {
45 tomas.vondra 2128 GNC 12 : AH->format = archDirectory;
2129 12 : if (_fileExistsInDirectory(AH->fSpec, "toc.dat"))
4459 heikki.linnakangas 2130 GIC 12 : return AH->format;
4459 heikki.linnakangas 2131 EUB : #ifdef HAVE_LIBZ
45 tomas.vondra 2132 UNC 0 : if (_fileExistsInDirectory(AH->fSpec, "toc.dat.gz"))
4459 heikki.linnakangas 2133 0 : return AH->format;
2134 : #endif
2135 : #ifdef USE_LZ4
45 tomas.vondra 2136 0 : if (_fileExistsInDirectory(AH->fSpec, "toc.dat.lz4"))
2137 0 : return AH->format;
2138 : #endif
2139 : #ifdef USE_ZSTD
4 2140 0 : if (_fileExistsInDirectory(AH->fSpec, "toc.dat.zst"))
4 tomas.vondra 2141 UIC 0 : return AH->format;
2142 : #endif
366 tgl 2143 0 : pg_fatal("directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)",
2144 : AH->fSpec);
2145 : fh = NULL; /* keep compiler quiet */
4459 heikki.linnakangas 2146 ECB : }
2147 : else
2148 : {
4459 heikki.linnakangas 2149 CBC 15 : fh = fopen(AH->fSpec, PG_BINARY_R);
4459 heikki.linnakangas 2150 GIC 15 : if (!fh)
366 tgl 2151 UIC 0 : pg_fatal("could not open input file \"%s\": %m", AH->fSpec);
4459 heikki.linnakangas 2152 ECB : }
8053 bruce 2153 : }
2154 : else
2155 : {
8297 pjw 2156 UIC 0 : fh = stdin;
5642 tgl 2157 0 : if (!fh)
366 2158 0 : pg_fatal("could not open input file: %m");
2159 : }
2160 :
3261 bruce 2161 CBC 15 : if ((cnt = fread(sig, 1, 5, fh)) != 5)
2162 : {
7956 peter_e 2163 LBC 0 : if (ferror(fh))
366 tgl 2164 UIC 0 : pg_fatal("could not read input file: %m");
7956 peter_e 2165 ECB : else
366 tgl 2166 LBC 0 : pg_fatal("input file is too short (read %lu, expected 5)",
366 tgl 2167 ECB : (unsigned long) cnt);
2168 : }
2169 :
2170 : /* Save it, just in case we need it later */
2997 tgl 2171 GIC 15 : memcpy(&AH->lookahead[0], sig, 5);
8297 pjw 2172 15 : AH->lookaheadLen = 5;
8314 bruce 2173 EUB :
8053 bruce 2174 GIC 15 : if (strncmp(sig, "PGDMP", 5) == 0)
2175 : {
738 tgl 2176 ECB : /* It's custom format, stop here */
738 tgl 2177 GIC 14 : AH->format = archCustom;
738 tgl 2178 GBC 14 : AH->readHeader = 1;
8053 bruce 2179 EUB : }
2180 : else
2181 : {
2182 : /*
2183 : * *Maybe* we have a tar archive format file or a text dump ... So,
3955 bruce 2184 ECB : * read first 512 byte header...
8297 pjw 2185 EUB : */
8297 pjw 2186 GIC 1 : cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh);
3261 bruce 2187 ECB : /* read failure is checked below */
8297 pjw 2188 GIC 1 : AH->lookaheadLen += cnt;
2189 :
4114 andrew 2190 1 : if (AH->lookaheadLen >= strlen(TEXT_DUMPALL_HEADER) &&
4114 andrew 2191 CBC 1 : (strncmp(AH->lookahead, TEXT_DUMP_HEADER, strlen(TEXT_DUMP_HEADER)) == 0 ||
4114 andrew 2192 GIC 1 : strncmp(AH->lookahead, TEXT_DUMPALL_HEADER, strlen(TEXT_DUMPALL_HEADER)) == 0))
4114 andrew 2193 ECB : {
3955 bruce 2194 EUB : /*
2195 : * looks like it's probably a text format dump. so suggest they
3955 bruce 2196 ECB : * try psql
2197 : */
366 tgl 2198 UIC 0 : pg_fatal("input file appears to be a text format dump. Please use psql.");
2199 : }
4114 andrew 2200 ECB :
3260 bruce 2201 GIC 1 : if (AH->lookaheadLen != 512)
2202 : {
3260 bruce 2203 UIC 0 : if (feof(fh))
366 tgl 2204 0 : pg_fatal("input file does not appear to be a valid archive (too short?)");
2205 : else
3260 bruce 2206 0 : READ_ERROR_EXIT(fh);
2207 : }
8314 bruce 2208 ECB :
8297 pjw 2209 GIC 1 : if (!isValidTarHeader(AH->lookahead))
366 tgl 2210 UIC 0 : pg_fatal("input file does not appear to be a valid archive");
2211 :
8297 pjw 2212 GIC 1 : AH->format = archTar;
2213 : }
2214 :
738 tgl 2215 ECB : /* Close the file if we opened it */
8053 bruce 2216 GIC 15 : if (wantClose)
738 tgl 2217 ECB : {
8122 pjw 2218 GIC 15 : if (fclose(fh) != 0)
366 tgl 2219 UIC 0 : pg_fatal("could not close input file: %m");
738 tgl 2220 ECB : /* Forget lookahead, since we'll re-read header after re-opening */
738 tgl 2221 GIC 15 : AH->readHeader = 0;
738 tgl 2222 CBC 15 : AH->lookaheadLen = 0;
2223 : }
2224 :
8053 bruce 2225 15 : return AH->format;
8314 bruce 2226 ECB : }
2227 :
2228 :
2229 : /*
2230 : * Allocate an archive handle
2231 : */
8053 2232 : static ArchiveHandle *
8053 bruce 2233 GIC 164 : _allocAH(const char *FileSpec, const ArchiveFormat fmt,
2234 : const pg_compress_specification compression_spec,
2235 : bool dosync, ArchiveMode mode,
2236 : SetupWorkerPtrType setupWorkerPtr)
8297 pjw 2237 ECB : {
8053 bruce 2238 : ArchiveHandle *AH;
2239 : CompressFileHandle *CFH;
45 tomas.vondra 2240 GNC 164 : pg_compress_specification out_compress_spec = {0};
8314 bruce 2241 ECB :
934 tgl 2242 GIC 164 : pg_log_debug("allocating AH for %s, format %d",
934 tgl 2243 ECB : FileSpec ? FileSpec : "(stdio)", fmt);
2244 :
3841 tgl 2245 GIC 164 : AH = (ArchiveHandle *) pg_malloc0(sizeof(ArchiveHandle));
2246 :
2357 peter_e 2247 164 : AH->version = K_VERS_SELF;
2248 :
2249 : /* initialize for backwards compatible string processing */
5657 tgl 2250 164 : AH->public.encoding = 0; /* PG_SQL_ASCII */
6160 2251 164 : AH->public.std_strings = false;
2252 :
6160 tgl 2253 ECB : /* sql error handling */
6160 tgl 2254 GIC 164 : AH->public.exit_on_error = true;
6160 tgl 2255 CBC 164 : AH->public.n_errors = 0;
6160 tgl 2256 ECB :
4792 tgl 2257 CBC 164 : AH->archiveDumpVersion = PG_VERSION;
4792 tgl 2258 ECB :
8297 pjw 2259 GIC 164 : AH->createDate = time(NULL);
8297 pjw 2260 ECB :
8053 bruce 2261 GIC 164 : AH->intSize = sizeof(int);
5893 magnus 2262 CBC 164 : AH->offSize = sizeof(pgoff_t);
8053 bruce 2263 164 : if (FileSpec)
2264 : {
4153 2265 141 : AH->fSpec = pg_strdup(FileSpec);
8053 bruce 2266 ECB :
8297 pjw 2267 : /*
2268 : * Not used; maybe later....
2269 : *
2270 : * AH->workDir = pg_strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
2271 : * i--) if (AH->workDir[i-1] == '/')
2272 : */
8053 bruce 2273 : }
2274 : else
8297 pjw 2275 GBC 23 : AH->fSpec = NULL;
8314 bruce 2276 ECB :
5179 andrew 2277 GIC 164 : AH->currUser = NULL; /* unknown */
2278 164 : AH->currSchema = NULL; /* ditto */
2279 164 : AH->currTablespace = NULL; /* ditto */
1418 tgl 2280 164 : AH->currTableAm = NULL; /* ditto */
2281 :
3841 2282 164 : AH->toc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
2283 :
8053 bruce 2284 164 : AH->toc->next = AH->toc;
2285 164 : AH->toc->prev = AH->toc;
2286 :
2287 164 : AH->mode = mode;
128 michael 2288 GNC 164 : AH->compression_spec = compression_spec;
2209 andrew 2289 GIC 164 : AH->dosync = dosync;
2290 :
4111 tgl 2291 164 : memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse));
2292 :
2293 : /* Open stdout with no compression for AH output handle */
45 tomas.vondra 2294 GNC 164 : out_compress_spec.algorithm = PG_COMPRESSION_NONE;
2295 164 : CFH = InitCompressFileHandle(out_compress_spec);
17 2296 164 : if (!CFH->open_func(NULL, fileno(stdout), PG_BINARY_A, CFH))
45 tomas.vondra 2297 UNC 0 : pg_fatal("could not open stdout for appending: %m");
45 tomas.vondra 2298 GNC 164 : AH->OF = CFH;
8314 bruce 2299 ECB :
6647 tgl 2300 : /*
2301 : * On Windows, we need to use binary mode to read/write non-text files,
2120 2302 : * which include all archive formats as well as compressed plain text.
2303 : * Force stdin/stdout into binary mode if that is what we are using.
6647 2304 : */
2305 : #ifdef WIN32
2306 : if ((fmt != archNull || compression_spec.algorithm != PG_COMPRESSION_NONE) &&
6419 2307 : (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
6647 2308 : {
2309 : if (mode == archModeWrite)
2095 heikki.linnakangas 2310 : _setmode(fileno(stdout), O_BINARY);
6647 tgl 2311 : else
2095 heikki.linnakangas 2312 : _setmode(fileno(stdin), O_BINARY);
2313 : }
6647 tgl 2314 : #endif
2315 :
3668 andrew 2316 CBC 164 : AH->SetupWorkerPtr = setupWorkerPtr;
2317 :
8053 bruce 2318 164 : if (fmt == archUnknown)
8297 pjw 2319 27 : AH->format = _discoverArchiveFormat(AH);
8297 pjw 2320 ECB : else
8297 pjw 2321 GIC 137 : AH->format = fmt;
8314 bruce 2322 EUB :
8053 bruce 2323 GBC 164 : switch (AH->format)
2324 : {
8297 pjw 2325 GIC 28 : case archCustom:
8297 pjw 2326 CBC 28 : InitArchiveFmt_Custom(AH);
8297 pjw 2327 GIC 28 : break;
2328 :
2329 107 : case archNull:
2330 107 : InitArchiveFmt_Null(AH);
2331 107 : break;
2332 :
4459 heikki.linnakangas 2333 CBC 24 : case archDirectory:
4459 heikki.linnakangas 2334 GIC 24 : InitArchiveFmt_Directory(AH);
2335 24 : break;
2336 :
8297 pjw 2337 CBC 5 : case archTar:
2338 5 : InitArchiveFmt_Tar(AH);
8297 pjw 2339 GIC 4 : break;
2340 :
8297 pjw 2341 UIC 0 : default:
366 tgl 2342 0 : pg_fatal("unrecognized file format \"%d\"", fmt);
2343 : }
2344 :
8053 bruce 2345 GIC 163 : return AH;
2346 : }
2347 :
2348 : /*
2349 : * Write out all data (tables & LOs)
2507 tgl 2350 ECB : */
8053 bruce 2351 : void
2643 tgl 2352 GIC 25 : WriteDataChunks(ArchiveHandle *AH, ParallelState *pstate)
2353 : {
5179 andrew 2354 ECB : TocEntry *te;
8314 bruce 2355 :
1668 tgl 2356 GIC 25 : if (pstate && pstate->numWorkers > 1)
8053 bruce 2357 CBC 9 : {
1668 tgl 2358 EUB : /*
2359 : * In parallel mode, this code runs in the leader process. We
1668 tgl 2360 ECB : * construct an array of candidate TEs, then sort it into decreasing
2361 : * size order, then dispatch each TE to a data-transfer worker. By
2362 : * dumping larger tables first, we avoid getting into a situation
2363 : * where we're down to one job and it's big, losing parallelism.
2364 : */
2365 : TocEntry **tes;
2366 : int ntes;
8314 bruce 2367 :
1668 tgl 2368 GIC 9 : tes = (TocEntry **) pg_malloc(AH->tocCount * sizeof(TocEntry *));
2369 9 : ntes = 0;
1668 tgl 2370 CBC 1207 : for (te = AH->toc->next; te != AH->toc; te = te->next)
2371 : {
2372 : /* Consider only TEs with dataDumper functions ... */
2373 1198 : if (!te->dataDumper)
1668 tgl 2374 GIC 1076 : continue;
2375 : /* ... and ignore ones not enabled for dump */
2376 122 : if ((te->reqs & REQ_DATA) == 0)
1668 tgl 2377 UIC 0 : continue;
1668 tgl 2378 ECB :
1668 tgl 2379 GIC 122 : tes[ntes++] = te;
2380 : }
2507 tgl 2381 ECB :
1668 tgl 2382 CBC 9 : if (ntes > 1)
61 peter 2383 GNC 8 : qsort(tes, ntes, sizeof(TocEntry *), TocEntrySizeCompare);
2384 :
1668 tgl 2385 CBC 131 : for (int i = 0; i < ntes; i++)
1668 tgl 2386 GIC 122 : DispatchJobForTocEntry(AH, pstate, tes[i], ACT_DUMP,
2387 : mark_dump_job_done, NULL);
1668 tgl 2388 ECB :
1668 tgl 2389 GIC 9 : pg_free(tes);
2390 :
2391 : /* Now wait for workers to finish. */
2385 2392 9 : WaitForWorkers(AH, pstate, WFW_ALL_IDLE);
2393 : }
2394 : else
2395 : {
2396 : /* Non-parallel mode: just dump all candidate TEs sequentially. */
1668 2397 3749 : for (te = AH->toc->next; te != AH->toc; te = te->next)
1668 tgl 2398 ECB : {
2399 : /* Must have same filter conditions as above */
1668 tgl 2400 GIC 3733 : if (!te->dataDumper)
2401 3572 : continue;
2402 161 : if ((te->reqs & REQ_DATA) == 0)
1668 tgl 2403 CBC 2 : continue;
2404 :
1668 tgl 2405 GIC 159 : WriteDataChunksForTocEntry(AH, te);
1668 tgl 2406 ECB : }
1668 tgl 2407 EUB : }
3668 andrew 2408 GIC 25 : }
8053 bruce 2409 ECB :
2410 :
2411 : /*
2412 : * Callback function that's invoked in the leader process after a step has
2385 tgl 2413 : * been parallel dumped.
2414 : *
2415 : * We don't need to do anything except check for worker failure.
2416 : */
2417 : static void
2385 tgl 2418 CBC 122 : mark_dump_job_done(ArchiveHandle *AH,
2419 : TocEntry *te,
2385 tgl 2420 ECB : int status,
2421 : void *callback_data)
2422 : {
1469 peter 2423 CBC 122 : pg_log_info("finished item %d %s %s",
2424 : te->dumpId, te->desc, te->tag);
2425 :
2385 tgl 2426 GIC 122 : if (status != 0)
366 tgl 2427 LBC 0 : pg_fatal("worker process failed: exit code %d",
366 tgl 2428 ECB : status);
2385 tgl 2429 GIC 122 : }
2430 :
2385 tgl 2431 ECB :
3668 andrew 2432 : void
2643 tgl 2433 GIC 281 : WriteDataChunksForTocEntry(ArchiveHandle *AH, TocEntry *te)
2434 : {
2435 : StartDataPtrType startPtr;
2436 : EndDataPtrType endPtr;
8053 bruce 2437 ECB :
3668 andrew 2438 GIC 281 : AH->currToc = te;
3668 andrew 2439 ECB :
3668 andrew 2440 CBC 281 : if (strcmp(te->desc, "BLOBS") == 0)
2441 : {
125 peter 2442 GNC 10 : startPtr = AH->StartLOsPtr;
2443 10 : endPtr = AH->EndLOsPtr;
2444 : }
2445 : else
3668 andrew 2446 ECB : {
3668 andrew 2447 GIC 271 : startPtr = AH->StartDataPtr;
2448 271 : endPtr = AH->EndDataPtr;
2449 : }
2450 :
2451 281 : if (startPtr != NULL)
2452 281 : (*startPtr) (AH, te);
2453 :
3668 andrew 2454 ECB : /*
2455 : * The user-provided DataDumper routine needs to call AH->WriteData
2456 : */
2040 peter_e 2457 CBC 281 : te->dataDumper((Archive *) AH, te->dataDumperArg);
3668 andrew 2458 ECB :
3668 andrew 2459 GIC 281 : if (endPtr != NULL)
2460 281 : (*endPtr) (AH, te);
2461 :
2462 281 : AH->currToc = NULL;
8314 bruce 2463 CBC 281 : }
2464 :
8053 bruce 2465 ECB : void
8053 bruce 2466 GIC 37 : WriteToc(ArchiveHandle *AH)
8314 bruce 2467 ECB : {
7064 tgl 2468 : TocEntry *te;
2469 : char workbuf[32];
3967 2470 : int tocCount;
8043 pjw 2471 : int i;
2472 :
2473 : /* count entries that will actually be dumped */
3967 tgl 2474 CBC 37 : tocCount = 0;
2475 8137 : for (te = AH->toc->next; te != AH->toc; te = te->next)
3967 tgl 2476 ECB : {
3967 tgl 2477 CBC 8100 : if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) != 0)
3967 tgl 2478 GIC 8096 : tocCount++;
3967 tgl 2479 ECB : }
2480 :
2481 : /* printf("%d TOC Entries to save\n", tocCount); */
8053 bruce 2482 :
3967 tgl 2483 CBC 37 : WriteInt(AH, tocCount);
7064 tgl 2484 ECB :
7064 tgl 2485 CBC 8137 : for (te = AH->toc->next; te != AH->toc; te = te->next)
8053 bruce 2486 ECB : {
3967 tgl 2487 CBC 8100 : if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) == 0)
2488 4 : continue;
3967 tgl 2489 ECB :
7064 tgl 2490 GIC 8096 : WriteInt(AH, te->dumpId);
8053 bruce 2491 8096 : WriteInt(AH, te->dataDumper ? 1 : 0);
7064 tgl 2492 ECB :
2493 : /* OID is recorded as a string for historical reasons */
7064 tgl 2494 CBC 8096 : sprintf(workbuf, "%u", te->catalogId.tableoid);
2495 8096 : WriteStr(AH, workbuf);
7064 tgl 2496 GIC 8096 : sprintf(workbuf, "%u", te->catalogId.oid);
7064 tgl 2497 CBC 8096 : WriteStr(AH, workbuf);
2498 :
7584 bruce 2499 8096 : WriteStr(AH, te->tag);
8053 2500 8096 : WriteStr(AH, te->desc);
5179 andrew 2501 GIC 8096 : WriteInt(AH, te->section);
8053 bruce 2502 CBC 8096 : WriteStr(AH, te->defn);
8053 bruce 2503 GIC 8096 : WriteStr(AH, te->dropStmt);
2504 8096 : WriteStr(AH, te->copyStmt);
7639 tgl 2505 CBC 8096 : WriteStr(AH, te->namespace);
6728 tgl 2506 GIC 8096 : WriteStr(AH, te->tablespace);
1495 andres 2507 8096 : WriteStr(AH, te->tableam);
8053 bruce 2508 8096 : WriteStr(AH, te->owner);
1601 andres 2509 8096 : WriteStr(AH, "false");
2510 :
2511 : /* Dump list of dependencies */
7064 tgl 2512 19943 : for (i = 0; i < te->nDeps; i++)
2513 : {
2514 11847 : sprintf(workbuf, "%d", te->dependencies[i]);
7064 tgl 2515 CBC 11847 : WriteStr(AH, workbuf);
8043 pjw 2516 ECB : }
7836 bruce 2517 GIC 8096 : WriteStr(AH, NULL); /* Terminate List */
8043 pjw 2518 ECB :
8053 bruce 2519 GIC 8096 : if (AH->WriteExtraTocPtr)
2040 peter_e 2520 CBC 8096 : AH->WriteExtraTocPtr(AH, te);
8053 bruce 2521 ECB : }
8314 bruce 2522 GIC 37 : }
8314 bruce 2523 ECB :
8053 2524 : void
8053 bruce 2525 GIC 31 : ReadToc(ArchiveHandle *AH)
2526 : {
8053 bruce 2527 ECB : int i;
7064 tgl 2528 EUB : char *tmp;
2529 : DumpId *deps;
2530 : int depIdx;
8043 pjw 2531 ECB : int depSize;
2532 : TocEntry *te;
424 dgustafsson 2533 : bool is_supported;
2534 :
8053 bruce 2535 CBC 31 : AH->tocCount = ReadInt(AH);
7064 tgl 2536 31 : AH->maxDumpId = 0;
8314 bruce 2537 ECB :
8053 bruce 2538 GIC 6271 : for (i = 0; i < AH->tocCount; i++)
2539 : {
3841 tgl 2540 GBC 6240 : te = (TocEntry *) pg_malloc0(sizeof(TocEntry));
7064 tgl 2541 CBC 6240 : te->dumpId = ReadInt(AH);
7064 tgl 2542 ECB :
7064 tgl 2543 CBC 6240 : if (te->dumpId > AH->maxDumpId)
7064 tgl 2544 GIC 1494 : AH->maxDumpId = te->dumpId;
8297 pjw 2545 ECB :
2546 : /* Sanity check */
7064 tgl 2547 GIC 6240 : if (te->dumpId <= 0)
366 tgl 2548 LBC 0 : pg_fatal("entry ID %d out of range -- perhaps a corrupt TOC",
2549 : te->dumpId);
8297 pjw 2550 ECB :
8297 pjw 2551 GIC 6240 : te->hadDumper = ReadInt(AH);
2552 :
7064 tgl 2553 6240 : if (AH->version >= K_VERS_1_8)
2554 : {
2555 6240 : tmp = ReadStr(AH);
2556 6240 : sscanf(tmp, "%u", &te->catalogId.tableoid);
2557 6240 : free(tmp);
2558 : }
7064 tgl 2559 EUB : else
7064 tgl 2560 UBC 0 : te->catalogId.tableoid = InvalidOid;
7064 tgl 2561 GBC 6240 : tmp = ReadStr(AH);
2562 6240 : sscanf(tmp, "%u", &te->catalogId.oid);
2563 6240 : free(tmp);
8043 pjw 2564 EUB :
7584 bruce 2565 GBC 6240 : te->tag = ReadStr(AH);
8297 pjw 2566 6240 : te->desc = ReadStr(AH);
5179 andrew 2567 EUB :
5179 andrew 2568 GBC 6240 : if (AH->version >= K_VERS_1_11)
5179 andrew 2569 EUB : {
5179 andrew 2570 GBC 6240 : te->section = ReadInt(AH);
5179 andrew 2571 EUB : }
2572 : else
2573 : {
2574 : /*
4798 tgl 2575 : * Rules for pre-8.4 archives wherein pg_dump hasn't classified
2576 : * the entries into sections. This list need not cover entry
2577 : * types added later than 8.4.
5179 andrew 2578 ECB : */
5179 andrew 2579 LBC 0 : if (strcmp(te->desc, "COMMENT") == 0 ||
4934 tgl 2580 UIC 0 : strcmp(te->desc, "ACL") == 0 ||
4798 tgl 2581 LBC 0 : strcmp(te->desc, "ACL LANGUAGE") == 0)
5179 andrew 2582 0 : te->section = SECTION_NONE;
5179 andrew 2583 UIC 0 : else if (strcmp(te->desc, "TABLE DATA") == 0 ||
5179 andrew 2584 LBC 0 : strcmp(te->desc, "BLOBS") == 0 ||
2585 0 : strcmp(te->desc, "BLOB COMMENTS") == 0)
5179 andrew 2586 UIC 0 : te->section = SECTION_DATA;
5179 andrew 2587 LBC 0 : else if (strcmp(te->desc, "CONSTRAINT") == 0 ||
2588 0 : strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
5179 andrew 2589 UIC 0 : strcmp(te->desc, "FK CONSTRAINT") == 0 ||
5179 andrew 2590 LBC 0 : strcmp(te->desc, "INDEX") == 0 ||
2591 0 : strcmp(te->desc, "RULE") == 0 ||
5179 andrew 2592 UIC 0 : strcmp(te->desc, "TRIGGER") == 0)
5179 andrew 2593 LBC 0 : te->section = SECTION_POST_DATA;
5179 andrew 2594 ECB : else
5179 andrew 2595 LBC 0 : te->section = SECTION_PRE_DATA;
5179 andrew 2596 EUB : }
2597 :
8297 pjw 2598 GIC 6240 : te->defn = ReadStr(AH);
8297 pjw 2599 CBC 6240 : te->dropStmt = ReadStr(AH);
2600 :
2601 6240 : if (AH->version >= K_VERS_1_3)
8297 pjw 2602 GBC 6240 : te->copyStmt = ReadStr(AH);
2603 :
7639 tgl 2604 CBC 6240 : if (AH->version >= K_VERS_1_6)
7639 tgl 2605 GIC 6240 : te->namespace = ReadStr(AH);
2606 :
6728 tgl 2607 CBC 6240 : if (AH->version >= K_VERS_1_10)
6728 tgl 2608 GBC 6240 : te->tablespace = ReadStr(AH);
2609 :
1495 andres 2610 GIC 6240 : if (AH->version >= K_VERS_1_14)
1495 andres 2611 CBC 6240 : te->tableam = ReadStr(AH);
2612 :
8297 pjw 2613 6240 : te->owner = ReadStr(AH);
424 dgustafsson 2614 6240 : is_supported = true;
2615 6240 : if (AH->version < K_VERS_1_9)
424 dgustafsson 2616 UIC 0 : is_supported = false;
2617 : else
424 dgustafsson 2618 ECB : {
332 tgl 2619 CBC 6240 : tmp = ReadStr(AH);
424 dgustafsson 2620 ECB :
332 tgl 2621 CBC 6240 : if (strcmp(tmp, "true") == 0)
332 tgl 2622 UIC 0 : is_supported = false;
424 dgustafsson 2623 EUB :
332 tgl 2624 GBC 6240 : free(tmp);
2625 : }
424 dgustafsson 2626 ECB :
424 dgustafsson 2627 CBC 6240 : if (!is_supported)
1469 peter 2628 LBC 0 : pg_log_warning("restoring tables WITH OIDS is not supported anymore");
2629 :
2630 : /* Read TOC entry dependencies */
8043 pjw 2631 CBC 6240 : if (AH->version >= K_VERS_1_5)
2632 : {
2633 6240 : depSize = 100;
4153 bruce 2634 6240 : deps = (DumpId *) pg_malloc(sizeof(DumpId) * depSize);
8043 pjw 2635 6240 : depIdx = 0;
2636 : for (;;)
2637 : {
7064 tgl 2638 GIC 15648 : tmp = ReadStr(AH);
7064 tgl 2639 CBC 15648 : if (!tmp)
2640 6240 : break; /* end of list */
7281 2641 9408 : if (depIdx >= depSize)
2642 : {
8043 pjw 2643 UIC 0 : depSize *= 2;
4149 tgl 2644 0 : deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depSize);
2645 : }
7064 tgl 2646 GBC 9408 : sscanf(tmp, "%d", &deps[depIdx]);
2647 9408 : free(tmp);
7064 tgl 2648 GIC 9408 : depIdx++;
7064 tgl 2649 ECB : }
2650 :
7064 tgl 2651 CBC 6240 : if (depIdx > 0) /* We have a non-null entry */
7064 tgl 2652 ECB : {
4149 tgl 2653 GIC 5067 : deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depIdx);
7064 tgl 2654 CBC 5067 : te->dependencies = deps;
7064 tgl 2655 GIC 5067 : te->nDeps = depIdx;
2656 : }
2657 : else
7281 tgl 2658 ECB : {
7281 tgl 2659 CBC 1173 : free(deps);
7064 2660 1173 : te->dependencies = NULL;
2661 1173 : te->nDeps = 0;
2662 : }
2663 : }
7956 peter_e 2664 ECB : else
7064 tgl 2665 : {
7064 tgl 2666 LBC 0 : te->dependencies = NULL;
2667 0 : te->nDeps = 0;
7064 tgl 2668 ECB : }
1668 tgl 2669 CBC 6240 : te->dataLength = 0;
2670 :
8053 bruce 2671 6240 : if (AH->ReadExtraTocPtr)
2040 peter_e 2672 GIC 6240 : AH->ReadExtraTocPtr(AH, te);
2673 :
1469 peter 2674 CBC 6240 : pg_log_debug("read TOC entry %d (ID %d) for %s %s",
2675 : i, te->dumpId, te->desc, te->tag);
2676 :
6160 tgl 2677 ECB : /* link completed entry into TOC circular list */
8297 pjw 2678 GIC 6240 : te->prev = AH->toc->prev;
8297 pjw 2679 CBC 6240 : AH->toc->prev->next = te;
8297 pjw 2680 GIC 6240 : AH->toc->prev = te;
2681 6240 : te->next = AH->toc;
6160 tgl 2682 ECB :
2683 : /* special processing immediately upon read for some items */
6160 tgl 2684 CBC 6240 : if (strcmp(te->desc, "ENCODING") == 0)
2685 31 : processEncodingEntry(AH, te);
6160 tgl 2686 GIC 6209 : else if (strcmp(te->desc, "STDSTRINGS") == 0)
6160 tgl 2687 CBC 31 : processStdStringsEntry(AH, te);
1868 2688 6178 : else if (strcmp(te->desc, "SEARCHPATH") == 0)
2689 31 : processSearchPathEntry(AH, te);
8053 bruce 2690 EUB : }
8314 bruce 2691 GIC 31 : }
8314 bruce 2692 ECB :
2693 : static void
6160 tgl 2694 GIC 31 : processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
6160 tgl 2695 EUB : {
2696 : /* te->defn should have the form SET client_encoding = 'foo'; */
4153 bruce 2697 GIC 31 : char *defn = pg_strdup(te->defn);
6160 tgl 2698 ECB : char *ptr1;
6160 tgl 2699 CBC 31 : char *ptr2 = NULL;
2700 : int encoding;
2701 :
2702 31 : ptr1 = strchr(defn, '\'');
6160 tgl 2703 GIC 31 : if (ptr1)
2704 31 : ptr2 = strchr(++ptr1, '\'');
2705 31 : if (ptr2)
2706 : {
6160 tgl 2707 CBC 31 : *ptr2 = '\0';
2708 31 : encoding = pg_char_to_encoding(ptr1);
2709 31 : if (encoding < 0)
366 tgl 2710 UBC 0 : pg_fatal("unrecognized encoding \"%s\"",
366 tgl 2711 EUB : ptr1);
6160 tgl 2712 GIC 31 : AH->public.encoding = encoding;
6160 tgl 2713 EUB : }
2714 : else
366 tgl 2715 LBC 0 : pg_fatal("invalid ENCODING item: %s",
2716 : te->defn);
2717 :
6160 tgl 2718 CBC 31 : free(defn);
6160 tgl 2719 GIC 31 : }
2720 :
2721 : static void
2722 31 : processStdStringsEntry(ArchiveHandle *AH, TocEntry *te)
2723 : {
6160 tgl 2724 ECB : /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2725 : char *ptr1;
2726 :
6160 tgl 2727 GIC 31 : ptr1 = strchr(te->defn, '\'');
6160 tgl 2728 GBC 31 : if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
6160 tgl 2729 GIC 31 : AH->public.std_strings = true;
6160 tgl 2730 UIC 0 : else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2731 0 : AH->public.std_strings = false;
6160 tgl 2732 EUB : else
366 tgl 2733 UIC 0 : pg_fatal("invalid STDSTRINGS item: %s",
366 tgl 2734 EUB : te->defn);
6160 tgl 2735 GIC 31 : }
6160 tgl 2736 EUB :
1868 2737 : static void
1868 tgl 2738 GBC 31 : processSearchPathEntry(ArchiveHandle *AH, TocEntry *te)
2739 : {
2740 : /*
1868 tgl 2741 EUB : * te->defn should contain a command to set search_path. We just copy it
2742 : * verbatim for use later.
2743 : */
1868 tgl 2744 GBC 31 : AH->public.searchpath = pg_strdup(te->defn);
2745 31 : }
2746 :
2747 : static void
2764 teodor 2748 UBC 0 : StrictNamesCheck(RestoreOptions *ropt)
2749 : {
2764 teodor 2750 EUB : const char *missing_name;
2751 :
2764 teodor 2752 UBC 0 : Assert(ropt->strict_names);
2753 :
2764 teodor 2754 UIC 0 : if (ropt->schemaNames.head != NULL)
2764 teodor 2755 EUB : {
2764 teodor 2756 UIC 0 : missing_name = simple_string_list_not_touched(&ropt->schemaNames);
2764 teodor 2757 UBC 0 : if (missing_name != NULL)
366 tgl 2758 0 : pg_fatal("schema \"%s\" not found", missing_name);
2764 teodor 2759 EUB : }
2760 :
2764 teodor 2761 UIC 0 : if (ropt->tableNames.head != NULL)
2764 teodor 2762 EUB : {
2764 teodor 2763 UIC 0 : missing_name = simple_string_list_not_touched(&ropt->tableNames);
2764 teodor 2764 UBC 0 : if (missing_name != NULL)
366 tgl 2765 0 : pg_fatal("table \"%s\" not found", missing_name);
2764 teodor 2766 EUB : }
2767 :
2764 teodor 2768 UBC 0 : if (ropt->indexNames.head != NULL)
2769 : {
2764 teodor 2770 UIC 0 : missing_name = simple_string_list_not_touched(&ropt->indexNames);
2771 0 : if (missing_name != NULL)
366 tgl 2772 0 : pg_fatal("index \"%s\" not found", missing_name);
2773 : }
2774 :
2764 teodor 2775 0 : if (ropt->functionNames.head != NULL)
2776 : {
2777 0 : missing_name = simple_string_list_not_touched(&ropt->functionNames);
2764 teodor 2778 LBC 0 : if (missing_name != NULL)
366 tgl 2779 UIC 0 : pg_fatal("function \"%s\" not found", missing_name);
2764 teodor 2780 ECB : }
2781 :
2764 teodor 2782 UIC 0 : if (ropt->triggerNames.head != NULL)
2783 : {
2764 teodor 2784 LBC 0 : missing_name = simple_string_list_not_touched(&ropt->triggerNames);
2785 0 : if (missing_name != NULL)
366 tgl 2786 0 : pg_fatal("trigger \"%s\" not found", missing_name);
2764 teodor 2787 ECB : }
2764 teodor 2788 UIC 0 : }
2789 :
2790 : /*
2791 : * Determine whether we want to restore this TOC entry.
2792 : *
2793 : * Returns 0 if entry should be skipped, or some combination of the
1900 tgl 2794 ECB : * REQ_SCHEMA and REQ_DATA bits if we want to restore schema and/or data
2795 : * portions of this TOC entry, or REQ_SPECIAL if it's a special entry.
2796 : */
849 peter 2797 : static int
1900 tgl 2798 CBC 27564 : _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
2799 : {
849 peter 2800 27564 : int res = REQ_SCHEMA | REQ_DATA;
1900 tgl 2801 GIC 27564 : RestoreOptions *ropt = AH->public.ropt;
2802 :
2803 : /* These items are treated specially */
6160 2804 27564 : if (strcmp(te->desc, "ENCODING") == 0 ||
1868 2805 27415 : strcmp(te->desc, "STDSTRINGS") == 0 ||
682 2806 27266 : strcmp(te->desc, "SEARCHPATH") == 0)
3967 2807 447 : return REQ_SPECIAL;
6984 tgl 2808 ECB :
1900 tgl 2809 EUB : /*
2810 : * DATABASE and DATABASE PROPERTIES also have a special rule: they are
2811 : * restored in createDB mode, and not restored otherwise, independently of
1900 tgl 2812 ECB : * all else.
1900 tgl 2813 EUB : */
1900 tgl 2814 GIC 27117 : if (strcmp(te->desc, "DATABASE") == 0 ||
2815 27036 : strcmp(te->desc, "DATABASE PROPERTIES") == 0)
2816 : {
2817 99 : if (ropt->createDB)
2818 74 : return REQ_SCHEMA;
1900 tgl 2819 ECB : else
1900 tgl 2820 GBC 25 : return 0;
1900 tgl 2821 EUB : }
2822 :
2823 : /*
2824 : * Process exclusions that affect certain classes of TOC entries.
2825 : */
1900 tgl 2826 ECB :
8053 bruce 2827 EUB : /* If it's an ACL, maybe ignore it */
3967 tgl 2828 GIC 27018 : if (ropt->aclsSkip && _tocEntryIsACL(te))
8297 pjw 2829 UIC 0 : return 0;
8314 bruce 2830 ECB :
1900 tgl 2831 EUB : /* If it's a comment, maybe ignore it */
1900 tgl 2832 GIC 27018 : if (ropt->no_comments && strcmp(te->desc, "COMMENT") == 0)
1900 tgl 2833 UIC 0 : return 0;
1900 tgl 2834 ECB :
2835 : /*
1657 michael 2836 : * If it's a publication or a table part of a publication, maybe ignore
2837 : * it.
2838 : */
1657 michael 2839 CBC 27018 : if (ropt->no_publications &&
1657 michael 2840 LBC 0 : (strcmp(te->desc, "PUBLICATION") == 0 ||
529 akapila 2841 0 : strcmp(te->desc, "PUBLICATION TABLE") == 0 ||
2842 0 : strcmp(te->desc, "PUBLICATION TABLES IN SCHEMA") == 0))
2158 peter_e 2843 0 : return 0;
2158 peter_e 2844 ECB :
1900 tgl 2845 : /* If it's a security label, maybe ignore it */
4343 peter_e 2846 CBC 27018 : if (ropt->no_security_labels && strcmp(te->desc, "SECURITY LABEL") == 0)
4577 rhaas 2847 LBC 0 : return 0;
4577 rhaas 2848 EUB :
2849 : /* If it's a subscription, maybe ignore it */
2161 peter_e 2850 GBC 27018 : if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0)
2161 peter_e 2851 UIC 0 : return 0;
2852 :
2853 : /* Ignore it if section is not to be dumped/restored */
3967 tgl 2854 CBC 27018 : switch (curSection)
4132 andrew 2855 EUB : {
3967 tgl 2856 GIC 16742 : case SECTION_PRE_DATA:
2857 16742 : if (!(ropt->dumpSections & DUMP_PRE_DATA))
2858 338 : return 0;
2859 16404 : break;
3967 tgl 2860 CBC 3974 : case SECTION_DATA:
2861 3974 : if (!(ropt->dumpSections & DUMP_DATA))
2862 64 : return 0;
3967 tgl 2863 GIC 3910 : break;
2864 6302 : case SECTION_POST_DATA:
3967 tgl 2865 CBC 6302 : if (!(ropt->dumpSections & DUMP_POST_DATA))
3967 tgl 2866 GIC 142 : return 0;
3967 tgl 2867 CBC 6160 : break;
3967 tgl 2868 LBC 0 : default:
2869 : /* shouldn't get here, really, but ignore it */
4132 andrew 2870 0 : return 0;
4132 andrew 2871 ECB : }
2872 :
2873 : /* Ignore it if rejected by idWanted[] (cf. SortTocFromFile) */
1900 tgl 2874 GIC 26474 : if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
2392 peter_e 2875 UIC 0 : return 0;
2876 :
2877 : /*
2878 : * Check options for selective dump/restore.
2879 : */
1900 tgl 2880 GIC 26474 : if (strcmp(te->desc, "ACL") == 0 ||
2881 23858 : strcmp(te->desc, "COMMENT") == 0 ||
2882 22708 : strcmp(te->desc, "SECURITY LABEL") == 0)
2883 : {
2884 : /* Database properties react to createDB, not selectivity options. */
2885 3766 : if (strncmp(te->tag, "DATABASE ", 9) == 0)
2886 : {
2887 47 : if (!ropt->createDB)
8297 pjw 2888 21 : return 0;
2889 : }
1900 tgl 2890 GBC 3719 : else if (ropt->schemaNames.head != NULL ||
2891 3719 : ropt->schemaExcludeNames.head != NULL ||
2892 3719 : ropt->selTypes)
2893 : {
2894 : /*
2895 : * In a selective dump/restore, we want to restore these dependent
2896 : * TOC entry types only if their parent object is being restored.
2897 : * Without selectivity options, we let through everything in the
1900 tgl 2898 ECB : * archive. Note there may be such entries with no parent, eg
2899 : * non-default ACLs for built-in objects.
2900 : *
1900 tgl 2901 EUB : * This code depends on the parent having been marked already,
2902 : * which should be the case; if it isn't, perhaps due to
2903 : * SortTocFromFile rearrangement, skipping the dependent entry
2904 : * seems prudent anyway.
2905 : *
2906 : * Ideally we'd handle, eg, table CHECK constraints this way too.
1900 tgl 2907 ECB : * But it's hard to tell which of their dependencies is the one to
1900 tgl 2908 EUB : * consult.
2909 : */
1900 tgl 2910 UBC 0 : if (te->nDeps != 1 ||
1900 tgl 2911 UIC 0 : TocIDRequired(AH, te->dependencies[0]) == 0)
8297 pjw 2912 LBC 0 : return 0;
2913 : }
1900 tgl 2914 EUB : }
2915 : else
2916 : {
2917 : /* Apply selective-restore rules for standalone TOC entries. */
1900 tgl 2918 GBC 22708 : if (ropt->schemaNames.head != NULL)
8053 bruce 2919 EUB : {
1900 tgl 2920 : /* If no namespace is specified, it means all. */
1900 tgl 2921 UBC 0 : if (!te->namespace)
8297 pjw 2922 UIC 0 : return 0;
1900 tgl 2923 UBC 0 : if (!simple_string_list_member(&ropt->schemaNames, te->namespace))
8297 pjw 2924 0 : return 0;
8053 bruce 2925 EUB : }
1900 tgl 2926 :
1900 tgl 2927 GBC 22708 : if (ropt->schemaExcludeNames.head != NULL &&
1900 tgl 2928 UIC 0 : te->namespace &&
1900 tgl 2929 UBC 0 : simple_string_list_member(&ropt->schemaExcludeNames, te->namespace))
1900 tgl 2930 UIC 0 : return 0;
1900 tgl 2931 EUB :
1900 tgl 2932 GBC 22708 : if (ropt->selTypes)
8053 bruce 2933 EUB : {
1900 tgl 2934 UBC 0 : if (strcmp(te->desc, "TABLE") == 0 ||
2935 0 : strcmp(te->desc, "TABLE DATA") == 0 ||
1900 tgl 2936 UIC 0 : strcmp(te->desc, "VIEW") == 0 ||
1900 tgl 2937 UBC 0 : strcmp(te->desc, "FOREIGN TABLE") == 0 ||
2938 0 : strcmp(te->desc, "MATERIALIZED VIEW") == 0 ||
2939 0 : strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 ||
1900 tgl 2940 UIC 0 : strcmp(te->desc, "SEQUENCE") == 0 ||
1900 tgl 2941 UBC 0 : strcmp(te->desc, "SEQUENCE SET") == 0)
1900 tgl 2942 EUB : {
1900 tgl 2943 UBC 0 : if (!ropt->selTable)
2944 0 : return 0;
2945 0 : if (ropt->tableNames.head != NULL &&
1900 tgl 2946 UIC 0 : !simple_string_list_member(&ropt->tableNames, te->tag))
1900 tgl 2947 UBC 0 : return 0;
2948 : }
2949 0 : else if (strcmp(te->desc, "INDEX") == 0)
1900 tgl 2950 EUB : {
1900 tgl 2951 UBC 0 : if (!ropt->selIndex)
2952 0 : return 0;
2953 0 : if (ropt->indexNames.head != NULL &&
1900 tgl 2954 UIC 0 : !simple_string_list_member(&ropt->indexNames, te->tag))
2955 0 : return 0;
1900 tgl 2956 EUB : }
1900 tgl 2957 UIC 0 : else if (strcmp(te->desc, "FUNCTION") == 0 ||
2958 0 : strcmp(te->desc, "AGGREGATE") == 0 ||
2959 0 : strcmp(te->desc, "PROCEDURE") == 0)
2960 : {
2961 0 : if (!ropt->selFunction)
2962 0 : return 0;
2963 0 : if (ropt->functionNames.head != NULL &&
2964 0 : !simple_string_list_member(&ropt->functionNames, te->tag))
2965 0 : return 0;
1900 tgl 2966 ECB : }
1900 tgl 2967 UIC 0 : else if (strcmp(te->desc, "TRIGGER") == 0)
2968 : {
2969 0 : if (!ropt->selTrigger)
2970 0 : return 0;
2971 0 : if (ropt->triggerNames.head != NULL &&
2972 0 : !simple_string_list_member(&ropt->triggerNames, te->tag))
2973 0 : return 0;
2974 : }
1900 tgl 2975 ECB : else
8297 pjw 2976 LBC 0 : return 0;
8297 pjw 2977 ECB : }
8314 bruce 2978 : }
2979 :
7825 2980 : /*
1900 tgl 2981 : * Determine whether the TOC entry contains schema and/or data components,
1900 tgl 2982 EUB : * and mask off inapplicable REQ bits. If it had a dataDumper, assume
1900 tgl 2983 ECB : * it's both schema and data. Otherwise it's probably schema-only, but
2984 : * there are exceptions.
7825 bruce 2985 : */
7825 bruce 2986 GIC 26453 : if (!te->hadDumper)
2987 : {
2988 : /*
2989 : * Special Case: If 'SEQUENCE SET' or anything to do with LOs, then
2990 : * it is considered a data entry. We don't need to check for the
2991 : * BLOBS entry or old-style BLOB COMMENTS, because they will have
1903 tgl 2992 ECB : * hadDumper = true ... but we do need to check new-style BLOB ACLs,
2993 : * comments, etc.
7825 bruce 2994 : */
4798 tgl 2995 GIC 22965 : if (strcmp(te->desc, "SEQUENCE SET") == 0 ||
2996 22543 : strcmp(te->desc, "BLOB") == 0 ||
2997 22423 : (strcmp(te->desc, "ACL") == 0 &&
2998 2616 : strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
2999 22373 : (strcmp(te->desc, "COMMENT") == 0 &&
4577 rhaas 3000 CBC 1129 : strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
4577 rhaas 3001 GBC 22310 : (strcmp(te->desc, "SECURITY LABEL") == 0 &&
4798 tgl 3002 UIC 0 : strncmp(te->tag, "LARGE OBJECT ", 13) == 0))
7825 bruce 3003 GIC 655 : res = res & REQ_DATA;
7825 bruce 3004 ECB : else
7826 pjw 3005 GIC 22310 : res = res & ~REQ_DATA;
3006 : }
3007 :
3008 : /*
3009 : * If there's no definition command, there's no schema component. Treat
3010 : * "load via partition root" comments as not schema.
3011 : */
23 tgl 3012 26453 : if (!te->defn || !te->defn[0] ||
3013 22977 : strncmp(te->defn, "-- load via partition root ", 27) == 0)
1900 tgl 3014 CBC 3488 : res = res & ~REQ_SCHEMA;
1900 tgl 3015 ECB :
7751 bruce 3016 : /*
6385 3017 : * Special case: <Init> type with <Max OID> tag; this is obsolete and we
3018 : * always ignore it.
7751 3019 : */
7584 bruce 3020 CBC 26453 : if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
6449 tgl 3021 LBC 0 : return 0;
7751 tgl 3022 EUB :
8053 bruce 3023 ECB : /* Mask it if we only want schema */
8053 bruce 3024 GIC 26453 : if (ropt->schemaOnly)
3025 : {
3026 : /*
1900 tgl 3027 ECB : * The sequence_data option overrides schemaOnly for SEQUENCE SET.
1903 3028 : *
3029 : * In binary-upgrade mode, even with schemaOnly set, we do not mask
1900 3030 : * out large objects. (Only large object definitions, comments and
3031 : * other metadata should be generated in binary-upgrade mode, not the
3032 : * actual data, but that need not concern us here.)
3033 : */
2225 sfrost 3034 GIC 2343 : if (!(ropt->sequence_data && strcmp(te->desc, "SEQUENCE SET") == 0) &&
1903 tgl 3035 2295 : !(ropt->binary_upgrade &&
3036 2063 : (strcmp(te->desc, "BLOB") == 0 ||
3037 2058 : (strcmp(te->desc, "ACL") == 0 &&
3038 75 : strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
1903 tgl 3039 CBC 2057 : (strcmp(te->desc, "COMMENT") == 0 &&
1903 tgl 3040 GIC 42 : strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
3041 2054 : (strcmp(te->desc, "SECURITY LABEL") == 0 &&
1903 tgl 3042 LBC 0 : strncmp(te->tag, "LARGE OBJECT ", 13) == 0))))
2420 peter_e 3043 CBC 2286 : res = res & REQ_SCHEMA;
2420 peter_e 3044 ECB : }
8314 bruce 3045 :
3967 tgl 3046 : /* Mask it if we only want data */
8002 pjw 3047 CBC 26453 : if (ropt->dataOnly)
7826 3048 121 : res = res & REQ_DATA;
3049 :
8053 bruce 3050 GIC 26453 : return res;
3051 : }
3052 :
3053 : /*
3054 : * Identify which pass we should restore this TOC entry in.
3055 : *
2075 tgl 3056 ECB : * See notes with the RestorePass typedef in pg_backup_archiver.h.
3057 : */
2075 tgl 3058 EUB : static RestorePass
2075 tgl 3059 GIC 58946 : _tocEntryRestorePass(TocEntry *te)
3060 : {
2075 tgl 3061 ECB : /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
2075 tgl 3062 GIC 58946 : if (strcmp(te->desc, "ACL") == 0 ||
3063 53640 : strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3064 53640 : strcmp(te->desc, "DEFAULT ACL") == 0)
3065 5708 : return RESTORE_PASS_ACL;
1126 3066 53238 : if (strcmp(te->desc, "EVENT TRIGGER") == 0 ||
3067 53137 : strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0)
3068 785 : return RESTORE_PASS_POST_ACL;
3069 :
3070 : /*
3071 : * Comments need to be emitted in the same pass as their parent objects.
1096 tgl 3072 ECB : * ACLs haven't got comments, and neither do matview data objects, but
3073 : * event triggers do. (Fortunately, event triggers haven't got ACLs, or
3074 : * we'd need yet another weird special case.)
3075 : */
1096 tgl 3076 CBC 52453 : if (strcmp(te->desc, "COMMENT") == 0 &&
3077 2276 : strncmp(te->tag, "EVENT TRIGGER ", 14) == 0)
1096 tgl 3078 LBC 0 : return RESTORE_PASS_POST_ACL;
1096 tgl 3079 ECB :
3080 : /* All else can be handled in the main pass. */
2075 tgl 3081 GIC 52453 : return RESTORE_PASS_MAIN;
3082 : }
3083 :
3084 : /*
3085 : * Identify TOC entries that are ACLs.
3086 : *
2075 tgl 3087 ECB : * Note: it seems worth duplicating some code here to avoid a hard-wired
3088 : * assumption that these are exactly the same entries that we restore during
3089 : * the RESTORE_PASS_ACL phase.
3090 : */
3091 : static bool
4798 tgl 3092 GIC 20858 : _tocEntryIsACL(TocEntry *te)
3093 : {
4798 tgl 3094 ECB : /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
4798 tgl 3095 CBC 20858 : if (strcmp(te->desc, "ACL") == 0 ||
3096 19028 : strcmp(te->desc, "ACL LANGUAGE") == 0 ||
4798 tgl 3097 GIC 19028 : strcmp(te->desc, "DEFAULT ACL") == 0)
3098 1964 : return true;
4798 tgl 3099 CBC 18894 : return false;
3100 : }
3101 :
3102 : /*
6984 tgl 3103 ECB : * Issue SET commands for parameters that we want to have set the same way
3104 : * at all times during execution of a restore script.
3105 : */
3106 : static void
6984 tgl 3107 CBC 179 : _doSetFixedOutputState(ArchiveHandle *AH)
6984 tgl 3108 EUB : {
2643 tgl 3109 GIC 179 : RestoreOptions *ropt = AH->public.ropt;
3110 :
2489 tgl 3111 ECB : /*
3112 : * Disable timeouts to allow for slow commands, idle parallel workers, etc
3113 : */
5453 andrew 3114 GIC 179 : ahprintf(AH, "SET statement_timeout = 0;\n");
3676 tgl 3115 CBC 179 : ahprintf(AH, "SET lock_timeout = 0;\n");
2489 tgl 3116 GIC 179 : ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
3117 :
6160 tgl 3118 ECB : /* Select the correct character set encoding */
6160 tgl 3119 GIC 179 : ahprintf(AH, "SET client_encoding = '%s';\n",
3120 : pg_encoding_to_char(AH->public.encoding));
6984 tgl 3121 ECB :
6160 3122 : /* Select the correct string literal syntax */
6160 tgl 3123 GBC 179 : ahprintf(AH, "SET standard_conforming_strings = %s;\n",
6160 tgl 3124 GIC 179 : AH->public.std_strings ? "on" : "off");
3125 :
5207 tgl 3126 ECB : /* Select the role to be used during restore */
2643 tgl 3127 GBC 179 : if (ropt && ropt->use_role)
2643 tgl 3128 UIC 0 : ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));
5207 tgl 3129 ECB :
3130 : /* Select the dump-time search_path */
1868 tgl 3131 CBC 179 : if (AH->public.searchpath)
3132 179 : ahprintf(AH, "%s", AH->public.searchpath);
3133 :
3134 : /* Make sure function checking is disabled */
6984 tgl 3135 GIC 179 : ahprintf(AH, "SET check_function_bodies = false;\n");
3136 :
3137 : /* Ensure that all valid XML data will be accepted */
1478 3138 179 : ahprintf(AH, "SET xmloption = content;\n");
3139 :
6806 bruce 3140 ECB : /* Avoid annoying notices etc */
6806 bruce 3141 GIC 179 : ahprintf(AH, "SET client_min_messages = warning;\n");
6160 tgl 3142 CBC 179 : if (!AH->public.std_strings)
6160 tgl 3143 UIC 0 : ahprintf(AH, "SET escape_string_warning = off;\n");
6806 bruce 3144 ECB :
3145 : /* Adjust row-security state */
2643 tgl 3146 GIC 179 : if (ropt && ropt->enable_row_security)
2972 tgl 3147 UIC 0 : ahprintf(AH, "SET row_security = on;\n");
3148 : else
2972 tgl 3149 CBC 179 : ahprintf(AH, "SET row_security = off;\n");
2972 tgl 3150 ECB :
6984 tgl 3151 GIC 179 : ahprintf(AH, "\n");
6984 tgl 3152 GBC 179 : }
6984 tgl 3153 ECB :
3154 : /*
7639 3155 : * Issue a SET SESSION AUTHORIZATION command. Caller is responsible
3156 : * for updating state if appropriate. If user is NULL or an empty string,
3157 : * the specification DEFAULT will be used.
3158 : */
7639 tgl 3159 EUB : static void
7539 peter_e 3160 GIC 1 : _doSetSessionAuth(ArchiveHandle *AH, const char *user)
7639 tgl 3161 EUB : {
7539 peter_e 3162 GIC 1 : PQExpBuffer cmd = createPQExpBuffer();
7522 bruce 3163 EUB :
3429 heikki.linnakangas 3164 GIC 1 : appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3165 :
7138 tgl 3166 EUB : /*
3167 : * SQL requires a string literal here. Might as well be correct.
3168 : */
7138 tgl 3169 CBC 1 : if (user && *user)
6160 tgl 3170 GIC 1 : appendStringLiteralAHX(cmd, user, AH);
7539 peter_e 3171 ECB : else
3429 heikki.linnakangas 3172 LBC 0 : appendPQExpBufferStr(cmd, "DEFAULT");
3429 heikki.linnakangas 3173 GIC 1 : appendPQExpBufferChar(cmd, ';');
3174 :
7639 tgl 3175 1 : if (RestoringToDB(AH))
3176 : {
3177 : PGresult *res;
3178 :
7539 peter_e 3179 UIC 0 : res = PQexec(AH->connection, cmd->data);
3180 :
7639 tgl 3181 0 : if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3182 : /* NOT warn_or_exit_horribly... use -O instead to skip this. */
366 tgl 3183 LBC 0 : pg_fatal("could not set session user to \"%s\": %s",
3184 : user, PQerrorMessage(AH->connection));
7639 tgl 3185 ECB :
7639 tgl 3186 LBC 0 : PQclear(res);
3187 : }
3188 : else
7539 peter_e 3189 GIC 1 : ahprintf(AH, "%s\n\n", cmd->data);
3190 :
7539 peter_e 3191 CBC 1 : destroyPQExpBuffer(cmd);
7639 tgl 3192 1 : }
7639 tgl 3193 ECB :
7900 peter_e 3194 :
3195 : /*
3196 : * Issue the commands to connect to the specified database.
3197 : *
3198 : * If we're currently restoring right into a database, this will
3199 : * actually establish a connection. Otherwise it puts a \connect into
3200 : * the script output.
3201 : */
8053 bruce 3202 : static void
6785 tgl 3203 GIC 44 : _reconnectToDB(ArchiveHandle *AH, const char *dbname)
3204 : {
7138 tgl 3205 CBC 44 : if (RestoringToDB(AH))
927 3206 13 : ReconnectToServer(AH, dbname);
3207 : else
7727 tgl 3208 ECB : {
927 3209 : PQExpBufferData connectbuf;
3210 :
927 tgl 3211 CBC 31 : initPQExpBuffer(&connectbuf);
3212 31 : appendPsqlMetaConnect(&connectbuf, dbname);
927 tgl 3213 GIC 31 : ahprintf(AH, "%s\n", connectbuf.data);
3214 31 : termPQExpBuffer(&connectbuf);
7727 tgl 3215 ECB : }
7900 peter_e 3216 :
3217 : /*
3218 : * NOTE: currUser keeps track of what the imaginary session user in our
3219 : * script is. It's now effectively reset to the original userID.
3220 : */
297 peter 3221 GNC 44 : free(AH->currUser);
5179 andrew 3222 GIC 44 : AH->currUser = NULL;
7900 peter_e 3223 ECB :
3224 : /* don't assume we still know the output schema, tablespace, etc either */
297 peter 3225 GNC 44 : free(AH->currSchema);
5179 andrew 3226 GIC 44 : AH->currSchema = NULL;
447 michael 3227 ECB :
297 peter 3228 GNC 44 : free(AH->currTableAm);
447 michael 3229 CBC 44 : AH->currTableAm = NULL;
3230 :
297 peter 3231 GNC 44 : free(AH->currTablespace);
5179 andrew 3232 GIC 44 : AH->currTablespace = NULL;
3233 :
6984 tgl 3234 ECB : /* re-establish fixed state */
6984 tgl 3235 CBC 44 : _doSetFixedOutputState(AH);
8286 pjw 3236 GIC 44 : }
3237 :
3238 : /*
3239 : * Become the specified user, and update state to avoid redundant commands
3240 : *
3241 : * NULL or empty argument is taken to mean restoring the session default
3242 : */
7138 tgl 3243 ECB : static void
7138 tgl 3244 GIC 48 : _becomeUser(ArchiveHandle *AH, const char *user)
7138 tgl 3245 ECB : {
7138 tgl 3246 GIC 48 : if (!user)
7138 tgl 3247 LBC 0 : user = ""; /* avoid null pointers */
7138 tgl 3248 ECB :
7138 tgl 3249 GIC 48 : if (AH->currUser && strcmp(AH->currUser, user) == 0)
7138 tgl 3250 GBC 47 : return; /* no need to do anything */
3251 :
7138 tgl 3252 GIC 1 : _doSetSessionAuth(AH, user);
3253 :
3254 : /*
3255 : * NOTE: currUser keeps track of what the imaginary session user in our
3256 : * script is
3257 : */
297 peter 3258 GNC 1 : free(AH->currUser);
4153 bruce 3259 GIC 1 : AH->currUser = pg_strdup(user);
3260 : }
3261 :
3262 : /*
3263 : * Become the owner of the given TOC entry object. If
3264 : * changes in ownership are not allowed, this doesn't do anything.
3265 : */
3266 : static void
7138 tgl 3267 23973 : _becomeOwner(ArchiveHandle *AH, TocEntry *te)
8286 pjw 3268 ECB : {
2643 tgl 3269 CBC 23973 : RestoreOptions *ropt = AH->public.ropt;
3270 :
2643 tgl 3271 GBC 23973 : if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
8286 pjw 3272 23973 : return;
8286 pjw 3273 EUB :
7138 tgl 3274 UIC 0 : _becomeUser(AH, te->owner);
8294 pjw 3275 EUB : }
3276 :
7900 peter_e 3277 :
3278 : /*
7639 tgl 3279 : * Issue the commands to select the specified schema as the current schema
3280 : * in the target database.
3281 : */
3282 : static void
7639 tgl 3283 GIC 24012 : _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
3284 : {
3285 : PQExpBuffer qry;
7621 tgl 3286 EUB :
3287 : /*
1868 3288 : * If there was a SEARCHPATH TOC entry, we're supposed to just stay with
3289 : * that search_path rather than switching to entry-specific paths.
3290 : * Otherwise, it's an old archive that will not restore correctly unless
3291 : * we set the search_path as it's expecting.
3292 : */
1868 tgl 3293 GBC 24012 : if (AH->public.searchpath)
1868 tgl 3294 GIC 24012 : return;
3295 :
7639 tgl 3296 UBC 0 : if (!schemaName || *schemaName == '\0' ||
6199 tgl 3297 UIC 0 : (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0))
7639 tgl 3298 UBC 0 : return; /* no need to do anything */
7639 tgl 3299 EUB :
7621 tgl 3300 UIC 0 : qry = createPQExpBuffer();
7621 tgl 3301 EUB :
7621 tgl 3302 UIC 0 : appendPQExpBuffer(qry, "SET search_path = %s",
3303 : fmtId(schemaName));
3304 0 : if (strcmp(schemaName, "pg_catalog") != 0)
3429 heikki.linnakangas 3305 0 : appendPQExpBufferStr(qry, ", pg_catalog");
3306 :
7639 tgl 3307 0 : if (RestoringToDB(AH))
3308 : {
7639 tgl 3309 ECB : PGresult *res;
3310 :
7639 tgl 3311 LBC 0 : res = PQexec(AH->connection, qry->data);
3312 :
7639 tgl 3313 UIC 0 : if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
1469 peter 3314 0 : warn_or_exit_horribly(AH,
3315 : "could not set search_path to \"%s\": %s",
4037 alvherre 3316 0 : schemaName, PQerrorMessage(AH->connection));
7639 tgl 3317 ECB :
7639 tgl 3318 UBC 0 : PQclear(res);
3319 : }
7639 tgl 3320 ECB : else
7621 tgl 3321 LBC 0 : ahprintf(AH, "%s;\n\n", qry->data);
3322 :
297 peter 3323 UNC 0 : free(AH->currSchema);
4153 bruce 3324 LBC 0 : AH->currSchema = pg_strdup(schemaName);
3325 :
7621 tgl 3326 0 : destroyPQExpBuffer(qry);
7639 tgl 3327 ECB : }
3328 :
6728 3329 : /*
3330 : * Issue the commands to select the specified tablespace as the current one
3331 : * in the target database.
3332 : */
3333 : static void
6728 tgl 3334 CBC 20646 : _selectTablespace(ArchiveHandle *AH, const char *tablespace)
3335 : {
2643 tgl 3336 GIC 20646 : RestoreOptions *ropt = AH->public.ropt;
3337 : PQExpBuffer qry;
3338 : const char *want,
6385 bruce 3339 EUB : *have;
3340 :
3341 : /* do nothing in --no-tablespaces mode */
2643 tgl 3342 CBC 20646 : if (ropt->noTablespace)
5498 tgl 3343 UIC 0 : return;
3344 :
6728 tgl 3345 GIC 20646 : have = AH->currTablespace;
6728 tgl 3346 CBC 20646 : want = tablespace;
3347 :
6728 tgl 3348 ECB : /* no need to do anything for non-tablespace object */
6728 tgl 3349 GBC 20646 : if (!want)
6728 tgl 3350 GIC 14513 : return;
6728 tgl 3351 EUB :
6728 tgl 3352 GIC 6133 : if (have && strcmp(want, have) == 0)
6728 tgl 3353 CBC 6056 : return; /* no need to do anything */
3354 :
6728 tgl 3355 GIC 77 : qry = createPQExpBuffer();
6728 tgl 3356 ECB :
6728 tgl 3357 GIC 77 : if (strcmp(want, "") == 0)
6728 tgl 3358 ECB : {
3359 : /* We want the tablespace to be the database's default */
3429 heikki.linnakangas 3360 GIC 77 : appendPQExpBufferStr(qry, "SET default_tablespace = ''");
6728 tgl 3361 ECB : }
3362 : else
3363 : {
3364 : /* We want an explicit tablespace */
6728 tgl 3365 UIC 0 : appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
3366 : }
3367 :
6728 tgl 3368 CBC 77 : if (RestoringToDB(AH))
3369 : {
6728 tgl 3370 ECB : PGresult *res;
3371 :
6728 tgl 3372 GIC 11 : res = PQexec(AH->connection, qry->data);
3373 :
3374 11 : if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
1469 peter 3375 UIC 0 : warn_or_exit_horribly(AH,
2118 tgl 3376 ECB : "could not set default_tablespace to %s: %s",
2118 tgl 3377 LBC 0 : fmtId(want), PQerrorMessage(AH->connection));
3378 :
6728 tgl 3379 CBC 11 : PQclear(res);
6728 tgl 3380 ECB : }
3381 : else
6728 tgl 3382 CBC 66 : ahprintf(AH, "%s;\n\n", qry->data);
6728 tgl 3383 ECB :
297 peter 3384 GNC 77 : free(AH->currTablespace);
4153 bruce 3385 CBC 77 : AH->currTablespace = pg_strdup(want);
3386 :
6728 tgl 3387 77 : destroyPQExpBuffer(qry);
6728 tgl 3388 ECB : }
3389 :
1495 andres 3390 : /*
3391 : * Set the proper default_table_access_method value for the table.
3392 : */
3393 : static void
1495 andres 3394 CBC 20646 : _selectTableAccessMethod(ArchiveHandle *AH, const char *tableam)
3395 : {
447 michael 3396 20646 : RestoreOptions *ropt = AH->public.ropt;
1495 andres 3397 EUB : PQExpBuffer cmd;
3398 : const char *want,
1418 tgl 3399 : *have;
3400 :
447 michael 3401 ECB : /* do nothing in --no-table-access-method mode */
447 michael 3402 GIC 20646 : if (ropt->noTableAm)
3403 256 : return;
447 michael 3404 ECB :
1495 andres 3405 GIC 20390 : have = AH->currTableAm;
1495 andres 3406 CBC 20390 : want = tableam;
3407 :
3408 20390 : if (!want)
3409 16530 : return;
3410 :
1495 andres 3411 GIC 3860 : if (have && strcmp(want, have) == 0)
3412 3636 : return;
3413 :
3414 224 : cmd = createPQExpBuffer();
3415 224 : appendPQExpBuffer(cmd, "SET default_table_access_method = %s;", fmtId(want));
3416 :
3417 224 : if (RestoringToDB(AH))
3418 : {
3419 : PGresult *res;
1495 andres 3420 ECB :
1495 andres 3421 GIC 9 : res = PQexec(AH->connection, cmd->data);
1495 andres 3422 ECB :
1495 andres 3423 GIC 9 : if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
1469 peter 3424 UIC 0 : warn_or_exit_horribly(AH,
1495 andres 3425 ECB : "could not set default_table_access_method: %s",
1495 andres 3426 LBC 0 : PQerrorMessage(AH->connection));
1495 andres 3427 ECB :
1495 andres 3428 CBC 9 : PQclear(res);
1495 andres 3429 ECB : }
3430 : else
1495 andres 3431 CBC 215 : ahprintf(AH, "%s\n\n", cmd->data);
1495 andres 3432 ECB :
1495 andres 3433 CBC 224 : destroyPQExpBuffer(cmd);
1495 andres 3434 ECB :
297 peter 3435 GNC 224 : free(AH->currTableAm);
1495 andres 3436 GIC 224 : AH->currTableAm = pg_strdup(want);
1495 andres 3437 ECB : }
3438 :
6662 tgl 3439 : /*
3440 : * Extract an object description for a TOC entry, and append it to buf.
3441 : *
3526 bruce 3442 : * This is used for ALTER ... OWNER TO.
3443 : *
3444 : * If the object type has no owner, do nothing.
6844 3445 : */
6662 tgl 3446 : static void
158 peter 3447 GNC 11391 : _getObjectDescription(PQExpBuffer buf, const TocEntry *te)
6844 bruce 3448 ECB : {
6662 tgl 3449 CBC 11391 : const char *type = te->desc;
6662 tgl 3450 ECB :
3526 bruce 3451 : /* objects that don't require special decoration */
4439 peter_e 3452 GIC 11391 : if (strcmp(type, "COLLATION") == 0 ||
3453 11320 : strcmp(type, "CONVERSION") == 0 ||
6662 tgl 3454 11286 : strcmp(type, "DOMAIN") == 0 ||
4481 rhaas 3455 CBC 11167 : strcmp(type, "FOREIGN TABLE") == 0 ||
158 peter 3456 GNC 11131 : strcmp(type, "MATERIALIZED VIEW") == 0 ||
3457 10819 : strcmp(type, "SEQUENCE") == 0 ||
3458 10614 : strcmp(type, "STATISTICS") == 0 ||
3459 10492 : strcmp(type, "TABLE") == 0 ||
5710 tgl 3460 CBC 6484 : strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
3526 bruce 3461 6405 : strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 ||
158 peter 3462 GNC 6351 : strcmp(type, "TYPE") == 0 ||
3463 5999 : strcmp(type, "VIEW") == 0 ||
3260 bruce 3464 ECB : /* non-schema-specified objects */
3526 bruce 3465 CBC 5730 : strcmp(type, "DATABASE") == 0 ||
5858 tgl 3466 GIC 5696 : strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
5224 peter_e 3467 5663 : strcmp(type, "SCHEMA") == 0 ||
2087 tgl 3468 CBC 5509 : strcmp(type, "EVENT TRIGGER") == 0 ||
5224 peter_e 3469 GIC 5476 : strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
3470 5437 : strcmp(type, "SERVER") == 0 ||
2271 3471 5396 : strcmp(type, "PUBLICATION") == 0 ||
158 peter 3472 GNC 5264 : strcmp(type, "SUBSCRIPTION") == 0)
3473 : {
1868 tgl 3474 CBC 6226 : appendPQExpBuffer(buf, "%s ", type);
3475 6226 : if (te->namespace && *te->namespace)
3476 5661 : appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
1868 tgl 3477 GIC 6226 : appendPQExpBufferStr(buf, fmtId(te->tag));
3478 : }
3479 : /* LOs just have a name, but it's numeric so must not use fmtId */
158 peter 3480 GNC 5165 : else if (strcmp(type, "BLOB") == 0)
3481 : {
4798 tgl 3482 CBC 85 : appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag);
4798 tgl 3483 ECB : }
6797 bruce 3484 : /*
6385 3485 : * These object types require additional decoration. Fortunately, the
3486 : * information needed is exactly what's in the DROP command.
6797 3487 : */
158 peter 3488 GNC 5080 : else if (strcmp(type, "AGGREGATE") == 0 ||
3489 4810 : strcmp(type, "FUNCTION") == 0 ||
3490 3319 : strcmp(type, "OPERATOR") == 0 ||
3491 3230 : strcmp(type, "OPERATOR CLASS") == 0 ||
3492 3113 : strcmp(type, "OPERATOR FAMILY") == 0 ||
3493 3010 : strcmp(type, "PROCEDURE") == 0)
3494 : {
3495 : /* Chop "DROP " off the front and make a modifiable copy */
4153 bruce 3496 GIC 2149 : char *first = pg_strdup(te->dropStmt + 5);
6662 tgl 3497 EUB : char *last;
3498 :
3499 : /* point to last character in string */
6662 tgl 3500 GIC 2149 : last = first + strlen(first) - 1;
3501 :
3502 : /* Strip off any ';' or '\n' at the end */
3503 6447 : while (last >= first && (*last == '\n' || *last == ';'))
3504 4298 : last--;
3505 2149 : *(last + 1) = '\0';
3506 :
3507 2149 : appendPQExpBufferStr(buf, first);
6797 bruce 3508 ECB :
6797 bruce 3509 GIC 2149 : free(first);
6662 tgl 3510 CBC 2149 : return;
3511 : }
3512 : /* these object types don't have separate owners */
158 peter 3513 GNC 2931 : else if (strcmp(type, "CAST") == 0 ||
3514 2931 : strcmp(type, "CHECK CONSTRAINT") == 0 ||
2 alvherre 3515 2906 : strcmp(type, "NOT NULL CONSTRAINT") == 0 ||
158 peter 3516 2906 : strcmp(type, "CONSTRAINT") == 0 ||
3517 2071 : strcmp(type, "DATABASE PROPERTIES") == 0 ||
3518 2070 : strcmp(type, "DEFAULT") == 0 ||
3519 1923 : strcmp(type, "FK CONSTRAINT") == 0 ||
3520 1775 : strcmp(type, "INDEX") == 0 ||
3521 850 : strcmp(type, "RULE") == 0 ||
3522 645 : strcmp(type, "TRIGGER") == 0 ||
3523 282 : strcmp(type, "ROW SECURITY") == 0 ||
3524 282 : strcmp(type, "POLICY") == 0 ||
3525 33 : strcmp(type, "USER MAPPING") == 0)
3526 : {
3527 : /* do nothing */
3528 : }
3529 : else
158 peter 3530 UNC 0 : pg_fatal("don't know how to set owner for object type \"%s\"", type);
6844 bruce 3531 ECB : }
3532 :
3533 : /*
3534 : * Emit the SQL commands to create the object represented by a TOC entry
2075 tgl 3535 : *
3536 : * This now also includes issuing an ALTER OWNER command to restore the
3537 : * object's ownership, if wanted. But note that the object's permissions
3538 : * will remain at default, until the matching ACL TOC entry is restored.
3539 : */
3540 : static void
2075 tgl 3541 GIC 20646 : _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
8314 bruce 3542 ECB : {
2643 tgl 3543 CBC 20646 : RestoreOptions *ropt = AH->public.ropt;
3544 :
1495 andres 3545 ECB : /* Select owner, schema, tablespace and default AM as necessary */
6813 tgl 3546 GIC 20646 : _becomeOwner(AH, te);
6813 tgl 3547 CBC 20646 : _selectOutputSchema(AH, te->namespace);
6728 3548 20646 : _selectTablespace(AH, te->tablespace);
1495 andres 3549 GIC 20646 : _selectTableAccessMethod(AH, te->tableam);
6813 tgl 3550 ECB :
3551 : /* Emit header comment for item */
6796 tgl 3552 CBC 20646 : if (!AH->noTocComments)
3553 : {
3554 : const char *pfx;
3555 : char *sanitized_name;
4063 tgl 3556 ECB : char *sanitized_schema;
3557 : char *sanitized_owner;
6796 3558 :
6796 tgl 3559 CBC 18713 : if (isData)
6796 tgl 3560 GIC 3090 : pfx = "Data for ";
3561 : else
3562 15623 : pfx = "";
6796 tgl 3563 ECB :
6796 tgl 3564 CBC 18713 : ahprintf(AH, "--\n");
3565 18713 : if (AH->public.verbose)
3566 : {
3567 779 : ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
3568 : te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
6796 tgl 3569 GIC 779 : if (te->nDeps > 0)
3570 : {
6796 tgl 3571 ECB : int i;
7064 3572 :
6796 tgl 3573 CBC 451 : ahprintf(AH, "-- Dependencies:");
6796 tgl 3574 GIC 1150 : for (i = 0; i < te->nDeps; i++)
6796 tgl 3575 CBC 699 : ahprintf(AH, " %d", te->dependencies[i]);
6796 tgl 3576 GIC 451 : ahprintf(AH, "\n");
3577 : }
3578 : }
4063 tgl 3579 EUB :
1528 alvherre 3580 GBC 18713 : sanitized_name = sanitize_line(te->tag, false);
3581 18713 : sanitized_schema = sanitize_line(te->namespace, true);
1528 alvherre 3582 GIC 18713 : sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
4063 tgl 3583 ECB :
6728 tgl 3584 GIC 18713 : ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
4063 tgl 3585 ECB : pfx, sanitized_name, te->desc, sanitized_schema,
3586 : sanitized_owner);
3587 :
4063 tgl 3588 GIC 18713 : free(sanitized_name);
3589 18713 : free(sanitized_schema);
3590 18713 : free(sanitized_owner);
3591 :
2890 bruce 3592 18713 : if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace)
3593 : {
3594 : char *sanitized_tablespace;
3595 :
1528 alvherre 3596 UIC 0 : sanitized_tablespace = sanitize_line(te->tablespace, false);
4063 tgl 3597 0 : ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
4063 tgl 3598 LBC 0 : free(sanitized_tablespace);
4063 tgl 3599 ECB : }
6728 tgl 3600 GIC 18713 : ahprintf(AH, "\n");
6728 tgl 3601 ECB :
2153 bruce 3602 GIC 18713 : if (AH->PrintExtraTocPtr != NULL)
2040 peter_e 3603 3164 : AH->PrintExtraTocPtr(AH, te);
6796 tgl 3604 18713 : ahprintf(AH, "--\n\n");
7064 tgl 3605 ECB : }
8314 bruce 3606 :
3607 : /*
3608 : * Actually print the definition.
3609 : *
3610 : * Really crude hack for suppressing AUTHORIZATION clause that old pg_dump
3611 : * versions put into CREATE SCHEMA. Don't mutate the variant for schema
3612 : * "public" that is a comment. We have to do this when --no-owner mode is
3613 : * selected. This is ugly, but I see no other good way ...
3614 : */
650 noah 3615 GIC 20646 : if (ropt->noOwner &&
650 noah 3616 CBC 272 : strcmp(te->desc, "SCHEMA") == 0 && strncmp(te->defn, "--", 2) != 0)
6844 bruce 3617 ECB : {
6662 tgl 3618 GBC 2 : ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
7138 tgl 3619 EUB : }
6813 tgl 3620 ECB : else
7138 3621 : {
1444 alvherre 3622 GIC 20644 : if (te->defn && strlen(te->defn) > 0)
6813 tgl 3623 17544 : ahprintf(AH, "%s\n\n", te->defn);
3624 : }
6813 tgl 3625 ECB :
3626 : /*
3627 : * If we aren't using SET SESSION AUTH to determine ownership, we must
3628 : * instead issue an ALTER OWNER command. Schema "public" is special; when
3629 : * a dump emits a comment in lieu of creating it, we use ALTER OWNER even
3630 : * when using SET SESSION for all other objects. We assume that anything
3631 : * without a DROP command is not a separately ownable object.
3632 : */
650 noah 3633 GIC 20646 : if (!ropt->noOwner &&
3634 20374 : (!ropt->use_setsessauth ||
650 noah 3635 UIC 0 : (strcmp(te->desc, "SCHEMA") == 0 &&
3636 0 : strncmp(te->defn, "--", 2) == 0)) &&
1444 alvherre 3637 GIC 20374 : te->owner && strlen(te->owner) > 0 &&
3638 19990 : te->dropStmt && strlen(te->dropStmt) > 0)
6662 tgl 3639 ECB : {
3640 : PQExpBufferData temp;
3641 :
158 peter 3642 GNC 11391 : initPQExpBuffer(&temp);
3643 11391 : _getObjectDescription(&temp, te);
3644 : /*
3645 : * If _getObjectDescription() didn't fill the buffer, then there is no
3646 : * owner.
3647 : */
3648 11391 : if (temp.data[0])
3649 8460 : ahprintf(AH, "ALTER %s OWNER TO %s;\n\n", temp.data, fmtId(te->owner));
3650 11391 : termPQExpBuffer(&temp);
7138 tgl 3651 ECB : }
8314 bruce 3652 :
6838 tgl 3653 : /*
3654 : * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
6385 bruce 3655 : * commands, so we can no longer assume we know the current auth setting.
6838 tgl 3656 : */
2075 tgl 3657 CBC 20646 : if (_tocEntryIsACL(te))
6838 tgl 3658 ECB : {
297 peter 3659 GNC 1964 : free(AH->currUser);
6838 tgl 3660 CBC 1964 : AH->currUser = NULL;
6838 tgl 3661 ECB : }
8314 bruce 3662 CBC 20646 : }
8314 bruce 3663 ECB :
3664 : /*
3665 : * Sanitize a string to be included in an SQL comment or TOC listing, by
1528 alvherre 3666 : * replacing any newlines with spaces. This ensures each logical output line
3667 : * is in fact one physical output line, to prevent corruption of the dump
3668 : * (which could, in the worst case, present an SQL injection vulnerability
3669 : * if someone were to incautiously load a dump containing objects with
3670 : * maliciously crafted names).
3671 : *
3672 : * The result is a freshly malloc'd string. If the input string is NULL,
3673 : * return a malloc'ed empty string, unless want_hyphen, in which case return a
3674 : * malloc'ed hyphen.
3675 : *
3676 : * Note that we currently don't bother to quote names, meaning that the name
3677 : * fields aren't automatically parseable. "pg_restore -L" doesn't care because
3678 : * it only examines the dumpId field, but someday we might want to try harder.
3679 : */
4063 tgl 3680 : static char *
1528 alvherre 3681 GIC 59984 : sanitize_line(const char *str, bool want_hyphen)
3682 : {
3683 : char *result;
3955 bruce 3684 ECB : char *s;
3685 :
1528 alvherre 3686 CBC 59984 : if (!str)
1528 alvherre 3687 GBC 2085 : return pg_strdup(want_hyphen ? "-" : "");
3688 :
4063 tgl 3689 GIC 57899 : result = pg_strdup(str);
4063 tgl 3690 ECB :
4063 tgl 3691 CBC 699630 : for (s = result; *s != '\0'; s++)
3692 : {
3693 641731 : if (*s == '\n' || *s == '\r')
4063 tgl 3694 LBC 0 : *s = ' ';
3695 : }
4063 tgl 3696 EUB :
4063 tgl 3697 GIC 57899 : return result;
4063 tgl 3698 ECB : }
3699 :
2075 3700 : /*
2075 tgl 3701 EUB : * Write the file header for a custom-format archive
3702 : */
3703 : void
8053 bruce 3704 CBC 25 : WriteHead(ArchiveHandle *AH)
8314 bruce 3705 ECB : {
8053 bruce 3706 EUB : struct tm crtm;
3707 :
2040 peter_e 3708 GIC 25 : AH->WriteBufPtr(AH, "PGDMP", 5); /* Magic code */
2040 peter_e 3709 CBC 25 : AH->WriteBytePtr(AH, ARCHIVE_MAJOR(AH->version));
2040 peter_e 3710 GBC 25 : AH->WriteBytePtr(AH, ARCHIVE_MINOR(AH->version));
2040 peter_e 3711 GIC 25 : AH->WriteBytePtr(AH, ARCHIVE_REV(AH->version));
2040 peter_e 3712 CBC 25 : AH->WriteBytePtr(AH, AH->intSize);
3713 25 : AH->WriteBytePtr(AH, AH->offSize);
2040 peter_e 3714 GIC 25 : AH->WriteBytePtr(AH, AH->format);
45 tomas.vondra 3715 GNC 25 : AH->WriteBytePtr(AH, AH->compression_spec.algorithm);
8297 pjw 3716 GIC 25 : crtm = *localtime(&AH->createDate);
8297 pjw 3717 CBC 25 : WriteInt(AH, crtm.tm_sec);
8297 pjw 3718 GIC 25 : WriteInt(AH, crtm.tm_min);
8297 pjw 3719 CBC 25 : WriteInt(AH, crtm.tm_hour);
8297 pjw 3720 GBC 25 : WriteInt(AH, crtm.tm_mday);
8297 pjw 3721 GIC 25 : WriteInt(AH, crtm.tm_mon);
3722 25 : WriteInt(AH, crtm.tm_year);
8297 pjw 3723 CBC 25 : WriteInt(AH, crtm.tm_isdst);
7547 peter_e 3724 25 : WriteStr(AH, PQdb(AH->connection));
6728 tgl 3725 GBC 25 : WriteStr(AH, AH->public.remoteVersionStr);
6728 tgl 3726 GIC 25 : WriteStr(AH, PG_VERSION);
8314 bruce 3727 25 : }
8314 bruce 3728 EUB :
8053 3729 : void
8053 bruce 3730 GIC 31 : ReadHead(ArchiveHandle *AH)
8314 bruce 3731 EUB : {
3732 : char *errmsg;
3733 : char vmaj,
738 tgl 3734 : vmin,
3735 : vrev;
3736 : int fmt;
3737 :
4668 3738 : /*
3739 : * If we haven't already read the header, do so.
4668 tgl 3740 ECB : *
3260 bruce 3741 : * NB: this code must agree with _discoverArchiveFormat(). Maybe find a
3742 : * way to unify the cases?
4668 tgl 3743 EUB : */
8053 bruce 3744 GIC 31 : if (!AH->readHeader)
8053 bruce 3745 EUB : {
3746 : char tmpMag[7];
3747 :
2040 peter_e 3748 CBC 31 : AH->ReadBufPtr(AH, tmpMag, 5);
3749 :
8053 bruce 3750 GIC 31 : if (strncmp(tmpMag, "PGDMP", 5) != 0)
366 tgl 3751 UIC 0 : pg_fatal("did not find magic string in file header");
738 tgl 3752 ECB : }
8314 bruce 3753 :
738 tgl 3754 CBC 31 : vmaj = AH->ReadBytePtr(AH);
3755 31 : vmin = AH->ReadBytePtr(AH);
8314 bruce 3756 ECB :
738 tgl 3757 CBC 31 : if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
3758 31 : vrev = AH->ReadBytePtr(AH);
3759 : else
738 tgl 3760 UIC 0 : vrev = 0;
3761 :
738 tgl 3762 GIC 31 : AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev);
3763 :
3764 31 : if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
366 tgl 3765 UIC 0 : pg_fatal("unsupported version (%d.%d) in file header",
3766 : vmaj, vmin);
3767 :
738 tgl 3768 GIC 31 : AH->intSize = AH->ReadBytePtr(AH);
3769 31 : if (AH->intSize > 32)
366 tgl 3770 UIC 0 : pg_fatal("sanity check on integer size (%lu) failed",
3771 : (unsigned long) AH->intSize);
3772 :
738 tgl 3773 CBC 31 : if (AH->intSize > sizeof(int))
738 tgl 3774 LBC 0 : pg_log_warning("archive was made on a machine with larger integers, some operations might fail");
3775 :
738 tgl 3776 GBC 31 : if (AH->version >= K_VERS_1_7)
3777 31 : AH->offSize = AH->ReadBytePtr(AH);
738 tgl 3778 EUB : else
738 tgl 3779 UBC 0 : AH->offSize = AH->intSize;
3780 :
738 tgl 3781 GIC 31 : fmt = AH->ReadBytePtr(AH);
3782 :
738 tgl 3783 CBC 31 : if (AH->format != fmt)
366 tgl 3784 UIC 0 : pg_fatal("expected format (%d) differs from format found in file (%d)",
366 tgl 3785 ECB : AH->format, fmt);
3786 :
45 tomas.vondra 3787 GNC 31 : if (AH->version >= K_VERS_1_15)
3788 31 : AH->compression_spec.algorithm = AH->ReadBytePtr(AH);
45 tomas.vondra 3789 UNC 0 : else if (AH->version >= K_VERS_1_2)
8053 bruce 3790 ECB : {
3791 : /* Guess the compression method based on the level */
8297 pjw 3792 UIC 0 : if (AH->version < K_VERS_1_4)
128 michael 3793 UNC 0 : AH->compression_spec.level = AH->ReadBytePtr(AH);
8297 pjw 3794 ECB : else
128 michael 3795 UNC 0 : AH->compression_spec.level = ReadInt(AH);
3796 :
3797 0 : if (AH->compression_spec.level != 0)
3798 0 : AH->compression_spec.algorithm = PG_COMPRESSION_GZIP;
8053 bruce 3799 ECB : }
3800 : else
128 michael 3801 UNC 0 : AH->compression_spec.algorithm = PG_COMPRESSION_GZIP;
3802 :
45 tomas.vondra 3803 GNC 31 : errmsg = supports_compression(AH->compression_spec);
3804 31 : if (errmsg)
3805 : {
45 tomas.vondra 3806 UNC 0 : pg_log_warning("archive is compressed, but this installation does not support compression (%s) -- no data will be available",
3807 : errmsg);
3808 0 : pg_free(errmsg);
3809 : }
8314 bruce 3810 ECB :
8297 pjw 3811 GIC 31 : if (AH->version >= K_VERS_1_4)
3812 : {
3813 : struct tm crtm;
3814 :
8297 pjw 3815 CBC 31 : crtm.tm_sec = ReadInt(AH);
3816 31 : crtm.tm_min = ReadInt(AH);
3817 31 : crtm.tm_hour = ReadInt(AH);
8297 pjw 3818 GIC 31 : crtm.tm_mday = ReadInt(AH);
3819 31 : crtm.tm_mon = ReadInt(AH);
3820 31 : crtm.tm_year = ReadInt(AH);
3821 31 : crtm.tm_isdst = ReadInt(AH);
3822 :
3823 : /*
665 tgl 3824 ECB : * Newer versions of glibc have mktime() report failure if tm_isdst is
665 tgl 3825 EUB : * inconsistent with the prevailing timezone, e.g. tm_isdst = 1 when
3826 : * TZ=UTC. This is problematic when restoring an archive under a
665 tgl 3827 ECB : * different timezone setting. If we get a failure, try again with
3828 : * tm_isdst set to -1 ("don't know").
3829 : *
3830 : * XXX with or without this hack, we reconstruct createDate
3831 : * incorrectly when the prevailing timezone is different from
3832 : * pg_dump's. Next time we bump the archive version, we should flush
3833 : * this representation and store a plain seconds-since-the-Epoch
3834 : * timestamp instead.
3835 : */
8297 pjw 3836 GIC 31 : AH->createDate = mktime(&crtm);
8053 bruce 3837 31 : if (AH->createDate == (time_t) -1)
3838 : {
665 tgl 3839 LBC 0 : crtm.tm_isdst = -1;
3840 0 : AH->createDate = mktime(&crtm);
3841 0 : if (AH->createDate == (time_t) -1)
665 tgl 3842 UIC 0 : pg_log_warning("invalid creation date in header");
3843 : }
3844 : }
3845 :
665 tgl 3846 GIC 31 : if (AH->version >= K_VERS_1_4)
3847 : {
3848 31 : AH->archdbname = ReadStr(AH);
3849 : }
3850 :
6728 3851 31 : if (AH->version >= K_VERS_1_10)
3852 : {
6728 tgl 3853 CBC 31 : AH->archiveRemoteVersion = ReadStr(AH);
6728 tgl 3854 GIC 31 : AH->archiveDumpVersion = ReadStr(AH);
3855 : }
8314 bruce 3856 31 : }
3857 :
8314 bruce 3858 ECB :
3859 : /*
3860 : * checkSeek
4668 tgl 3861 : * check to see if ftell/fseek can be performed.
3862 : */
3863 : bool
7471 bruce 3864 GIC 33 : checkSeek(FILE *fp)
3865 : {
3866 : pgoff_t tpos;
3867 :
3868 : /* Check that ftello works on this file */
4668 tgl 3869 33 : tpos = ftello(fp);
3346 sfrost 3870 33 : if (tpos < 0)
4668 tgl 3871 1 : return false;
3872 :
3873 : /*
3874 : * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
3875 : * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
3876 : * successful no-op even on files that are otherwise unseekable.
3877 : */
3878 32 : if (fseeko(fp, tpos, SEEK_SET) != 0)
4668 tgl 3879 UIC 0 : return false;
3880 :
4668 tgl 3881 GIC 32 : return true;
3882 : }
6568 tgl 3883 ECB :
3884 :
3885 : /*
3886 : * dumpTimestamp
3887 : */
3888 : static void
6568 tgl 3889 CBC 34 : dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
3890 : {
3891 : char buf[64];
6568 tgl 3892 ECB :
3087 tgl 3893 CBC 34 : if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
6568 tgl 3894 GIC 34 : ahprintf(AH, "-- %s %s\n\n", msg, buf);
6568 tgl 3895 CBC 34 : }
5179 andrew 3896 ECB :
3897 : /*
3898 : * Main engine for parallel restore.
3899 : *
3900 : * Parallel restore is done in three phases. In this first phase,
3901 : * we'll process all SECTION_PRE_DATA TOC entries that are allowed to be
3902 : * processed in the RESTORE_PASS_MAIN pass. (In practice, that's all
3903 : * PRE_DATA items other than ACLs.) Entries we can't process now are
3904 : * added to the pending_list for later phases to deal with.
3905 : */
5179 andrew 3906 EUB : static void
2075 tgl 3907 GBC 4 : restore_toc_entries_prefork(ArchiveHandle *AH, TocEntry *pending_list)
3908 : {
3909 : bool skipped_some;
3910 : TocEntry *next_work_item;
3911 :
1469 peter 3912 GIC 4 : pg_log_debug("entering restore_toc_entries_prefork");
3913 :
3914 : /* Adjust dependency information */
5179 andrew 3915 4 : fix_dependencies(AH);
5179 andrew 3916 ECB :
5179 andrew 3917 EUB : /*
3918 : * Do all the early stuff in a single connection in the parent. There's no
5050 bruce 3919 ECB : * great point in running it in parallel, in fact it will actually run
3920 : * faster in a single connection because we avoid all the connection and
3921 : * setup overhead. Also, pre-9.2 pg_dump versions were not very good
3940 tgl 3922 : * about showing all the dependencies of SECTION_PRE_DATA items, so we do
3923 : * not risk trying to process them out-of-order.
3924 : *
3925 : * Stuff that we can't do immediately gets added to the pending_list.
2075 3926 : * Note: we don't yet filter out entries that aren't going to be restored.
3927 : * They might participate in dependency chains connecting entries that
3928 : * should be restored, so we treat them as live until we actually process
3929 : * them.
3930 : *
3931 : * Note: as of 9.2, it should be guaranteed that all PRE_DATA items appear
3932 : * before DATA items, and all DATA items before POST_DATA items. That is
3933 : * not certain to be true in older archives, though, and in any case use
2059 3934 : * of a list file would destroy that ordering (cf. SortTocFromFile). So
3935 : * this loop cannot assume that it holds.
3936 : */
2075 tgl 3937 GIC 4 : AH->restorePass = RESTORE_PASS_MAIN;
4433 3938 4 : skipped_some = false;
4993 3939 100 : for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
3940 : {
2075 3941 96 : bool do_now = true;
3942 :
4433 tgl 3943 CBC 96 : if (next_work_item->section != SECTION_PRE_DATA)
3944 : {
3945 : /* DATA and POST_DATA items are just ignored for now */
3946 46 : if (next_work_item->section == SECTION_DATA ||
3947 30 : next_work_item->section == SECTION_POST_DATA)
4433 tgl 3948 ECB : {
2075 tgl 3949 CBC 46 : do_now = false;
4433 3950 46 : skipped_some = true;
4433 tgl 3951 ECB : }
3952 : else
3953 : {
3954 : /*
3955 : * SECTION_NONE items, such as comments, can be processed now
3956 : * if we are still in the PRE_DATA part of the archive. Once
3957 : * we've skipped any items, we have to consider whether the
3958 : * comment's dependencies are satisfied, so skip it for now.
3959 : */
4433 tgl 3960 UIC 0 : if (skipped_some)
2075 3961 0 : do_now = false;
3962 : }
3963 : }
3964 :
3965 : /*
3966 : * Also skip items that need to be forced into later passes. We need
3967 : * not set skipped_some in this case, since by assumption no main-pass
2075 tgl 3968 ECB : * items could depend on these.
3969 : */
2075 tgl 3970 GIC 96 : if (_tocEntryRestorePass(next_work_item) != RESTORE_PASS_MAIN)
2075 tgl 3971 UIC 0 : do_now = false;
3972 :
2075 tgl 3973 GIC 96 : if (do_now)
2075 tgl 3974 ECB : {
3975 : /* OK, restore the item and update its dependencies */
1469 peter 3976 GIC 50 : pg_log_info("processing item %d %s %s",
1418 tgl 3977 ECB : next_work_item->dumpId,
3978 : next_work_item->desc, next_work_item->tag);
3979 :
2075 tgl 3980 GIC 50 : (void) restore_toc_entry(AH, next_work_item, false);
3981 :
3982 : /* Reduce dependencies, but don't move anything to ready_list */
3983 50 : reduce_dependencies(AH, next_work_item, NULL);
3984 : }
3985 : else
3986 : {
2075 tgl 3987 ECB : /* Nope, so add it to pending_list */
1668 tgl 3988 CBC 46 : pending_list_append(pending_list, next_work_item);
3989 : }
3990 : }
3991 :
3992 : /*
3993 : * Now close parent connection in prep for parallel steps. We do this
3994 : * mainly to ensure that we don't exceed the specified number of parallel
3995 : * connections.
3996 : */
4070 rhaas 3997 4 : DisconnectDatabase(&AH->public);
3998 :
3999 : /* blow away any transient state from the old connection */
297 peter 4000 GNC 4 : free(AH->currUser);
5179 andrew 4001 CBC 4 : AH->currUser = NULL;
297 peter 4002 GNC 4 : free(AH->currSchema);
5179 andrew 4003 GIC 4 : AH->currSchema = NULL;
297 peter 4004 GNC 4 : free(AH->currTablespace);
5179 andrew 4005 GBC 4 : AH->currTablespace = NULL;
297 peter 4006 GNC 4 : free(AH->currTableAm);
1495 andres 4007 GIC 4 : AH->currTableAm = NULL;
3668 andrew 4008 GBC 4 : }
4009 :
3668 andrew 4010 EUB : /*
4011 : * Main engine for parallel restore.
4012 : *
2075 tgl 4013 ECB : * Parallel restore is done in three phases. In this second phase,
4014 : * we process entries by dispatching them to parallel worker children
4015 : * (processes on Unix, threads on Windows), each of which connects
4016 : * separately to the database. Inter-entry dependencies are respected,
4017 : * and so is the RestorePass multi-pass structure. When we can no longer
4018 : * make any entries ready to process, we exit. Normally, there will be
4019 : * nothing left to do; but if there is, the third phase will mop up.
4020 : */
3668 andrew 4021 : static void
3668 andrew 4022 GIC 4 : restore_toc_entries_parallel(ArchiveHandle *AH, ParallelState *pstate,
4023 : TocEntry *pending_list)
4024 : {
4025 : ParallelReadyList ready_list;
4026 : TocEntry *next_work_item;
3668 andrew 4027 ECB :
1469 peter 4028 CBC 4 : pg_log_debug("entering restore_toc_entries_parallel");
4029 :
4030 : /* Set up ready_list with enough room for all known TocEntrys */
1668 tgl 4031 4 : ready_list_init(&ready_list, AH->tocCount);
4032 :
4993 tgl 4033 ECB : /*
4034 : * The pending_list contains all items that we need to restore. Move all
2075 4035 : * items that are available to process immediately into the ready_list.
4036 : * After this setup, the pending list is everything that needs to be done
4037 : * but is blocked by one or more dependencies, while the ready list
4038 : * contains items that have no remaining dependencies and are OK to
4039 : * process in the current restore pass.
4040 : */
2075 tgl 4041 GIC 4 : AH->restorePass = RESTORE_PASS_MAIN;
4042 4 : move_to_ready_list(pending_list, &ready_list, AH->restorePass);
4043 :
4044 : /*
4045 : * main parent loop
4046 : *
4047 : * Keep going until there is no worker still running AND there is no work
4048 : * left to be done. Note invariant: at top of loop, there should always
4049 : * be at least one worker available to dispatch a job to.
4050 : */
1469 peter 4051 4 : pg_log_info("entering main parallel loop");
4052 :
4053 : for (;;)
4054 : {
4055 : /* Look for an item ready to be dispatched to a worker */
957 4056 68 : next_work_item = pop_next_work_item(&ready_list, pstate);
5179 andrew 4057 68 : if (next_work_item != NULL)
5179 andrew 4058 ECB : {
4059 : /* If not to be restored, don't waste time launching a worker */
2075 tgl 4060 GIC 46 : if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA)) == 0)
4061 : {
1469 peter 4062 UIC 0 : pg_log_info("skipping item %d %s %s",
1418 tgl 4063 ECB : next_work_item->dumpId,
4064 : next_work_item->desc, next_work_item->tag);
1668 4065 : /* Update its dependencies as though we'd completed it */
4993 tgl 4066 UIC 0 : reduce_dependencies(AH, next_work_item, &ready_list);
2075 tgl 4067 ECB : /* Loop around to see if anything else can be dispatched */
5179 andrew 4068 LBC 0 : continue;
4069 : }
4070 :
1469 peter 4071 GIC 46 : pg_log_info("launching item %d %s %s",
4072 : next_work_item->dumpId,
4073 : next_work_item->desc, next_work_item->tag);
4074 :
4075 : /* Dispatch to some worker */
2385 tgl 4076 46 : DispatchJobForTocEntry(AH, pstate, next_work_item, ACT_RESTORE,
4077 : mark_restore_job_done, &ready_list);
4078 : }
2075 4079 22 : else if (IsEveryWorkerIdle(pstate))
2075 tgl 4080 ECB : {
4081 : /*
4082 : * Nothing is ready and no worker is running, so we're done with
4083 : * the current pass or maybe with the whole process.
4084 : */
2075 tgl 4085 CBC 12 : if (AH->restorePass == RESTORE_PASS_LAST)
2075 tgl 4086 GIC 4 : break; /* No more parallel processing is possible */
4087 :
4088 : /* Advance to next restore pass */
4089 8 : AH->restorePass++;
2075 tgl 4090 ECB : /* That probably allows some stuff to be made ready */
2075 tgl 4091 GIC 8 : move_to_ready_list(pending_list, &ready_list, AH->restorePass);
4092 : /* Loop around to see if anything's now ready */
2075 tgl 4093 CBC 8 : continue;
4094 : }
4095 : else
4096 : {
4097 : /*
4098 : * We have nothing ready, but at least one child is working, so
4099 : * wait for some subjob to finish.
4100 : */
3667 andrew 4101 ECB : }
4102 :
2385 tgl 4103 EUB : /*
4104 : * Before dispatching another job, check to see if anything has
4105 : * finished. We should check every time through the loop so as to
4106 : * reduce dependencies as soon as possible. If we were unable to
2385 tgl 4107 ECB : * dispatch any job this time through, wait until some worker finishes
4108 : * (and, hopefully, unblocks some pending item). If we did dispatch
4109 : * something, continue as soon as there's at least one idle worker.
4110 : * Note that in either case, there's guaranteed to be at least one
4111 : * idle worker when we return to the top of the loop. This ensures we
4112 : * won't block inside DispatchJobForTocEntry, which would be
4113 : * undesirable: we'd rather postpone dispatching until we see what's
4114 : * been unblocked by finished jobs.
4115 : */
2385 tgl 4116 GIC 56 : WaitForWorkers(AH, pstate,
4117 : next_work_item ? WFW_ONE_IDLE : WFW_GOT_STATUS);
4118 : }
5179 andrew 4119 ECB :
4120 : /* There should now be nothing in ready_list. */
1668 tgl 4121 CBC 4 : Assert(ready_list.first_te > ready_list.last_te);
4122 :
4123 4 : ready_list_free(&ready_list);
2075 tgl 4124 ECB :
1469 peter 4125 GIC 4 : pg_log_info("finished main parallel loop");
3668 andrew 4126 4 : }
5179 andrew 4127 ECB :
4128 : /*
4129 : * Main engine for parallel restore.
4130 : *
4131 : * Parallel restore is done in three phases. In this third phase,
4132 : * we mop up any remaining TOC entries by processing them serially.
4133 : * This phase normally should have nothing to do, but if we've somehow
4134 : * gotten stuck due to circular dependencies or some such, this provides
4135 : * at least some chance of completing the restore successfully.
4136 : */
4137 : static void
3668 andrew 4138 GIC 4 : restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list)
3668 andrew 4139 ECB : {
2643 tgl 4140 GIC 4 : RestoreOptions *ropt = AH->public.ropt;
3668 andrew 4141 ECB : TocEntry *te;
4142 :
1469 peter 4143 GIC 4 : pg_log_debug("entering restore_toc_entries_postfork");
4144 :
4145 : /*
5179 andrew 4146 ECB : * Now reconnect the single parent connection.
4147 : */
927 tgl 4148 CBC 4 : ConnectDatabase((Archive *) AH, &ropt->cparams, true);
5179 andrew 4149 ECB :
2503 tgl 4150 : /* re-establish fixed state */
5179 andrew 4151 CBC 4 : _doSetFixedOutputState(AH);
5179 andrew 4152 ECB :
4153 : /*
4154 : * Make sure there is no work left due to, say, circular dependencies, or
4155 : * some other pathological condition. If so, do it in the single parent
2075 tgl 4156 : * connection. We don't sweat about RestorePass ordering; it's likely we
4157 : * already violated that.
5179 andrew 4158 : */
1668 tgl 4159 CBC 4 : for (te = pending_list->pending_next; te != pending_list; te = te->pending_next)
5179 andrew 4160 ECB : {
1469 peter 4161 LBC 0 : pg_log_info("processing missed item %d %s %s",
1418 tgl 4162 ECB : te->dumpId, te->desc, te->tag);
2643 tgl 4163 UIC 0 : (void) restore_toc_entry(AH, te, false);
4164 : }
5179 andrew 4165 GIC 4 : }
4166 :
4167 : /*
4168 : * Check if te1 has an exclusive lock requirement for an item that te2 also
5110 andrew 4169 ECB : * requires, whether or not te2's requirement is for an exclusive lock.
4170 : */
4171 : static bool
5110 andrew 4172 CBC 154 : has_lock_conflicts(TocEntry *te1, TocEntry *te2)
5110 andrew 4173 ECB : {
5050 bruce 4174 : int j,
4175 : k;
5110 andrew 4176 :
5110 andrew 4177 GIC 391 : for (j = 0; j < te1->nLockDeps; j++)
4178 : {
4179 1075 : for (k = 0; k < te2->nDeps; k++)
4180 : {
4181 838 : if (te1->lockDeps[j] == te2->dependencies[k])
5110 andrew 4182 CBC 2 : return true;
4183 : }
5110 andrew 4184 ECB : }
5110 andrew 4185 CBC 152 : return false;
4186 : }
4187 :
4188 :
4993 tgl 4189 ECB : /*
4190 : * Initialize the header of the pending-items list.
4191 : *
4192 : * This is a circular list with a dummy TocEntry as header, just like the
4193 : * main TOC list; but we use separate list links so that an entry can be in
1668 4194 : * the main TOC list as well as in the pending list.
4195 : */
4196 : static void
1668 tgl 4197 GIC 4 : pending_list_header_init(TocEntry *l)
1668 tgl 4198 ECB : {
1668 tgl 4199 GIC 4 : l->pending_prev = l->pending_next = l;
1668 tgl 4200 CBC 4 : }
4201 :
1668 tgl 4202 ECB : /* Append te to the end of the pending-list headed by l */
4203 : static void
1668 tgl 4204 GIC 46 : pending_list_append(TocEntry *l, TocEntry *te)
4205 : {
4206 46 : te->pending_prev = l->pending_prev;
4207 46 : l->pending_prev->pending_next = te;
4208 46 : l->pending_prev = te;
4209 46 : te->pending_next = l;
4210 46 : }
1668 tgl 4211 ECB :
4212 : /* Remove te from the pending-list */
1668 tgl 4213 EUB : static void
1668 tgl 4214 GIC 46 : pending_list_remove(TocEntry *te)
1668 tgl 4215 EUB : {
1668 tgl 4216 GIC 46 : te->pending_prev->pending_next = te->pending_next;
1668 tgl 4217 CBC 46 : te->pending_next->pending_prev = te->pending_prev;
4218 46 : te->pending_prev = NULL;
1668 tgl 4219 GIC 46 : te->pending_next = NULL;
4220 46 : }
4221 :
1668 tgl 4222 ECB :
4223 : /*
4224 : * Initialize the ready_list with enough room for up to tocCount entries.
4225 : */
4993 4226 : static void
1668 tgl 4227 GIC 4 : ready_list_init(ParallelReadyList *ready_list, int tocCount)
4993 tgl 4228 ECB : {
1668 tgl 4229 CBC 4 : ready_list->tes = (TocEntry **)
1668 tgl 4230 GIC 4 : pg_malloc(tocCount * sizeof(TocEntry *));
4231 4 : ready_list->first_te = 0;
1668 tgl 4232 CBC 4 : ready_list->last_te = -1;
1668 tgl 4233 GIC 4 : ready_list->sorted = false;
4993 tgl 4234 CBC 4 : }
4235 :
4236 : /*
4237 : * Free storage for a ready_list.
1668 tgl 4238 ECB : */
4239 : static void
1668 tgl 4240 CBC 4 : ready_list_free(ParallelReadyList *ready_list)
1668 tgl 4241 ECB : {
1668 tgl 4242 GIC 4 : pg_free(ready_list->tes);
4243 4 : }
1668 tgl 4244 ECB :
4245 : /* Add te to the ready_list */
4993 4246 : static void
1668 tgl 4247 CBC 46 : ready_list_insert(ParallelReadyList *ready_list, TocEntry *te)
4248 : {
1668 tgl 4249 GIC 46 : ready_list->tes[++ready_list->last_te] = te;
1668 tgl 4250 ECB : /* List is (probably) not sorted anymore. */
1668 tgl 4251 CBC 46 : ready_list->sorted = false;
4252 46 : }
1668 tgl 4253 ECB :
4254 : /* Remove the i'th entry in the ready_list */
1668 tgl 4255 EUB : static void
1668 tgl 4256 GIC 46 : ready_list_remove(ParallelReadyList *ready_list, int i)
4257 : {
4258 46 : int f = ready_list->first_te;
4259 :
4260 46 : Assert(i >= f && i <= ready_list->last_te);
4261 :
4262 : /*
4263 : * In the typical case where the item to be removed is the first ready
4264 : * entry, we need only increment first_te to remove it. Otherwise, move
4265 : * the entries before it to compact the list. (This preserves sortedness,
4266 : * if any.) We could alternatively move the entries after i, but there
1668 tgl 4267 ECB : * are typically many more of those.
4268 : */
1668 tgl 4269 GIC 46 : if (i > f)
4270 : {
1668 tgl 4271 UIC 0 : TocEntry **first_te_ptr = &ready_list->tes[f];
4272 :
4273 0 : memmove(first_te_ptr + 1, first_te_ptr, (i - f) * sizeof(TocEntry *));
1668 tgl 4274 ECB : }
1668 tgl 4275 GIC 46 : ready_list->first_te++;
4993 4276 46 : }
4993 tgl 4277 ECB :
4278 : /* Sort the ready_list into the desired order */
4279 : static void
1668 tgl 4280 CBC 68 : ready_list_sort(ParallelReadyList *ready_list)
4281 : {
1668 tgl 4282 GIC 68 : if (!ready_list->sorted)
1668 tgl 4283 ECB : {
1668 tgl 4284 GIC 22 : int n = ready_list->last_te - ready_list->first_te + 1;
1668 tgl 4285 ECB :
1668 tgl 4286 GIC 22 : if (n > 1)
4287 14 : qsort(ready_list->tes + ready_list->first_te, n,
1668 tgl 4288 ECB : sizeof(TocEntry *),
4289 : TocEntrySizeCompare);
1668 tgl 4290 GIC 22 : ready_list->sorted = true;
4291 : }
4292 68 : }
4293 :
4294 : /* qsort comparator for sorting TocEntries by dataLength */
4295 : static int
4296 540 : TocEntrySizeCompare(const void *p1, const void *p2)
4297 : {
4298 540 : const TocEntry *te1 = *(const TocEntry *const *) p1;
4299 540 : const TocEntry *te2 = *(const TocEntry *const *) p2;
4300 :
4301 : /* Sort by decreasing dataLength */
1668 tgl 4302 CBC 540 : if (te1->dataLength > te2->dataLength)
1668 tgl 4303 GIC 47 : return -1;
4304 493 : if (te1->dataLength < te2->dataLength)
4305 54 : return 1;
4306 :
4307 : /* For equal dataLengths, sort by dumpId, just to be stable */
1668 tgl 4308 CBC 439 : if (te1->dumpId < te2->dumpId)
1668 tgl 4309 GIC 183 : return -1;
4310 256 : if (te1->dumpId > te2->dumpId)
4311 256 : return 1;
4312 :
1668 tgl 4313 LBC 0 : return 0;
4314 : }
4993 tgl 4315 ECB :
5110 andrew 4316 :
4317 : /*
4318 : * Move all immediately-ready items from pending_list to ready_list.
4319 : *
4320 : * Items are considered ready if they have no remaining dependencies and
4321 : * they belong in the current restore pass. (See also reduce_dependencies,
4322 : * which applies the same logic one-at-a-time.)
2075 tgl 4323 : */
4324 : static void
1668 tgl 4325 CBC 12 : move_to_ready_list(TocEntry *pending_list,
4326 : ParallelReadyList *ready_list,
2075 tgl 4327 ECB : RestorePass pass)
4328 : {
4329 : TocEntry *te;
4330 : TocEntry *next_te;
4331 :
1668 tgl 4332 CBC 58 : for (te = pending_list->pending_next; te != pending_list; te = next_te)
2075 tgl 4333 ECB : {
4334 : /* must save list link before possibly removing te from list */
1668 tgl 4335 GIC 46 : next_te = te->pending_next;
4336 :
2075 tgl 4337 CBC 66 : if (te->depCount == 0 &&
4338 20 : _tocEntryRestorePass(te) == pass)
4339 : {
4340 : /* Remove it from pending_list ... */
1668 4341 20 : pending_list_remove(te);
2075 tgl 4342 ECB : /* ... and add to ready_list */
1668 tgl 4343 GIC 20 : ready_list_insert(ready_list, te);
4344 : }
2075 tgl 4345 ECB : }
2075 tgl 4346 CBC 12 : }
4347 :
4348 : /*
4349 : * Find the next work item (if any) that is capable of being run now,
4350 : * and remove it from the ready_list.
4351 : *
4352 : * Returns the item, or NULL if nothing is runnable.
4353 : *
4354 : * To qualify, the item must have no remaining dependencies
4355 : * and no requirements for locks that are incompatible with
4356 : * items currently running. Items in the ready_list are known to have
4357 : * no remaining dependencies, but we have to check for lock conflicts.
4358 : */
5179 andrew 4359 ECB : static TocEntry *
957 peter 4360 GIC 68 : pop_next_work_item(ParallelReadyList *ready_list,
4361 : ParallelState *pstate)
4362 : {
1668 tgl 4363 ECB : /*
4364 : * Sort the ready_list so that we'll tackle larger jobs first.
4365 : */
1668 tgl 4366 CBC 68 : ready_list_sort(ready_list);
4367 :
4368 : /*
4993 tgl 4369 ECB : * Search the ready_list until we find a suitable item.
4370 : */
1668 tgl 4371 CBC 70 : for (int i = ready_list->first_te; i <= ready_list->last_te; i++)
4372 : {
1668 tgl 4373 GIC 48 : TocEntry *te = ready_list->tes[i];
5050 bruce 4374 48 : bool conflicts = false;
4375 :
4376 : /*
4377 : * Check to see if the item would need exclusive lock on something
4378 : * that a currently running item also needs lock on, or vice versa. If
4379 : * so, we don't want to schedule them together.
4380 : */
1668 tgl 4381 186 : for (int k = 0; k < pstate->numWorkers; k++)
5179 andrew 4382 ECB : {
1668 tgl 4383 GIC 140 : TocEntry *running_te = pstate->te[k];
4384 :
2385 4385 140 : if (running_te == NULL)
5179 andrew 4386 62 : continue;
5110 andrew 4387 CBC 154 : if (has_lock_conflicts(te, running_te) ||
5110 andrew 4388 GIC 76 : has_lock_conflicts(running_te, te))
5179 andrew 4389 ECB : {
5110 andrew 4390 GIC 2 : conflicts = true;
4391 2 : break;
5179 andrew 4392 ECB : }
5179 andrew 4393 EUB : }
5179 andrew 4394 ECB :
5179 andrew 4395 GIC 48 : if (conflicts)
5179 andrew 4396 GBC 2 : continue;
5179 andrew 4397 EUB :
4398 : /* passed all tests, so this item can run */
1668 tgl 4399 CBC 46 : ready_list_remove(ready_list, i);
5179 andrew 4400 GBC 46 : return te;
5179 andrew 4401 ECB : }
5179 andrew 4402 EUB :
1469 peter 4403 GIC 22 : pg_log_debug("no item ready");
5179 andrew 4404 22 : return NULL;
5179 andrew 4405 ECB : }
4406 :
4407 :
4408 : /*
4409 : * Restore a single TOC item in parallel with others
4410 : *
4411 : * this is run in the worker, i.e. in a thread (Windows) or a separate process
4412 : * (everything else). A worker process executes several such work items during
4413 : * a parallel backup or restore. Once we terminate here and report back that
4414 : * our work is finished, the leader process will assign us a new work item.
4415 : */
4416 : int
2385 tgl 4417 GIC 46 : parallel_restore(ArchiveHandle *AH, TocEntry *te)
4418 : {
4419 : int status;
4420 :
3668 andrew 4421 46 : Assert(AH->connection != NULL);
4422 :
2503 tgl 4423 ECB : /* Count only errors associated with this TOC entry */
3668 andrew 4424 GIC 46 : AH->public.n_errors = 0;
4425 :
4426 : /* Restore the TOC item */
2643 tgl 4427 46 : status = restore_toc_entry(AH, te, true);
4428 :
3668 andrew 4429 46 : return status;
4430 : }
4431 :
5179 andrew 4432 ECB :
4433 : /*
1029 andres 4434 : * Callback function that's invoked in the leader process after a step has
2385 tgl 4435 : * been parallel restored.
5179 andrew 4436 : *
2385 tgl 4437 : * Update status and reduce the dependency count of any dependent items.
5179 andrew 4438 : */
4439 : static void
2385 tgl 4440 GIC 46 : mark_restore_job_done(ArchiveHandle *AH,
4441 : TocEntry *te,
4442 : int status,
4443 : void *callback_data)
4444 : {
1668 4445 46 : ParallelReadyList *ready_list = (ParallelReadyList *) callback_data;
5179 andrew 4446 ECB :
1469 peter 4447 GIC 46 : pg_log_info("finished item %d %s %s",
4448 : te->dumpId, te->desc, te->tag);
4449 :
5179 andrew 4450 46 : if (status == WORKER_CREATE_DONE)
5179 andrew 4451 UIC 0 : mark_create_done(AH, te);
5179 andrew 4452 GIC 46 : else if (status == WORKER_INHIBIT_DATA)
5179 andrew 4453 ECB : {
5179 andrew 4454 UIC 0 : inhibit_data_for_failed_table(AH, te);
5179 andrew 4455 UBC 0 : AH->public.n_errors++;
4456 : }
5179 andrew 4457 GBC 46 : else if (status == WORKER_IGNORED_ERRORS)
5179 andrew 4458 UIC 0 : AH->public.n_errors++;
5179 andrew 4459 GIC 46 : else if (status != 0)
366 tgl 4460 UIC 0 : pg_fatal("worker process failed: exit code %d",
366 tgl 4461 EUB : status);
4462 :
4993 tgl 4463 GBC 46 : reduce_dependencies(AH, te, ready_list);
5179 andrew 4464 GIC 46 : }
5179 andrew 4465 EUB :
4466 :
4467 : /*
4468 : * Process the dependency information into a form useful for parallel restore.
4469 : *
4470 : * This function takes care of fixing up some missing or badly designed
4471 : * dependencies, and then prepares subsidiary data structures that will be
4504 tgl 4472 : * used in the main parallel-restore logic, including:
4473 : * 1. We build the revDeps[] arrays of incoming dependency dumpIds.
4474 : * 2. We set up depCount fields that are the number of as-yet-unprocessed
4475 : * dependencies for each TOC entry.
4476 : *
4477 : * We also identify locking dependencies so that we can avoid trying to
4478 : * schedule conflicting items at the same time.
4479 : */
4480 : static void
5179 andrew 4481 GIC 4 : fix_dependencies(ArchiveHandle *AH)
4482 : {
4483 : TocEntry *te;
4484 : int i;
4485 :
4486 : /*
4487 : * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC
3968 tgl 4488 ECB : * items are marked as not being in any parallel-processing list.
4489 : */
5179 andrew 4490 CBC 100 : for (te = AH->toc->next; te != AH->toc; te = te->next)
4491 : {
4492 96 : te->depCount = te->nDeps;
4504 tgl 4493 GIC 96 : te->revDeps = NULL;
4504 tgl 4494 CBC 96 : te->nRevDeps = 0;
1668 4495 96 : te->pending_prev = NULL;
1668 tgl 4496 GIC 96 : te->pending_next = NULL;
5179 andrew 4497 EUB : }
4498 :
4499 : /*
4500 : * POST_DATA items that are shown as depending on a table need to be
4501 : * re-pointed to depend on that table's data, instead. This ensures they
4502 : * won't get scheduled until the data has been loaded.
4503 : */
3968 tgl 4504 GIC 4 : repoint_table_dependencies(AH);
5179 andrew 4505 ECB :
4506 : /*
5050 bruce 4507 : * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB
4508 : * COMMENTS to BLOBS. Cope. (We assume there's only one BLOBS and only
4509 : * one BLOB COMMENTS in such files.)
4510 : */
5179 andrew 4511 GIC 4 : if (AH->version < K_VERS_1_11)
4512 : {
5179 andrew 4513 UIC 0 : for (te = AH->toc->next; te != AH->toc; te = te->next)
4514 : {
4515 0 : if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0)
5179 andrew 4516 ECB : {
4517 : TocEntry *te2;
4518 :
5179 andrew 4519 UIC 0 : for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next)
5179 andrew 4520 ECB : {
5179 andrew 4521 UIC 0 : if (strcmp(te2->desc, "BLOBS") == 0)
5179 andrew 4522 ECB : {
4153 bruce 4523 UIC 0 : te->dependencies = (DumpId *) pg_malloc(sizeof(DumpId));
5179 andrew 4524 LBC 0 : te->dependencies[0] = te2->dumpId;
5179 andrew 4525 UIC 0 : te->nDeps++;
5179 andrew 4526 LBC 0 : te->depCount++;
5179 andrew 4527 UIC 0 : break;
4528 : }
4529 : }
4530 0 : break;
4531 : }
4532 : }
4533 : }
5179 andrew 4534 ECB :
4535 : /*
4504 tgl 4536 : * At this point we start to build the revDeps reverse-dependency arrays,
4537 : * so all changes of dependencies must be complete.
4538 : */
4539 :
4540 : /*
4541 : * Count the incoming dependencies for each item. Also, it is possible
4542 : * that the dependencies list items that are not in the archive at all
4543 : * (that should not happen in 9.2 and later, but is highly likely in older
4544 : * archives). Subtract such items from the depCounts.
4545 : */
5179 andrew 4546 GIC 100 : for (te = AH->toc->next; te != AH->toc; te = te->next)
4547 : {
4548 288 : for (i = 0; i < te->nDeps; i++)
4549 : {
4828 tgl 4550 192 : DumpId depid = te->dependencies[i];
4551 :
3968 4552 192 : if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
3968 tgl 4553 CBC 192 : AH->tocsByDumpId[depid]->nRevDeps++;
4554 : else
5179 andrew 4555 UIC 0 : te->depCount--;
4556 : }
4557 : }
4558 :
4504 tgl 4559 ECB : /*
4560 : * Allocate space for revDeps[] arrays, and reset nRevDeps so we can use
4382 bruce 4561 : * it as a counter below.
4504 tgl 4562 : */
4504 tgl 4563 CBC 100 : for (te = AH->toc->next; te != AH->toc; te = te->next)
4564 : {
4565 96 : if (te->nRevDeps > 0)
4153 bruce 4566 52 : te->revDeps = (DumpId *) pg_malloc(te->nRevDeps * sizeof(DumpId));
4504 tgl 4567 96 : te->nRevDeps = 0;
4568 : }
4504 tgl 4569 ECB :
4570 : /*
4571 : * Build the revDeps[] arrays of incoming-dependency dumpIds. This had
4382 bruce 4572 : * better agree with the loops above.
4504 tgl 4573 : */
4504 tgl 4574 CBC 100 : for (te = AH->toc->next; te != AH->toc; te = te->next)
4575 : {
4504 tgl 4576 GIC 288 : for (i = 0; i < te->nDeps; i++)
4577 : {
4578 192 : DumpId depid = te->dependencies[i];
4504 tgl 4579 ECB :
3968 tgl 4580 GIC 192 : if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4581 : {
4582 192 : TocEntry *otherte = AH->tocsByDumpId[depid];
4583 :
4504 4584 192 : otherte->revDeps[otherte->nRevDeps++] = te->dumpId;
4585 : }
4586 : }
4504 tgl 4587 ECB : }
4588 :
4589 : /*
4590 : * Lastly, work out the locking dependencies.
4591 : */
5179 andrew 4592 GIC 100 : for (te = AH->toc->next; te != AH->toc; te = te->next)
4593 : {
4594 96 : te->lockDeps = NULL;
4595 96 : te->nLockDeps = 0;
3968 tgl 4596 96 : identify_locking_dependencies(AH, te);
5179 andrew 4597 ECB : }
5179 andrew 4598 CBC 4 : }
4599 :
4600 : /*
3968 tgl 4601 ECB : * Change dependencies on table items to depend on table data items instead,
5179 andrew 4602 EUB : * but only in POST_DATA items.
4603 : *
4604 : * Also, for any item having such dependency(s), set its dataLength to the
4605 : * largest dataLength of the table data items it depends on. This ensures
4606 : * that parallel restore will prioritize larger jobs (index builds, FK
4607 : * constraint checks, etc) over smaller ones, avoiding situations where we
4608 : * end a restore with only one active job working on a large table.
4609 : */
5179 andrew 4610 ECB : static void
3968 tgl 4611 GBC 4 : repoint_table_dependencies(ArchiveHandle *AH)
4612 : {
4613 : TocEntry *te;
4614 : int i;
4615 : DumpId olddep;
4616 :
5179 andrew 4617 GIC 100 : for (te = AH->toc->next; te != AH->toc; te = te->next)
4618 : {
4619 96 : if (te->section != SECTION_POST_DATA)
4620 66 : continue;
4621 160 : for (i = 0; i < te->nDeps; i++)
4622 : {
3968 tgl 4623 CBC 130 : olddep = te->dependencies[i];
4624 130 : if (olddep <= AH->maxDumpId &&
4625 130 : AH->tableDataId[olddep] != 0)
4626 : {
1668 4627 62 : DumpId tabledataid = AH->tableDataId[olddep];
1668 tgl 4628 GIC 62 : TocEntry *tabledatate = AH->tocsByDumpId[tabledataid];
1668 tgl 4629 ECB :
1668 tgl 4630 CBC 62 : te->dependencies[i] = tabledataid;
4631 62 : te->dataLength = Max(te->dataLength, tabledatate->dataLength);
1469 peter 4632 62 : pg_log_debug("transferring dependency %d -> %d to %d",
4633 : te->dumpId, olddep, tabledataid);
4634 : }
5179 andrew 4635 ECB : }
4636 : }
5179 andrew 4637 GBC 4 : }
5179 andrew 4638 EUB :
4639 : /*
4640 : * Identify which objects we'll need exclusive lock on in order to restore
5179 andrew 4641 ECB : * the given TOC entry (*other* than the one identified by the TOC entry
4642 : * itself). Record their dump IDs in the entry's lockDeps[] array.
4643 : */
4644 : static void
3968 tgl 4645 GIC 96 : identify_locking_dependencies(ArchiveHandle *AH, TocEntry *te)
4646 : {
4647 : DumpId *lockids;
4648 : int nlockids;
4649 : int i;
4650 :
1685 tgl 4651 ECB : /*
4652 : * We only care about this for POST_DATA items. PRE_DATA items are not
4653 : * run in parallel, and DATA items are all independent by assumption.
4654 : */
1685 tgl 4655 GIC 96 : if (te->section != SECTION_POST_DATA)
1685 tgl 4656 CBC 66 : return;
4657 :
5179 andrew 4658 ECB : /* Quick exit if no dependencies at all */
5179 andrew 4659 GIC 30 : if (te->nDeps == 0)
5179 andrew 4660 LBC 0 : return;
4661 :
1685 tgl 4662 ECB : /*
4663 : * Most POST_DATA items are ALTER TABLEs or some moral equivalent of that,
4664 : * and hence require exclusive lock. However, we know that CREATE INDEX
4665 : * does not. (Maybe someday index-creating CONSTRAINTs will fall in that
4666 : * category too ... but today is not that day.)
4667 : */
1685 tgl 4668 GIC 30 : if (strcmp(te->desc, "INDEX") == 0)
5179 andrew 4669 UIC 0 : return;
4670 :
4671 : /*
4672 : * We assume the entry requires exclusive lock on each TABLE or TABLE DATA
3117 rhaas 4673 ECB : * item listed among its dependencies. Originally all of these would have
4674 : * been TABLE items, but repoint_table_dependencies would have repointed
4675 : * them to the TABLE DATA items if those are present (which they might not
4676 : * be, eg in a schema-only dump). Note that all of the entries we are
4677 : * processing here are POST_DATA; otherwise there might be a significant
4678 : * difference between a dependency on a table and a dependency on its
4679 : * data, so that closer analysis would be needed here.
4680 : */
4153 bruce 4681 CBC 30 : lockids = (DumpId *) pg_malloc(te->nDeps * sizeof(DumpId));
5179 andrew 4682 GIC 30 : nlockids = 0;
4683 160 : for (i = 0; i < te->nDeps; i++)
5179 andrew 4684 ECB : {
5050 bruce 4685 GIC 130 : DumpId depid = te->dependencies[i];
4686 :
3968 tgl 4687 130 : if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL &&
3117 rhaas 4688 130 : ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) ||
3096 tgl 4689 68 : strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0))
5179 andrew 4690 82 : lockids[nlockids++] = depid;
5179 andrew 4691 ECB : }
4692 :
5179 andrew 4693 CBC 30 : if (nlockids == 0)
4694 : {
5179 andrew 4695 LBC 0 : free(lockids);
5179 andrew 4696 UIC 0 : return;
5179 andrew 4697 ECB : }
4698 :
4149 tgl 4699 CBC 30 : te->lockDeps = pg_realloc(lockids, nlockids * sizeof(DumpId));
5179 andrew 4700 GIC 30 : te->nLockDeps = nlockids;
4701 : }
4702 :
4703 : /*
4704 : * Remove the specified TOC entry from the depCounts of items that depend on
4705 : * it, thereby possibly making them ready-to-run. Any pending item that
2059 tgl 4706 EUB : * becomes ready should be moved to the ready_list, if that's provided.
4707 : */
5179 andrew 4708 : static void
1668 tgl 4709 GIC 96 : reduce_dependencies(ArchiveHandle *AH, TocEntry *te,
4710 : ParallelReadyList *ready_list)
5179 andrew 4711 EUB : {
4712 : int i;
4713 :
1469 peter 4714 GIC 96 : pg_log_debug("reducing dependencies for %d", te->dumpId);
5179 andrew 4715 EUB :
4504 tgl 4716 GIC 288 : for (i = 0; i < te->nRevDeps; i++)
5179 andrew 4717 EUB : {
3968 tgl 4718 GIC 192 : TocEntry *otherte = AH->tocsByDumpId[te->revDeps[i]];
4719 :
2075 4720 192 : Assert(otherte->depCount > 0);
4504 4721 192 : otherte->depCount--;
4722 :
4723 : /*
4724 : * It's ready if it has no remaining dependencies, and it belongs in
4725 : * the current restore pass, and it is currently a member of the
2059 tgl 4726 ECB : * pending list (that check is needed to prevent double restore in
4727 : * some cases where a list-file forces out-of-order restoring).
4728 : * However, if ready_list == NULL then caller doesn't want any list
4729 : * memberships changed.
4730 : */
2075 tgl 4731 CBC 192 : if (otherte->depCount == 0 &&
4732 74 : _tocEntryRestorePass(otherte) == AH->restorePass &&
1668 tgl 4733 GIC 74 : otherte->pending_prev != NULL &&
4734 : ready_list != NULL)
5179 andrew 4735 ECB : {
4736 : /* Remove it from pending list ... */
1668 tgl 4737 GIC 26 : pending_list_remove(otherte);
4504 tgl 4738 ECB : /* ... and add to ready_list */
1668 tgl 4739 CBC 26 : ready_list_insert(ready_list, otherte);
5179 andrew 4740 ECB : }
4741 : }
5179 andrew 4742 CBC 96 : }
5179 andrew 4743 ECB :
4744 : /*
4745 : * Set the created flag on the DATA member corresponding to the given
4746 : * TABLE member
5179 andrew 4747 EUB : */
4748 : static void
5179 andrew 4749 GIC 4036 : mark_create_done(ArchiveHandle *AH, TocEntry *te)
5179 andrew 4750 ECB : {
3968 tgl 4751 GIC 4036 : if (AH->tableDataId[te->dumpId] != 0)
4752 : {
4753 2976 : TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4754 :
4755 2976 : ted->created = true;
5179 andrew 4756 ECB : }
5179 andrew 4757 GIC 4036 : }
4758 :
5179 andrew 4759 ECB : /*
4760 : * Mark the DATA member corresponding to the given TABLE member
4761 : * as not wanted
4762 : */
4763 : static void
5179 andrew 4764 LBC 0 : inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te)
4765 : {
1469 peter 4766 0 : pg_log_info("table \"%s\" could not be created, will not restore its data",
1418 tgl 4767 ECB : te->tag);
4768 :
3968 tgl 4769 UIC 0 : if (AH->tableDataId[te->dumpId] != 0)
4770 : {
3967 4771 0 : TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4772 :
4773 0 : ted->reqs = 0;
4774 : }
5179 andrew 4775 0 : }
5179 andrew 4776 ECB :
4777 : /*
4778 : * Clone and de-clone routines used in parallel restoration.
4779 : *
4780 : * Enough of the structure is cloned to ensure that there is no
4781 : * conflict between different threads each with their own clone.
4782 : */
4783 : ArchiveHandle *
5179 andrew 4784 GIC 28 : CloneArchive(ArchiveHandle *AH)
5179 andrew 4785 ECB : {
4786 : ArchiveHandle *clone;
4787 :
4788 : /* Make a "flat" copy */
4153 bruce 4789 CBC 28 : clone = (ArchiveHandle *) pg_malloc(sizeof(ArchiveHandle));
5179 andrew 4790 28 : memcpy(clone, AH, sizeof(ArchiveHandle));
5179 andrew 4791 ECB :
4111 tgl 4792 : /* Handle format-independent fields */
4111 tgl 4793 CBC 28 : memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse));
4794 :
5179 andrew 4795 ECB : /* The clone will have its own connection, so disregard connection state */
5179 andrew 4796 CBC 28 : clone->connection = NULL;
2502 tgl 4797 GIC 28 : clone->connCancel = NULL;
5179 andrew 4798 28 : clone->currUser = NULL;
4799 28 : clone->currSchema = NULL;
447 michael 4800 28 : clone->currTableAm = NULL;
5179 andrew 4801 28 : clone->currTablespace = NULL;
4802 :
4803 : /* savedPassword must be local in case we change it while connecting */
4804 28 : if (clone->savedPassword)
4153 bruce 4805 UIC 0 : clone->savedPassword = pg_strdup(clone->savedPassword);
4806 :
4807 : /* clone has its own error count, too */
5179 andrew 4808 GIC 28 : clone->public.n_errors = 0;
4809 :
4810 : /*
4811 : * Connect our new clone object to the database, using the same connection
4812 : * parameters used for the original connection.
4813 : */
927 tgl 4814 28 : ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true);
4815 :
4816 : /* re-establish fixed state */
4817 28 : if (AH->mode == archModeRead)
2503 4818 10 : _doSetFixedOutputState(clone);
4819 : /* in write case, setupDumpWorker will fix up connection state */
4820 :
4821 : /* Let the format-specific code have a chance too */
2040 peter_e 4822 28 : clone->ClonePtr(clone);
4823 :
3668 andrew 4824 28 : Assert(clone->connection != NULL);
5179 4825 28 : return clone;
4826 : }
4827 :
4828 : /*
4829 : * Release clone-local storage.
4830 : *
4831 : * Note: we assume any clone-local connection was already closed.
4832 : */
4833 : void
4834 28 : DeCloneArchive(ArchiveHandle *AH)
4835 : {
4836 : /* Should not have an open database connection */
2502 tgl 4837 28 : Assert(AH->connection == NULL);
4838 :
4839 : /* Clear format-specific state */
2040 peter_e 4840 28 : AH->DeClonePtr(AH);
4841 :
4842 : /* Clear state allocated by CloneArchive */
4111 tgl 4843 28 : if (AH->sqlparse.curCmd)
4844 3 : destroyPQExpBuffer(AH->sqlparse.curCmd);
4845 :
4846 : /* Clear any connection-local state */
297 peter 4847 GNC 28 : free(AH->currUser);
4848 28 : free(AH->currSchema);
4849 28 : free(AH->currTablespace);
4850 28 : free(AH->currTableAm);
4851 28 : free(AH->savedPassword);
4852 :
5179 andrew 4853 GIC 28 : free(AH);
4854 28 : }
|