PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_backup_archiver.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "catalog/pg_class_d.h"
#include "catalog/pg_largeobject_metadata_d.h"
#include "catalog/pg_shdepend_d.h"
#include "common/string.h"
#include "compress_io.h"
#include "dumputils.h"
#include "fe_utils/string_utils.h"
#include "lib/binaryheap.h"
#include "lib/stringinfo.h"
#include "libpq/libpq-fs.h"
#include "parallel.h"
#include "pg_backup_archiver.h"
#include "pg_backup_db.h"
#include "pg_backup_utils.h"
#include "pgtar.h"
Include dependency graph for pg_backup_archiver.c:

Go to the source code of this file.

Macros

#define TEXT_DUMP_HEADER   "--\n-- PostgreSQL database dump\n--\n\n"
 
#define TEXT_DUMPALL_HEADER   "--\n-- PostgreSQL database cluster dump\n--\n\n"
 
#define TOC_PREFIX_NONE   ""
 
#define TOC_PREFIX_DATA   "Data for "
 
#define TOC_PREFIX_STATS   "Statistics for "
 

Functions

static ArchiveHandle_allocAH (const char *FileSpec, const ArchiveFormat fmt, const pg_compress_specification compression_spec, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupWorkerPtr, DataDirSyncMethod sync_method)
 
static void _getObjectDescription (PQExpBuffer buf, const TocEntry *te)
 
static void _printTocEntry (ArchiveHandle *AH, TocEntry *te, const char *pfx)
 
static void _doSetFixedOutputState (ArchiveHandle *AH)
 
static void _doSetSessionAuth (ArchiveHandle *AH, const char *user)
 
static void _reconnectToDB (ArchiveHandle *AH, const char *dbname)
 
static void _becomeUser (ArchiveHandle *AH, const char *user)
 
static void _becomeOwner (ArchiveHandle *AH, TocEntry *te)
 
static void _selectOutputSchema (ArchiveHandle *AH, const char *schemaName)
 
static void _selectTablespace (ArchiveHandle *AH, const char *tablespace)
 
static void _selectTableAccessMethod (ArchiveHandle *AH, const char *tableam)
 
static void _printTableAccessMethodNoStorage (ArchiveHandle *AH, TocEntry *te)
 
static void processEncodingEntry (ArchiveHandle *AH, TocEntry *te)
 
static void processStdStringsEntry (ArchiveHandle *AH, TocEntry *te)
 
static void processSearchPathEntry (ArchiveHandle *AH, TocEntry *te)
 
static int _tocEntryRequired (TocEntry *te, teSection curSection, ArchiveHandle *AH)
 
static RestorePass _tocEntryRestorePass (TocEntry *te)
 
static bool _tocEntryIsACL (TocEntry *te)
 
static void _disableTriggersIfNecessary (ArchiveHandle *AH, TocEntry *te)
 
static void _enableTriggersIfNecessary (ArchiveHandle *AH, TocEntry *te)
 
static bool is_load_via_partition_root (TocEntry *te)
 
static void buildTocEntryArrays (ArchiveHandle *AH)
 
static void _moveBefore (TocEntry *pos, TocEntry *te)
 
static int _discoverArchiveFormat (ArchiveHandle *AH)
 
static int RestoringToDB (ArchiveHandle *AH)
 
static void dump_lo_buf (ArchiveHandle *AH)
 
static void dumpTimestamp (ArchiveHandle *AH, const char *msg, time_t tim)
 
static void SetOutput (ArchiveHandle *AH, const char *filename, const pg_compress_specification compression_spec)
 
static CompressFileHandleSaveOutput (ArchiveHandle *AH)
 
static void RestoreOutput (ArchiveHandle *AH, CompressFileHandle *savedOutput)
 
static int restore_toc_entry (ArchiveHandle *AH, TocEntry *te, bool is_parallel)
 
static void restore_toc_entries_prefork (ArchiveHandle *AH, TocEntry *pending_list)
 
static void restore_toc_entries_parallel (ArchiveHandle *AH, ParallelState *pstate, TocEntry *pending_list)
 
static void restore_toc_entries_postfork (ArchiveHandle *AH, TocEntry *pending_list)
 
static void pending_list_header_init (TocEntry *l)
 
static void pending_list_append (TocEntry *l, TocEntry *te)
 
static void pending_list_remove (TocEntry *te)
 
static int TocEntrySizeCompareQsort (const void *p1, const void *p2)
 
static int TocEntrySizeCompareBinaryheap (void *p1, void *p2, void *arg)
 
static void move_to_ready_heap (TocEntry *pending_list, binaryheap *ready_heap, RestorePass pass)
 
static TocEntrypop_next_work_item (binaryheap *ready_heap, ParallelState *pstate)
 
static void mark_dump_job_done (ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
 
static void mark_restore_job_done (ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
 
static void fix_dependencies (ArchiveHandle *AH)
 
static bool has_lock_conflicts (TocEntry *te1, TocEntry *te2)
 
static void repoint_table_dependencies (ArchiveHandle *AH)
 
static void identify_locking_dependencies (ArchiveHandle *AH, TocEntry *te)
 
static void reduce_dependencies (ArchiveHandle *AH, TocEntry *te, binaryheap *ready_heap)
 
static void mark_create_done (ArchiveHandle *AH, TocEntry *te)
 
static void inhibit_data_for_failed_table (ArchiveHandle *AH, TocEntry *te)
 
static void StrictNamesCheck (RestoreOptions *ropt)
 
DumpOptionsNewDumpOptions (void)
 
void InitDumpOptions (DumpOptions *opts)
 
DumpOptionsdumpOptionsFromRestoreOptions (RestoreOptions *ropt)
 
static void setupRestoreWorker (Archive *AHX)
 
ArchiveCreateArchive (const char *FileSpec, const ArchiveFormat fmt, const pg_compress_specification compression_spec, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupDumpWorker, DataDirSyncMethod sync_method)
 
ArchiveOpenArchive (const char *FileSpec, const ArchiveFormat fmt)
 
void CloseArchive (Archive *AHX)
 
void SetArchiveOptions (Archive *AH, DumpOptions *dopt, RestoreOptions *ropt)
 
void ProcessArchiveRestoreOptions (Archive *AHX)
 
void RestoreArchive (Archive *AHX)
 
RestoreOptionsNewRestoreOptions (void)
 
void WriteData (Archive *AHX, const void *data, size_t dLen)
 
TocEntryArchiveEntry (Archive *AHX, CatalogId catalogId, DumpId dumpId, ArchiveOpts *opts)
 
void PrintTOCSummary (Archive *AHX)
 
int StartLO (Archive *AHX, Oid oid)
 
int EndLO (Archive *AHX, Oid oid)
 
void StartRestoreLOs (ArchiveHandle *AH)
 
void EndRestoreLOs (ArchiveHandle *AH)
 
void StartRestoreLO (ArchiveHandle *AH, Oid oid, bool drop)
 
void EndRestoreLO (ArchiveHandle *AH, Oid oid)
 
void SortTocFromFile (Archive *AHX)
 
void archputs (const char *s, Archive *AH)
 
int archprintf (Archive *AH, const char *fmt,...)
 
int ahprintf (ArchiveHandle *AH, const char *fmt,...)
 
void ahwrite (const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
 
void warn_or_exit_horribly (ArchiveHandle *AH, const char *fmt,...)
 
TocEntrygetTocEntryByDumpId (ArchiveHandle *AH, DumpId id)
 
int TocIDRequired (ArchiveHandle *AH, DumpId id)
 
size_t WriteOffset (ArchiveHandle *AH, pgoff_t o, int wasSet)
 
int ReadOffset (ArchiveHandle *AH, pgoff_t *o)
 
size_t WriteInt (ArchiveHandle *AH, int i)
 
int ReadInt (ArchiveHandle *AH)
 
size_t WriteStr (ArchiveHandle *AH, const char *c)
 
charReadStr (ArchiveHandle *AH)
 
static bool _fileExistsInDirectory (const char *dir, const char *filename)
 
void WriteDataChunks (ArchiveHandle *AH, ParallelState *pstate)
 
void WriteDataChunksForTocEntry (ArchiveHandle *AH, TocEntry *te)
 
void WriteToc (ArchiveHandle *AH)
 
void ReadToc (ArchiveHandle *AH)
 
void WriteHead (ArchiveHandle *AH)
 
void ReadHead (ArchiveHandle *AH)
 
bool checkSeek (FILE *fp)
 
int parallel_restore (ArchiveHandle *AH, TocEntry *te)
 
ArchiveHandleCloneArchive (ArchiveHandle *AH)
 
void DeCloneArchive (ArchiveHandle *AH)
 

Macro Definition Documentation

◆ TEXT_DUMP_HEADER

#define TEXT_DUMP_HEADER   "--\n-- PostgreSQL database dump\n--\n\n"

Definition at line 49 of file pg_backup_archiver.c.

◆ TEXT_DUMPALL_HEADER

#define TEXT_DUMPALL_HEADER   "--\n-- PostgreSQL database cluster dump\n--\n\n"

Definition at line 50 of file pg_backup_archiver.c.

◆ TOC_PREFIX_DATA

#define TOC_PREFIX_DATA   "Data for "

Definition at line 53 of file pg_backup_archiver.c.

◆ TOC_PREFIX_NONE

#define TOC_PREFIX_NONE   ""

Definition at line 52 of file pg_backup_archiver.c.

◆ TOC_PREFIX_STATS

#define TOC_PREFIX_STATS   "Statistics for "

Definition at line 54 of file pg_backup_archiver.c.

Function Documentation

◆ _allocAH()

static ArchiveHandle * _allocAH ( const char FileSpec,
const ArchiveFormat  fmt,
const pg_compress_specification  compression_spec,
bool  dosync,
ArchiveMode  mode,
SetupWorkerPtrType  setupWorkerPtr,
DataDirSyncMethod  sync_method 
)
static

Definition at line 2376 of file pg_backup_archiver.c.

2380{
2381 ArchiveHandle *AH;
2384
2385 pg_log_debug("allocating AH for %s, format %d",
2386 FileSpec ? FileSpec : "(stdio)", fmt);
2387
2389
2390 AH->version = K_VERS_SELF;
2391
2392 /* initialize for backwards compatible string processing */
2393 AH->public.encoding = 0; /* PG_SQL_ASCII */
2394 AH->public.std_strings = false;
2395
2396 /* sql error handling */
2397 AH->public.exit_on_error = true;
2398 AH->public.n_errors = 0;
2399
2401
2402 AH->createDate = time(NULL);
2403
2404 AH->intSize = sizeof(int);
2405 AH->offSize = sizeof(pgoff_t);
2406 if (FileSpec)
2407 {
2408 AH->fSpec = pg_strdup(FileSpec);
2409
2410 /*
2411 * Not used; maybe later....
2412 *
2413 * AH->workDir = pg_strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
2414 * i--) if (AH->workDir[i-1] == '/')
2415 */
2416 }
2417 else
2418 AH->fSpec = NULL;
2419
2420 AH->currUser = NULL; /* unknown */
2421 AH->currSchema = NULL; /* ditto */
2422 AH->currTablespace = NULL; /* ditto */
2423 AH->currTableAm = NULL; /* ditto */
2424
2426
2427 AH->toc->next = AH->toc;
2428 AH->toc->prev = AH->toc;
2429
2430 AH->mode = mode;
2431 AH->compression_spec = compression_spec;
2432 AH->dosync = dosync;
2434
2435 memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse));
2436
2437 /* Open stdout with no compression for AH output handle */
2440 if (!CFH->open_func(NULL, fileno(stdout), PG_BINARY_A, CFH))
2441 pg_fatal("could not open stdout for appending: %m");
2442 AH->OF = CFH;
2443
2444 /*
2445 * On Windows, we need to use binary mode to read/write non-text files,
2446 * which include all archive formats as well as compressed plain text.
2447 * Force stdin/stdout into binary mode if that is what we are using.
2448 */
2449#ifdef WIN32
2450 if ((fmt != archNull || compression_spec.algorithm != PG_COMPRESSION_NONE) &&
2451 (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
2452 {
2453 if (mode == archModeWrite)
2454 _setmode(fileno(stdout), O_BINARY);
2455 else
2456 _setmode(fileno(stdin), O_BINARY);
2457 }
2458#endif
2459
2461
2462 if (fmt == archUnknown)
2464 else
2465 AH->format = fmt;
2466
2467 switch (AH->format)
2468 {
2469 case archCustom:
2471 break;
2472
2473 case archNull:
2475 break;
2476
2477 case archDirectory:
2479 break;
2480
2481 case archTar:
2483 break;
2484
2485 default:
2486 pg_fatal("unrecognized file format \"%d\"", AH->format);
2487 }
2488
2489 return AH;
2490}
#define PG_BINARY_A
Definition c.h:1432
CompressFileHandle * InitCompressFileHandle(const pg_compress_specification compression_spec)
@ PG_COMPRESSION_NONE
Definition compression.h:23
char * pg_strdup(const char *in)
Definition fe_memutils.c:91
#define pg_malloc0_object(type)
Definition fe_memutils.h:61
static DataDirSyncMethod sync_method
Definition initdb.c:170
#define pg_log_debug(...)
Definition logging.h:135
@ archModeWrite
Definition pg_backup.h:51
@ archUnknown
Definition pg_backup.h:41
@ archTar
Definition pg_backup.h:43
@ archCustom
Definition pg_backup.h:42
@ archDirectory
Definition pg_backup.h:45
@ archNull
Definition pg_backup.h:44
static int _discoverArchiveFormat(ArchiveHandle *AH)
void InitArchiveFmt_Null(ArchiveHandle *AH)
#define K_VERS_SELF
void InitArchiveFmt_Custom(ArchiveHandle *AH)
void InitArchiveFmt_Tar(ArchiveHandle *AH)
void InitArchiveFmt_Directory(ArchiveHandle *AH)
#define pg_fatal(...)
static PgChecksumMode mode
static bool dosync
Definition pg_dump.c:152
off_t pgoff_t
Definition port.h:422
static int fb(int x)
bool exit_on_error
Definition pg_backup.h:252
int n_errors
Definition pg_backup.h:253
bool std_strings
Definition pg_backup.h:245
int encoding
Definition pg_backup.h:244
ArchiveFormat format
struct _tocEntry * toc
DataDirSyncMethod sync_method
pg_compress_specification compression_spec
sqlparseInfo sqlparse
SetupWorkerPtrType SetupWorkerPtr
struct _tocEntry * prev
struct _tocEntry * next
pg_compress_algorithm algorithm
Definition compression.h:34
#define O_BINARY
Definition zic.c:26

References _discoverArchiveFormat(), pg_compress_specification::algorithm, archCustom, archDirectory, _archiveHandle::archiveDumpVersion, archModeWrite, archNull, archTar, archUnknown, _archiveHandle::compression_spec, _archiveHandle::createDate, _archiveHandle::currSchema, _archiveHandle::currTableAm, _archiveHandle::currTablespace, _archiveHandle::currUser, _archiveHandle::dosync, dosync, Archive::encoding, Archive::exit_on_error, fb(), _archiveHandle::format, _archiveHandle::fSpec, InitArchiveFmt_Custom(), InitArchiveFmt_Directory(), InitArchiveFmt_Null(), InitArchiveFmt_Tar(), InitCompressFileHandle(), _archiveHandle::intSize, K_VERS_SELF, mode, _archiveHandle::mode, Archive::n_errors, _tocEntry::next, O_BINARY, _archiveHandle::OF, _archiveHandle::offSize, PG_BINARY_A, PG_COMPRESSION_NONE, pg_fatal, pg_log_debug, pg_malloc0_object, pg_strdup(), _tocEntry::prev, _archiveHandle::public, _archiveHandle::SetupWorkerPtr, _archiveHandle::sqlparse, Archive::std_strings, sync_method, _archiveHandle::sync_method, _archiveHandle::toc, and _archiveHandle::version.

Referenced by CreateArchive(), and OpenArchive().

◆ _becomeOwner()

static void _becomeOwner ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 3610 of file pg_backup_archiver.c.

3611{
3612 RestoreOptions *ropt = AH->public.ropt;
3613
3614 if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
3615 return;
3616
3617 _becomeUser(AH, te->owner);
3618}
static void _becomeUser(ArchiveHandle *AH, const char *user)
RestoreOptions * ropt
Definition pg_backup.h:230

References _becomeUser(), _restoreOptions::noOwner, _tocEntry::owner, _archiveHandle::public, Archive::ropt, and _restoreOptions::use_setsessauth.

Referenced by _printTocEntry(), restore_toc_entry(), and RestoreArchive().

◆ _becomeUser()

static void _becomeUser ( ArchiveHandle AH,
const char user 
)
static

Definition at line 3587 of file pg_backup_archiver.c.

3588{
3589 if (!user)
3590 user = ""; /* avoid null pointers */
3591
3592 if (AH->currUser && strcmp(AH->currUser, user) == 0)
3593 return; /* no need to do anything */
3594
3596
3597 /*
3598 * NOTE: currUser keeps track of what the imaginary session user in our
3599 * script is
3600 */
3601 pg_free(AH->currUser);
3602 AH->currUser = pg_strdup(user);
3603}
void pg_free(void *ptr)
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user)
static char * user
Definition pg_regress.c:121

References _doSetSessionAuth(), _archiveHandle::currUser, fb(), pg_free(), pg_strdup(), and user.

Referenced by _becomeOwner(), _disableTriggersIfNecessary(), and _enableTriggersIfNecessary().

◆ _disableTriggersIfNecessary()

static void _disableTriggersIfNecessary ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 1127 of file pg_backup_archiver.c.

1128{
1129 RestoreOptions *ropt = AH->public.ropt;
1130
1131 /* This hack is only needed in a data-only restore */
1132 if (ropt->dumpSchema || !ropt->disable_triggers)
1133 return;
1134
1135 pg_log_info("disabling triggers for %s", te->tag);
1136
1137 /*
1138 * Become superuser if possible, since they are the only ones who can
1139 * disable constraint triggers. If -S was not given, assume the initial
1140 * user identity is a superuser. (XXX would it be better to become the
1141 * table owner?)
1142 */
1143 _becomeUser(AH, ropt->superuser);
1144
1145 /*
1146 * Disable them.
1147 */
1148 ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
1149 fmtQualifiedId(te->namespace, te->tag));
1150}
#define pg_log_info(...)
Definition logging.h:126
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
const char * fmtQualifiedId(const char *schema, const char *id)

References _becomeUser(), ahprintf(), _restoreOptions::disable_triggers, _restoreOptions::dumpSchema, fmtQualifiedId(), pg_log_info, _archiveHandle::public, Archive::ropt, _restoreOptions::superuser, and _tocEntry::tag.

Referenced by restore_toc_entry().

◆ _discoverArchiveFormat()

static int _discoverArchiveFormat ( ArchiveHandle AH)
static

Definition at line 2243 of file pg_backup_archiver.c.

2244{
2245 FILE *fh;
2246 char sig[6]; /* More than enough */
2247 size_t cnt;
2248 int wantClose = 0;
2249
2250 pg_log_debug("attempting to ascertain archive format");
2251
2252 pg_free(AH->lookahead);
2253
2254 AH->readHeader = 0;
2255 AH->lookaheadSize = 512;
2256 AH->lookahead = pg_malloc0(512);
2257 AH->lookaheadLen = 0;
2258 AH->lookaheadPos = 0;
2259
2260 if (AH->fSpec)
2261 {
2262 struct stat st;
2263
2264 wantClose = 1;
2265
2266 /*
2267 * Check if the specified archive is a directory. If so, check if
2268 * there's a "toc.dat" (or "toc.dat.{gz,lz4,zst}") file in it.
2269 */
2270 if (stat(AH->fSpec, &st) == 0 && S_ISDIR(st.st_mode))
2271 {
2272 AH->format = archDirectory;
2273 if (_fileExistsInDirectory(AH->fSpec, "toc.dat"))
2274 return AH->format;
2275#ifdef HAVE_LIBZ
2276 if (_fileExistsInDirectory(AH->fSpec, "toc.dat.gz"))
2277 return AH->format;
2278#endif
2279#ifdef USE_LZ4
2280 if (_fileExistsInDirectory(AH->fSpec, "toc.dat.lz4"))
2281 return AH->format;
2282#endif
2283#ifdef USE_ZSTD
2284 if (_fileExistsInDirectory(AH->fSpec, "toc.dat.zst"))
2285 return AH->format;
2286#endif
2287 pg_fatal("directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)",
2288 AH->fSpec);
2289 fh = NULL; /* keep compiler quiet */
2290 }
2291 else
2292 {
2293 fh = fopen(AH->fSpec, PG_BINARY_R);
2294 if (!fh)
2295 pg_fatal("could not open input file \"%s\": %m", AH->fSpec);
2296 }
2297 }
2298 else
2299 {
2300 fh = stdin;
2301 if (!fh)
2302 pg_fatal("could not open input file: %m");
2303 }
2304
2305 if ((cnt = fread(sig, 1, 5, fh)) != 5)
2306 {
2307 if (ferror(fh))
2308 pg_fatal("could not read input file: %m");
2309 else
2310 pg_fatal("input file is too short (read %zu, expected 5)", cnt);
2311 }
2312
2313 /* Save it, just in case we need it later */
2314 memcpy(&AH->lookahead[0], sig, 5);
2315 AH->lookaheadLen = 5;
2316
2317 if (strncmp(sig, "PGDMP", 5) == 0)
2318 {
2319 /* It's custom format, stop here */
2320 AH->format = archCustom;
2321 AH->readHeader = 1;
2322 }
2323 else
2324 {
2325 /*
2326 * *Maybe* we have a tar archive format file or a text dump ... So,
2327 * read first 512 byte header...
2328 */
2329 cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh);
2330 /* read failure is checked below */
2331 AH->lookaheadLen += cnt;
2332
2336 {
2337 /*
2338 * looks like it's probably a text format dump. so suggest they
2339 * try psql
2340 */
2341 pg_fatal("input file appears to be a text format dump. Please use psql.");
2342 }
2343
2344 if (AH->lookaheadLen != 512)
2345 {
2346 if (feof(fh))
2347 pg_fatal("input file does not appear to be a valid archive (too short?)");
2348 else
2350 }
2351
2352 if (!isValidTarHeader(AH->lookahead))
2353 pg_fatal("input file does not appear to be a valid tar archive");
2354
2355 AH->format = archTar;
2356 }
2357
2358 /* Close the file if we opened it */
2359 if (wantClose)
2360 {
2361 if (fclose(fh) != 0)
2362 pg_fatal("could not close input file: %m");
2363 /* Forget lookahead, since we'll re-read header after re-opening */
2364 AH->readHeader = 0;
2365 AH->lookaheadLen = 0;
2366 }
2367
2368 return AH->format;
2369}
#define PG_BINARY_R
Definition c.h:1433
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
void * pg_malloc0(size_t size)
Definition fe_memutils.c:59
#define TEXT_DUMPALL_HEADER
#define TEXT_DUMP_HEADER
static bool _fileExistsInDirectory(const char *dir, const char *filename)
#define READ_ERROR_EXIT(fd)
static int sig
Definition pg_ctl.c:81
bool isValidTarHeader(const char *header)
Definition tar.c:112
#define stat
Definition win32_port.h:74
#define S_ISDIR(m)
Definition win32_port.h:332

References _fileExistsInDirectory(), archCustom, archDirectory, archTar, fb(), _archiveHandle::format, _archiveHandle::fSpec, isValidTarHeader(), _archiveHandle::lookahead, _archiveHandle::lookaheadLen, _archiveHandle::lookaheadPos, _archiveHandle::lookaheadSize, memcpy(), PG_BINARY_R, pg_fatal, pg_free(), pg_log_debug, pg_malloc0(), READ_ERROR_EXIT, _archiveHandle::readHeader, S_ISDIR, sig, stat::st_mode, stat, TEXT_DUMP_HEADER, and TEXT_DUMPALL_HEADER.

Referenced by _allocAH().

◆ _doSetFixedOutputState()

static void _doSetFixedOutputState ( ArchiveHandle AH)
static

Definition at line 3428 of file pg_backup_archiver.c.

3429{
3430 RestoreOptions *ropt = AH->public.ropt;
3431
3432 /*
3433 * Disable timeouts to allow for slow commands, idle parallel workers, etc
3434 */
3435 ahprintf(AH, "SET statement_timeout = 0;\n");
3436 ahprintf(AH, "SET lock_timeout = 0;\n");
3437 ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
3438 ahprintf(AH, "SET transaction_timeout = 0;\n");
3439
3440 /* Select the correct character set encoding */
3441 ahprintf(AH, "SET client_encoding = '%s';\n",
3443
3444 /* Select the correct string literal syntax */
3445 ahprintf(AH, "SET standard_conforming_strings = %s;\n",
3446 AH->public.std_strings ? "on" : "off");
3447
3448 /* Select the role to be used during restore */
3449 if (ropt && ropt->use_role)
3450 ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));
3451
3452 /* Select the dump-time search_path */
3453 if (AH->public.searchpath)
3454 ahprintf(AH, "%s", AH->public.searchpath);
3455
3456 /* Make sure function checking is disabled */
3457 ahprintf(AH, "SET check_function_bodies = false;\n");
3458
3459 /* Ensure that all valid XML data will be accepted */
3460 ahprintf(AH, "SET xmloption = content;\n");
3461
3462 /* Avoid annoying notices etc */
3463 ahprintf(AH, "SET client_min_messages = warning;\n");
3464
3465 /* Adjust row-security state */
3466 if (ropt && ropt->enable_row_security)
3467 ahprintf(AH, "SET row_security = on;\n");
3468 else
3469 ahprintf(AH, "SET row_security = off;\n");
3470
3471 /*
3472 * In --transaction-size mode, we should always be in a transaction when
3473 * we begin to restore objects.
3474 */
3475 if (ropt && ropt->txn_size > 0)
3476 {
3477 if (AH->connection)
3479 else
3480 ahprintf(AH, "\nBEGIN;\n");
3481 AH->txnCount = 0;
3482 }
3483
3484 ahprintf(AH, "\n");
3485}
#define pg_encoding_to_char
Definition pg_wchar.h:483
const char * fmtId(const char *rawid)
char * searchpath
Definition pg_backup.h:248
int enable_row_security
Definition pg_backup.h:159
static void StartTransaction(void)
Definition xact.c:2106

References ahprintf(), _archiveHandle::connection, _restoreOptions::enable_row_security, Archive::encoding, fmtId(), pg_encoding_to_char, _archiveHandle::public, Archive::ropt, Archive::searchpath, StartTransaction(), Archive::std_strings, _restoreOptions::txn_size, _archiveHandle::txnCount, and _restoreOptions::use_role.

Referenced by _reconnectToDB(), CloneArchive(), restore_toc_entries_postfork(), and RestoreArchive().

◆ _doSetSessionAuth()

static void _doSetSessionAuth ( ArchiveHandle AH,
const char user 
)
static

Definition at line 3493 of file pg_backup_archiver.c.

3494{
3496
3497 appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3498
3499 /*
3500 * SQL requires a string literal here. Might as well be correct.
3501 */
3502 if (user && *user)
3503 appendStringLiteralAHX(cmd, user, AH);
3504 else
3505 appendPQExpBufferStr(cmd, "DEFAULT");
3506 appendPQExpBufferChar(cmd, ';');
3507
3508 if (RestoringToDB(AH))
3509 {
3510 PGresult *res;
3511
3512 res = PQexec(AH->connection, cmd->data);
3513
3514 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3515 /* NOT warn_or_exit_horribly... use -O instead to skip this. */
3516 pg_fatal("could not set session user to \"%s\": %s",
3518
3519 PQclear(res);
3520 }
3521 else
3522 ahprintf(AH, "%s\n\n", cmd->data);
3523
3524 destroyPQExpBuffer(cmd);
3525}
char * PQerrorMessage(const PGconn *conn)
PGresult * PQexec(PGconn *conn, const char *query)
Definition fe-exec.c:2279
#define PQclear
#define PQresultStatus
@ PGRES_COMMAND_OK
Definition libpq-fe.h:131
static int RestoringToDB(ArchiveHandle *AH)
#define appendStringLiteralAHX(buf, str, AH)
PQExpBuffer createPQExpBuffer(void)
Definition pqexpbuffer.c:72
void destroyPQExpBuffer(PQExpBuffer str)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)

References ahprintf(), appendPQExpBufferChar(), appendPQExpBufferStr(), appendStringLiteralAHX, _archiveHandle::connection, createPQExpBuffer(), PQExpBufferData::data, destroyPQExpBuffer(), pg_fatal, PGRES_COMMAND_OK, PQclear, PQerrorMessage(), PQexec(), PQresultStatus, RestoringToDB(), and user.

Referenced by _becomeUser().

◆ _enableTriggersIfNecessary()

static void _enableTriggersIfNecessary ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 1153 of file pg_backup_archiver.c.

1154{
1155 RestoreOptions *ropt = AH->public.ropt;
1156
1157 /* This hack is only needed in a data-only restore */
1158 if (ropt->dumpSchema || !ropt->disable_triggers)
1159 return;
1160
1161 pg_log_info("enabling triggers for %s", te->tag);
1162
1163 /*
1164 * Become superuser if possible, since they are the only ones who can
1165 * disable constraint triggers. If -S was not given, assume the initial
1166 * user identity is a superuser. (XXX would it be better to become the
1167 * table owner?)
1168 */
1169 _becomeUser(AH, ropt->superuser);
1170
1171 /*
1172 * Enable them.
1173 */
1174 ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
1175 fmtQualifiedId(te->namespace, te->tag));
1176}

References _becomeUser(), ahprintf(), _restoreOptions::disable_triggers, _restoreOptions::dumpSchema, fmtQualifiedId(), pg_log_info, _archiveHandle::public, Archive::ropt, _restoreOptions::superuser, and _tocEntry::tag.

Referenced by restore_toc_entry().

◆ _fileExistsInDirectory()

static bool _fileExistsInDirectory ( const char dir,
const char filename 
)
static

Definition at line 2231 of file pg_backup_archiver.c.

2232{
2233 struct stat st;
2234 char buf[MAXPGPATH];
2235
2236 if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
2237 pg_fatal("directory name too long: \"%s\"", dir);
2238
2239 return (stat(buf, &st) == 0 && S_ISREG(st.st_mode));
2240}
#define MAXPGPATH
static char * filename
Definition pg_dumpall.c:120
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:261
#define S_ISREG(m)
Definition win32_port.h:335

References buf, filename, MAXPGPATH, pg_fatal, S_ISREG, snprintf, stat::st_mode, and stat.

Referenced by _discoverArchiveFormat().

◆ _getObjectDescription()

static void _getObjectDescription ( PQExpBuffer  buf,
const TocEntry te 
)
static

Definition at line 3835 of file pg_backup_archiver.c.

3836{
3837 const char *type = te->desc;
3838
3839 /* objects that don't require special decoration */
3840 if (strcmp(type, "COLLATION") == 0 ||
3841 strcmp(type, "CONVERSION") == 0 ||
3842 strcmp(type, "DOMAIN") == 0 ||
3843 strcmp(type, "FOREIGN TABLE") == 0 ||
3844 strcmp(type, "MATERIALIZED VIEW") == 0 ||
3845 strcmp(type, "PROPERTY GRAPH") == 0 ||
3846 strcmp(type, "SEQUENCE") == 0 ||
3847 strcmp(type, "STATISTICS") == 0 ||
3848 strcmp(type, "TABLE") == 0 ||
3849 strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
3850 strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 ||
3851 strcmp(type, "TYPE") == 0 ||
3852 strcmp(type, "VIEW") == 0 ||
3853 /* non-schema-specified objects */
3854 strcmp(type, "DATABASE") == 0 ||
3855 strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
3856 strcmp(type, "SCHEMA") == 0 ||
3857 strcmp(type, "EVENT TRIGGER") == 0 ||
3858 strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
3859 strcmp(type, "SERVER") == 0 ||
3860 strcmp(type, "PUBLICATION") == 0 ||
3861 strcmp(type, "SUBSCRIPTION") == 0)
3862 {
3863 appendPQExpBuffer(buf, "%s ", type);
3864 if (te->namespace && *te->namespace)
3865 appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
3867 }
3868 /* LOs just have a name, but it's numeric so must not use fmtId */
3869 else if (strcmp(type, "BLOB") == 0)
3870 {
3871 appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag);
3872 }
3873
3874 /*
3875 * These object types require additional decoration. Fortunately, the
3876 * information needed is exactly what's in the DROP command.
3877 */
3878 else if (strcmp(type, "AGGREGATE") == 0 ||
3879 strcmp(type, "FUNCTION") == 0 ||
3880 strcmp(type, "OPERATOR") == 0 ||
3881 strcmp(type, "OPERATOR CLASS") == 0 ||
3882 strcmp(type, "OPERATOR FAMILY") == 0 ||
3883 strcmp(type, "PROCEDURE") == 0)
3884 {
3885 /* Chop "DROP " off the front and make a modifiable copy */
3886 char *first = pg_strdup(te->dropStmt + 5);
3887 char *last;
3888
3889 /* point to last character in string */
3890 last = first + strlen(first) - 1;
3891
3892 /* Strip off any ';' or '\n' at the end */
3893 while (last >= first && (*last == '\n' || *last == ';'))
3894 last--;
3895 *(last + 1) = '\0';
3896
3897 appendPQExpBufferStr(buf, first);
3898
3899 pg_free(first);
3900 return;
3901 }
3902 /* these object types don't have separate owners */
3903 else if (strcmp(type, "CAST") == 0 ||
3904 strcmp(type, "CHECK CONSTRAINT") == 0 ||
3905 strcmp(type, "CONSTRAINT") == 0 ||
3906 strcmp(type, "DATABASE PROPERTIES") == 0 ||
3907 strcmp(type, "DEFAULT") == 0 ||
3908 strcmp(type, "FK CONSTRAINT") == 0 ||
3909 strcmp(type, "INDEX") == 0 ||
3910 strcmp(type, "RULE") == 0 ||
3911 strcmp(type, "TRIGGER") == 0 ||
3912 strcmp(type, "ROW SECURITY") == 0 ||
3913 strcmp(type, "POLICY") == 0 ||
3914 strcmp(type, "USER MAPPING") == 0)
3915 {
3916 /* do nothing */
3917 }
3918 else
3919 pg_fatal("don't know how to set owner for object type \"%s\"", type);
3920}
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
const char * type

References appendPQExpBuffer(), appendPQExpBufferStr(), buf, _tocEntry::desc, _tocEntry::dropStmt, fb(), fmtId(), pg_fatal, pg_free(), pg_strdup(), _tocEntry::tag, and type.

Referenced by _printTocEntry().

◆ _moveBefore()

static void _moveBefore ( TocEntry pos,
TocEntry te 
)
static

Definition at line 1969 of file pg_backup_archiver.c.

1970{
1971 /* Unlink te from list */
1972 te->prev->next = te->next;
1973 te->next->prev = te->prev;
1974
1975 /* and insert it before "pos" */
1976 te->prev = pos->prev;
1977 te->next = pos;
1978 pos->prev->next = te;
1979 pos->prev = te;
1980}

References _tocEntry::next, and _tocEntry::prev.

Referenced by SortTocFromFile().

◆ _printTableAccessMethodNoStorage()

static void _printTableAccessMethodNoStorage ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 3787 of file pg_backup_archiver.c.

3788{
3789 RestoreOptions *ropt = AH->public.ropt;
3790 const char *tableam = te->tableam;
3791 PQExpBuffer cmd;
3792
3793 /* do nothing in --no-table-access-method mode */
3794 if (ropt->noTableAm)
3795 return;
3796
3797 if (!tableam)
3798 return;
3799
3801
3802 cmd = createPQExpBuffer();
3803
3804 appendPQExpBufferStr(cmd, "ALTER TABLE ");
3805 appendPQExpBuffer(cmd, "%s ", fmtQualifiedId(te->namespace, te->tag));
3806 appendPQExpBuffer(cmd, "SET ACCESS METHOD %s;",
3807 fmtId(tableam));
3808
3809 if (RestoringToDB(AH))
3810 {
3811 PGresult *res;
3812
3813 res = PQexec(AH->connection, cmd->data);
3814
3815 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3817 "could not alter table access method: %s",
3819 PQclear(res);
3820 }
3821 else
3822 ahprintf(AH, "%s\n\n", cmd->data);
3823
3824 destroyPQExpBuffer(cmd);
3825}
#define Assert(condition)
Definition c.h:1002
void warn_or_exit_horribly(ArchiveHandle *AH, const char *fmt,...)

References ahprintf(), appendPQExpBuffer(), appendPQExpBufferStr(), Assert, _archiveHandle::connection, createPQExpBuffer(), PQExpBufferData::data, destroyPQExpBuffer(), fb(), fmtId(), fmtQualifiedId(), _restoreOptions::noTableAm, PGRES_COMMAND_OK, PQclear, PQerrorMessage(), PQexec(), PQresultStatus, _archiveHandle::public, _tocEntry::relkind, RestoringToDB(), Archive::ropt, _tocEntry::tableam, _tocEntry::tag, and warn_or_exit_horribly().

Referenced by _printTocEntry().

◆ _printTocEntry()

static void _printTocEntry ( ArchiveHandle AH,
TocEntry te,
const char pfx 
)
static

Definition at line 3930 of file pg_backup_archiver.c.

3931{
3932 RestoreOptions *ropt = AH->public.ropt;
3933
3934 /*
3935 * Select owner, schema, tablespace and default AM as necessary. The
3936 * default access method for partitioned tables is handled after
3937 * generating the object definition, as it requires an ALTER command
3938 * rather than SET.
3939 */
3940 _becomeOwner(AH, te);
3941 _selectOutputSchema(AH, te->namespace);
3945
3946 /* Emit header comment for item */
3947 if (!AH->noTocComments)
3948 {
3949 char *sanitized_name;
3950 char *sanitized_schema;
3951 char *sanitized_owner;
3952
3953 ahprintf(AH, "--\n");
3954 if (AH->public.verbose)
3955 {
3956 ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
3957 te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
3958 if (te->nDeps > 0)
3959 {
3960 int i;
3961
3962 ahprintf(AH, "-- Dependencies:");
3963 for (i = 0; i < te->nDeps; i++)
3964 ahprintf(AH, " %d", te->dependencies[i]);
3965 ahprintf(AH, "\n");
3966 }
3967 }
3968
3969 sanitized_name = sanitize_line(te->tag, false);
3970 sanitized_schema = sanitize_line(te->namespace, true);
3971 sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
3972
3973 ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
3976
3980
3981 if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace)
3982 {
3984
3986 ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
3988 }
3989 ahprintf(AH, "\n");
3990
3991 if (AH->PrintExtraTocPtr != NULL)
3992 AH->PrintExtraTocPtr(AH, te);
3993 ahprintf(AH, "--\n\n");
3994 }
3995
3996 /*
3997 * Actually print the definition. Normally we can just print the defn
3998 * string if any, but we have four special cases:
3999 *
4000 * 1. A crude hack for suppressing AUTHORIZATION clause that old pg_dump
4001 * versions put into CREATE SCHEMA. Don't mutate the variant for schema
4002 * "public" that is a comment. We have to do this when --no-owner mode is
4003 * selected. This is ugly, but I see no other good way ...
4004 *
4005 * 2. BLOB METADATA entries need special processing since their defn
4006 * strings are just lists of OIDs, not complete SQL commands.
4007 *
4008 * 3. ACL LARGE OBJECTS entries need special processing because they
4009 * contain only one copy of the ACL GRANT/REVOKE commands, which we must
4010 * apply to each large object listed in the associated BLOB METADATA.
4011 *
4012 * 4. Entries with a defnDumper need to call it to generate the
4013 * definition. This is primarily intended to provide a way to save memory
4014 * for objects that would otherwise need a lot of it (e.g., statistics
4015 * data).
4016 */
4017 if (ropt->noOwner &&
4018 strcmp(te->desc, "SCHEMA") == 0 && strncmp(te->defn, "--", 2) != 0)
4019 {
4020 ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
4021 }
4022 else if (strcmp(te->desc, "BLOB METADATA") == 0)
4023 {
4024 IssueCommandPerBlob(AH, te, "SELECT pg_catalog.lo_create('", "')");
4025 }
4026 else if (strcmp(te->desc, "ACL") == 0 &&
4027 strncmp(te->tag, "LARGE OBJECTS", 13) == 0)
4028 {
4029 IssueACLPerBlob(AH, te);
4030 }
4031 else if (te->defnLen && AH->format != archTar)
4032 {
4033 /*
4034 * If defnLen is set, the defnDumper has already been called for this
4035 * TOC entry. We don't normally expect a defnDumper to be called for
4036 * a TOC entry a second time in _printTocEntry(), but there's an
4037 * exception. The tar format first calls WriteToc(), which scans the
4038 * entire TOC, and then it later calls RestoreArchive() to generate
4039 * restore.sql, which scans the TOC again. There doesn't appear to be
4040 * a good way to prevent a second defnDumper call in this case without
4041 * storing the definition in memory, which defeats the purpose. This
4042 * second defnDumper invocation should generate the same output as the
4043 * first, but even if it doesn't, the worst-case scenario is that
4044 * restore.sql might have different statistics data than the archive.
4045 *
4046 * In all other cases, encountering a TOC entry a second time in
4047 * _printTocEntry() is unexpected, so we fail because one of our
4048 * assumptions must no longer hold true.
4049 *
4050 * XXX This is a layering violation, but the alternative is an awkward
4051 * and complicated callback infrastructure for this special case. This
4052 * might be worth revisiting in the future.
4053 */
4054 pg_fatal("unexpected TOC entry in _printTocEntry(): %d %s %s",
4055 te->dumpId, te->desc, te->tag);
4056 }
4057 else if (te->defnDumper)
4058 {
4059 char *defn = te->defnDumper((Archive *) AH, te->defnDumperArg, te);
4060
4061 te->defnLen = ahprintf(AH, "%s\n\n", defn);
4062 pg_free(defn);
4063 }
4064 else if (te->defn && strlen(te->defn) > 0)
4065 {
4066 ahprintf(AH, "%s\n\n", te->defn);
4067
4068 /*
4069 * If the defn string contains multiple SQL commands, txn_size mode
4070 * should count it as N actions not one. But rather than build a full
4071 * SQL parser, approximate this by counting semicolons. One case
4072 * where that tends to be badly fooled is function definitions, so
4073 * ignore them. (restore_toc_entry will count one action anyway.)
4074 */
4075 if (ropt->txn_size > 0 &&
4076 strcmp(te->desc, "FUNCTION") != 0 &&
4077 strcmp(te->desc, "PROCEDURE") != 0)
4078 {
4079 const char *p = te->defn;
4080 int nsemis = 0;
4081
4082 while ((p = strchr(p, ';')) != NULL)
4083 {
4084 nsemis++;
4085 p++;
4086 }
4087 if (nsemis > 1)
4088 AH->txnCount += nsemis - 1;
4089 }
4090 }
4091
4092 /*
4093 * If we aren't using SET SESSION AUTH to determine ownership, we must
4094 * instead issue an ALTER OWNER command. Schema "public" is special; when
4095 * a dump emits a comment in lieu of creating it, we use ALTER OWNER even
4096 * when using SET SESSION for all other objects. We assume that anything
4097 * without a DROP command is not a separately ownable object.
4098 */
4099 if (!ropt->noOwner &&
4100 (!ropt->use_setsessauth ||
4101 (strcmp(te->desc, "SCHEMA") == 0 &&
4102 strncmp(te->defn, "--", 2) == 0)) &&
4103 te->owner && strlen(te->owner) > 0 &&
4104 te->dropStmt && strlen(te->dropStmt) > 0)
4105 {
4106 if (strcmp(te->desc, "BLOB METADATA") == 0)
4107 {
4108 /* BLOB METADATA needs special code to handle multiple LOs */
4109 char *cmdEnd = psprintf(" OWNER TO %s", fmtId(te->owner));
4110
4111 IssueCommandPerBlob(AH, te, "ALTER LARGE OBJECT ", cmdEnd);
4112 pfree(cmdEnd);
4113 }
4114 else
4115 {
4116 /* For all other cases, we can use _getObjectDescription */
4118
4121
4122 /*
4123 * If _getObjectDescription() didn't fill the buffer, then there
4124 * is no owner.
4125 */
4126 if (temp.data[0])
4127 ahprintf(AH, "ALTER %s OWNER TO %s;\n\n",
4128 temp.data, fmtId(te->owner));
4130 }
4131 }
4132
4133 /*
4134 * Select a partitioned table's default AM, once the table definition has
4135 * been generated.
4136 */
4139
4140 /*
4141 * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
4142 * commands, so we can no longer assume we know the current auth setting.
4143 */
4144 if (_tocEntryIsACL(te))
4145 {
4146 free(AH->currUser);
4147 AH->currUser = NULL;
4148 }
4149}
char * sanitize_line(const char *str, bool want_hyphen)
Definition dumputils.c:52
return true
Definition isn.c:130
int i
Definition isn.c:77
void pfree(void *pointer)
Definition mcxt.c:1619
static void _becomeOwner(ArchiveHandle *AH, TocEntry *te)
static bool _tocEntryIsACL(TocEntry *te)
static void _getObjectDescription(PQExpBuffer buf, const TocEntry *te)
static void _selectTableAccessMethod(ArchiveHandle *AH, const char *tableam)
static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
static void _printTableAccessMethodNoStorage(ArchiveHandle *AH, TocEntry *te)
static void _selectTablespace(ArchiveHandle *AH, const char *tablespace)
void IssueACLPerBlob(ArchiveHandle *AH, TocEntry *te)
void IssueCommandPerBlob(ArchiveHandle *AH, TocEntry *te, const char *cmdBegin, const char *cmdEnd)
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
#define free(a)
int verbose
Definition pg_backup.h:232
Oid tableoid
Definition pg_backup.h:281
PrintExtraTocPtrType PrintExtraTocPtr
DefnDumperPtr defnDumper
CatalogId catalogId
const void * defnDumperArg
DumpId * dependencies

References _becomeOwner(), _getObjectDescription(), _printTableAccessMethodNoStorage(), _selectOutputSchema(), _selectTableAccessMethod(), _selectTablespace(), _tocEntryIsACL(), ahprintf(), archTar, _tocEntry::catalogId, _archiveHandle::currUser, _tocEntry::defn, _tocEntry::defnDumper, _tocEntry::defnDumperArg, _tocEntry::defnLen, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dropStmt, _tocEntry::dumpId, fb(), fmtId(), _archiveHandle::format, free, i, initPQExpBuffer(), IssueACLPerBlob(), IssueCommandPerBlob(), _tocEntry::nDeps, _restoreOptions::noOwner, _restoreOptions::noTablespace, _archiveHandle::noTocComments, CatalogId::oid, _tocEntry::owner, pfree(), pg_fatal, pg_free(), _archiveHandle::PrintExtraTocPtr, psprintf(), _archiveHandle::public, _tocEntry::relkind, Archive::ropt, sanitize_line(), _tocEntry::tableam, CatalogId::tableoid, _tocEntry::tablespace, _tocEntry::tag, termPQExpBuffer(), _restoreOptions::txn_size, _archiveHandle::txnCount, _restoreOptions::use_setsessauth, and Archive::verbose.

Referenced by restore_toc_entry().

◆ _reconnectToDB()

static void _reconnectToDB ( ArchiveHandle AH,
const char dbname 
)
static

Definition at line 3536 of file pg_backup_archiver.c.

3537{
3538 if (RestoringToDB(AH))
3540 else
3541 {
3543 RestoreOptions *ropt = AH->public.ropt;
3544
3545 /*
3546 * We must temporarily exit restricted mode for \connect, etc.
3547 * Anything added between this line and the following \restrict must
3548 * be careful to avoid any possible meta-command injection vectors.
3549 */
3550 ahprintf(AH, "\\unrestrict %s\n", ropt->restrict_key);
3551
3554 ahprintf(AH, "%s", connectbuf.data);
3556
3557 ahprintf(AH, "\\restrict %s\n\n", ropt->restrict_key);
3558 }
3559
3560 /*
3561 * NOTE: currUser keeps track of what the imaginary session user in our
3562 * script is. It's now effectively reset to the original userID.
3563 */
3564 free(AH->currUser);
3565 AH->currUser = NULL;
3566
3567 /* don't assume we still know the output schema, tablespace, etc either */
3568 free(AH->currSchema);
3569 AH->currSchema = NULL;
3570
3571 free(AH->currTableAm);
3572 AH->currTableAm = NULL;
3573
3574 free(AH->currTablespace);
3575 AH->currTablespace = NULL;
3576
3577 /* re-establish fixed state */
3579}
static void _doSetFixedOutputState(ArchiveHandle *AH)
void ReconnectToServer(ArchiveHandle *AH, const char *dbname)
char * dbname
Definition streamutil.c:49
void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname)
char * restrict_key
Definition pg_backup.h:168

References _doSetFixedOutputState(), ahprintf(), appendPsqlMetaConnect(), _archiveHandle::currSchema, _archiveHandle::currTableAm, _archiveHandle::currTablespace, _archiveHandle::currUser, dbname, fb(), free, initPQExpBuffer(), _archiveHandle::public, ReconnectToServer(), RestoringToDB(), _restoreOptions::restrict_key, Archive::ropt, and termPQExpBuffer().

Referenced by restore_toc_entry().

◆ _selectOutputSchema()

static void _selectOutputSchema ( ArchiveHandle AH,
const char schemaName 
)
static

Definition at line 3626 of file pg_backup_archiver.c.

3627{
3628 PQExpBuffer qry;
3629
3630 /*
3631 * If there was a SEARCHPATH TOC entry, we're supposed to just stay with
3632 * that search_path rather than switching to entry-specific paths.
3633 * Otherwise, it's an old archive that will not restore correctly unless
3634 * we set the search_path as it's expecting.
3635 */
3636 if (AH->public.searchpath)
3637 return;
3638
3639 if (!schemaName || *schemaName == '\0' ||
3640 (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0))
3641 return; /* no need to do anything */
3642
3643 qry = createPQExpBuffer();
3644
3645 appendPQExpBuffer(qry, "SET search_path = %s",
3646 fmtId(schemaName));
3647 if (strcmp(schemaName, "pg_catalog") != 0)
3648 appendPQExpBufferStr(qry, ", pg_catalog");
3649
3650 if (RestoringToDB(AH))
3651 {
3652 PGresult *res;
3653
3654 res = PQexec(AH->connection, qry->data);
3655
3656 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3658 "could not set \"search_path\" to \"%s\": %s",
3660
3661 PQclear(res);
3662 }
3663 else
3664 ahprintf(AH, "%s;\n\n", qry->data);
3665
3666 pg_free(AH->currSchema);
3668
3669 destroyPQExpBuffer(qry);
3670}

References ahprintf(), appendPQExpBuffer(), appendPQExpBufferStr(), _archiveHandle::connection, createPQExpBuffer(), _archiveHandle::currSchema, PQExpBufferData::data, destroyPQExpBuffer(), fb(), fmtId(), pg_free(), pg_strdup(), PGRES_COMMAND_OK, PQclear, PQerrorMessage(), PQexec(), PQresultStatus, _archiveHandle::public, RestoringToDB(), Archive::searchpath, and warn_or_exit_horribly().

Referenced by _printTocEntry(), restore_toc_entry(), and RestoreArchive().

◆ _selectTableAccessMethod()

static void _selectTableAccessMethod ( ArchiveHandle AH,
const char tableam 
)
static

Definition at line 3737 of file pg_backup_archiver.c.

3738{
3739 RestoreOptions *ropt = AH->public.ropt;
3740 PQExpBuffer cmd;
3741 const char *want,
3742 *have;
3743
3744 /* do nothing in --no-table-access-method mode */
3745 if (ropt->noTableAm)
3746 return;
3747
3748 have = AH->currTableAm;
3749 want = tableam;
3750
3751 if (!want)
3752 return;
3753
3754 if (have && strcmp(want, have) == 0)
3755 return;
3756
3757 cmd = createPQExpBuffer();
3758 appendPQExpBuffer(cmd, "SET default_table_access_method = %s;", fmtId(want));
3759
3760 if (RestoringToDB(AH))
3761 {
3762 PGresult *res;
3763
3764 res = PQexec(AH->connection, cmd->data);
3765
3766 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3768 "could not set \"default_table_access_method\": %s",
3770
3771 PQclear(res);
3772 }
3773 else
3774 ahprintf(AH, "%s\n\n", cmd->data);
3775
3776 destroyPQExpBuffer(cmd);
3777
3778 pg_free(AH->currTableAm);
3779 AH->currTableAm = pg_strdup(want);
3780}

References ahprintf(), appendPQExpBuffer(), _archiveHandle::connection, createPQExpBuffer(), _archiveHandle::currTableAm, PQExpBufferData::data, destroyPQExpBuffer(), fb(), fmtId(), _restoreOptions::noTableAm, pg_free(), pg_strdup(), PGRES_COMMAND_OK, PQclear, PQerrorMessage(), PQexec(), PQresultStatus, _archiveHandle::public, RestoringToDB(), Archive::ropt, and warn_or_exit_horribly().

Referenced by _printTocEntry().

◆ _selectTablespace()

static void _selectTablespace ( ArchiveHandle AH,
const char tablespace 
)
static

Definition at line 3677 of file pg_backup_archiver.c.

3678{
3679 RestoreOptions *ropt = AH->public.ropt;
3680 PQExpBuffer qry;
3681 const char *want,
3682 *have;
3683
3684 /* do nothing in --no-tablespaces mode */
3685 if (ropt->noTablespace)
3686 return;
3687
3688 have = AH->currTablespace;
3689 want = tablespace;
3690
3691 /* no need to do anything for non-tablespace object */
3692 if (!want)
3693 return;
3694
3695 if (have && strcmp(want, have) == 0)
3696 return; /* no need to do anything */
3697
3698 qry = createPQExpBuffer();
3699
3700 if (strcmp(want, "") == 0)
3701 {
3702 /* We want the tablespace to be the database's default */
3703 appendPQExpBufferStr(qry, "SET default_tablespace = ''");
3704 }
3705 else
3706 {
3707 /* We want an explicit tablespace */
3708 appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
3709 }
3710
3711 if (RestoringToDB(AH))
3712 {
3713 PGresult *res;
3714
3715 res = PQexec(AH->connection, qry->data);
3716
3717 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3719 "could not set \"default_tablespace\" to %s: %s",
3721
3722 PQclear(res);
3723 }
3724 else
3725 ahprintf(AH, "%s;\n\n", qry->data);
3726
3729
3730 destroyPQExpBuffer(qry);
3731}
static char * tablespace
Definition pgbench.c:217

References ahprintf(), appendPQExpBuffer(), appendPQExpBufferStr(), _archiveHandle::connection, createPQExpBuffer(), _archiveHandle::currTablespace, PQExpBufferData::data, destroyPQExpBuffer(), fb(), fmtId(), _restoreOptions::noTablespace, pg_free(), pg_strdup(), PGRES_COMMAND_OK, PQclear, PQerrorMessage(), PQexec(), PQresultStatus, _archiveHandle::public, RestoringToDB(), Archive::ropt, tablespace, and warn_or_exit_horribly().

Referenced by _printTocEntry().

◆ _tocEntryIsACL()

static bool _tocEntryIsACL ( TocEntry te)
static

Definition at line 3413 of file pg_backup_archiver.c.

3414{
3415 /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3416 if (strcmp(te->desc, "ACL") == 0 ||
3417 strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3418 strcmp(te->desc, "DEFAULT ACL") == 0)
3419 return true;
3420 return false;
3421}

References _tocEntry::desc, and fb().

Referenced by _printTocEntry(), and _tocEntryRequired().

◆ _tocEntryRequired()

static int _tocEntryRequired ( TocEntry te,
teSection  curSection,
ArchiveHandle AH 
)
static

Definition at line 2986 of file pg_backup_archiver.c.

2987{
2988 int res = REQ_SCHEMA | REQ_DATA;
2989 RestoreOptions *ropt = AH->public.ropt;
2990
2991 /*
2992 * For binary upgrade mode, dump pg_largeobject_metadata and the
2993 * associated pg_shdepend rows. This is faster to restore than the
2994 * equivalent set of large object commands.
2995 */
2996 if (ropt->binary_upgrade && strcmp(te->desc, "TABLE DATA") == 0 &&
2999 return REQ_DATA;
3000
3001 /* These items are treated specially */
3002 if (strcmp(te->desc, "ENCODING") == 0 ||
3003 strcmp(te->desc, "STDSTRINGS") == 0 ||
3004 strcmp(te->desc, "SEARCHPATH") == 0)
3005 return REQ_SPECIAL;
3006
3007 if ((strcmp(te->desc, "STATISTICS DATA") == 0) ||
3008 (strcmp(te->desc, "EXTENDED STATISTICS DATA") == 0))
3009 {
3010 if (!ropt->dumpStatistics)
3011 return 0;
3012
3013 res = REQ_STATS;
3014 }
3015
3016 /*
3017 * DATABASE and DATABASE PROPERTIES also have a special rule: they are
3018 * restored in createDB mode, and not restored otherwise, independently of
3019 * all else.
3020 */
3021 if (strcmp(te->desc, "DATABASE") == 0 ||
3022 strcmp(te->desc, "DATABASE PROPERTIES") == 0)
3023 {
3024 if (ropt->createDB)
3025 return REQ_SCHEMA;
3026 else
3027 return 0;
3028 }
3029
3030 /*
3031 * Process exclusions that affect certain classes of TOC entries.
3032 */
3033
3034 /* If it's an ACL, maybe ignore it */
3035 if (ropt->aclsSkip && _tocEntryIsACL(te))
3036 return 0;
3037
3038 /* If it's a comment, maybe ignore it */
3039 if (ropt->no_comments && strcmp(te->desc, "COMMENT") == 0)
3040 return 0;
3041
3042 /* If it's a policy, maybe ignore it */
3043 if (ropt->no_policies &&
3044 (strcmp(te->desc, "POLICY") == 0 ||
3045 strcmp(te->desc, "ROW SECURITY") == 0))
3046 return 0;
3047
3048 /*
3049 * If it's a comment on a policy, a publication, or a subscription, maybe
3050 * ignore it.
3051 */
3052 if (strcmp(te->desc, "COMMENT") == 0)
3053 {
3054 if (ropt->no_policies &&
3055 strncmp(te->tag, "POLICY", strlen("POLICY")) == 0)
3056 return 0;
3057
3058 if (ropt->no_publications &&
3059 strncmp(te->tag, "PUBLICATION", strlen("PUBLICATION")) == 0)
3060 return 0;
3061
3062 if (ropt->no_subscriptions &&
3063 strncmp(te->tag, "SUBSCRIPTION", strlen("SUBSCRIPTION")) == 0)
3064 return 0;
3065 }
3066
3067 /*
3068 * If it's a publication or a table part of a publication, maybe ignore
3069 * it.
3070 */
3071 if (ropt->no_publications &&
3072 (strcmp(te->desc, "PUBLICATION") == 0 ||
3073 strcmp(te->desc, "PUBLICATION TABLE") == 0 ||
3074 strcmp(te->desc, "PUBLICATION TABLES IN SCHEMA") == 0))
3075 return 0;
3076
3077 /* If it's a security label, maybe ignore it */
3078 if (ropt->no_security_labels && strcmp(te->desc, "SECURITY LABEL") == 0)
3079 return 0;
3080
3081 /*
3082 * If it's a security label on a publication or a subscription, maybe
3083 * ignore it.
3084 */
3085 if (strcmp(te->desc, "SECURITY LABEL") == 0)
3086 {
3087 if (ropt->no_publications &&
3088 strncmp(te->tag, "PUBLICATION", strlen("PUBLICATION")) == 0)
3089 return 0;
3090
3091 if (ropt->no_subscriptions &&
3092 strncmp(te->tag, "SUBSCRIPTION", strlen("SUBSCRIPTION")) == 0)
3093 return 0;
3094 }
3095
3096 /* If it's a subscription, maybe ignore it */
3097 if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0)
3098 return 0;
3099
3100 /* Ignore it if section is not to be dumped/restored */
3101 switch (curSection)
3102 {
3103 case SECTION_PRE_DATA:
3104 if (!(ropt->dumpSections & DUMP_PRE_DATA))
3105 return 0;
3106 break;
3107 case SECTION_DATA:
3108 if (!(ropt->dumpSections & DUMP_DATA))
3109 return 0;
3110 break;
3111 case SECTION_POST_DATA:
3112 if (!(ropt->dumpSections & DUMP_POST_DATA))
3113 return 0;
3114 break;
3115 default:
3116 /* shouldn't get here, really, but ignore it */
3117 return 0;
3118 }
3119
3120 /* Ignore it if rejected by idWanted[] (cf. SortTocFromFile) */
3121 if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
3122 return 0;
3123
3124 /*
3125 * Check options for selective dump/restore.
3126 */
3127 if (strcmp(te->desc, "ACL") == 0 ||
3128 strcmp(te->desc, "COMMENT") == 0 ||
3129 strcmp(te->desc, "SECURITY LABEL") == 0)
3130 {
3131 /* Database properties react to createDB, not selectivity options. */
3132 if (strncmp(te->tag, "DATABASE ", 9) == 0)
3133 {
3134 if (!ropt->createDB)
3135 return 0;
3136 }
3137 else if (ropt->schemaNames.head != NULL ||
3138 ropt->schemaExcludeNames.head != NULL ||
3139 ropt->selTypes)
3140 {
3141 /*
3142 * In a selective dump/restore, we want to restore these dependent
3143 * TOC entry types only if their parent object is being restored.
3144 * Without selectivity options, we let through everything in the
3145 * archive. Note there may be such entries with no parent, eg
3146 * non-default ACLs for built-in objects. Also, we make
3147 * per-column ACLs additionally depend on the table's ACL if any
3148 * to ensure correct restore order, so those dependencies should
3149 * be ignored in this check.
3150 *
3151 * This code depends on the parent having been marked already,
3152 * which should be the case; if it isn't, perhaps due to
3153 * SortTocFromFile rearrangement, skipping the dependent entry
3154 * seems prudent anyway.
3155 *
3156 * Ideally we'd handle, eg, table CHECK constraints this way too.
3157 * But it's hard to tell which of their dependencies is the one to
3158 * consult.
3159 */
3160 bool dumpthis = false;
3161
3162 for (int i = 0; i < te->nDeps; i++)
3163 {
3165
3166 if (!pte)
3167 continue; /* probably shouldn't happen */
3168 if (strcmp(pte->desc, "ACL") == 0)
3169 continue; /* ignore dependency on another ACL */
3170 if (pte->reqs == 0)
3171 continue; /* this object isn't marked, so ignore it */
3172 /* Found a parent to be dumped, so we want to dump this too */
3173 dumpthis = true;
3174 break;
3175 }
3176 if (!dumpthis)
3177 return 0;
3178 }
3179 }
3180 else
3181 {
3182 /* Apply selective-restore rules for standalone TOC entries. */
3183 if (ropt->schemaNames.head != NULL)
3184 {
3185 /* If no namespace is specified, it means all. */
3186 if (!te->namespace)
3187 return 0;
3188 if (!simple_string_list_member(&ropt->schemaNames, te->namespace))
3189 return 0;
3190 }
3191
3192 if (ropt->schemaExcludeNames.head != NULL &&
3193 te->namespace &&
3194 simple_string_list_member(&ropt->schemaExcludeNames, te->namespace))
3195 return 0;
3196
3197 if (ropt->selTypes)
3198 {
3199 if (strcmp(te->desc, "STATISTICS DATA") == 0)
3200 {
3201 bool dumpthis = false;
3202
3203 /*
3204 * Statistics data entries can be for tables or indexes. Check
3205 * the parent dependency to determine which type this entry
3206 * belongs to, then apply the appropriate name filter.
3207 */
3208 for (int i = 0; i < te->nDeps; i++)
3209 {
3211
3212 if (!pte)
3213 continue;
3214
3215 if (ropt->selTable &&
3216 (strcmp(pte->desc, "TABLE") == 0 ||
3217 strcmp(pte->desc, "VIEW") == 0 ||
3218 strcmp(pte->desc, "FOREIGN TABLE") == 0 ||
3219 strcmp(pte->desc, "MATERIALIZED VIEW") == 0))
3220 {
3221 if (ropt->tableNames.head == NULL ||
3223 dumpthis = true;
3224 }
3225
3226 if (ropt->selIndex &&
3227 strcmp(pte->desc, "INDEX") == 0)
3228 {
3229 if (ropt->indexNames.head == NULL ||
3231 dumpthis = true;
3232 }
3233 }
3234 if (!dumpthis)
3235 return 0;
3236 }
3237 else if (strcmp(te->desc, "TABLE") == 0 ||
3238 strcmp(te->desc, "TABLE DATA") == 0 ||
3239 strcmp(te->desc, "VIEW") == 0 ||
3240 strcmp(te->desc, "FOREIGN TABLE") == 0 ||
3241 strcmp(te->desc, "MATERIALIZED VIEW") == 0 ||
3242 strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 ||
3243 strcmp(te->desc, "SEQUENCE") == 0 ||
3244 strcmp(te->desc, "SEQUENCE SET") == 0)
3245 {
3246 if (!ropt->selTable)
3247 return 0;
3248 if (ropt->tableNames.head != NULL &&
3250 return 0;
3251 }
3252 else if (strcmp(te->desc, "INDEX") == 0)
3253 {
3254 if (!ropt->selIndex)
3255 return 0;
3256 if (ropt->indexNames.head != NULL &&
3258 return 0;
3259 }
3260 else if (strcmp(te->desc, "FUNCTION") == 0 ||
3261 strcmp(te->desc, "AGGREGATE") == 0 ||
3262 strcmp(te->desc, "PROCEDURE") == 0)
3263 {
3264 if (!ropt->selFunction)
3265 return 0;
3266 if (ropt->functionNames.head != NULL &&
3268 return 0;
3269 }
3270 else if (strcmp(te->desc, "TRIGGER") == 0)
3271 {
3272 if (!ropt->selTrigger)
3273 return 0;
3274 if (ropt->triggerNames.head != NULL &&
3276 return 0;
3277 }
3278 else
3279 return 0;
3280 }
3281 }
3282
3283
3284 /*
3285 * Determine whether the TOC entry contains schema and/or data components,
3286 * and mask off inapplicable REQ bits. If it had a dataDumper, assume
3287 * it's both schema and data. Otherwise it's probably schema-only, but
3288 * there are exceptions.
3289 */
3290 if (!te->hadDumper)
3291 {
3292 /*
3293 * Special Case: If 'SEQUENCE SET' or anything to do with LOs, then it
3294 * is considered a data entry. We don't need to check for BLOBS or
3295 * old-style BLOB COMMENTS entries, because they will have hadDumper =
3296 * true ... but we do need to check new-style BLOB ACLs, comments,
3297 * etc.
3298 */
3299 if (strcmp(te->desc, "SEQUENCE SET") == 0 ||
3300 strcmp(te->desc, "BLOB") == 0 ||
3301 strcmp(te->desc, "BLOB METADATA") == 0 ||
3302 (strcmp(te->desc, "ACL") == 0 &&
3303 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3304 (strcmp(te->desc, "COMMENT") == 0 &&
3305 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3306 (strcmp(te->desc, "SECURITY LABEL") == 0 &&
3307 strncmp(te->tag, "LARGE OBJECT", 12) == 0))
3308 res = res & REQ_DATA;
3309 else
3310 res = res & ~REQ_DATA;
3311 }
3312
3313 /*
3314 * If there's no definition command, there's no schema component. Treat
3315 * "load via partition root" comments as not schema.
3316 */
3317 if (!te->defn || !te->defn[0] ||
3318 strncmp(te->defn, "-- load via partition root ", 27) == 0)
3319 res = res & ~REQ_SCHEMA;
3320
3321 /*
3322 * Special case: <Init> type with <Max OID> tag; this is obsolete and we
3323 * always ignore it.
3324 */
3325 if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
3326 return 0;
3327
3328 /* Mask it if we don't want data */
3329 if (!ropt->dumpData)
3330 {
3331 /*
3332 * The sequence_data option overrides dumpData for SEQUENCE SET.
3333 *
3334 * In binary-upgrade mode, even with dumpData unset, we do not mask
3335 * out large objects. (Only large object definitions, comments and
3336 * other metadata should be generated in binary-upgrade mode, not the
3337 * actual data, but that need not concern us here.)
3338 */
3339 if (!(ropt->sequence_data && strcmp(te->desc, "SEQUENCE SET") == 0) &&
3340 !(ropt->binary_upgrade &&
3341 (strcmp(te->desc, "BLOB") == 0 ||
3342 strcmp(te->desc, "BLOB METADATA") == 0 ||
3343 (strcmp(te->desc, "ACL") == 0 &&
3344 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3345 (strcmp(te->desc, "COMMENT") == 0 &&
3346 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3347 (strcmp(te->desc, "SECURITY LABEL") == 0 &&
3348 strncmp(te->tag, "LARGE OBJECT", 12) == 0))))
3349 res = res & (REQ_SCHEMA | REQ_STATS);
3350 }
3351
3352 /* Mask it if we don't want schema */
3353 if (!ropt->dumpSchema)
3354 res = res & (REQ_DATA | REQ_STATS);
3355
3356 return res;
3357}
@ SECTION_POST_DATA
Definition pg_backup.h:60
@ SECTION_PRE_DATA
Definition pg_backup.h:58
@ SECTION_DATA
Definition pg_backup.h:59
TocEntry * getTocEntryByDumpId(ArchiveHandle *AH, DumpId id)
#define REQ_SCHEMA
#define REQ_STATS
#define REQ_SPECIAL
#define REQ_DATA
#define DUMP_PRE_DATA
#define DUMP_DATA
#define DUMP_POST_DATA
bool simple_string_list_member(SimpleStringList *list, const char *val)
Definition simple_list.c:87
SimpleStringListCell * head
Definition simple_list.h:42
SimpleStringList schemaExcludeNames
Definition pg_backup.h:141
SimpleStringList functionNames
Definition pg_backup.h:139
SimpleStringList tableNames
Definition pg_backup.h:143
SimpleStringList indexNames
Definition pg_backup.h:138
SimpleStringList triggerNames
Definition pg_backup.h:142
SimpleStringList schemaNames
Definition pg_backup.h:140

References _tocEntryIsACL(), _restoreOptions::aclsSkip, _restoreOptions::binary_upgrade, _tocEntry::catalogId, _restoreOptions::createDB, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, DUMP_DATA, DUMP_POST_DATA, DUMP_PRE_DATA, _restoreOptions::dumpData, _tocEntry::dumpId, _restoreOptions::dumpSchema, _restoreOptions::dumpSections, _restoreOptions::dumpStatistics, fb(), _restoreOptions::functionNames, getTocEntryByDumpId(), _tocEntry::hadDumper, SimpleStringList::head, i, _restoreOptions::idWanted, _restoreOptions::indexNames, _tocEntry::nDeps, _restoreOptions::no_comments, _restoreOptions::no_policies, _restoreOptions::no_publications, _restoreOptions::no_security_labels, _restoreOptions::no_subscriptions, CatalogId::oid, _archiveHandle::public, REQ_DATA, REQ_SCHEMA, REQ_SPECIAL, REQ_STATS, Archive::ropt, _restoreOptions::schemaExcludeNames, _restoreOptions::schemaNames, SECTION_DATA, SECTION_POST_DATA, SECTION_PRE_DATA, _restoreOptions::selFunction, _restoreOptions::selIndex, _restoreOptions::selTable, _restoreOptions::selTrigger, _restoreOptions::selTypes, _restoreOptions::sequence_data, simple_string_list_member(), _restoreOptions::tableNames, _tocEntry::tag, and _restoreOptions::triggerNames.

Referenced by PrintTOCSummary(), and ProcessArchiveRestoreOptions().

◆ _tocEntryRestorePass()

static RestorePass _tocEntryRestorePass ( TocEntry te)
static

Definition at line 3365 of file pg_backup_archiver.c.

3366{
3367 /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3368 if (strcmp(te->desc, "ACL") == 0 ||
3369 strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3370 strcmp(te->desc, "DEFAULT ACL") == 0)
3371 return RESTORE_PASS_ACL;
3372 if (strcmp(te->desc, "EVENT TRIGGER") == 0 ||
3373 strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0)
3374 return RESTORE_PASS_POST_ACL;
3375
3376 /*
3377 * Comments and security labels need to be emitted in the same pass as
3378 * their parent objects. ACLs haven't got comments and security labels,
3379 * and neither do matview data objects, but event triggers do.
3380 * (Fortunately, event triggers haven't got ACLs, or we'd need yet another
3381 * weird special case.)
3382 */
3383 if ((strcmp(te->desc, "COMMENT") == 0 ||
3384 strcmp(te->desc, "SECURITY LABEL") == 0) &&
3385 strncmp(te->tag, "EVENT TRIGGER ", 14) == 0)
3386 return RESTORE_PASS_POST_ACL;
3387
3388 /*
3389 * If statistics data is dependent on materialized view data, it must be
3390 * deferred to RESTORE_PASS_POST_ACL. Those entries are already marked as
3391 * SECTION_POST_DATA, and some other stats entries (e.g., index stats)
3392 * will also be marked as SECTION_POST_DATA. Additionally, our lookahead
3393 * code in fetchAttributeStats() assumes that we dump all statistics data
3394 * entries in TOC order. To ensure this assumption holds, we move all
3395 * statistics data entries in SECTION_POST_DATA to RESTORE_PASS_POST_ACL.
3396 */
3397 if (strcmp(te->desc, "STATISTICS DATA") == 0 &&
3399 return RESTORE_PASS_POST_ACL;
3400
3401 /* All else can be handled in the main pass. */
3402 return RESTORE_PASS_MAIN;
3403}
@ RESTORE_PASS_POST_ACL
@ RESTORE_PASS_ACL
@ RESTORE_PASS_MAIN
teSection section

References _tocEntry::desc, fb(), RESTORE_PASS_ACL, RESTORE_PASS_MAIN, RESTORE_PASS_POST_ACL, _tocEntry::section, SECTION_POST_DATA, and _tocEntry::tag.

Referenced by move_to_ready_heap(), reduce_dependencies(), restore_toc_entries_prefork(), and RestoreArchive().

◆ ahprintf()

int ahprintf ( ArchiveHandle AH,
const char fmt,
  ... 
)

Definition at line 1759 of file pg_backup_archiver.c.

1760{
1761 int save_errno = errno;
1762 char *p;
1763 size_t len = 128; /* initial assumption about buffer size */
1764 size_t cnt;
1765
1766 for (;;)
1767 {
1768 va_list args;
1769
1770 /* Allocate work buffer. */
1771 p = (char *) pg_malloc(len);
1772
1773 /* Try to format the data. */
1774 errno = save_errno;
1775 va_start(args, fmt);
1776 cnt = pvsnprintf(p, len, fmt, args);
1777 va_end(args);
1778
1779 if (cnt < len)
1780 break; /* success */
1781
1782 /* Release buffer and loop around to try again with larger len. */
1783 pg_free(p);
1784 len = cnt;
1785 }
1786
1787 ahwrite(p, 1, cnt, AH);
1788 pg_free(p);
1789 return (int) cnt;
1790}
void * pg_malloc(size_t size)
Definition fe_memutils.c:53
void ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
const void size_t len
size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
Definition psprintf.c:103

References ahwrite(), fb(), len, pg_free(), pg_malloc(), and pvsnprintf().

Referenced by _disableTriggersIfNecessary(), _doSetFixedOutputState(), _doSetSessionAuth(), _enableTriggersIfNecessary(), _EndData(), _EndLO(), _EndLOs(), _PrintExtraToc(), _PrintExtraToc(), _PrintExtraToc(), _printTableAccessMethodNoStorage(), _PrintTocData(), _printTocEntry(), _reconnectToDB(), _selectOutputSchema(), _selectTableAccessMethod(), _selectTablespace(), _StartLO(), _StartLOs(), _WriteLOData(), DropLOIfExists(), dump_lo_buf(), dumpTimestamp(), EndRestoreLO(), EndRestoreLOs(), IssueCommandPerBlob(), PrintTOCSummary(), restore_toc_entry(), RestoreArchive(), StartRestoreLO(), and StartRestoreLOs().

◆ ahwrite()

void ahwrite ( const void ptr,
size_t  size,
size_t  nmemb,
ArchiveHandle AH 
)

Definition at line 1850 of file pg_backup_archiver.c.

1851{
1852 int bytes_written = 0;
1853
1854 if (AH->writingLO)
1855 {
1856 size_t remaining = size * nmemb;
1857
1858 while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1859 {
1860 size_t avail = AH->lo_buf_size - AH->lo_buf_used;
1861
1862 memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1863 ptr = (const char *) ptr + avail;
1864 remaining -= avail;
1865 AH->lo_buf_used += avail;
1866 dump_lo_buf(AH);
1867 }
1868
1869 memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1870 AH->lo_buf_used += remaining;
1871
1872 bytes_written = size * nmemb;
1873 }
1874 else if (AH->CustomOutPtr)
1875 bytes_written = AH->CustomOutPtr(AH, ptr, size * nmemb);
1876
1877 /*
1878 * If we're doing a restore, and it's direct to DB, and we're connected
1879 * then send it to the DB.
1880 */
1881 else if (RestoringToDB(AH))
1882 bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb);
1883 else
1884 {
1886
1887 CFH->write_func(ptr, size * nmemb, CFH);
1888 bytes_written = size * nmemb;
1889 }
1890
1891 if (bytes_written != size * nmemb)
1893}
int remaining
Definition informix.c:692
static void dump_lo_buf(ArchiveHandle *AH)
#define WRITE_ERROR_EXIT
int ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen)
CustomOutPtrType CustomOutPtr

References _archiveHandle::CustomOutPtr, dump_lo_buf(), ExecuteSqlCommandBuf(), fb(), _archiveHandle::lo_buf, _archiveHandle::lo_buf_size, _archiveHandle::lo_buf_used, memcpy(), _archiveHandle::OF, _archiveHandle::public, remaining, RestoringToDB(), WRITE_ERROR_EXIT, and _archiveHandle::writingLO.

Referenced by _LoadLOs(), _PrintFileData(), _PrintFileData(), _PrintTocData(), _WriteData(), ahprintf(), and ReadDataFromArchiveNone().

◆ ArchiveEntry()

TocEntry * ArchiveEntry ( Archive AHX,
CatalogId  catalogId,
DumpId  dumpId,
ArchiveOpts opts 
)

Definition at line 1242 of file pg_backup_archiver.c.

1244{
1245 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1247
1249
1250 AH->tocCount++;
1251 if (dumpId > AH->maxDumpId)
1252 AH->maxDumpId = dumpId;
1253
1254 newToc->prev = AH->toc->prev;
1255 newToc->next = AH->toc;
1256 AH->toc->prev->next = newToc;
1257 AH->toc->prev = newToc;
1258
1259 newToc->catalogId = catalogId;
1260 newToc->dumpId = dumpId;
1261 newToc->section = opts->section;
1262
1263 newToc->tag = pg_strdup(opts->tag);
1264 newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
1265 newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
1266 newToc->tableam = opts->tableam ? pg_strdup(opts->tableam) : NULL;
1267 newToc->relkind = opts->relkind;
1268 newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
1269 newToc->desc = pg_strdup(opts->description);
1270 newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
1271 newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
1272 newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
1273
1274 if (opts->nDeps > 0)
1275 {
1276 newToc->dependencies = pg_malloc_array(DumpId, opts->nDeps);
1277 memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
1278 newToc->nDeps = opts->nDeps;
1279 }
1280 else
1281 {
1282 newToc->dependencies = NULL;
1283 newToc->nDeps = 0;
1284 }
1285
1286 newToc->dataDumper = opts->dumpFn;
1287 newToc->dataDumperArg = opts->dumpArg;
1288 newToc->hadDumper = opts->dumpFn ? true : false;
1289
1290 newToc->defnDumper = opts->defnFn;
1291 newToc->defnDumperArg = opts->defnArg;
1292
1293 newToc->formatData = NULL;
1294 newToc->dataLength = 0;
1295
1296 if (AH->ArchiveEntryPtr != NULL)
1297 AH->ArchiveEntryPtr(AH, newToc);
1298
1299 return newToc;
1300}
#define pg_malloc_array(type, count)
Definition fe_memutils.h:66
static AmcheckOptions opts
Definition pg_amcheck.c:112
int DumpId
Definition pg_backup.h:285
ArchiveEntryPtrType ArchiveEntryPtr

References _archiveHandle::ArchiveEntryPtr, _tocEntry::catalogId, fb(), _archiveHandle::maxDumpId, memcpy(), _tocEntry::next, opts, pg_malloc0_object, pg_malloc_array, pg_strdup(), _tocEntry::prev, _archiveHandle::toc, _archiveHandle::tocCount, and true.

Referenced by dumpAccessMethod(), dumpACL(), dumpAgg(), dumpAttrDef(), dumpBaseType(), dumpCast(), dumpCollation(), dumpCommentExtended(), dumpCompositeType(), dumpCompositeTypeColComments(), dumpConstraint(), dumpConversion(), dumpDatabase(), dumpDefaultACL(), dumpDomain(), dumpDumpableObject(), dumpEncoding(), dumpEnumType(), dumpEventTrigger(), dumpExtension(), dumpForeignDataWrapper(), dumpForeignServer(), dumpFunc(), dumpIndex(), dumpIndexAttach(), dumpLO(), dumpNamespace(), dumpOpclass(), dumpOpfamily(), dumpOpr(), dumpPolicy(), dumpProcLang(), dumpPublication(), dumpPublicationNamespace(), dumpPublicationTable(), dumpRangeType(), dumpRelationStats(), dumpRule(), dumpSearchPath(), dumpSecLabel(), dumpSequence(), dumpSequenceData(), dumpShellType(), dumpStatisticsExt(), dumpStatisticsExtStats(), dumpStdStrings(), dumpSubscription(), dumpSubscriptionTable(), dumpTableAttach(), dumpTableComment(), dumpTableData(), dumpTableSchema(), dumpTableSecLabel(), dumpTransform(), dumpTrigger(), dumpTSConfig(), dumpTSDictionary(), dumpTSParser(), dumpTSTemplate(), dumpUndefinedType(), dumpUserMappings(), and refreshMatViewData().

◆ archprintf()

int archprintf ( Archive AH,
const char fmt,
  ... 
)

Definition at line 1659 of file pg_backup_archiver.c.

1660{
1661 int save_errno = errno;
1662 char *p;
1663 size_t len = 128; /* initial assumption about buffer size */
1664 size_t cnt;
1665
1666 for (;;)
1667 {
1668 va_list args;
1669
1670 /* Allocate work buffer. */
1671 p = (char *) pg_malloc(len);
1672
1673 /* Try to format the data. */
1674 errno = save_errno;
1675 va_start(args, fmt);
1676 cnt = pvsnprintf(p, len, fmt, args);
1677 va_end(args);
1678
1679 if (cnt < len)
1680 break; /* success */
1681
1682 /* Release buffer and loop around to try again with larger len. */
1683 pg_free(p);
1684 len = cnt;
1685 }
1686
1687 WriteData(AH, p, cnt);
1688 pg_free(p);
1689 return (int) cnt;
1690}
void WriteData(Archive *AHX, const void *data, size_t dLen)

References fb(), len, pg_free(), pg_malloc(), pvsnprintf(), and WriteData().

◆ archputs()

void archputs ( const char s,
Archive AH 
)

Definition at line 1652 of file pg_backup_archiver.c.

1653{
1654 WriteData(AH, s, strlen(s));
1655}

References fb(), and WriteData().

Referenced by dumpTableData_insert().

◆ buildTocEntryArrays()

static void buildTocEntryArrays ( ArchiveHandle AH)
static

Definition at line 1994 of file pg_backup_archiver.c.

1995{
1996 DumpId maxDumpId = AH->maxDumpId;
1997 TocEntry *te;
1998
1999 AH->tocsByDumpId = pg_malloc0_array(TocEntry *, (maxDumpId + 1));
2000 AH->tableDataId = pg_malloc0_array(DumpId, (maxDumpId + 1));
2001
2002 for (te = AH->toc->next; te != AH->toc; te = te->next)
2003 {
2004 /* this check is purely paranoia, maxDumpId should be correct */
2005 if (te->dumpId <= 0 || te->dumpId > maxDumpId)
2006 pg_fatal("bad dumpId");
2007
2008 /* tocsByDumpId indexes all TOCs by their dump ID */
2009 AH->tocsByDumpId[te->dumpId] = te;
2010
2011 /*
2012 * tableDataId provides the TABLE DATA item's dump ID for each TABLE
2013 * TOC entry that has a DATA item. We compute this by reversing the
2014 * TABLE DATA item's dependency, knowing that a TABLE DATA item has
2015 * just one dependency and it is the TABLE item.
2016 */
2017 if (strcmp(te->desc, "TABLE DATA") == 0 && te->nDeps > 0)
2018 {
2019 DumpId tableId = te->dependencies[0];
2020
2021 /*
2022 * The TABLE item might not have been in the archive, if this was
2023 * a data-only dump; but its dump ID should be less than its data
2024 * item's dump ID, so there should be a place for it in the array.
2025 */
2026 if (tableId <= 0 || tableId > maxDumpId)
2027 pg_fatal("bad table dumpId for TABLE DATA item");
2028
2029 AH->tableDataId[tableId] = te->dumpId;
2030 }
2031 }
2032}
#define pg_malloc0_array(type, count)
Definition fe_memutils.h:67
struct _tocEntry ** tocsByDumpId

References _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dumpId, fb(), _archiveHandle::maxDumpId, _tocEntry::nDeps, _tocEntry::next, pg_fatal, pg_malloc0_array, _archiveHandle::tableDataId, _archiveHandle::toc, and _archiveHandle::tocsByDumpId.

Referenced by getTocEntryByDumpId(), and RestoreArchive().

◆ checkSeek()

bool checkSeek ( FILE fp)

Definition at line 4314 of file pg_backup_archiver.c.

4315{
4316 pgoff_t tpos;
4317
4318 /* Check that ftello works on this file */
4319 tpos = ftello(fp);
4320 if (tpos < 0)
4321 return false;
4322
4323 /*
4324 * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
4325 * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
4326 * successful no-op even on files that are otherwise unseekable.
4327 */
4328 if (fseeko(fp, tpos, SEEK_SET) != 0)
4329 return false;
4330
4331 return true;
4332}
#define ftello(stream)
Definition win32_port.h:209
#define fseeko(stream, offset, origin)
Definition win32_port.h:206

References fb(), fseeko, and ftello.

Referenced by InitArchiveFmt_Custom(), and InitArchiveFmt_Tar().

◆ CloneArchive()

ArchiveHandle * CloneArchive ( ArchiveHandle AH)

Definition at line 5181 of file pg_backup_archiver.c.

5182{
5184
5185 /* Make a "flat" copy */
5187 memcpy(clone, AH, sizeof(ArchiveHandle));
5188
5189 /* Likewise flat-copy the RestoreOptions, so we can alter them locally */
5190 clone->public.ropt = pg_malloc_object(RestoreOptions);
5191 memcpy(clone->public.ropt, AH->public.ropt, sizeof(RestoreOptions));
5192
5193 /* Handle format-independent fields */
5194 memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse));
5195
5196 /* The clone will have its own connection, so disregard connection state */
5197 clone->connection = NULL;
5198 clone->connCancel = NULL;
5199 clone->currUser = NULL;
5200 clone->currSchema = NULL;
5201 clone->currTableAm = NULL;
5202 clone->currTablespace = NULL;
5203
5204 /* savedPassword must be local in case we change it while connecting */
5205 if (clone->savedPassword)
5206 clone->savedPassword = pg_strdup(clone->savedPassword);
5207
5208 /* clone has its own error count, too */
5209 clone->public.n_errors = 0;
5210
5211 /* clones should not share lo_buf */
5212 clone->lo_buf = NULL;
5213
5214 /*
5215 * Clone connections disregard --transaction-size; they must commit after
5216 * each command so that the results are immediately visible to other
5217 * workers.
5218 */
5219 clone->public.ropt->txn_size = 0;
5220
5221 /*
5222 * Connect our new clone object to the database, using the same connection
5223 * parameters used for the original connection.
5224 */
5225 ConnectDatabaseAhx((Archive *) clone, &clone->public.ropt->cparams, true);
5226
5227 /* re-establish fixed state */
5228 if (AH->mode == archModeRead)
5230 /* in write case, setupDumpWorker will fix up connection state */
5231
5232 /* Let the format-specific code have a chance too */
5233 clone->ClonePtr(clone);
5234
5235 Assert(clone->connection != NULL);
5236 return clone;
5237}
#define pg_malloc_object(type)
Definition fe_memutils.h:60
void ConnectDatabaseAhx(Archive *AHX, const ConnParams *cparams, bool isReconnect)
@ archModeRead
Definition pg_backup.h:52

References _doSetFixedOutputState(), archModeRead, Assert, ConnectDatabaseAhx(), fb(), memcpy(), _archiveHandle::mode, pg_malloc_object, pg_strdup(), _archiveHandle::public, and Archive::ropt.

Referenced by RunWorker().

◆ CloseArchive()

void CloseArchive ( Archive AHX)

Definition at line 263 of file pg_backup_archiver.c.

264{
265 ArchiveHandle *AH = (ArchiveHandle *) AHX;
266
267 AH->ClosePtr(AH);
268
269 /* Close the output */
270 errno = 0;
271 if (!EndCompressFileHandle(AH->OF))
272 pg_fatal("could not close output file: %m");
273}
bool EndCompressFileHandle(CompressFileHandle *CFH)
ClosePtrType ClosePtr

References _archiveHandle::ClosePtr, EndCompressFileHandle(), fb(), _archiveHandle::OF, and pg_fatal.

Referenced by main().

◆ CreateArchive()

Archive * CreateArchive ( const char FileSpec,
const ArchiveFormat  fmt,
const pg_compress_specification  compression_spec,
bool  dosync,
ArchiveMode  mode,
SetupWorkerPtrType  setupDumpWorker,
DataDirSyncMethod  sync_method 
)

Definition at line 232 of file pg_backup_archiver.c.

238{
239 ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression_spec,
241
242 return (Archive *) AH;
243}
static ArchiveHandle * _allocAH(const char *FileSpec, const ArchiveFormat fmt, const pg_compress_specification compression_spec, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupWorkerPtr, DataDirSyncMethod sync_method)
static void setupDumpWorker(Archive *AH)
Definition pg_dump.c:1571

References _allocAH(), dosync, fb(), mode, setupDumpWorker(), and sync_method.

Referenced by main().

◆ DeCloneArchive()

void DeCloneArchive ( ArchiveHandle AH)

Definition at line 5245 of file pg_backup_archiver.c.

5246{
5247 /* Should not have an open database connection */
5248 Assert(AH->connection == NULL);
5249
5250 /* Clear format-specific state */
5251 AH->DeClonePtr(AH);
5252
5253 /* Clear state allocated by CloneArchive */
5254 if (AH->sqlparse.curCmd)
5256
5257 /* Clear any connection-local state */
5258 free(AH->currUser);
5259 free(AH->currSchema);
5260 free(AH->currTablespace);
5261 free(AH->currTableAm);
5262 free(AH->savedPassword);
5263
5264 free(AH);
5265}
DeClonePtrType DeClonePtr

References Assert, _archiveHandle::connection, sqlparseInfo::curCmd, _archiveHandle::currSchema, _archiveHandle::currTableAm, _archiveHandle::currTablespace, _archiveHandle::currUser, _archiveHandle::DeClonePtr, destroyPQExpBuffer(), fb(), free, _archiveHandle::savedPassword, and _archiveHandle::sqlparse.

Referenced by RunWorker().

◆ dump_lo_buf()

static void dump_lo_buf ( ArchiveHandle AH)
static

Definition at line 1807 of file pg_backup_archiver.c.

1808{
1809 if (AH->connection)
1810 {
1811 int res;
1812
1813 res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1814 pg_log_debug(ngettext("wrote %zu byte of large object data (result = %d)",
1815 "wrote %zu bytes of large object data (result = %d)",
1816 AH->lo_buf_used),
1817 AH->lo_buf_used, res);
1818 /* We assume there are no short writes, only errors */
1819 if (res != AH->lo_buf_used)
1820 warn_or_exit_horribly(AH, "could not write to large object: %s",
1822 }
1823 else
1824 {
1826
1828 (const unsigned char *) AH->lo_buf,
1829 AH->lo_buf_used,
1830 AH);
1831
1832 /* Hack: turn off writingLO so ahwrite doesn't recurse to here */
1833 AH->writingLO = false;
1834 ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
1835 AH->writingLO = true;
1836
1838 }
1839 AH->lo_buf_used = 0;
1840}
int lo_write(int fd, const char *buf, int len)
Definition be-fsstubs.c:182
#define ngettext(s, p, n)
Definition c.h:1310
#define appendByteaLiteralAHX(buf, str, len, AH)

References ahprintf(), appendByteaLiteralAHX, buf, _archiveHandle::connection, createPQExpBuffer(), destroyPQExpBuffer(), _archiveHandle::lo_buf, _archiveHandle::lo_buf_used, lo_write(), _archiveHandle::loFd, ngettext, pg_log_debug, PQerrorMessage(), warn_or_exit_horribly(), and _archiveHandle::writingLO.

Referenced by ahwrite(), and EndRestoreLO().

◆ dumpOptionsFromRestoreOptions()

DumpOptions * dumpOptionsFromRestoreOptions ( RestoreOptions ropt)

Definition at line 165 of file pg_backup_archiver.c.

166{
167 DumpOptions *dopt = NewDumpOptions();
168
169 /* this is the inverse of what's at the end of pg_dump.c's main() */
170 dopt->cparams.dbname = ropt->cparams.dbname ? pg_strdup(ropt->cparams.dbname) : NULL;
171 dopt->cparams.pgport = ropt->cparams.pgport ? pg_strdup(ropt->cparams.pgport) : NULL;
172 dopt->cparams.pghost = ropt->cparams.pghost ? pg_strdup(ropt->cparams.pghost) : NULL;
175 dopt->outputClean = ropt->dropSchema;
176 dopt->dumpData = ropt->dumpData;
177 dopt->dumpSchema = ropt->dumpSchema;
178 dopt->dumpSections = ropt->dumpSections;
179 dopt->dumpStatistics = ropt->dumpStatistics;
180 dopt->if_exists = ropt->if_exists;
181 dopt->column_inserts = ropt->column_inserts;
182 dopt->aclsSkip = ropt->aclsSkip;
183 dopt->outputSuperuser = ropt->superuser;
184 dopt->outputCreateDB = ropt->createDB;
185 dopt->outputNoOwner = ropt->noOwner;
186 dopt->outputNoTableAm = ropt->noTableAm;
187 dopt->outputNoTablespaces = ropt->noTablespace;
189 dopt->use_setsessauth = ropt->use_setsessauth;
191 dopt->dump_inserts = ropt->dump_inserts;
192 dopt->no_comments = ropt->no_comments;
193 dopt->no_policies = ropt->no_policies;
194 dopt->no_publications = ropt->no_publications;
197 dopt->lockWaitTimeout = ropt->lockWaitTimeout;
200 dopt->sequence_data = ropt->sequence_data;
201 dopt->restrict_key = ropt->restrict_key ? pg_strdup(ropt->restrict_key) : NULL;
202
203 return dopt;
204}
DumpOptions * NewDumpOptions(void)
char * pgport
Definition pg_backup.h:88
char * pghost
Definition pg_backup.h:89
trivalue promptPassword
Definition pg_backup.h:91
char * username
Definition pg_backup.h:90
char * dbname
Definition pg_backup.h:87
char * restrict_key
Definition pg_backup.h:220
int column_inserts
Definition pg_backup.h:185
int use_setsessauth
Definition pg_backup.h:198
int outputCreateDB
Definition pg_backup.h:206
bool include_everything
Definition pg_backup.h:203
int sequence_data
Definition pg_backup.h:212
int disable_dollar_quoting
Definition pg_backup.h:184
bool dumpSchema
Definition pg_backup.h:216
int outputNoTableAm
Definition pg_backup.h:196
int enable_row_security
Definition pg_backup.h:199
char * outputSuperuser
Definition pg_backup.h:210
int no_security_labels
Definition pg_backup.h:190
bool dumpStatistics
Definition pg_backup.h:218
int no_publications
Definition pg_backup.h:189
ConnParams cparams
Definition pg_backup.h:173
const char * lockWaitTimeout
Definition pg_backup.h:180
int no_subscriptions
Definition pg_backup.h:191
int outputNoTablespaces
Definition pg_backup.h:197
int disable_triggers
Definition pg_backup.h:195
int outputNoOwner
Definition pg_backup.h:209
ConnParams cparams
Definition pg_backup.h:146
int disable_dollar_quoting
Definition pg_backup.h:110
const char * lockWaitTimeout
Definition pg_backup.h:125

References _restoreOptions::aclsSkip, _dumpOptions::aclsSkip, _restoreOptions::column_inserts, _dumpOptions::column_inserts, _restoreOptions::cparams, _dumpOptions::cparams, _restoreOptions::createDB, _connParams::dbname, _restoreOptions::disable_dollar_quoting, _dumpOptions::disable_dollar_quoting, _restoreOptions::disable_triggers, _dumpOptions::disable_triggers, _restoreOptions::dropSchema, _restoreOptions::dump_inserts, _dumpOptions::dump_inserts, _restoreOptions::dumpData, _dumpOptions::dumpData, _restoreOptions::dumpSchema, _dumpOptions::dumpSchema, _restoreOptions::dumpSections, _dumpOptions::dumpSections, _restoreOptions::dumpStatistics, _dumpOptions::dumpStatistics, _restoreOptions::enable_row_security, _dumpOptions::enable_row_security, fb(), _restoreOptions::if_exists, _dumpOptions::if_exists, _restoreOptions::include_everything, _dumpOptions::include_everything, _restoreOptions::lockWaitTimeout, _dumpOptions::lockWaitTimeout, NewDumpOptions(), _restoreOptions::no_comments, _dumpOptions::no_comments, _restoreOptions::no_policies, _dumpOptions::no_policies, _restoreOptions::no_publications, _dumpOptions::no_publications, _restoreOptions::no_security_labels, _dumpOptions::no_security_labels, _restoreOptions::no_subscriptions, _dumpOptions::no_subscriptions, _restoreOptions::noOwner, _restoreOptions::noTableAm, _restoreOptions::noTablespace, _dumpOptions::outputClean, _dumpOptions::outputCreateDB, _dumpOptions::outputNoOwner, _dumpOptions::outputNoTableAm, _dumpOptions::outputNoTablespaces, _dumpOptions::outputSuperuser, pg_strdup(), _connParams::pghost, _connParams::pgport, _connParams::promptPassword, _restoreOptions::restrict_key, _dumpOptions::restrict_key, _restoreOptions::sequence_data, _dumpOptions::sequence_data, _restoreOptions::superuser, _restoreOptions::use_setsessauth, _dumpOptions::use_setsessauth, and _connParams::username.

Referenced by SetArchiveOptions().

◆ dumpTimestamp()

static void dumpTimestamp ( ArchiveHandle AH,
const char msg,
time_t  tim 
)
static

Definition at line 4339 of file pg_backup_archiver.c.

4340{
4341 char buf[64];
4342
4343 if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
4344 ahprintf(AH, "-- %s %s\n\n", msg, buf);
4345}
#define PGDUMP_STRFTIME_FMT
Definition dumputils.h:34

References ahprintf(), buf, fb(), and PGDUMP_STRFTIME_FMT.

Referenced by RestoreArchive().

◆ EndLO()

int EndLO ( Archive AHX,
Oid  oid 
)

Definition at line 1430 of file pg_backup_archiver.c.

1431{
1432 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1433
1434 if (AH->EndLOPtr)
1435 AH->EndLOPtr(AH, AH->currToc, oid);
1436
1437 return 1;
1438}
EndLOPtrType EndLOPtr
struct _tocEntry * currToc

References _archiveHandle::currToc, and _archiveHandle::EndLOPtr.

Referenced by dumpLOs().

◆ EndRestoreLO()

void EndRestoreLO ( ArchiveHandle AH,
Oid  oid 
)

Definition at line 1545 of file pg_backup_archiver.c.

1546{
1547 if (AH->lo_buf_used > 0)
1548 {
1549 /* Write remaining bytes from the LO buffer */
1550 dump_lo_buf(AH);
1551 }
1552
1553 AH->writingLO = false;
1554
1555 if (AH->connection)
1556 {
1557 lo_close(AH->connection, AH->loFd);
1558 AH->loFd = -1;
1559 }
1560 else
1561 {
1562 ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
1563 }
1564}
int lo_close(PGconn *conn, int fd)
Definition fe-lobj.c:96

References ahprintf(), _archiveHandle::connection, dump_lo_buf(), _archiveHandle::lo_buf_used, lo_close(), _archiveHandle::loFd, and _archiveHandle::writingLO.

Referenced by _LoadLOs(), _LoadLOs(), and _LoadLOs().

◆ EndRestoreLOs()

void EndRestoreLOs ( ArchiveHandle AH)

Definition at line 1472 of file pg_backup_archiver.c.

1473{
1474 RestoreOptions *ropt = AH->public.ropt;
1475
1476 if (!(ropt->single_txn || ropt->txn_size > 0))
1477 {
1478 if (AH->connection)
1480 else
1481 ahprintf(AH, "COMMIT;\n\n");
1482 }
1483
1484 pg_log_info(ngettext("restored %d large object",
1485 "restored %d large objects",
1486 AH->loCount),
1487 AH->loCount);
1488}
static void CommitTransaction(void)
Definition xact.c:2270

References ahprintf(), CommitTransaction(), _archiveHandle::connection, _archiveHandle::loCount, ngettext, pg_log_info, _archiveHandle::public, Archive::ropt, _restoreOptions::single_txn, and _restoreOptions::txn_size.

Referenced by _LoadLOs(), _LoadLOs(), and _LoadLOs().

◆ fix_dependencies()

static void fix_dependencies ( ArchiveHandle AH)
static

Definition at line 4878 of file pg_backup_archiver.c.

4879{
4880 TocEntry *te;
4881 int i;
4882
4883 /*
4884 * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC
4885 * items are marked as not being in any parallel-processing list.
4886 */
4887 for (te = AH->toc->next; te != AH->toc; te = te->next)
4888 {
4889 te->depCount = te->nDeps;
4890 te->revDeps = NULL;
4891 te->nRevDeps = 0;
4892 te->pending_prev = NULL;
4893 te->pending_next = NULL;
4894 }
4895
4896 /*
4897 * POST_DATA items that are shown as depending on a table need to be
4898 * re-pointed to depend on that table's data, instead. This ensures they
4899 * won't get scheduled until the data has been loaded.
4900 */
4902
4903 /*
4904 * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB
4905 * COMMENTS to BLOBS. Cope. (We assume there's only one BLOBS and only
4906 * one BLOB COMMENTS in such files.)
4907 */
4908 if (AH->version < K_VERS_1_11)
4909 {
4910 for (te = AH->toc->next; te != AH->toc; te = te->next)
4911 {
4912 if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0)
4913 {
4914 TocEntry *te2;
4915
4916 for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next)
4917 {
4918 if (strcmp(te2->desc, "BLOBS") == 0)
4919 {
4921 te->dependencies[0] = te2->dumpId;
4922 te->nDeps++;
4923 te->depCount++;
4924 break;
4925 }
4926 }
4927 break;
4928 }
4929 }
4930 }
4931
4932 /*
4933 * At this point we start to build the revDeps reverse-dependency arrays,
4934 * so all changes of dependencies must be complete.
4935 */
4936
4937 /*
4938 * Count the incoming dependencies for each item. Also, it is possible
4939 * that the dependencies list items that are not in the archive at all
4940 * (that should not happen in 9.2 and later, but is highly likely in older
4941 * archives). Subtract such items from the depCounts.
4942 */
4943 for (te = AH->toc->next; te != AH->toc; te = te->next)
4944 {
4945 for (i = 0; i < te->nDeps; i++)
4946 {
4947 DumpId depid = te->dependencies[i];
4948
4949 if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4950 AH->tocsByDumpId[depid]->nRevDeps++;
4951 else
4952 te->depCount--;
4953 }
4954 }
4955
4956 /*
4957 * Allocate space for revDeps[] arrays, and reset nRevDeps so we can use
4958 * it as a counter below.
4959 */
4960 for (te = AH->toc->next; te != AH->toc; te = te->next)
4961 {
4962 if (te->nRevDeps > 0)
4964 te->nRevDeps = 0;
4965 }
4966
4967 /*
4968 * Build the revDeps[] arrays of incoming-dependency dumpIds. This had
4969 * better agree with the loops above.
4970 */
4971 for (te = AH->toc->next; te != AH->toc; te = te->next)
4972 {
4973 for (i = 0; i < te->nDeps; i++)
4974 {
4975 DumpId depid = te->dependencies[i];
4976
4977 if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4978 {
4980
4981 otherte->revDeps[otherte->nRevDeps++] = te->dumpId;
4982 }
4983 }
4984 }
4985
4986 /*
4987 * Lastly, work out the locking dependencies.
4988 */
4989 for (te = AH->toc->next; te != AH->toc; te = te->next)
4990 {
4991 te->lockDeps = NULL;
4992 te->nLockDeps = 0;
4994 }
4995}
static void repoint_table_dependencies(ArchiveHandle *AH)
static void identify_locking_dependencies(ArchiveHandle *AH, TocEntry *te)
#define K_VERS_1_11
struct _tocEntry * pending_next
struct _tocEntry * pending_prev

References _tocEntry::depCount, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dumpId, fb(), i, identify_locking_dependencies(), K_VERS_1_11, _tocEntry::lockDeps, _tocEntry::nDeps, _tocEntry::next, _tocEntry::nLockDeps, _tocEntry::nRevDeps, _tocEntry::pending_next, _tocEntry::pending_prev, pg_malloc_array, pg_malloc_object, repoint_table_dependencies(), _tocEntry::revDeps, _archiveHandle::toc, _archiveHandle::tocsByDumpId, and _archiveHandle::version.

Referenced by IndexSetParentIndex(), and restore_toc_entries_prefork().

◆ getTocEntryByDumpId()

TocEntry * getTocEntryByDumpId ( ArchiveHandle AH,
DumpId  id 
)

Definition at line 2035 of file pg_backup_archiver.c.

2036{
2037 /* build index arrays if we didn't already */
2038 if (AH->tocsByDumpId == NULL)
2040
2041 if (id > 0 && id <= AH->maxDumpId)
2042 return AH->tocsByDumpId[id];
2043
2044 return NULL;
2045}
static void buildTocEntryArrays(ArchiveHandle *AH)

References buildTocEntryArrays(), fb(), and _archiveHandle::tocsByDumpId.

Referenced by _PrintTocData(), _tocEntryRequired(), IssueACLPerBlob(), parseWorkerCommand(), SortTocFromFile(), and TocIDRequired().

◆ has_lock_conflicts()

static bool has_lock_conflicts ( TocEntry te1,
TocEntry te2 
)
static

Definition at line 4632 of file pg_backup_archiver.c.

4633{
4634 int j,
4635 k;
4636
4637 for (j = 0; j < te1->nLockDeps; j++)
4638 {
4639 for (k = 0; k < te2->nDeps; k++)
4640 {
4641 if (te1->lockDeps[j] == te2->dependencies[k])
4642 return true;
4643 }
4644 }
4645 return false;
4646}
int j
Definition isn.c:78

References fb(), and j.

Referenced by pop_next_work_item().

◆ identify_locking_dependencies()

static void identify_locking_dependencies ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 5042 of file pg_backup_archiver.c.

5043{
5044 DumpId *lockids;
5045 int nlockids;
5046 int i;
5047
5048 /*
5049 * We only care about this for POST_DATA items. PRE_DATA items are not
5050 * run in parallel, and DATA items are all independent by assumption.
5051 */
5052 if (te->section != SECTION_POST_DATA)
5053 return;
5054
5055 /* Quick exit if no dependencies at all */
5056 if (te->nDeps == 0)
5057 return;
5058
5059 /*
5060 * Most POST_DATA items are ALTER TABLEs or some moral equivalent of that,
5061 * and hence require exclusive lock. However, we know that CREATE INDEX
5062 * does not. (Maybe someday index-creating CONSTRAINTs will fall in that
5063 * category too ... but today is not that day.)
5064 */
5065 if (strcmp(te->desc, "INDEX") == 0)
5066 return;
5067
5068 /*
5069 * We assume the entry requires exclusive lock on each TABLE or TABLE DATA
5070 * item listed among its dependencies. Originally all of these would have
5071 * been TABLE items, but repoint_table_dependencies would have repointed
5072 * them to the TABLE DATA items if those are present (which they might not
5073 * be, eg in a schema-only dump). Note that all of the entries we are
5074 * processing here are POST_DATA; otherwise there might be a significant
5075 * difference between a dependency on a table and a dependency on its
5076 * data, so that closer analysis would be needed here.
5077 */
5079 nlockids = 0;
5080 for (i = 0; i < te->nDeps; i++)
5081 {
5082 DumpId depid = te->dependencies[i];
5083
5084 if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL &&
5085 ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) ||
5086 strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0))
5087 lockids[nlockids++] = depid;
5088 }
5089
5090 if (nlockids == 0)
5091 {
5093 return;
5094 }
5095
5097 te->nLockDeps = nlockids;
5098}
#define pg_realloc_array(pointer, type, count)
Definition fe_memutils.h:74

References _tocEntry::dependencies, _tocEntry::desc, fb(), i, _tocEntry::lockDeps, _tocEntry::nDeps, _tocEntry::nLockDeps, pg_free(), pg_malloc_array, pg_realloc_array, _tocEntry::section, SECTION_POST_DATA, and _archiveHandle::tocsByDumpId.

Referenced by fix_dependencies().

◆ inhibit_data_for_failed_table()

static void inhibit_data_for_failed_table ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 5161 of file pg_backup_archiver.c.

5162{
5163 pg_log_info("table \"%s\" could not be created, will not restore its data",
5164 te->tag);
5165
5166 if (AH->tableDataId[te->dumpId] != 0)
5167 {
5168 TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
5169
5170 ted->reqs = 0;
5171 }
5172}

References _tocEntry::dumpId, fb(), pg_log_info, _tocEntry::reqs, _archiveHandle::tableDataId, _tocEntry::tag, and _archiveHandle::tocsByDumpId.

Referenced by mark_restore_job_done(), and restore_toc_entry().

◆ InitDumpOptions()

void InitDumpOptions ( DumpOptions opts)

Definition at line 148 of file pg_backup_archiver.c.

149{
150 memset(opts, 0, sizeof(DumpOptions));
151 /* set any fields that shouldn't default to zeroes */
152 opts->include_everything = true;
153 opts->cparams.promptPassword = TRI_DEFAULT;
154 opts->dumpSections = DUMP_UNSECTIONED;
155 opts->dumpSchema = true;
156 opts->dumpData = true;
157 opts->dumpStatistics = false;
158}
#define DUMP_UNSECTIONED
@ TRI_DEFAULT
Definition vacuumlo.c:36

References DUMP_UNSECTIONED, fb(), opts, and TRI_DEFAULT.

Referenced by main(), and NewDumpOptions().

◆ is_load_via_partition_root()

static bool is_load_via_partition_root ( TocEntry te)
static

Definition at line 1190 of file pg_backup_archiver.c.

1191{
1192 if (te->defn &&
1193 strncmp(te->defn, "-- load via partition root ", 27) == 0)
1194 return true;
1195 if (te->copyStmt && *te->copyStmt)
1196 {
1197 PQExpBuffer copyStmt = createPQExpBuffer();
1198 bool result;
1199
1200 /*
1201 * Build the initial part of the COPY as it would appear if the
1202 * nominal target table is the actual target. If we see anything
1203 * else, it must be a load-via-partition-root case.
1204 */
1205 appendPQExpBuffer(copyStmt, "COPY %s ",
1206 fmtQualifiedId(te->namespace, te->tag));
1207 result = strncmp(te->copyStmt, copyStmt->data, copyStmt->len) != 0;
1208 destroyPQExpBuffer(copyStmt);
1209 return result;
1210 }
1211 /* Assume it's not load-via-partition-root */
1212 return false;
1213}
uint32 result

References appendPQExpBuffer(), _tocEntry::copyStmt, createPQExpBuffer(), PQExpBufferData::data, _tocEntry::defn, destroyPQExpBuffer(), fb(), fmtQualifiedId(), PQExpBufferData::len, result, and _tocEntry::tag.

Referenced by restore_toc_entry().

◆ mark_create_done()

static void mark_create_done ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 5146 of file pg_backup_archiver.c.

5147{
5148 if (AH->tableDataId[te->dumpId] != 0)
5149 {
5150 TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
5151
5152 ted->created = true;
5153 }
5154}

References _tocEntry::created, _tocEntry::dumpId, fb(), _archiveHandle::tableDataId, and _archiveHandle::tocsByDumpId.

Referenced by mark_restore_job_done(), and restore_toc_entry().

◆ mark_dump_job_done()

static void mark_dump_job_done ( ArchiveHandle AH,
TocEntry te,
int  status,
void callback_data 
)
static

Definition at line 2562 of file pg_backup_archiver.c.

2566{
2567 pg_log_info("finished item %d %s %s",
2568 te->dumpId, te->desc, te->tag);
2569
2570 if (status != 0)
2571 pg_fatal("worker process failed: exit code %d",
2572 status);
2573}

References _tocEntry::desc, _tocEntry::dumpId, pg_fatal, pg_log_info, and _tocEntry::tag.

Referenced by WriteDataChunks().

◆ mark_restore_job_done()

static void mark_restore_job_done ( ArchiveHandle AH,
TocEntry te,
int  status,
void callback_data 
)
static

Definition at line 4837 of file pg_backup_archiver.c.

4841{
4842 binaryheap *ready_heap = (binaryheap *) callback_data;
4843
4844 pg_log_info("finished item %d %s %s",
4845 te->dumpId, te->desc, te->tag);
4846
4847 if (status == WORKER_CREATE_DONE)
4848 mark_create_done(AH, te);
4849 else if (status == WORKER_INHIBIT_DATA)
4850 {
4852 AH->public.n_errors++;
4853 }
4854 else if (status == WORKER_IGNORED_ERRORS)
4855 AH->public.n_errors++;
4856 else if (status != 0)
4857 pg_fatal("worker process failed: exit code %d",
4858 status);
4859
4861}
static void mark_create_done(ArchiveHandle *AH, TocEntry *te)
static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te)
static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te, binaryheap *ready_heap)
#define WORKER_CREATE_DONE
#define WORKER_IGNORED_ERRORS
#define WORKER_INHIBIT_DATA

References _tocEntry::desc, _tocEntry::dumpId, fb(), inhibit_data_for_failed_table(), mark_create_done(), Archive::n_errors, pg_fatal, pg_log_info, _archiveHandle::public, reduce_dependencies(), _tocEntry::tag, WORKER_CREATE_DONE, WORKER_IGNORED_ERRORS, and WORKER_INHIBIT_DATA.

Referenced by restore_toc_entries_parallel().

◆ move_to_ready_heap()

static void move_to_ready_heap ( TocEntry pending_list,
binaryheap ready_heap,
RestorePass  pass 
)
static

Definition at line 4722 of file pg_backup_archiver.c.

4725{
4726 TocEntry *te;
4728
4729 for (te = pending_list->pending_next; te != pending_list; te = next_te)
4730 {
4731 /* must save list link before possibly removing te from list */
4732 next_te = te->pending_next;
4733
4734 if (te->depCount == 0 &&
4736 {
4737 /* Remove it from pending_list ... */
4739 /* ... and add to ready_heap */
4741 }
4742 }
4743}
void binaryheap_add(binaryheap *heap, bh_node_type d)
Definition binaryheap.c:152
static RestorePass _tocEntryRestorePass(TocEntry *te)
static void pending_list_remove(TocEntry *te)

References _tocEntryRestorePass(), binaryheap_add(), _tocEntry::depCount, fb(), pending_list_remove(), and _tocEntry::pending_next.

Referenced by restore_toc_entries_parallel().

◆ NewDumpOptions()

DumpOptions * NewDumpOptions ( void  )

Definition at line 136 of file pg_backup_archiver.c.

137{
139
141 return opts;
142}
void InitDumpOptions(DumpOptions *opts)

References InitDumpOptions(), opts, and pg_malloc_object.

Referenced by dumpOptionsFromRestoreOptions().

◆ NewRestoreOptions()

RestoreOptions * NewRestoreOptions ( void  )

Definition at line 1107 of file pg_backup_archiver.c.

1108{
1110
1112
1113 /* set any fields that shouldn't default to zeroes */
1114 opts->format = archUnknown;
1115 opts->cparams.promptPassword = TRI_DEFAULT;
1116 opts->dumpSections = DUMP_UNSECTIONED;
1117 opts->compression_spec.algorithm = PG_COMPRESSION_NONE;
1118 opts->compression_spec.level = 0;
1119 opts->dumpSchema = true;
1120 opts->dumpData = true;
1121 opts->dumpStatistics = true;
1122
1123 return opts;
1124}

References archUnknown, DUMP_UNSECTIONED, opts, PG_COMPRESSION_NONE, pg_malloc0_object, and TRI_DEFAULT.

Referenced by _CloseArchive(), and main().

◆ OpenArchive()

Archive * OpenArchive ( const char FileSpec,
const ArchiveFormat  fmt 
)

Definition at line 248 of file pg_backup_archiver.c.

249{
250 ArchiveHandle *AH;
251 pg_compress_specification compression_spec = {0};
252
253 compression_spec.algorithm = PG_COMPRESSION_NONE;
254 AH = _allocAH(FileSpec, fmt, compression_spec, true,
257
258 return (Archive *) AH;
259}
@ DATA_DIR_SYNC_METHOD_FSYNC
Definition file_utils.h:29
static void setupRestoreWorker(Archive *AHX)

References _allocAH(), pg_compress_specification::algorithm, archModeRead, DATA_DIR_SYNC_METHOD_FSYNC, fb(), PG_COMPRESSION_NONE, and setupRestoreWorker().

Referenced by main().

◆ parallel_restore()

int parallel_restore ( ArchiveHandle AH,
TocEntry te 
)

Definition at line 4814 of file pg_backup_archiver.c.

4815{
4816 int status;
4817
4818 Assert(AH->connection != NULL);
4819
4820 /* Count only errors associated with this TOC entry */
4821 AH->public.n_errors = 0;
4822
4823 /* Restore the TOC item */
4824 status = restore_toc_entry(AH, te, true);
4825
4826 return status;
4827}
static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)

References Assert, _archiveHandle::connection, fb(), Archive::n_errors, _archiveHandle::public, and restore_toc_entry().

Referenced by _WorkerJobRestoreCustom(), and _WorkerJobRestoreDirectory().

◆ pending_list_append()

static void pending_list_append ( TocEntry l,
TocEntry te 
)
static

Definition at line 4664 of file pg_backup_archiver.c.

4665{
4666 te->pending_prev = l->pending_prev;
4667 l->pending_prev->pending_next = te;
4668 l->pending_prev = te;
4669 te->pending_next = l;
4670}

References _tocEntry::pending_next, and _tocEntry::pending_prev.

Referenced by restore_toc_entries_prefork().

◆ pending_list_header_init()

static void pending_list_header_init ( TocEntry l)
static

Definition at line 4657 of file pg_backup_archiver.c.

4658{
4659 l->pending_prev = l->pending_next = l;
4660}

References _tocEntry::pending_next, and _tocEntry::pending_prev.

Referenced by RestoreArchive().

◆ pending_list_remove()

static void pending_list_remove ( TocEntry te)
static

Definition at line 4674 of file pg_backup_archiver.c.

4675{
4678 te->pending_prev = NULL;
4679 te->pending_next = NULL;
4680}

References fb(), _tocEntry::pending_next, and _tocEntry::pending_prev.

Referenced by move_to_ready_heap(), and reduce_dependencies().

◆ pop_next_work_item()

static TocEntry * pop_next_work_item ( binaryheap ready_heap,
ParallelState pstate 
)
static

Definition at line 4757 of file pg_backup_archiver.c.

4759{
4760 /*
4761 * Search the ready_heap until we find a suitable item. Note that we do a
4762 * sequential scan through the heap nodes, so even though we will first
4763 * try to choose the highest-priority item, we might end up picking
4764 * something with a much lower priority. However, we expect that we will
4765 * typically be able to pick one of the first few items, which should
4766 * usually have a relatively high priority.
4767 */
4768 for (int i = 0; i < binaryheap_size(ready_heap); i++)
4769 {
4771 bool conflicts = false;
4772
4773 /*
4774 * Check to see if the item would need exclusive lock on something
4775 * that a currently running item also needs lock on, or vice versa. If
4776 * so, we don't want to schedule them together.
4777 */
4778 for (int k = 0; k < pstate->numWorkers; k++)
4779 {
4780 TocEntry *running_te = pstate->te[k];
4781
4782 if (running_te == NULL)
4783 continue;
4784 if (has_lock_conflicts(te, running_te) ||
4786 {
4787 conflicts = true;
4788 break;
4789 }
4790 }
4791
4792 if (conflicts)
4793 continue;
4794
4795 /* passed all tests, so this item can run */
4797 return te;
4798 }
4799
4800 pg_log_debug("no item ready");
4801 return NULL;
4802}
void binaryheap_remove_node(binaryheap *heap, int n)
Definition binaryheap.c:223
#define binaryheap_size(h)
Definition binaryheap.h:66
#define binaryheap_get_node(h, n)
Definition binaryheap.h:67
static bool has_lock_conflicts(TocEntry *te1, TocEntry *te2)
TocEntry ** te
Definition parallel.h:59

References binaryheap_get_node, binaryheap_remove_node(), binaryheap_size, fb(), has_lock_conflicts(), i, ParallelState::numWorkers, pg_log_debug, and ParallelState::te.

Referenced by restore_toc_entries_parallel().

◆ PrintTOCSummary()

void PrintTOCSummary ( Archive AHX)

Definition at line 1304 of file pg_backup_archiver.c.

1305{
1306 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1307 RestoreOptions *ropt = AH->public.ropt;
1308 TocEntry *te;
1312 const char *fmtName;
1313 char stamp_str[64];
1314
1315 /* TOC is always uncompressed */
1317
1318 sav = SaveOutput(AH);
1319 if (ropt->filename)
1321
1323 localtime(&AH->createDate)) == 0)
1324 strcpy(stamp_str, "[unknown]");
1325
1326 ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
1327 ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %s\n",
1328 sanitize_line(AH->archdbname, false),
1329 AH->tocCount,
1331
1332 switch (AH->format)
1333 {
1334 case archCustom:
1335 fmtName = "CUSTOM";
1336 break;
1337 case archDirectory:
1338 fmtName = "DIRECTORY";
1339 break;
1340 case archTar:
1341 fmtName = "TAR";
1342 break;
1343 default:
1344 fmtName = "UNKNOWN";
1345 }
1346
1347 ahprintf(AH, "; Dump Version: %d.%d-%d\n",
1349 ahprintf(AH, "; Format: %s\n", fmtName);
1350 ahprintf(AH, "; Integer: %zu bytes\n", AH->intSize);
1351 ahprintf(AH, "; Offset: %zu bytes\n", AH->offSize);
1352 if (AH->archiveRemoteVersion)
1353 ahprintf(AH, "; Dumped from database version: %s\n",
1355 if (AH->archiveDumpVersion)
1356 ahprintf(AH, "; Dumped by pg_dump version: %s\n",
1357 AH->archiveDumpVersion);
1358
1359 ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");
1360
1362 for (te = AH->toc->next; te != AH->toc; te = te->next)
1363 {
1364 /* This bit must match ProcessArchiveRestoreOptions' marking logic */
1365 if (te->section != SECTION_NONE)
1366 curSection = te->section;
1367 te->reqs = _tocEntryRequired(te, curSection, AH);
1368 /* Now, should we print it? */
1369 if (ropt->verbose ||
1370 (te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0)
1371 {
1372 char *sanitized_name;
1373 char *sanitized_schema;
1374 char *sanitized_owner;
1375
1376 /*
1377 */
1378 sanitized_name = sanitize_line(te->tag, false);
1379 sanitized_schema = sanitize_line(te->namespace, true);
1380 sanitized_owner = sanitize_line(te->owner, false);
1381
1382 ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
1386
1390 }
1391 if (ropt->verbose && te->nDeps > 0)
1392 {
1393 int i;
1394
1395 ahprintf(AH, ";\tdepends on:");
1396 for (i = 0; i < te->nDeps; i++)
1397 ahprintf(AH, " %d", te->dependencies[i]);
1398 ahprintf(AH, "\n");
1399 }
1400 }
1401
1402 /* Enforce strict names checking */
1403 if (ropt->strict_names)
1404 StrictNamesCheck(ropt);
1405
1406 if (ropt->filename)
1407 RestoreOutput(AH, sav);
1408}
const char * get_compress_algorithm_name(pg_compress_algorithm algorithm)
Definition compression.c:99
@ SECTION_NONE
Definition pg_backup.h:57
enum _teSection teSection
static CompressFileHandle * SaveOutput(ArchiveHandle *AH)
static void StrictNamesCheck(RestoreOptions *ropt)
static void SetOutput(ArchiveHandle *AH, const char *filename, const pg_compress_specification compression_spec)
static void RestoreOutput(ArchiveHandle *AH, CompressFileHandle *savedOutput)
static int _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
#define ARCHIVE_MAJOR(version)
#define ARCHIVE_MINOR(version)
#define ARCHIVE_REV(version)
const char * filename
Definition pg_backup.h:121

References _tocEntryRequired(), ahprintf(), pg_compress_specification::algorithm, archCustom, _archiveHandle::archdbname, archDirectory, ARCHIVE_MAJOR, ARCHIVE_MINOR, ARCHIVE_REV, _archiveHandle::archiveDumpVersion, _archiveHandle::archiveRemoteVersion, archTar, _tocEntry::catalogId, _archiveHandle::compression_spec, _archiveHandle::createDate, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dumpId, fb(), _restoreOptions::filename, _archiveHandle::format, free, get_compress_algorithm_name(), i, _archiveHandle::intSize, _tocEntry::nDeps, _tocEntry::next, _archiveHandle::offSize, CatalogId::oid, _tocEntry::owner, PG_COMPRESSION_NONE, PGDUMP_STRFTIME_FMT, _archiveHandle::public, REQ_DATA, REQ_SCHEMA, REQ_STATS, _tocEntry::reqs, RestoreOutput(), Archive::ropt, sanitize_line(), SaveOutput(), _tocEntry::section, SECTION_NONE, SECTION_PRE_DATA, SetOutput(), _restoreOptions::strict_names, StrictNamesCheck(), CatalogId::tableoid, _tocEntry::tag, _archiveHandle::toc, _archiveHandle::tocCount, _restoreOptions::verbose, and _archiveHandle::version.

Referenced by main().

◆ ProcessArchiveRestoreOptions()

void ProcessArchiveRestoreOptions ( Archive AHX)

Definition at line 290 of file pg_backup_archiver.c.

291{
292 ArchiveHandle *AH = (ArchiveHandle *) AHX;
293 RestoreOptions *ropt = AH->public.ropt;
294 TocEntry *te;
296
297 /* Decide which TOC entries will be dumped/restored, and mark them */
299 for (te = AH->toc->next; te != AH->toc; te = te->next)
300 {
301 /*
302 * When writing an archive, we also take this opportunity to check
303 * that we have generated the entries in a sane order that respects
304 * the section divisions. When reading, don't complain, since buggy
305 * old versions of pg_dump might generate out-of-order archives.
306 */
307 if (AH->mode != archModeRead)
308 {
309 switch (te->section)
310 {
311 case SECTION_NONE:
312 /* ok to be anywhere */
313 break;
314 case SECTION_PRE_DATA:
316 pg_log_warning("archive items not in correct section order");
317 break;
318 case SECTION_DATA:
320 pg_log_warning("archive items not in correct section order");
321 break;
323 /* ok no matter which section we were in */
324 break;
325 default:
326 pg_fatal("unexpected section code %d",
327 (int) te->section);
328 break;
329 }
330 }
331
332 if (te->section != SECTION_NONE)
333 curSection = te->section;
334
335 te->reqs = _tocEntryRequired(te, curSection, AH);
336 }
337
338 /* Enforce strict names checking */
339 if (ropt->strict_names)
340 StrictNamesCheck(ropt);
341}
#define pg_log_warning(...)
Definition pgfnames.c:24

References _tocEntryRequired(), archModeRead, fb(), _archiveHandle::mode, _tocEntry::next, pg_fatal, pg_log_warning, _archiveHandle::public, _tocEntry::reqs, Archive::ropt, _tocEntry::section, SECTION_DATA, SECTION_NONE, SECTION_POST_DATA, SECTION_PRE_DATA, _restoreOptions::strict_names, StrictNamesCheck(), and _archiveHandle::toc.

Referenced by main().

◆ processEncodingEntry()

static void processEncodingEntry ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 2880 of file pg_backup_archiver.c.

2881{
2882 /* te->defn should have the form SET client_encoding = 'foo'; */
2883 char *defn = pg_strdup(te->defn);
2884 char *ptr1;
2885 char *ptr2 = NULL;
2886 int encoding;
2887
2888 ptr1 = strchr(defn, '\'');
2889 if (ptr1)
2890 ptr2 = strchr(++ptr1, '\'');
2891 if (ptr2)
2892 {
2893 *ptr2 = '\0';
2895 if (encoding < 0)
2896 pg_fatal("unrecognized encoding \"%s\"",
2897 ptr1);
2898 AH->public.encoding = encoding;
2900 }
2901 else
2902 pg_fatal("invalid ENCODING item: %s",
2903 te->defn);
2904
2905 pg_free(defn);
2906}
static char * encoding
Definition initdb.c:139
#define pg_char_to_encoding
Definition pg_wchar.h:482
void setFmtEncoding(int encoding)

References _tocEntry::defn, encoding, Archive::encoding, fb(), pg_char_to_encoding, pg_fatal, pg_free(), pg_strdup(), _archiveHandle::public, and setFmtEncoding().

Referenced by ReadToc().

◆ processSearchPathEntry()

static void processSearchPathEntry ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 2925 of file pg_backup_archiver.c.

2926{
2927 /*
2928 * te->defn should contain a command to set search_path. We just copy it
2929 * verbatim for use later.
2930 */
2931 AH->public.searchpath = pg_strdup(te->defn);
2932}

References _tocEntry::defn, pg_strdup(), _archiveHandle::public, and Archive::searchpath.

Referenced by ReadToc().

◆ processStdStringsEntry()

static void processStdStringsEntry ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 2909 of file pg_backup_archiver.c.

2910{
2911 /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2912 char *ptr1;
2913
2914 ptr1 = strchr(te->defn, '\'');
2915 if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2916 AH->public.std_strings = true;
2917 else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2918 AH->public.std_strings = false;
2919 else
2920 pg_fatal("invalid STDSTRINGS item: %s",
2921 te->defn);
2922}

References _tocEntry::defn, fb(), pg_fatal, _archiveHandle::public, and Archive::std_strings.

Referenced by ReadToc().

◆ ReadHead()

void ReadHead ( ArchiveHandle AH)

Definition at line 4181 of file pg_backup_archiver.c.

4182{
4183 char *errmsg;
4184 char vmaj,
4185 vmin,
4186 vrev;
4187 int fmt;
4188
4189 /*
4190 * If we haven't already read the header, do so.
4191 *
4192 * NB: this code must agree with _discoverArchiveFormat(). Maybe find a
4193 * way to unify the cases?
4194 */
4195 if (!AH->readHeader)
4196 {
4197 char tmpMag[7];
4198
4199 AH->ReadBufPtr(AH, tmpMag, 5);
4200
4201 if (strncmp(tmpMag, "PGDMP", 5) != 0)
4202 pg_fatal("did not find magic string in file header");
4203 }
4204
4205 vmaj = AH->ReadBytePtr(AH);
4206 vmin = AH->ReadBytePtr(AH);
4207
4208 if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
4209 vrev = AH->ReadBytePtr(AH);
4210 else
4211 vrev = 0;
4212
4214
4215 if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
4216 pg_fatal("unsupported version (%d.%d) in file header",
4217 vmaj, vmin);
4218
4219 AH->intSize = AH->ReadBytePtr(AH);
4220 if (AH->intSize > 32)
4221 pg_fatal("sanity check on integer size (%zu) failed", AH->intSize);
4222
4223 if (AH->intSize > sizeof(int))
4224 pg_log_warning("archive was made on a machine with larger integers, some operations might fail");
4225
4226 if (AH->version >= K_VERS_1_7)
4227 AH->offSize = AH->ReadBytePtr(AH);
4228 else
4229 AH->offSize = AH->intSize;
4230
4231 fmt = AH->ReadBytePtr(AH);
4232
4233 if (AH->format != fmt)
4234 pg_fatal("expected format (%d) differs from format found in file (%d)",
4235 AH->format, fmt);
4236
4237 if (AH->version >= K_VERS_1_15)
4239 else if (AH->version >= K_VERS_1_2)
4240 {
4241 /* Guess the compression method based on the level */
4242 if (AH->version < K_VERS_1_4)
4243 AH->compression_spec.level = AH->ReadBytePtr(AH);
4244 else
4245 AH->compression_spec.level = ReadInt(AH);
4246
4247 if (AH->compression_spec.level != 0)
4249 }
4250 else
4252
4254 if (errmsg)
4255 {
4256 pg_log_warning("archive is compressed, but this installation does not support compression (%s) -- no data will be available",
4257 errmsg);
4258 pg_free(errmsg);
4259 }
4260
4261 if (AH->version >= K_VERS_1_4)
4262 {
4263 struct tm crtm;
4264
4265 crtm.tm_sec = ReadInt(AH);
4266 crtm.tm_min = ReadInt(AH);
4267 crtm.tm_hour = ReadInt(AH);
4268 crtm.tm_mday = ReadInt(AH);
4269 crtm.tm_mon = ReadInt(AH);
4270 crtm.tm_year = ReadInt(AH);
4271 crtm.tm_isdst = ReadInt(AH);
4272
4273 /*
4274 * Newer versions of glibc have mktime() report failure if tm_isdst is
4275 * inconsistent with the prevailing timezone, e.g. tm_isdst = 1 when
4276 * TZ=UTC. This is problematic when restoring an archive under a
4277 * different timezone setting. If we get a failure, try again with
4278 * tm_isdst set to -1 ("don't know").
4279 *
4280 * XXX with or without this hack, we reconstruct createDate
4281 * incorrectly when the prevailing timezone is different from
4282 * pg_dump's. Next time we bump the archive version, we should flush
4283 * this representation and store a plain seconds-since-the-Epoch
4284 * timestamp instead.
4285 */
4286 AH->createDate = mktime(&crtm);
4287 if (AH->createDate == (time_t) -1)
4288 {
4289 crtm.tm_isdst = -1;
4290 AH->createDate = mktime(&crtm);
4291 if (AH->createDate == (time_t) -1)
4292 pg_log_warning("invalid creation date in header");
4293 }
4294 }
4295
4296 if (AH->version >= K_VERS_1_4)
4297 {
4298 AH->archdbname = ReadStr(AH);
4299 }
4300
4301 if (AH->version >= K_VERS_1_10)
4302 {
4303 AH->archiveRemoteVersion = ReadStr(AH);
4304 AH->archiveDumpVersion = ReadStr(AH);
4305 }
4306}
char * supports_compression(const pg_compress_specification compression_spec)
Definition compress_io.c:87
@ PG_COMPRESSION_GZIP
Definition compression.h:24
static struct pg_tm tm
Definition localtime.c:148
static char * errmsg
char * ReadStr(ArchiveHandle *AH)
int ReadInt(ArchiveHandle *AH)
#define K_VERS_1_15
#define K_VERS_1_10
#define K_VERS_1_2
#define K_VERS_1_4
#define MAKE_ARCHIVE_VERSION(major, minor, rev)
#define K_VERS_1_0
#define K_VERS_MAX
#define K_VERS_1_7
ReadBytePtrType ReadBytePtr
ReadBufPtrType ReadBufPtr
int tm_sec
Definition pgtime.h:36

References pg_compress_specification::algorithm, _archiveHandle::archdbname, _archiveHandle::archiveDumpVersion, _archiveHandle::archiveRemoteVersion, _archiveHandle::compression_spec, _archiveHandle::createDate, errmsg, fb(), _archiveHandle::format, _archiveHandle::intSize, K_VERS_1_0, K_VERS_1_10, K_VERS_1_15, K_VERS_1_2, K_VERS_1_4, K_VERS_1_7, K_VERS_MAX, pg_compress_specification::level, MAKE_ARCHIVE_VERSION, _archiveHandle::offSize, PG_COMPRESSION_GZIP, pg_fatal, pg_free(), pg_log_warning, _archiveHandle::ReadBufPtr, _archiveHandle::ReadBytePtr, _archiveHandle::readHeader, ReadInt(), ReadStr(), supports_compression(), tm, pg_tm::tm_sec, and _archiveHandle::version.

Referenced by InitArchiveFmt_Custom(), InitArchiveFmt_Directory(), and InitArchiveFmt_Tar().

◆ ReadInt()

int ReadInt ( ArchiveHandle AH)

Definition at line 2166 of file pg_backup_archiver.c.

2167{
2168 int res = 0;
2169 int bv;
2170 int sign = 0; /* Default positive */
2171 int bitShift = 0;
2172
2173 if (AH->version > K_VERS_1_0)
2174 /* Read a sign byte */
2175 sign = AH->ReadBytePtr(AH);
2176
2177 for (size_t b = 0; b < AH->intSize; b++)
2178 {
2179 bv = AH->ReadBytePtr(AH) & 0xFF;
2180 if (bv != 0)
2181 res = res + (bv << bitShift);
2182 bitShift += 8;
2183 }
2184
2185 if (sign)
2186 res = -res;
2187
2188 return res;
2189}
char sign
Definition informix.c:693
int b
Definition isn.c:74

References b, fb(), _archiveHandle::intSize, K_VERS_1_0, _archiveHandle::ReadBytePtr, sign, and _archiveHandle::version.

Referenced by _CustomReadFunc(), _LoadLOs(), _readBlockHeader(), _ReadExtraToc(), _skipData(), _skipLOs(), ReadHead(), ReadOffset(), ReadStr(), and ReadToc().

◆ ReadOffset()

int ReadOffset ( ArchiveHandle AH,
pgoff_t o 
)

Definition at line 2074 of file pg_backup_archiver.c.

2075{
2076 int i;
2077 int offsetFlg;
2078
2079 /* Initialize to zero */
2080 *o = 0;
2081
2082 /* Check for old version */
2083 if (AH->version < K_VERS_1_7)
2084 {
2085 /* Prior versions wrote offsets using WriteInt */
2086 i = ReadInt(AH);
2087 /* -1 means not set */
2088 if (i < 0)
2089 return K_OFFSET_POS_NOT_SET;
2090 else if (i == 0)
2091 return K_OFFSET_NO_DATA;
2092
2093 /* Cast to pgoff_t because it was written as an int. */
2094 *o = (pgoff_t) i;
2095 return K_OFFSET_POS_SET;
2096 }
2097
2098 /*
2099 * Read the flag indicating the state of the data pointer. Check if valid
2100 * and die if not.
2101 *
2102 * This used to be handled by a negative or zero pointer, now we use an
2103 * extra byte specifically for the state.
2104 */
2105 offsetFlg = AH->ReadBytePtr(AH) & 0xFF;
2106
2107 switch (offsetFlg)
2108 {
2110 case K_OFFSET_NO_DATA:
2111 case K_OFFSET_POS_SET:
2112
2113 break;
2114
2115 default:
2116 pg_fatal("unexpected data offset flag %d", offsetFlg);
2117 }
2118
2119 /*
2120 * Read the bytes
2121 */
2122 for (size_t off = 0; off < AH->offSize; off++)
2123 {
2124 if (off < sizeof(pgoff_t))
2125 *o |= ((pgoff_t) (AH->ReadBytePtr(AH))) << (off * 8);
2126 else
2127 {
2128 if (AH->ReadBytePtr(AH) != 0)
2129 pg_fatal("file offset in dump file is too large");
2130 }
2131 }
2132
2133 return offsetFlg;
2134}
#define K_OFFSET_NO_DATA
#define K_OFFSET_POS_NOT_SET
#define K_OFFSET_POS_SET

References fb(), i, K_OFFSET_NO_DATA, K_OFFSET_POS_NOT_SET, K_OFFSET_POS_SET, K_VERS_1_7, _archiveHandle::offSize, pg_fatal, _archiveHandle::ReadBytePtr, ReadInt(), and _archiveHandle::version.

Referenced by _ReadExtraToc().

◆ ReadStr()

char * ReadStr ( ArchiveHandle AH)

Definition at line 2211 of file pg_backup_archiver.c.

2212{
2213 char *buf;
2214 int l;
2215
2216 l = ReadInt(AH);
2217 if (l < 0)
2218 buf = NULL;
2219 else
2220 {
2221 buf = (char *) pg_malloc(l + 1);
2222 AH->ReadBufPtr(AH, buf, l);
2223
2224 buf[l] = '\0';
2225 }
2226
2227 return buf;
2228}

References buf, fb(), pg_malloc(), _archiveHandle::ReadBufPtr, and ReadInt().

Referenced by _ReadExtraToc(), _ReadExtraToc(), ReadHead(), and ReadToc().

◆ ReadToc()

void ReadToc ( ArchiveHandle AH)

Definition at line 2708 of file pg_backup_archiver.c.

2709{
2710 int i;
2711 char *tmp;
2712 DumpId *deps;
2713 int depIdx;
2714 int depSize;
2715 TocEntry *te;
2716 bool is_supported;
2717
2718 AH->tocCount = ReadInt(AH);
2719 AH->maxDumpId = 0;
2720
2721 for (i = 0; i < AH->tocCount; i++)
2722 {
2724 te->dumpId = ReadInt(AH);
2725
2726 if (te->dumpId > AH->maxDumpId)
2727 AH->maxDumpId = te->dumpId;
2728
2729 /* Sanity check */
2730 if (te->dumpId <= 0)
2731 pg_fatal("entry ID %d out of range -- perhaps a corrupt TOC",
2732 te->dumpId);
2733
2734 te->hadDumper = ReadInt(AH);
2735
2736 if (AH->version >= K_VERS_1_8)
2737 {
2738 tmp = ReadStr(AH);
2739 sscanf(tmp, "%u", &te->catalogId.tableoid);
2740 free(tmp);
2741 }
2742 else
2744 tmp = ReadStr(AH);
2745 sscanf(tmp, "%u", &te->catalogId.oid);
2746 free(tmp);
2747
2748 te->tag = ReadStr(AH);
2749 te->desc = ReadStr(AH);
2750
2751 if (AH->version >= K_VERS_1_11)
2752 {
2753 te->section = ReadInt(AH);
2754 }
2755 else
2756 {
2757 /*
2758 * Rules for pre-8.4 archives wherein pg_dump hasn't classified
2759 * the entries into sections. This list need not cover entry
2760 * types added later than 8.4.
2761 */
2762 if (strcmp(te->desc, "COMMENT") == 0 ||
2763 strcmp(te->desc, "ACL") == 0 ||
2764 strcmp(te->desc, "ACL LANGUAGE") == 0)
2765 te->section = SECTION_NONE;
2766 else if (strcmp(te->desc, "TABLE DATA") == 0 ||
2767 strcmp(te->desc, "BLOBS") == 0 ||
2768 strcmp(te->desc, "BLOB COMMENTS") == 0)
2769 te->section = SECTION_DATA;
2770 else if (strcmp(te->desc, "CONSTRAINT") == 0 ||
2771 strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2772 strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2773 strcmp(te->desc, "INDEX") == 0 ||
2774 strcmp(te->desc, "RULE") == 0 ||
2775 strcmp(te->desc, "TRIGGER") == 0)
2777 else
2779 }
2780
2781 te->defn = ReadStr(AH);
2782 te->dropStmt = ReadStr(AH);
2783
2784 if (AH->version >= K_VERS_1_3)
2785 te->copyStmt = ReadStr(AH);
2786
2787 if (AH->version >= K_VERS_1_6)
2788 te->namespace = ReadStr(AH);
2789
2790 if (AH->version >= K_VERS_1_10)
2791 te->tablespace = ReadStr(AH);
2792
2793 if (AH->version >= K_VERS_1_14)
2794 te->tableam = ReadStr(AH);
2795
2796 if (AH->version >= K_VERS_1_16)
2797 te->relkind = ReadInt(AH);
2798
2799 te->owner = ReadStr(AH);
2800 is_supported = true;
2801 if (AH->version < K_VERS_1_9)
2802 is_supported = false;
2803 else
2804 {
2805 tmp = ReadStr(AH);
2806
2807 if (strcmp(tmp, "true") == 0)
2808 is_supported = false;
2809
2810 free(tmp);
2811 }
2812
2813 if (!is_supported)
2814 pg_log_warning("restoring tables WITH OIDS is not supported anymore");
2815
2816 /* Read TOC entry dependencies */
2817 if (AH->version >= K_VERS_1_5)
2818 {
2819 depSize = 100;
2821 depIdx = 0;
2822 for (;;)
2823 {
2824 tmp = ReadStr(AH);
2825 if (!tmp)
2826 break; /* end of list */
2827 if (depIdx >= depSize)
2828 {
2829 depSize *= 2;
2830 deps = pg_realloc_array(deps, DumpId, depSize);
2831 }
2832 sscanf(tmp, "%d", &deps[depIdx]);
2833 free(tmp);
2834 depIdx++;
2835 }
2836
2837 if (depIdx > 0) /* We have a non-null entry */
2838 {
2839 deps = pg_realloc_array(deps, DumpId, depIdx);
2840 te->dependencies = deps;
2841 te->nDeps = depIdx;
2842 }
2843 else
2844 {
2845 pg_free(deps);
2846 te->dependencies = NULL;
2847 te->nDeps = 0;
2848 }
2849 }
2850 else
2851 {
2852 te->dependencies = NULL;
2853 te->nDeps = 0;
2854 }
2855 te->dataLength = 0;
2856
2857 if (AH->ReadExtraTocPtr)
2858 AH->ReadExtraTocPtr(AH, te);
2859
2860 pg_log_debug("read TOC entry %d (ID %d) for %s %s",
2861 i, te->dumpId, te->desc, te->tag);
2862
2863 /* link completed entry into TOC circular list */
2864 te->prev = AH->toc->prev;
2865 AH->toc->prev->next = te;
2866 AH->toc->prev = te;
2867 te->next = AH->toc;
2868
2869 /* special processing immediately upon read for some items */
2870 if (strcmp(te->desc, "ENCODING") == 0)
2871 processEncodingEntry(AH, te);
2872 else if (strcmp(te->desc, "STDSTRINGS") == 0)
2873 processStdStringsEntry(AH, te);
2874 else if (strcmp(te->desc, "SEARCHPATH") == 0)
2875 processSearchPathEntry(AH, te);
2876 }
2877}
static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
static void processSearchPathEntry(ArchiveHandle *AH, TocEntry *te)
static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te)
#define K_VERS_1_14
#define K_VERS_1_5
#define K_VERS_1_6
#define K_VERS_1_8
#define K_VERS_1_9
#define K_VERS_1_16
#define K_VERS_1_3
#define InvalidOid
ReadExtraTocPtrType ReadExtraTocPtr

References _tocEntry::catalogId, _tocEntry::copyStmt, _tocEntry::dataLength, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dropStmt, _tocEntry::dumpId, fb(), free, _tocEntry::hadDumper, i, InvalidOid, K_VERS_1_10, K_VERS_1_11, K_VERS_1_14, K_VERS_1_16, K_VERS_1_3, K_VERS_1_5, K_VERS_1_6, K_VERS_1_8, K_VERS_1_9, _archiveHandle::maxDumpId, _tocEntry::nDeps, _tocEntry::next, CatalogId::oid, _tocEntry::owner, pg_fatal, pg_free(), pg_log_debug, pg_log_warning, pg_malloc0_object, pg_malloc_array, pg_realloc_array, _tocEntry::prev, processEncodingEntry(), processSearchPathEntry(), processStdStringsEntry(), _archiveHandle::ReadExtraTocPtr, ReadInt(), ReadStr(), _tocEntry::relkind, _tocEntry::section, SECTION_DATA, SECTION_NONE, SECTION_POST_DATA, SECTION_PRE_DATA, _tocEntry::tableam, CatalogId::tableoid, _tocEntry::tablespace, _tocEntry::tag, _archiveHandle::toc, _archiveHandle::tocCount, and _archiveHandle::version.

Referenced by InitArchiveFmt_Custom(), InitArchiveFmt_Directory(), and InitArchiveFmt_Tar().

◆ reduce_dependencies()

static void reduce_dependencies ( ArchiveHandle AH,
TocEntry te,
binaryheap ready_heap 
)
static

Definition at line 5106 of file pg_backup_archiver.c.

5108{
5109 int i;
5110
5111 pg_log_debug("reducing dependencies for %d", te->dumpId);
5112
5113 for (i = 0; i < te->nRevDeps; i++)
5114 {
5115 TocEntry *otherte = AH->tocsByDumpId[te->revDeps[i]];
5116
5117 Assert(otherte->depCount > 0);
5118 otherte->depCount--;
5119
5120 /*
5121 * It's ready if it has no remaining dependencies, and it belongs in
5122 * the current restore pass, and it is currently a member of the
5123 * pending list (that check is needed to prevent double restore in
5124 * some cases where a list-file forces out-of-order restoring).
5125 * However, if ready_heap == NULL then caller doesn't want any list
5126 * memberships changed.
5127 */
5128 if (otherte->depCount == 0 &&
5130 otherte->pending_prev != NULL &&
5131 ready_heap != NULL)
5132 {
5133 /* Remove it from pending list ... */
5135 /* ... and add to ready_heap */
5137 }
5138 }
5139}
RestorePass restorePass

References _tocEntryRestorePass(), Assert, binaryheap_add(), _tocEntry::dumpId, fb(), i, _tocEntry::nRevDeps, pending_list_remove(), pg_log_debug, _archiveHandle::restorePass, _tocEntry::revDeps, and _archiveHandle::tocsByDumpId.

Referenced by mark_restore_job_done(), restore_toc_entries_parallel(), and restore_toc_entries_prefork().

◆ repoint_table_dependencies()

static void repoint_table_dependencies ( ArchiveHandle AH)
static

Definition at line 5008 of file pg_backup_archiver.c.

5009{
5010 TocEntry *te;
5011 int i;
5012 DumpId olddep;
5013
5014 for (te = AH->toc->next; te != AH->toc; te = te->next)
5015 {
5016 if (te->section != SECTION_POST_DATA)
5017 continue;
5018 for (i = 0; i < te->nDeps; i++)
5019 {
5020 olddep = te->dependencies[i];
5021 if (olddep <= AH->maxDumpId &&
5022 AH->tableDataId[olddep] != 0)
5023 {
5026
5027 te->dependencies[i] = tabledataid;
5028 te->dataLength = Max(te->dataLength, tabledatate->dataLength);
5029 pg_log_debug("transferring dependency %d -> %d to %d",
5030 te->dumpId, olddep, tabledataid);
5031 }
5032 }
5033 }
5034}
#define Max(x, y)
Definition c.h:1125

References _tocEntry::dataLength, _tocEntry::dependencies, _tocEntry::dumpId, fb(), i, Max, _tocEntry::nDeps, _tocEntry::next, pg_log_debug, _tocEntry::section, SECTION_POST_DATA, _archiveHandle::tableDataId, _archiveHandle::toc, and _archiveHandle::tocsByDumpId.

Referenced by fix_dependencies().

◆ restore_toc_entries_parallel()

static void restore_toc_entries_parallel ( ArchiveHandle AH,
ParallelState pstate,
TocEntry pending_list 
)
static

Definition at line 4480 of file pg_backup_archiver.c.

4482{
4485
4486 pg_log_debug("entering restore_toc_entries_parallel");
4487
4488 /* Set up ready_heap with enough room for all known TocEntrys */
4491 NULL);
4492
4493 /*
4494 * The pending_list contains all items that we need to restore. Move all
4495 * items that are available to process immediately into the ready_heap.
4496 * After this setup, the pending list is everything that needs to be done
4497 * but is blocked by one or more dependencies, while the ready heap
4498 * contains items that have no remaining dependencies and are OK to
4499 * process in the current restore pass.
4500 */
4503
4504 /*
4505 * main parent loop
4506 *
4507 * Keep going until there is no worker still running AND there is no work
4508 * left to be done. Note invariant: at top of loop, there should always
4509 * be at least one worker available to dispatch a job to.
4510 */
4511 pg_log_info("entering main parallel loop");
4512
4513 for (;;)
4514 {
4515 /* Look for an item ready to be dispatched to a worker */
4517 if (next_work_item != NULL)
4518 {
4519 /* If not to be restored, don't waste time launching a worker */
4520 if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) == 0)
4521 {
4522 pg_log_info("skipping item %d %s %s",
4523 next_work_item->dumpId,
4524 next_work_item->desc, next_work_item->tag);
4525 /* Update its dependencies as though we'd completed it */
4527 /* Loop around to see if anything else can be dispatched */
4528 continue;
4529 }
4530
4531 pg_log_info("launching item %d %s %s",
4532 next_work_item->dumpId,
4533 next_work_item->desc, next_work_item->tag);
4534
4535 /* Dispatch to some worker */
4538 }
4539 else if (IsEveryWorkerIdle(pstate))
4540 {
4541 /*
4542 * Nothing is ready and no worker is running, so we're done with
4543 * the current pass or maybe with the whole process.
4544 */
4545 if (AH->restorePass == RESTORE_PASS_LAST)
4546 break; /* No more parallel processing is possible */
4547
4548 /* Advance to next restore pass */
4549 AH->restorePass++;
4550 /* That probably allows some stuff to be made ready */
4552 /* Loop around to see if anything's now ready */
4553 continue;
4554 }
4555 else
4556 {
4557 /*
4558 * We have nothing ready, but at least one child is working, so
4559 * wait for some subjob to finish.
4560 */
4561 }
4562
4563 /*
4564 * Before dispatching another job, check to see if anything has
4565 * finished. We should check every time through the loop so as to
4566 * reduce dependencies as soon as possible. If we were unable to
4567 * dispatch any job this time through, wait until some worker finishes
4568 * (and, hopefully, unblocks some pending item). If we did dispatch
4569 * something, continue as soon as there's at least one idle worker.
4570 * Note that in either case, there's guaranteed to be at least one
4571 * idle worker when we return to the top of the loop. This ensures we
4572 * won't block inside DispatchJobForTocEntry, which would be
4573 * undesirable: we'd rather postpone dispatching until we see what's
4574 * been unblocked by finished jobs.
4575 */
4576 WaitForWorkers(AH, pstate,
4578 }
4579
4580 /* There should now be nothing in ready_heap. */
4582
4584
4585 pg_log_info("finished main parallel loop");
4586}
void WaitForWorkers(ArchiveHandle *AH, ParallelState *pstate, WFW_WaitOption mode)
Definition parallel.c:1451
void DispatchJobForTocEntry(ArchiveHandle *AH, ParallelState *pstate, TocEntry *te, T_Action act, ParallelCompletionPtr callback, void *callback_data)
Definition parallel.c:1205
bool IsEveryWorkerIdle(ParallelState *pstate)
Definition parallel.c:1268
@ WFW_GOT_STATUS
Definition parallel.h:33
@ WFW_ONE_IDLE
Definition parallel.h:34
void binaryheap_free(binaryheap *heap)
Definition binaryheap.c:73
binaryheap * binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
Definition binaryheap.c:37
#define binaryheap_empty(h)
Definition binaryheap.h:65
static void move_to_ready_heap(TocEntry *pending_list, binaryheap *ready_heap, RestorePass pass)
static void mark_restore_job_done(ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
static int TocEntrySizeCompareBinaryheap(void *p1, void *p2, void *arg)
static TocEntry * pop_next_work_item(binaryheap *ready_heap, ParallelState *pstate)
#define RESTORE_PASS_LAST
@ ACT_RESTORE

References ACT_RESTORE, Assert, binaryheap_allocate(), binaryheap_empty, binaryheap_free(), DispatchJobForTocEntry(), fb(), IsEveryWorkerIdle(), mark_restore_job_done(), move_to_ready_heap(), pg_log_debug, pg_log_info, pop_next_work_item(), reduce_dependencies(), REQ_DATA, REQ_SCHEMA, REQ_STATS, RESTORE_PASS_LAST, RESTORE_PASS_MAIN, _archiveHandle::restorePass, _archiveHandle::tocCount, TocEntrySizeCompareBinaryheap(), WaitForWorkers(), WFW_GOT_STATUS, and WFW_ONE_IDLE.

Referenced by RestoreArchive().

◆ restore_toc_entries_postfork()

static void restore_toc_entries_postfork ( ArchiveHandle AH,
TocEntry pending_list 
)
static

Definition at line 4598 of file pg_backup_archiver.c.

4599{
4600 RestoreOptions *ropt = AH->public.ropt;
4601 TocEntry *te;
4602
4603 pg_log_debug("entering restore_toc_entries_postfork");
4604
4605 /*
4606 * Now reconnect the single parent connection.
4607 */
4608 ConnectDatabaseAhx((Archive *) AH, &ropt->cparams, true);
4609
4610 /* re-establish fixed state */
4612
4613 /*
4614 * Make sure there is no work left due to, say, circular dependencies, or
4615 * some other pathological condition. If so, do it in the single parent
4616 * connection. We don't sweat about RestorePass ordering; it's likely we
4617 * already violated that.
4618 */
4619 for (te = pending_list->pending_next; te != pending_list; te = te->pending_next)
4620 {
4621 pg_log_info("processing missed item %d %s %s",
4622 te->dumpId, te->desc, te->tag);
4623 (void) restore_toc_entry(AH, te, false);
4624 }
4625}

References _doSetFixedOutputState(), ConnectDatabaseAhx(), _restoreOptions::cparams, _tocEntry::desc, _tocEntry::dumpId, fb(), _tocEntry::pending_next, pg_log_debug, pg_log_info, _archiveHandle::public, restore_toc_entry(), Archive::ropt, and _tocEntry::tag.

Referenced by RestoreArchive().

◆ restore_toc_entries_prefork()

static void restore_toc_entries_prefork ( ArchiveHandle AH,
TocEntry pending_list 
)
static

Definition at line 4357 of file pg_backup_archiver.c.

4358{
4359 bool skipped_some;
4361
4362 pg_log_debug("entering restore_toc_entries_prefork");
4363
4364 /* Adjust dependency information */
4365 fix_dependencies(AH);
4366
4367 /*
4368 * Do all the early stuff in a single connection in the parent. There's no
4369 * great point in running it in parallel, in fact it will actually run
4370 * faster in a single connection because we avoid all the connection and
4371 * setup overhead. Also, pre-9.2 pg_dump versions were not very good
4372 * about showing all the dependencies of SECTION_PRE_DATA items, so we do
4373 * not risk trying to process them out-of-order.
4374 *
4375 * Stuff that we can't do immediately gets added to the pending_list.
4376 * Note: we don't yet filter out entries that aren't going to be restored.
4377 * They might participate in dependency chains connecting entries that
4378 * should be restored, so we treat them as live until we actually process
4379 * them.
4380 *
4381 * Note: as of 9.2, it should be guaranteed that all PRE_DATA items appear
4382 * before DATA items, and all DATA items before POST_DATA items. That is
4383 * not certain to be true in older archives, though, and in any case use
4384 * of a list file would destroy that ordering (cf. SortTocFromFile). So
4385 * this loop cannot assume that it holds.
4386 */
4388 skipped_some = false;
4390 {
4391 bool do_now = true;
4392
4393 if (next_work_item->section != SECTION_PRE_DATA)
4394 {
4395 /* DATA and POST_DATA items are just ignored for now */
4396 if (next_work_item->section == SECTION_DATA ||
4398 {
4399 do_now = false;
4400 skipped_some = true;
4401 }
4402 else
4403 {
4404 /*
4405 * SECTION_NONE items, such as comments, can be processed now
4406 * if we are still in the PRE_DATA part of the archive. Once
4407 * we've skipped any items, we have to consider whether the
4408 * comment's dependencies are satisfied, so skip it for now.
4409 */
4410 if (skipped_some)
4411 do_now = false;
4412 }
4413 }
4414
4415 /*
4416 * Also skip items that need to be forced into later passes. We need
4417 * not set skipped_some in this case, since by assumption no main-pass
4418 * items could depend on these.
4419 */
4421 do_now = false;
4422
4423 if (do_now)
4424 {
4425 /* OK, restore the item and update its dependencies */
4426 pg_log_info("processing item %d %s %s",
4427 next_work_item->dumpId,
4428 next_work_item->desc, next_work_item->tag);
4429
4431
4432 /* Reduce dependencies, but don't move anything to ready_heap */
4434 }
4435 else
4436 {
4437 /* Nope, so add it to pending_list */
4439 }
4440 }
4441
4442 /*
4443 * In --transaction-size mode, we must commit the open transaction before
4444 * dropping the database connection. This also ensures that child workers
4445 * can see the objects we've created so far.
4446 */
4447 if (AH->public.ropt->txn_size > 0)
4449
4450 /*
4451 * Now close parent connection in prep for parallel steps. We do this
4452 * mainly to ensure that we don't exceed the specified number of parallel
4453 * connections.
4454 */
4456
4457 /* blow away any transient state from the old connection */
4458 free(AH->currUser);
4459 AH->currUser = NULL;
4460 free(AH->currSchema);
4461 AH->currSchema = NULL;
4462 free(AH->currTablespace);
4463 AH->currTablespace = NULL;
4464 free(AH->currTableAm);
4465 AH->currTableAm = NULL;
4466}
void DisconnectDatabase(Archive *AHX)
static void fix_dependencies(ArchiveHandle *AH)
static void pending_list_append(TocEntry *l, TocEntry *te)

References _tocEntryRestorePass(), CommitTransaction(), _archiveHandle::currSchema, _archiveHandle::currTableAm, _archiveHandle::currTablespace, _archiveHandle::currUser, DisconnectDatabase(), fb(), fix_dependencies(), free, _tocEntry::next, pending_list_append(), pg_log_debug, pg_log_info, _archiveHandle::public, reduce_dependencies(), RESTORE_PASS_MAIN, restore_toc_entry(), _archiveHandle::restorePass, Archive::ropt, SECTION_DATA, SECTION_POST_DATA, SECTION_PRE_DATA, _archiveHandle::toc, and _restoreOptions::txn_size.

Referenced by RestoreArchive().

◆ restore_toc_entry()

static int restore_toc_entry ( ArchiveHandle AH,
TocEntry te,
bool  is_parallel 
)
static

Definition at line 845 of file pg_backup_archiver.c.

846{
847 RestoreOptions *ropt = AH->public.ropt;
848 int status = WORKER_OK;
849 int reqs;
850 bool defnDumped;
851
852 AH->currentTE = te;
853
854 /* Dump any relevant dump warnings to stderr */
855 if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0)
856 {
857 if (ropt->dumpSchema && te->defn != NULL && strlen(te->defn) != 0)
858 pg_log_warning("warning from original dump file: %s", te->defn);
859 else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0)
860 pg_log_warning("warning from original dump file: %s", te->copyStmt);
861 }
862
863 /* Work out what, if anything, we want from this entry */
864 reqs = te->reqs;
865
866 defnDumped = false;
867
868 /*
869 * If it has a schema component that we want, then process that
870 */
871 if ((reqs & REQ_SCHEMA) != 0)
872 {
873 bool object_is_db = false;
874
875 /*
876 * In --transaction-size mode, must exit our transaction block to
877 * create a database or set its properties.
878 */
879 if (strcmp(te->desc, "DATABASE") == 0 ||
880 strcmp(te->desc, "DATABASE PROPERTIES") == 0)
881 {
882 object_is_db = true;
883 if (ropt->txn_size > 0)
884 {
885 if (AH->connection)
887 else
888 ahprintf(AH, "COMMIT;\n\n");
889 }
890 }
891
892 /* Show namespace in log message if available */
893 if (te->namespace)
894 pg_log_info("creating %s \"%s.%s\"",
895 te->desc, te->namespace, te->tag);
896 else
897 pg_log_info("creating %s \"%s\"",
898 te->desc, te->tag);
899
901 defnDumped = true;
902
903 if (strcmp(te->desc, "TABLE") == 0)
904 {
905 if (AH->lastErrorTE == te)
906 {
907 /*
908 * We failed to create the table. If
909 * --no-data-for-failed-tables was given, mark the
910 * corresponding TABLE DATA to be ignored.
911 *
912 * In the parallel case this must be done in the parent, so we
913 * just set the return value.
914 */
915 if (ropt->noDataForFailedTables)
916 {
917 if (is_parallel)
918 status = WORKER_INHIBIT_DATA;
919 else
921 }
922 }
923 else
924 {
925 /*
926 * We created the table successfully. Mark the corresponding
927 * TABLE DATA for possible truncation.
928 *
929 * In the parallel case this must be done in the parent, so we
930 * just set the return value.
931 */
932 if (is_parallel)
933 status = WORKER_CREATE_DONE;
934 else
935 mark_create_done(AH, te);
936 }
937 }
938
939 /*
940 * If we created a DB, connect to it. Also, if we changed DB
941 * properties, reconnect to ensure that relevant GUC settings are
942 * applied to our session. (That also restarts the transaction block
943 * in --transaction-size mode.)
944 */
945 if (object_is_db)
946 {
947 pg_log_info("connecting to new database \"%s\"", te->tag);
948 _reconnectToDB(AH, te->tag);
949 }
950 }
951
952 /*
953 * If it has a data component that we want, then process that
954 */
955 if ((reqs & REQ_DATA) != 0)
956 {
957 /*
958 * hadDumper will be set if there is genuine data component for this
959 * node. Otherwise, we need to check the defn field for statements
960 * that need to be executed in data-only restores.
961 */
962 if (te->hadDumper)
963 {
964 /*
965 * If we can output the data, then restore it.
966 */
967 if (AH->PrintTocDataPtr != NULL)
968 {
970
971 if (strcmp(te->desc, "BLOBS") == 0 ||
972 strcmp(te->desc, "BLOB COMMENTS") == 0)
973 {
974 pg_log_info("processing %s", te->desc);
975
976 _selectOutputSchema(AH, "pg_catalog");
977
978 /* Send BLOB COMMENTS data to ExecuteSimpleCommands() */
979 if (strcmp(te->desc, "BLOB COMMENTS") == 0)
981
982 AH->PrintTocDataPtr(AH, te);
983
985 }
986 else
987 {
988 bool use_truncate;
989
991
992 /* Select owner and schema as necessary */
993 _becomeOwner(AH, te);
994 _selectOutputSchema(AH, te->namespace);
995
996 pg_log_info("processing data for table \"%s.%s\"",
997 te->namespace, te->tag);
998
999 /*
1000 * In parallel restore, if we created the table earlier in
1001 * this run (so that we know it is empty) and we are not
1002 * restoring a load-via-partition-root data item then we
1003 * wrap the COPY in a transaction and precede it with a
1004 * TRUNCATE. If wal_level is set to minimal this prevents
1005 * WAL-logging the COPY. This obtains a speedup similar
1006 * to that from using single_txn mode in non-parallel
1007 * restores.
1008 *
1009 * We mustn't do this for load-via-partition-root cases
1010 * because some data might get moved across partition
1011 * boundaries, risking deadlock and/or loss of previously
1012 * loaded data. (We assume that all partitions of a
1013 * partitioned table will be treated the same way.)
1014 */
1015 use_truncate = is_parallel && te->created &&
1017
1018 if (use_truncate)
1019 {
1020 /*
1021 * Parallel restore is always talking directly to a
1022 * server, so no need to see if we should issue BEGIN.
1023 */
1025
1026 /*
1027 * Issue TRUNCATE with ONLY so that child tables are
1028 * not wiped.
1029 */
1030 ahprintf(AH, "TRUNCATE TABLE ONLY %s;\n\n",
1031 fmtQualifiedId(te->namespace, te->tag));
1032 }
1033
1034 /*
1035 * If we have a copy statement, use it.
1036 */
1037 if (te->copyStmt && strlen(te->copyStmt) > 0)
1038 {
1039 ahprintf(AH, "%s", te->copyStmt);
1041 }
1042 else
1044
1045 AH->PrintTocDataPtr(AH, te);
1046
1047 /*
1048 * Terminate COPY if needed.
1049 */
1050 if (AH->outputKind == OUTPUT_COPYDATA &&
1051 RestoringToDB(AH))
1052 EndDBCopyMode(&AH->public, te->tag);
1054
1055 /* close out the transaction started above */
1056 if (use_truncate)
1058
1060 }
1061 }
1062 }
1063 else if (!defnDumped)
1064 {
1065 /* If we haven't already dumped the defn part, do so now */
1066 pg_log_info("executing %s %s", te->desc, te->tag);
1068 }
1069 }
1070
1071 /*
1072 * If it has a statistics component that we want, then process that
1073 */
1074 if ((reqs & REQ_STATS) != 0)
1076
1077 /*
1078 * If we emitted anything for this TOC entry, that counts as one action
1079 * against the transaction-size limit. Commit if it's time to.
1080 */
1081 if ((reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 && ropt->txn_size > 0)
1082 {
1083 if (++AH->txnCount >= ropt->txn_size)
1084 {
1085 if (AH->connection)
1086 {
1089 }
1090 else
1091 ahprintf(AH, "COMMIT;\nBEGIN;\n\n");
1092 AH->txnCount = 0;
1093 }
1094 }
1095
1096 if (AH->public.n_errors > 0 && status == WORKER_OK)
1097 status = WORKER_IGNORED_ERRORS;
1098
1099 return status;
1100}
#define TOC_PREFIX_DATA
static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, const char *pfx)
#define TOC_PREFIX_STATS
static void _reconnectToDB(ArchiveHandle *AH, const char *dbname)
static bool is_load_via_partition_root(TocEntry *te)
static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te)
#define TOC_PREFIX_NONE
static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te)
#define WORKER_OK
@ OUTPUT_COPYDATA
@ OUTPUT_SQLCMDS
@ OUTPUT_OTHERDATA
void EndDBCopyMode(Archive *AHX, const char *tocEntryTag)
struct _tocEntry * lastErrorTE
struct _tocEntry * currentTE
PrintTocDataPtrType PrintTocDataPtr
ArchiverOutput outputKind
int suppressDumpWarnings
Definition pg_backup.h:152
int noDataForFailedTables
Definition pg_backup.h:148

References _becomeOwner(), _disableTriggersIfNecessary(), _enableTriggersIfNecessary(), _printTocEntry(), _reconnectToDB(), _selectOutputSchema(), ahprintf(), CommitTransaction(), _archiveHandle::connection, _tocEntry::copyStmt, _tocEntry::created, _archiveHandle::currentTE, _tocEntry::defn, _tocEntry::desc, _restoreOptions::dumpSchema, EndDBCopyMode(), fb(), fmtQualifiedId(), _tocEntry::hadDumper, inhibit_data_for_failed_table(), is_load_via_partition_root(), _archiveHandle::lastErrorTE, mark_create_done(), Archive::n_errors, _restoreOptions::noDataForFailedTables, OUTPUT_COPYDATA, OUTPUT_OTHERDATA, OUTPUT_SQLCMDS, _archiveHandle::outputKind, pg_log_info, pg_log_warning, _archiveHandle::PrintTocDataPtr, _archiveHandle::public, REQ_DATA, REQ_SCHEMA, REQ_STATS, _tocEntry::reqs, RestoringToDB(), Archive::ropt, StartTransaction(), _restoreOptions::suppressDumpWarnings, _tocEntry::tag, TOC_PREFIX_DATA, TOC_PREFIX_NONE, TOC_PREFIX_STATS, _restoreOptions::txn_size, _archiveHandle::txnCount, WORKER_CREATE_DONE, WORKER_IGNORED_ERRORS, WORKER_INHIBIT_DATA, and WORKER_OK.

Referenced by parallel_restore(), restore_toc_entries_postfork(), restore_toc_entries_prefork(), and RestoreArchive().

◆ RestoreArchive()

void RestoreArchive ( Archive AHX)

Definition at line 345 of file pg_backup_archiver.c.

346{
347 ArchiveHandle *AH = (ArchiveHandle *) AHX;
348 RestoreOptions *ropt = AH->public.ropt;
349 bool parallel_mode;
350 TocEntry *te;
352
354
355 /*
356 * If we're going to do parallel restore, there are some restrictions.
357 */
358 parallel_mode = (AH->public.numWorkers > 1 && ropt->useDB);
359 if (parallel_mode)
360 {
361 /* We haven't got round to making this work for all archive formats */
362 if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
363 pg_fatal("parallel restore is not supported with this archive file format");
364
365 /* Doesn't work if the archive represents dependencies as OIDs */
366 if (AH->version < K_VERS_1_8)
367 pg_fatal("parallel restore is not supported with archives made by pre-8.0 pg_dump");
368
369 /*
370 * It's also not gonna work if we can't reopen the input file, so
371 * let's try that immediately.
372 */
373 AH->ReopenPtr(AH);
374 }
375
376 /*
377 * Make sure we won't need (de)compression we haven't got
378 */
379 if (AH->PrintTocDataPtr != NULL)
380 {
381 for (te = AH->toc->next; te != AH->toc; te = te->next)
382 {
383 if (te->hadDumper && (te->reqs & REQ_DATA) != 0)
384 {
386
387 if (errmsg)
388 pg_fatal("cannot restore from compressed archive (%s)",
389 errmsg);
390 else
391 break;
392 }
393 }
394 }
395
396 /*
397 * Prepare index arrays, so we can assume we have them throughout restore.
398 * It's possible we already did this, though.
399 */
400 if (AH->tocsByDumpId == NULL)
402
403 /*
404 * If we're using a DB connection, then connect it.
405 */
406 if (ropt->useDB)
407 {
408 pg_log_info("connecting to database for restore");
409 if (AH->version < K_VERS_1_3)
410 pg_fatal("direct database connections are not supported in pre-1.3 archives");
411
412 /*
413 * We don't want to guess at whether the dump will successfully
414 * restore; allow the attempt regardless of the version of the restore
415 * target.
416 */
417 AHX->minRemoteVersion = 0;
418 AHX->maxRemoteVersion = 9999999;
419
420 ConnectDatabaseAhx(AHX, &ropt->cparams, false);
421
422 /*
423 * If we're talking to the DB directly, don't send comments since they
424 * obscure SQL when displaying errors
425 */
426 AH->noTocComments = 1;
427 }
428
429 /*
430 * Work out if we have an implied schema-less restore. This can happen if
431 * the dump excluded the schema or the user has used a toc list to exclude
432 * all of the schema data. All we do is look for schema entries - if none
433 * are found then we unset the dumpSchema flag.
434 *
435 * We could scan for wanted TABLE entries, but that is not the same as
436 * data-only. At this stage, it seems unnecessary (6-Mar-2001).
437 */
438 if (ropt->dumpSchema)
439 {
440 bool no_schema_found = true;
441
442 for (te = AH->toc->next; te != AH->toc; te = te->next)
443 {
444 if ((te->reqs & REQ_SCHEMA) != 0)
445 {
446 no_schema_found = false;
447 break;
448 }
449 }
450 if (no_schema_found)
451 {
452 ropt->dumpSchema = false;
453 pg_log_info("implied no-schema restore");
454 }
455 }
456
457 /*
458 * Setup the output file if necessary.
459 */
460 sav = SaveOutput(AH);
462 SetOutput(AH, ropt->filename, ropt->compression_spec);
463
464 ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n");
465
466 /*
467 * If generating plain-text output, enter restricted mode to block any
468 * unexpected psql meta-commands. A malicious source might try to inject
469 * a variety of things via bogus responses to queries. While we cannot
470 * prevent such sources from affecting the destination at restore time, we
471 * can block psql meta-commands so that the client machine that runs psql
472 * with the dump output remains unaffected.
473 */
474 if (ropt->restrict_key)
475 ahprintf(AH, "\\restrict %s\n\n", ropt->restrict_key);
476
477 if (AH->archiveRemoteVersion)
478 ahprintf(AH, "-- Dumped from database version %s\n",
480 if (AH->archiveDumpVersion)
481 ahprintf(AH, "-- Dumped by pg_dump version %s\n",
483
484 ahprintf(AH, "\n");
485
486 if (AH->public.verbose)
487 dumpTimestamp(AH, "Started on", AH->createDate);
488
489 if (ropt->single_txn)
490 {
491 if (AH->connection)
492 StartTransaction(AHX);
493 else
494 ahprintf(AH, "BEGIN;\n\n");
495 }
496
497 /*
498 * Establish important parameter values right away.
499 */
501
503
504 /*
505 * Drop the items at the start, in reverse order
506 */
507 if (ropt->dropSchema)
508 {
509 for (te = AH->toc->prev; te != AH->toc; te = te->prev)
510 {
511 AH->currentTE = te;
512
513 /*
514 * In createDB mode, issue a DROP *only* for the database as a
515 * whole. Issuing drops against anything else would be wrong,
516 * because at this point we're connected to the wrong database.
517 * (The DATABASE PROPERTIES entry, if any, should be treated like
518 * the DATABASE entry.)
519 */
520 if (ropt->createDB)
521 {
522 if (strcmp(te->desc, "DATABASE") != 0 &&
523 strcmp(te->desc, "DATABASE PROPERTIES") != 0)
524 continue;
525 }
526
527 /* Otherwise, drop anything that's selected and has a dropStmt */
528 if (((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0) && te->dropStmt)
529 {
530 bool not_allowed_in_txn = false;
531
532 pg_log_info("dropping %s %s", te->desc, te->tag);
533
534 /*
535 * In --transaction-size mode, we have to temporarily exit our
536 * transaction block to drop objects that can't be dropped
537 * within a transaction.
538 */
539 if (ropt->txn_size > 0)
540 {
541 if (strcmp(te->desc, "DATABASE") == 0 ||
542 strcmp(te->desc, "DATABASE PROPERTIES") == 0)
543 {
544 not_allowed_in_txn = true;
545 if (AH->connection)
547 else
548 ahprintf(AH, "COMMIT;\n");
549 }
550 }
551
552 /* Select owner and schema as necessary */
553 _becomeOwner(AH, te);
554 _selectOutputSchema(AH, te->namespace);
555
556 /*
557 * Now emit the DROP command, if the object has one. Note we
558 * don't necessarily emit it verbatim; at this point we add an
559 * appropriate IF EXISTS clause, if the user requested it.
560 */
561 if (strcmp(te->desc, "BLOB METADATA") == 0)
562 {
563 /* We must generate the per-blob commands */
564 if (ropt->if_exists)
565 IssueCommandPerBlob(AH, te,
566 "SELECT pg_catalog.lo_unlink(oid) "
567 "FROM pg_catalog.pg_largeobject_metadata "
568 "WHERE oid = '", "'");
569 else
570 IssueCommandPerBlob(AH, te,
571 "SELECT pg_catalog.lo_unlink('",
572 "')");
573 }
574 else if (*te->dropStmt != '\0')
575 {
576 if (!ropt->if_exists ||
577 strncmp(te->dropStmt, "--", 2) == 0)
578 {
579 /*
580 * Without --if-exists, or if it's just a comment (as
581 * happens for the public schema), print the dropStmt
582 * as-is.
583 */
584 ahprintf(AH, "%s", te->dropStmt);
585 }
586 else
587 {
588 /*
589 * Inject an appropriate spelling of "if exists". For
590 * old-style large objects, we have a routine that
591 * knows how to do it, without depending on
592 * te->dropStmt; use that. For other objects we need
593 * to parse the command.
594 */
595 if (strcmp(te->desc, "BLOB") == 0)
596 {
598 }
599 else
600 {
601 char *dropStmt = pg_strdup(te->dropStmt);
602 char *dropStmtOrig = dropStmt;
604
605 /*
606 * Need to inject IF EXISTS clause after ALTER
607 * TABLE part in ALTER TABLE .. DROP statement
608 */
609 if (strncmp(dropStmt, "ALTER TABLE", 11) == 0)
610 {
612 "ALTER TABLE IF EXISTS");
613 dropStmt = dropStmt + 11;
614 }
615
616 /*
617 * ALTER TABLE..ALTER COLUMN..DROP DEFAULT does
618 * not support the IF EXISTS clause, and therefore
619 * we simply emit the original command for DEFAULT
620 * objects (modulo the adjustment made above).
621 *
622 * Likewise, don't mess with DATABASE PROPERTIES.
623 *
624 * If we used CREATE OR REPLACE VIEW as a means of
625 * quasi-dropping an ON SELECT rule, that should
626 * be emitted unchanged as well.
627 *
628 * For other object types, we need to extract the
629 * first part of the DROP which includes the
630 * object type. Most of the time this matches
631 * te->desc, so search for that; however for the
632 * different kinds of CONSTRAINTs, we know to
633 * search for hardcoded "DROP CONSTRAINT" instead.
634 */
635 if (strcmp(te->desc, "DEFAULT") == 0 ||
636 strcmp(te->desc, "DATABASE PROPERTIES") == 0 ||
637 strncmp(dropStmt, "CREATE OR REPLACE VIEW", 22) == 0)
638 appendPQExpBufferStr(ftStmt, dropStmt);
639 else
640 {
641 char buffer[40];
642 char *mark;
643
644 if (strcmp(te->desc, "CONSTRAINT") == 0 ||
645 strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
646 strcmp(te->desc, "FK CONSTRAINT") == 0)
647 strcpy(buffer, "DROP CONSTRAINT");
648 else
649 snprintf(buffer, sizeof(buffer), "DROP %s",
650 te->desc);
651
652 mark = strstr(dropStmt, buffer);
653
654 if (mark)
655 {
656 *mark = '\0';
657 appendPQExpBuffer(ftStmt, "%s%s IF EXISTS%s",
658 dropStmt, buffer,
659 mark + strlen(buffer));
660 }
661 else
662 {
663 /* complain and emit unmodified command */
664 pg_log_warning("could not find where to insert IF EXISTS in statement \"%s\"",
666 appendPQExpBufferStr(ftStmt, dropStmt);
667 }
668 }
669
670 ahprintf(AH, "%s", ftStmt->data);
671
674 }
675 }
676 }
677
678 /*
679 * In --transaction-size mode, re-establish the transaction
680 * block if needed; otherwise, commit after every N drops.
681 */
682 if (ropt->txn_size > 0)
683 {
685 {
686 if (AH->connection)
687 StartTransaction(AHX);
688 else
689 ahprintf(AH, "BEGIN;\n");
690 AH->txnCount = 0;
691 }
692 else if (++AH->txnCount >= ropt->txn_size)
693 {
694 if (AH->connection)
695 {
697 StartTransaction(AHX);
698 }
699 else
700 ahprintf(AH, "COMMIT;\nBEGIN;\n");
701 AH->txnCount = 0;
702 }
703 }
704 }
705 }
706
707 /*
708 * _selectOutputSchema may have set currSchema to reflect the effect
709 * of a "SET search_path" command it emitted. However, by now we may
710 * have dropped that schema; or it might not have existed in the first
711 * place. In either case the effective value of search_path will not
712 * be what we think. Forcibly reset currSchema so that we will
713 * re-establish the search_path setting when needed (after creating
714 * the schema).
715 *
716 * If we treated users as pg_dump'able objects then we'd need to reset
717 * currUser here too.
718 */
719 free(AH->currSchema);
720 AH->currSchema = NULL;
721 }
722
723 if (parallel_mode)
724 {
725 /*
726 * In parallel mode, turn control over to the parallel-restore logic.
727 */
728 ParallelState *pstate;
730
731 /* The archive format module may need some setup for this */
734
736
737 /* This runs PRE_DATA items and then disconnects from the database */
739 Assert(AH->connection == NULL);
740
741 /* ParallelBackupStart() will actually fork the processes */
742 pstate = ParallelBackupStart(AH);
744 ParallelBackupEnd(AH, pstate);
745
746 /* reconnect the leader and see if we missed something */
748 Assert(AH->connection != NULL);
749 }
750 else
751 {
752 /*
753 * In serial mode, process everything in three phases: normal items,
754 * then ACLs, then post-ACL items. We might be able to skip one or
755 * both extra phases in some cases, eg data-only restores.
756 */
757 bool haveACL = false;
758 bool havePostACL = false;
759
760 for (te = AH->toc->next; te != AH->toc; te = te->next)
761 {
762 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) == 0)
763 continue; /* ignore if not to be dumped at all */
764
765 switch (_tocEntryRestorePass(te))
766 {
768 (void) restore_toc_entry(AH, te, false);
769 break;
770 case RESTORE_PASS_ACL:
771 haveACL = true;
772 break;
774 havePostACL = true;
775 break;
776 }
777 }
778
779 if (haveACL)
780 {
781 for (te = AH->toc->next; te != AH->toc; te = te->next)
782 {
783 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 &&
785 (void) restore_toc_entry(AH, te, false);
786 }
787 }
788
789 if (havePostACL)
790 {
791 for (te = AH->toc->next; te != AH->toc; te = te->next)
792 {
793 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 &&
795 (void) restore_toc_entry(AH, te, false);
796 }
797 }
798 }
799
800 /*
801 * Close out any persistent transaction we may have. While these two
802 * cases are started in different places, we can end both cases here.
803 */
804 if (ropt->single_txn || ropt->txn_size > 0)
805 {
806 if (AH->connection)
808 else
809 ahprintf(AH, "COMMIT;\n\n");
810 }
811
812 if (AH->public.verbose)
813 dumpTimestamp(AH, "Completed on", time(NULL));
814
815 ahprintf(AH, "--\n-- PostgreSQL database dump complete\n--\n\n");
816
817 /*
818 * If generating plain-text output, exit restricted mode at the very end
819 * of the script. This is not pro forma; in particular, pg_dumpall
820 * requires this when transitioning from one database to another.
821 */
822 if (ropt->restrict_key)
823 ahprintf(AH, "\\unrestrict %s\n\n", ropt->restrict_key);
824
825 /*
826 * Clean up & we're done.
827 */
829
831 RestoreOutput(AH, sav);
832
833 if (ropt->useDB)
835}
void ParallelBackupEnd(ArchiveHandle *AH, ParallelState *pstate)
Definition parallel.c:1059
ParallelState * ParallelBackupStart(ArchiveHandle *AH)
Definition parallel.c:895
static void pending_list_header_init(TocEntry *l)
static void restore_toc_entries_parallel(ArchiveHandle *AH, ParallelState *pstate, TocEntry *pending_list)
static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
static void restore_toc_entries_prefork(ArchiveHandle *AH, TocEntry *pending_list)
static void restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list)
void DropLOIfExists(ArchiveHandle *AH, Oid oid)
@ STAGE_INITIALIZING
@ STAGE_PROCESSING
@ STAGE_FINALIZING
int minRemoteVersion
Definition pg_backup.h:237
int maxRemoteVersion
Definition pg_backup.h:238
int numWorkers
Definition pg_backup.h:240
ArchiverStage stage
ClonePtrType ClonePtr
PrepParallelRestorePtrType PrepParallelRestorePtr
ReopenPtrType ReopenPtr
pg_compress_specification compression_spec
Definition pg_backup.h:150

References _becomeOwner(), _doSetFixedOutputState(), _selectOutputSchema(), _tocEntryRestorePass(), ahprintf(), pg_compress_specification::algorithm, appendPQExpBuffer(), appendPQExpBufferStr(), _archiveHandle::archiveDumpVersion, _archiveHandle::archiveRemoteVersion, Assert, buildTocEntryArrays(), _tocEntry::catalogId, _archiveHandle::ClonePtr, CommitTransaction(), _restoreOptions::compression_spec, _archiveHandle::compression_spec, ConnectDatabaseAhx(), _archiveHandle::connection, _restoreOptions::cparams, _archiveHandle::createDate, _restoreOptions::createDB, createPQExpBuffer(), _archiveHandle::currentTE, _archiveHandle::currSchema, _tocEntry::desc, destroyPQExpBuffer(), DisconnectDatabase(), DropLOIfExists(), _restoreOptions::dropSchema, _tocEntry::dropStmt, _restoreOptions::dumpSchema, dumpTimestamp(), errmsg, fb(), _restoreOptions::filename, free, _tocEntry::hadDumper, _restoreOptions::if_exists, IssueCommandPerBlob(), K_VERS_1_3, K_VERS_1_8, Archive::maxRemoteVersion, Archive::minRemoteVersion, _tocEntry::next, _archiveHandle::noTocComments, Archive::numWorkers, CatalogId::oid, ParallelBackupEnd(), ParallelBackupStart(), pending_list_header_init(), PG_COMPRESSION_NONE, pg_fatal, pg_free(), pg_log_info, pg_log_warning, pg_strdup(), _archiveHandle::PrepParallelRestorePtr, _tocEntry::prev, _archiveHandle::PrintTocDataPtr, _archiveHandle::public, _archiveHandle::ReopenPtr, REQ_DATA, REQ_SCHEMA, REQ_STATS, _tocEntry::reqs, RESTORE_PASS_ACL, RESTORE_PASS_MAIN, RESTORE_PASS_POST_ACL, restore_toc_entries_parallel(), restore_toc_entries_postfork(), restore_toc_entries_prefork(), restore_toc_entry(), RestoreOutput(), _restoreOptions::restrict_key, Archive::ropt, SaveOutput(), SetOutput(), _restoreOptions::single_txn, snprintf, _archiveHandle::stage, STAGE_FINALIZING, STAGE_INITIALIZING, STAGE_PROCESSING, StartTransaction(), supports_compression(), _tocEntry::tag, _archiveHandle::toc, _archiveHandle::tocsByDumpId, _restoreOptions::txn_size, _archiveHandle::txnCount, _restoreOptions::useDB, Archive::verbose, and _archiveHandle::version.

Referenced by _CloseArchive(), and main().

◆ RestoreOutput()

static void RestoreOutput ( ArchiveHandle AH,
CompressFileHandle savedOutput 
)
static

Definition at line 1744 of file pg_backup_archiver.c.

1745{
1746 errno = 0;
1747 if (!EndCompressFileHandle(AH->OF))
1748 pg_fatal("could not close output file: %m");
1749
1750 AH->OF = savedOutput;
1751}

References EndCompressFileHandle(), fb(), _archiveHandle::OF, and pg_fatal.

Referenced by PrintTOCSummary(), and RestoreArchive().

◆ RestoringToDB()

◆ SaveOutput()

static CompressFileHandle * SaveOutput ( ArchiveHandle AH)
static

Definition at line 1738 of file pg_backup_archiver.c.

1739{
1740 return (CompressFileHandle *) AH->OF;
1741}

References _archiveHandle::OF.

Referenced by PrintTOCSummary(), and RestoreArchive().

◆ SetArchiveOptions()

void SetArchiveOptions ( Archive AH,
DumpOptions dopt,
RestoreOptions ropt 
)

Definition at line 277 of file pg_backup_archiver.c.

278{
279 /* Caller can omit dump options, in which case we synthesize them */
280 if (dopt == NULL && ropt != NULL)
282
283 /* Save options for later access */
284 AH->dopt = dopt;
285 AH->ropt = ropt;
286}
DumpOptions * dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
DumpOptions * dopt
Definition pg_backup.h:229

References Archive::dopt, dumpOptionsFromRestoreOptions(), fb(), and Archive::ropt.

Referenced by _CloseArchive(), and main().

◆ SetOutput()

static void SetOutput ( ArchiveHandle AH,
const char filename,
const pg_compress_specification  compression_spec 
)
static

Definition at line 1698 of file pg_backup_archiver.c.

1700{
1702 const char *mode;
1703 int fn = -1;
1704
1705 if (filename)
1706 {
1707 if (strcmp(filename, "-") == 0)
1708 fn = fileno(stdout);
1709 }
1710 else if (AH->FH)
1711 fn = fileno(AH->FH);
1712 else if (AH->fSpec)
1713 {
1714 filename = AH->fSpec;
1715 }
1716 else
1717 fn = fileno(stdout);
1718
1719 if (AH->mode == archModeAppend)
1720 mode = PG_BINARY_A;
1721 else
1722 mode = PG_BINARY_W;
1723
1724 CFH = InitCompressFileHandle(compression_spec);
1725
1726 if (!CFH->open_func(filename, fn, mode, CFH))
1727 {
1728 if (filename)
1729 pg_fatal("could not open output file \"%s\": %m", filename);
1730 else
1731 pg_fatal("could not open output file: %m");
1732 }
1733
1734 AH->OF = CFH;
1735}
#define PG_BINARY_W
Definition c.h:1434
@ archModeAppend
Definition pg_backup.h:50
static void * fn(void *arg)

References archModeAppend, fb(), _archiveHandle::FH, filename, fn(), _archiveHandle::fSpec, InitCompressFileHandle(), mode, _archiveHandle::mode, _archiveHandle::OF, PG_BINARY_A, PG_BINARY_W, and pg_fatal.

Referenced by PrintTOCSummary(), and RestoreArchive().

◆ setupRestoreWorker()

static void setupRestoreWorker ( Archive AHX)
static

Definition at line 221 of file pg_backup_archiver.c.

222{
223 ArchiveHandle *AH = (ArchiveHandle *) AHX;
224
225 AH->ReopenPtr(AH);
226}

References _archiveHandle::ReopenPtr.

Referenced by OpenArchive().

◆ SortTocFromFile()

void SortTocFromFile ( Archive AHX)

Definition at line 1571 of file pg_backup_archiver.c.

1572{
1573 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1574 RestoreOptions *ropt = AH->public.ropt;
1575 FILE *fh;
1577
1578 /* Allocate space for the 'wanted' array, and init it */
1579 ropt->idWanted = pg_malloc0_array(bool, AH->maxDumpId);
1580
1581 /* Setup the file */
1582 fh = fopen(ropt->tocFile, PG_BINARY_R);
1583 if (!fh)
1584 pg_fatal("could not open TOC file \"%s\": %m", ropt->tocFile);
1585
1587
1588 while (pg_get_line_buf(fh, &linebuf))
1589 {
1590 char *cmnt;
1591 char *endptr;
1592 DumpId id;
1593 TocEntry *te;
1594
1595 /* Truncate line at comment, if any */
1596 cmnt = strchr(linebuf.data, ';');
1597 if (cmnt != NULL)
1598 {
1599 cmnt[0] = '\0';
1600 linebuf.len = cmnt - linebuf.data;
1601 }
1602
1603 /* Ignore if all blank */
1604 if (strspn(linebuf.data, " \t\r\n") == linebuf.len)
1605 continue;
1606
1607 /* Get an ID, check it's valid and not already seen */
1608 id = strtol(linebuf.data, &endptr, 10);
1609 if (endptr == linebuf.data || id <= 0 || id > AH->maxDumpId ||
1610 ropt->idWanted[id - 1])
1611 {
1612 pg_log_warning("line ignored: %s", linebuf.data);
1613 continue;
1614 }
1615
1616 /* Find TOC entry */
1617 te = getTocEntryByDumpId(AH, id);
1618 if (!te)
1619 pg_fatal("could not find entry for ID %d",
1620 id);
1621
1622 /* Mark it wanted */
1623 ropt->idWanted[id - 1] = true;
1624
1625 /*
1626 * Move each item to the end of the list as it is selected, so that
1627 * they are placed in the desired order. Any unwanted items will end
1628 * up at the front of the list, which may seem unintuitive but it's
1629 * what we need. In an ordinary serial restore that makes no
1630 * difference, but in a parallel restore we need to mark unrestored
1631 * items' dependencies as satisfied before we start examining
1632 * restorable items. Otherwise they could have surprising
1633 * side-effects on the order in which restorable items actually get
1634 * restored.
1635 */
1636 _moveBefore(AH->toc, te);
1637 }
1638
1639 pg_free(linebuf.data);
1640
1641 if (fclose(fh) != 0)
1642 pg_fatal("could not close TOC file: %m");
1643}
static void _moveBefore(TocEntry *pos, TocEntry *te)
bool pg_get_line_buf(FILE *stream, StringInfo buf)
Definition pg_get_line.c:95
void initStringInfo(StringInfo str)
Definition stringinfo.c:97

References _moveBefore(), fb(), getTocEntryByDumpId(), _restoreOptions::idWanted, initStringInfo(), _archiveHandle::maxDumpId, PG_BINARY_R, pg_fatal, pg_free(), pg_get_line_buf(), pg_log_warning, pg_malloc0_array, _archiveHandle::public, Archive::ropt, _archiveHandle::toc, and _restoreOptions::tocFile.

Referenced by main().

◆ StartLO()

int StartLO ( Archive AHX,
Oid  oid 
)

Definition at line 1416 of file pg_backup_archiver.c.

1417{
1418 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1419
1420 if (!AH->StartLOPtr)
1421 pg_fatal("large-object output not supported in chosen format");
1422
1423 AH->StartLOPtr(AH, AH->currToc, oid);
1424
1425 return 1;
1426}
StartLOPtrType StartLOPtr

References _archiveHandle::currToc, pg_fatal, and _archiveHandle::StartLOPtr.

Referenced by dumpLOs().

◆ StartRestoreLO()

void StartRestoreLO ( ArchiveHandle AH,
Oid  oid,
bool  drop 
)

Definition at line 1495 of file pg_backup_archiver.c.

1496{
1497 bool old_lo_style = (AH->version < K_VERS_1_12);
1498 Oid loOid;
1499
1500 AH->loCount++;
1501
1502 /* Initialize the LO Buffer */
1503 if (AH->lo_buf == NULL)
1504 {
1505 /* First time through (in this process) so allocate the buffer */
1506 AH->lo_buf_size = LOBBUFSIZE;
1508 }
1509 AH->lo_buf_used = 0;
1510
1511 pg_log_info("restoring large object with OID %u", oid);
1512
1513 /* With an old archive we must do drop and create logic here */
1514 if (old_lo_style && drop)
1515 DropLOIfExists(AH, oid);
1516
1517 if (AH->connection)
1518 {
1519 if (old_lo_style)
1520 {
1521 loOid = lo_create(AH->connection, oid);
1522 if (loOid == 0 || loOid != oid)
1523 pg_fatal("could not create large object %u: %s",
1524 oid, PQerrorMessage(AH->connection));
1525 }
1526 AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
1527 if (AH->loFd == -1)
1528 pg_fatal("could not open large object %u: %s",
1529 oid, PQerrorMessage(AH->connection));
1530 }
1531 else
1532 {
1533 if (old_lo_style)
1534 ahprintf(AH, "SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n",
1535 oid, INV_WRITE);
1536 else
1537 ahprintf(AH, "SELECT pg_catalog.lo_open('%u', %d);\n",
1538 oid, INV_WRITE);
1539 }
1540
1541 AH->writingLO = true;
1542}
int lo_open(PGconn *conn, Oid lobjId, int mode)
Definition fe-lobj.c:57
Oid lo_create(PGconn *conn, Oid lobjId)
Definition fe-lobj.c:474
#define INV_WRITE
Definition libpq-fs.h:21
#define LOBBUFSIZE
#define K_VERS_1_12
unsigned int Oid

References ahprintf(), _archiveHandle::connection, DropLOIfExists(), fb(), INV_WRITE, K_VERS_1_12, _archiveHandle::lo_buf, _archiveHandle::lo_buf_size, _archiveHandle::lo_buf_used, lo_create(), lo_open(), LOBBUFSIZE, _archiveHandle::loCount, _archiveHandle::loFd, pg_fatal, pg_log_info, pg_malloc(), PQerrorMessage(), _archiveHandle::version, and _archiveHandle::writingLO.

Referenced by _LoadLOs(), _LoadLOs(), and _LoadLOs().

◆ StartRestoreLOs()

void StartRestoreLOs ( ArchiveHandle AH)

Definition at line 1448 of file pg_backup_archiver.c.

1449{
1450 RestoreOptions *ropt = AH->public.ropt;
1451
1452 /*
1453 * LOs must be restored within a transaction block, since we need the LO
1454 * handle to stay open while we write it. Establish a transaction unless
1455 * there's one being used globally.
1456 */
1457 if (!(ropt->single_txn || ropt->txn_size > 0))
1458 {
1459 if (AH->connection)
1461 else
1462 ahprintf(AH, "BEGIN;\n\n");
1463 }
1464
1465 AH->loCount = 0;
1466}

References ahprintf(), _archiveHandle::connection, _archiveHandle::loCount, _archiveHandle::public, Archive::ropt, _restoreOptions::single_txn, StartTransaction(), and _restoreOptions::txn_size.

Referenced by _LoadLOs(), _LoadLOs(), and _LoadLOs().

◆ StrictNamesCheck()

static void StrictNamesCheck ( RestoreOptions ropt)
static

Definition at line 2935 of file pg_backup_archiver.c.

2936{
2937 const char *missing_name;
2938
2939 Assert(ropt->strict_names);
2940
2941 if (ropt->schemaNames.head != NULL)
2942 {
2944 if (missing_name != NULL)
2945 pg_fatal("schema \"%s\" not found", missing_name);
2946 }
2947
2948 if (ropt->tableNames.head != NULL)
2949 {
2951 if (missing_name != NULL)
2952 pg_fatal("table \"%s\" not found", missing_name);
2953 }
2954
2955 if (ropt->indexNames.head != NULL)
2956 {
2958 if (missing_name != NULL)
2959 pg_fatal("index \"%s\" not found", missing_name);
2960 }
2961
2962 if (ropt->functionNames.head != NULL)
2963 {
2965 if (missing_name != NULL)
2966 pg_fatal("function \"%s\" not found", missing_name);
2967 }
2968
2969 if (ropt->triggerNames.head != NULL)
2970 {
2972 if (missing_name != NULL)
2973 pg_fatal("trigger \"%s\" not found", missing_name);
2974 }
2975}
const char * simple_string_list_not_touched(SimpleStringList *list)

References Assert, fb(), _restoreOptions::functionNames, SimpleStringList::head, _restoreOptions::indexNames, pg_fatal, _restoreOptions::schemaNames, simple_string_list_not_touched(), _restoreOptions::strict_names, _restoreOptions::tableNames, and _restoreOptions::triggerNames.

Referenced by PrintTOCSummary(), and ProcessArchiveRestoreOptions().

◆ TocEntrySizeCompareBinaryheap()

static int TocEntrySizeCompareBinaryheap ( void p1,
void p2,
void arg 
)
static

Definition at line 4707 of file pg_backup_archiver.c.

4708{
4709 /* return opposite of qsort comparator for max-heap */
4710 return -TocEntrySizeCompareQsort(&p1, &p2);
4711}
static int TocEntrySizeCompareQsort(const void *p1, const void *p2)

References fb(), and TocEntrySizeCompareQsort().

Referenced by restore_toc_entries_parallel().

◆ TocEntrySizeCompareQsort()

static int TocEntrySizeCompareQsort ( const void p1,
const void p2 
)
static

Definition at line 4685 of file pg_backup_archiver.c.

4686{
4687 const TocEntry *te1 = *(const TocEntry *const *) p1;
4688 const TocEntry *te2 = *(const TocEntry *const *) p2;
4689
4690 /* Sort by decreasing dataLength */
4691 if (te1->dataLength > te2->dataLength)
4692 return -1;
4693 if (te1->dataLength < te2->dataLength)
4694 return 1;
4695
4696 /* For equal dataLengths, sort by dumpId, just to be stable */
4697 if (te1->dumpId < te2->dumpId)
4698 return -1;
4699 if (te1->dumpId > te2->dumpId)
4700 return 1;
4701
4702 return 0;
4703}

References fb().

Referenced by TocEntrySizeCompareBinaryheap(), and WriteDataChunks().

◆ TocIDRequired()

int TocIDRequired ( ArchiveHandle AH,
DumpId  id 
)

Definition at line 2048 of file pg_backup_archiver.c.

2049{
2050 TocEntry *te = getTocEntryByDumpId(AH, id);
2051
2052 if (!te)
2053 return 0;
2054
2055 return te->reqs;
2056}

References getTocEntryByDumpId(), and _tocEntry::reqs.

Referenced by _tarPositionTo(), and findDumpableDependencies().

◆ warn_or_exit_horribly()

void warn_or_exit_horribly ( ArchiveHandle AH,
const char fmt,
  ... 
)

Definition at line 1897 of file pg_backup_archiver.c.

1898{
1899 /* Stay quiet if this is a result of our own cancellation. */
1900 if (!is_cancel_in_progress())
1901 {
1902 va_list ap;
1903
1904 switch (AH->stage)
1905 {
1906
1907 case STAGE_NONE:
1908 /* Do nothing special */
1909 break;
1910
1911 case STAGE_INITIALIZING:
1912 if (AH->stage != AH->lastErrorStage)
1913 pg_log_info("while INITIALIZING:");
1914 break;
1915
1916 case STAGE_PROCESSING:
1917 if (AH->stage != AH->lastErrorStage)
1918 pg_log_info("while PROCESSING TOC:");
1919 break;
1920
1921 case STAGE_FINALIZING:
1922 if (AH->stage != AH->lastErrorStage)
1923 pg_log_info("while FINALIZING:");
1924 break;
1925 }
1926 if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE)
1927 {
1928 pg_log_info("from TOC entry %d; %u %u %s %s %s",
1929 AH->currentTE->dumpId,
1931 AH->currentTE->catalogId.oid,
1932 AH->currentTE->desc ? AH->currentTE->desc : "(no desc)",
1933 AH->currentTE->tag ? AH->currentTE->tag : "(no tag)",
1934 AH->currentTE->owner ? AH->currentTE->owner : "(no owner)");
1935 }
1936
1937 va_start(ap, fmt);
1939 va_end(ap);
1940 }
1941
1942 AH->lastErrorStage = AH->stage;
1943 AH->lastErrorTE = AH->currentTE;
1944
1945 if (AH->public.exit_on_error)
1946 exit_nicely(1);
1947 else
1948 AH->public.n_errors++;
1949}
void pg_log_generic_v(enum pg_log_level level, enum pg_log_part part, const char *pg_restrict fmt, va_list ap)
Definition logging.c:233
@ PG_LOG_PRIMARY
Definition logging.h:67
@ PG_LOG_ERROR
Definition logging.h:43
@ STAGE_NONE
void exit_nicely(int code)
#define is_cancel_in_progress()
ArchiverStage lastErrorStage

References _tocEntry::catalogId, _archiveHandle::currentTE, _tocEntry::desc, _tocEntry::dumpId, exit_nicely(), Archive::exit_on_error, fb(), is_cancel_in_progress, _archiveHandle::lastErrorStage, _archiveHandle::lastErrorTE, Archive::n_errors, CatalogId::oid, _tocEntry::owner, PG_LOG_ERROR, pg_log_generic_v(), pg_log_info, PG_LOG_PRIMARY, _archiveHandle::public, _archiveHandle::stage, STAGE_FINALIZING, STAGE_INITIALIZING, STAGE_NONE, STAGE_PROCESSING, CatalogId::tableoid, and _tocEntry::tag.

Referenced by _printTableAccessMethodNoStorage(), _selectOutputSchema(), _selectTableAccessMethod(), _selectTablespace(), dump_lo_buf(), EndDBCopyMode(), and ExecuteSqlCommand().

◆ WriteData()

void WriteData ( Archive AHX,
const void data,
size_t  dLen 
)

Definition at line 1221 of file pg_backup_archiver.c.

1222{
1223 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1224
1225 if (!AH->currToc)
1226 pg_fatal("internal error -- WriteData cannot be called outside the context of a DataDumper routine");
1227
1228 AH->WriteDataPtr(AH, data, dLen);
1229}
const void * data
WriteDataPtrType WriteDataPtr

References _archiveHandle::currToc, data, fb(), pg_fatal, and _archiveHandle::WriteDataPtr.

Referenced by archprintf(), archputs(), dumpLOs(), and dumpTableData_copy().

◆ WriteDataChunks()

void WriteDataChunks ( ArchiveHandle AH,
ParallelState pstate 
)

Definition at line 2496 of file pg_backup_archiver.c.

2497{
2498 TocEntry *te;
2499
2500 if (pstate && pstate->numWorkers > 1)
2501 {
2502 /*
2503 * In parallel mode, this code runs in the leader process. We
2504 * construct an array of candidate TEs, then sort it into decreasing
2505 * size order, then dispatch each TE to a data-transfer worker. By
2506 * dumping larger tables first, we avoid getting into a situation
2507 * where we're down to one job and it's big, losing parallelism.
2508 */
2509 TocEntry **tes;
2510 int ntes;
2511
2513 ntes = 0;
2514 for (te = AH->toc->next; te != AH->toc; te = te->next)
2515 {
2516 /* Consider only TEs with dataDumper functions ... */
2517 if (!te->dataDumper)
2518 continue;
2519 /* ... and ignore ones not enabled for dump */
2520 if ((te->reqs & REQ_DATA) == 0)
2521 continue;
2522
2523 tes[ntes++] = te;
2524 }
2525
2526 if (ntes > 1)
2528
2529 for (int i = 0; i < ntes; i++)
2530 DispatchJobForTocEntry(AH, pstate, tes[i], ACT_DUMP,
2532
2533 pg_free(tes);
2534
2535 /* Now wait for workers to finish. */
2536 WaitForWorkers(AH, pstate, WFW_ALL_IDLE);
2537 }
2538 else
2539 {
2540 /* Non-parallel mode: just dump all candidate TEs sequentially. */
2541 for (te = AH->toc->next; te != AH->toc; te = te->next)
2542 {
2543 /* Must have same filter conditions as above */
2544 if (!te->dataDumper)
2545 continue;
2546 if ((te->reqs & REQ_DATA) == 0)
2547 continue;
2548
2550 }
2551 }
2552}
@ WFW_ALL_IDLE
Definition parallel.h:35
void WriteDataChunksForTocEntry(ArchiveHandle *AH, TocEntry *te)
static void mark_dump_job_done(ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
#define qsort(a, b, c, d)
Definition port.h:496
DataDumperPtr dataDumper

References ACT_DUMP, _tocEntry::dataDumper, DispatchJobForTocEntry(), fb(), i, mark_dump_job_done(), _tocEntry::next, ParallelState::numWorkers, pg_free(), pg_malloc_array, qsort, REQ_DATA, _tocEntry::reqs, _archiveHandle::toc, _archiveHandle::tocCount, TocEntrySizeCompareQsort(), WaitForWorkers(), WFW_ALL_IDLE, and WriteDataChunksForTocEntry().

Referenced by _CloseArchive(), _CloseArchive(), and _CloseArchive().

◆ WriteDataChunksForTocEntry()

void WriteDataChunksForTocEntry ( ArchiveHandle AH,
TocEntry te 
)

Definition at line 2577 of file pg_backup_archiver.c.

2578{
2581
2582 AH->currToc = te;
2583
2584 if (strcmp(te->desc, "BLOBS") == 0)
2585 {
2586 startPtr = AH->StartLOsPtr;
2587 endPtr = AH->EndLOsPtr;
2588 }
2589 else
2590 {
2591 startPtr = AH->StartDataPtr;
2592 endPtr = AH->EndDataPtr;
2593 }
2594
2595 if (startPtr != NULL)
2596 (*startPtr) (AH, te);
2597
2598 /*
2599 * The user-provided DataDumper routine needs to call AH->WriteData
2600 */
2601 te->dataDumper((Archive *) AH, te->dataDumperArg);
2602
2603 if (endPtr != NULL)
2604 (*endPtr) (AH, te);
2605
2606 AH->currToc = NULL;
2607}
void(* EndDataPtrType)(ArchiveHandle *AH, TocEntry *te)
void(* StartDataPtrType)(ArchiveHandle *AH, TocEntry *te)
EndLOsPtrType EndLOsPtr
StartLOsPtrType StartLOsPtr
StartDataPtrType StartDataPtr
EndDataPtrType EndDataPtr
const void * dataDumperArg

References _archiveHandle::currToc, _tocEntry::dataDumper, _tocEntry::dataDumperArg, _tocEntry::desc, _archiveHandle::EndDataPtr, _archiveHandle::EndLOsPtr, fb(), _archiveHandle::StartDataPtr, and _archiveHandle::StartLOsPtr.

Referenced by _WorkerJobDumpDirectory(), and WriteDataChunks().

◆ WriteHead()

void WriteHead ( ArchiveHandle AH)

Definition at line 4155 of file pg_backup_archiver.c.

4156{
4157 struct tm crtm;
4158
4159 AH->WriteBufPtr(AH, "PGDMP", 5); /* Magic code */
4160 AH->WriteBytePtr(AH, ARCHIVE_MAJOR(AH->version));
4161 AH->WriteBytePtr(AH, ARCHIVE_MINOR(AH->version));
4162 AH->WriteBytePtr(AH, ARCHIVE_REV(AH->version));
4163 AH->WriteBytePtr(AH, AH->intSize);
4164 AH->WriteBytePtr(AH, AH->offSize);
4165 AH->WriteBytePtr(AH, AH->format);
4167 crtm = *localtime(&AH->createDate);
4168 WriteInt(AH, crtm.tm_sec);
4169 WriteInt(AH, crtm.tm_min);
4170 WriteInt(AH, crtm.tm_hour);
4171 WriteInt(AH, crtm.tm_mday);
4172 WriteInt(AH, crtm.tm_mon);
4173 WriteInt(AH, crtm.tm_year);
4174 WriteInt(AH, crtm.tm_isdst);
4175 WriteStr(AH, PQdb(AH->connection));
4177 WriteStr(AH, PG_VERSION);
4178}
char * PQdb(const PGconn *conn)
size_t WriteInt(ArchiveHandle *AH, int i)
size_t WriteStr(ArchiveHandle *AH, const char *c)
char * remoteVersionStr
Definition pg_backup.h:233
WriteBufPtrType WriteBufPtr
WriteBytePtrType WriteBytePtr

References pg_compress_specification::algorithm, ARCHIVE_MAJOR, ARCHIVE_MINOR, ARCHIVE_REV, _archiveHandle::compression_spec, _archiveHandle::connection, _archiveHandle::createDate, fb(), _archiveHandle::format, _archiveHandle::intSize, _archiveHandle::offSize, PQdb(), _archiveHandle::public, Archive::remoteVersionStr, tm, _archiveHandle::version, _archiveHandle::WriteBufPtr, _archiveHandle::WriteBytePtr, WriteInt(), and WriteStr().

Referenced by _CloseArchive(), _CloseArchive(), and _CloseArchive().

◆ WriteInt()

size_t WriteInt ( ArchiveHandle AH,
int  i 
)

Definition at line 2137 of file pg_backup_archiver.c.

2138{
2139 /*
2140 * This is a bit yucky, but I don't want to make the binary format very
2141 * dependent on representation, and not knowing much about it, I write out
2142 * a sign byte. If you change this, don't forget to change the file
2143 * version #, and modify ReadInt to read the new format AS WELL AS the old
2144 * formats.
2145 */
2146
2147 /* SIGN byte */
2148 if (i < 0)
2149 {
2150 AH->WriteBytePtr(AH, 1);
2151 i = -i;
2152 }
2153 else
2154 AH->WriteBytePtr(AH, 0);
2155
2156 for (size_t b = 0; b < AH->intSize; b++)
2157 {
2158 AH->WriteBytePtr(AH, i & 0xFF);
2159 i >>= 8;
2160 }
2161
2162 return AH->intSize + 1;
2163}

References b, i, _archiveHandle::intSize, and _archiveHandle::WriteBytePtr.

Referenced by _CustomWriteFunc(), _EndData(), _EndLO(), _EndLOs(), _StartData(), _StartLO(), _StartLOs(), WriteHead(), WriteStr(), and WriteToc().

◆ WriteOffset()

size_t WriteOffset ( ArchiveHandle AH,
pgoff_t  o,
int  wasSet 
)

Definition at line 2059 of file pg_backup_archiver.c.

2060{
2061 /* Save the flag */
2062 AH->WriteBytePtr(AH, wasSet);
2063
2064 /* Write out pgoff_t smallest byte first, prevents endian mismatch */
2065 for (size_t off = 0; off < sizeof(pgoff_t); off++)
2066 {
2067 AH->WriteBytePtr(AH, o & 0xFF);
2068 o >>= 8;
2069 }
2070 return sizeof(pgoff_t) + 1;
2071}

References fb(), and _archiveHandle::WriteBytePtr.

Referenced by _WriteExtraToc().

◆ WriteStr()

size_t WriteStr ( ArchiveHandle AH,
const char c 
)

Definition at line 2192 of file pg_backup_archiver.c.

2193{
2194 size_t res;
2195
2196 if (c)
2197 {
2198 int len = strlen(c);
2199
2200 res = WriteInt(AH, len);
2201 AH->WriteBufPtr(AH, c, len);
2202 res += len;
2203 }
2204 else
2205 res = WriteInt(AH, -1);
2206
2207 return res;
2208}
char * c

References fb(), len, _archiveHandle::WriteBufPtr, and WriteInt().

Referenced by _WriteExtraToc(), _WriteExtraToc(), WriteHead(), and WriteToc().

◆ WriteToc()

void WriteToc ( ArchiveHandle AH)

Definition at line 2610 of file pg_backup_archiver.c.

2611{
2612 TocEntry *te;
2613 char workbuf[32];
2614 int tocCount;
2615 int i;
2616
2617 /* count entries that will actually be dumped */
2618 tocCount = 0;
2619 for (te = AH->toc->next; te != AH->toc; te = te->next)
2620 {
2621 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS | REQ_SPECIAL)) != 0)
2622 tocCount++;
2623 }
2624
2625 /* printf("%d TOC Entries to save\n", tocCount); */
2626
2627 WriteInt(AH, tocCount);
2628
2629 for (te = AH->toc->next; te != AH->toc; te = te->next)
2630 {
2631 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS | REQ_SPECIAL)) == 0)
2632 continue;
2633
2634 WriteInt(AH, te->dumpId);
2635 WriteInt(AH, te->dataDumper ? 1 : 0);
2636
2637 /* OID is recorded as a string for historical reasons */
2638 sprintf(workbuf, "%u", te->catalogId.tableoid);
2639 WriteStr(AH, workbuf);
2640 sprintf(workbuf, "%u", te->catalogId.oid);
2641 WriteStr(AH, workbuf);
2642
2643 WriteStr(AH, te->tag);
2644 WriteStr(AH, te->desc);
2645 WriteInt(AH, te->section);
2646
2647 if (te->defnLen)
2648 {
2649 /*
2650 * defnLen should only be set for custom format's second call to
2651 * WriteToc(), which rewrites the TOC in place to update data
2652 * offsets. Instead of calling the defnDumper a second time
2653 * (which could involve re-executing queries), just skip writing
2654 * the entry. While regenerating the definition should
2655 * theoretically produce the same result as before, it's expensive
2656 * and feels risky.
2657 *
2658 * The custom format only calls WriteToc() a second time if
2659 * fseeko() is usable (see _CloseArchive() in pg_backup_custom.c),
2660 * so we can safely use it without checking. For other formats,
2661 * we fail because one of our assumptions must no longer hold
2662 * true.
2663 *
2664 * XXX This is a layering violation, but the alternative is an
2665 * awkward and complicated callback infrastructure for this
2666 * special case. This might be worth revisiting in the future.
2667 */
2668 if (AH->format != archCustom)
2669 pg_fatal("unexpected TOC entry in WriteToc(): %d %s %s",
2670 te->dumpId, te->desc, te->tag);
2671
2672 if (fseeko(AH->FH, te->defnLen, SEEK_CUR) != 0)
2673 pg_fatal("error during file seek: %m");
2674 }
2675 else if (te->defnDumper)
2676 {
2677 char *defn = te->defnDumper((Archive *) AH, te->defnDumperArg, te);
2678
2679 te->defnLen = WriteStr(AH, defn);
2680 pg_free(defn);
2681 }
2682 else
2683 WriteStr(AH, te->defn);
2684
2685 WriteStr(AH, te->dropStmt);
2686 WriteStr(AH, te->copyStmt);
2687 WriteStr(AH, te->namespace);
2688 WriteStr(AH, te->tablespace);
2689 WriteStr(AH, te->tableam);
2690 WriteInt(AH, te->relkind);
2691 WriteStr(AH, te->owner);
2692 WriteStr(AH, "false");
2693
2694 /* Dump list of dependencies */
2695 for (i = 0; i < te->nDeps; i++)
2696 {
2697 sprintf(workbuf, "%d", te->dependencies[i]);
2698 WriteStr(AH, workbuf);
2699 }
2700 WriteStr(AH, NULL); /* Terminate List */
2701
2702 if (AH->WriteExtraTocPtr)
2703 AH->WriteExtraTocPtr(AH, te);
2704 }
2705}
#define sprintf
Definition port.h:263
WriteExtraTocPtrType WriteExtraTocPtr

References archCustom, _tocEntry::catalogId, _tocEntry::copyStmt, _tocEntry::dataDumper, _tocEntry::defn, _tocEntry::defnDumper, _tocEntry::defnDumperArg, _tocEntry::defnLen, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dropStmt, _tocEntry::dumpId, fb(), _archiveHandle::FH, _archiveHandle::format, fseeko, i, _tocEntry::nDeps, _tocEntry::next, CatalogId::oid, _tocEntry::owner, pg_fatal, pg_free(), _tocEntry::relkind, REQ_DATA, REQ_SCHEMA, REQ_SPECIAL, REQ_STATS, _tocEntry::reqs, _tocEntry::section, sprintf, _tocEntry::tableam, CatalogId::tableoid, _tocEntry::tablespace, _tocEntry::tag, _archiveHandle::toc, _archiveHandle::WriteExtraTocPtr, WriteInt(), and WriteStr().

Referenced by _CloseArchive(), _CloseArchive(), and _CloseArchive().