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 2377 of file pg_backup_archiver.c.

2381{
2382 ArchiveHandle *AH;
2385
2386 pg_log_debug("allocating AH for %s, format %d",
2387 FileSpec ? FileSpec : "(stdio)", fmt);
2388
2390
2391 AH->version = K_VERS_SELF;
2392
2393 /* initialize for backwards compatible string processing */
2394 AH->public.encoding = 0; /* PG_SQL_ASCII */
2395 AH->public.std_strings = false;
2396
2397 /* sql error handling */
2398 AH->public.exit_on_error = true;
2399 AH->public.n_errors = 0;
2400
2402
2403 AH->createDate = time(NULL);
2404
2405 AH->intSize = sizeof(int);
2406 AH->offSize = sizeof(pgoff_t);
2407 if (FileSpec)
2408 {
2409 AH->fSpec = pg_strdup(FileSpec);
2410
2411 /*
2412 * Not used; maybe later....
2413 *
2414 * AH->workDir = pg_strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
2415 * i--) if (AH->workDir[i-1] == '/')
2416 */
2417 }
2418 else
2419 AH->fSpec = NULL;
2420
2421 AH->currUser = NULL; /* unknown */
2422 AH->currSchema = NULL; /* ditto */
2423 AH->currTablespace = NULL; /* ditto */
2424 AH->currTableAm = NULL; /* ditto */
2425
2427
2428 AH->toc->next = AH->toc;
2429 AH->toc->prev = AH->toc;
2430
2431 AH->mode = mode;
2432 AH->compression_spec = compression_spec;
2433 AH->dosync = dosync;
2435
2436 memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse));
2437
2438 /* Open stdout with no compression for AH output handle */
2441 if (!CFH->open_func(NULL, fileno(stdout), PG_BINARY_A, CFH))
2442 pg_fatal("could not open stdout for appending: %m");
2443 AH->OF = CFH;
2444
2445 /*
2446 * On Windows, we need to use binary mode to read/write non-text files,
2447 * which include all archive formats as well as compressed plain text.
2448 * Force stdin/stdout into binary mode if that is what we are using.
2449 */
2450#ifdef WIN32
2451 if ((fmt != archNull || compression_spec.algorithm != PG_COMPRESSION_NONE) &&
2452 (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
2453 {
2454 if (mode == archModeWrite)
2455 _setmode(fileno(stdout), O_BINARY);
2456 else
2457 _setmode(fileno(stdin), O_BINARY);
2458 }
2459#endif
2460
2462
2463 if (fmt == archUnknown)
2465 else
2466 AH->format = fmt;
2467
2468 switch (AH->format)
2469 {
2470 case archCustom:
2472 break;
2473
2474 case archNull:
2476 break;
2477
2478 case archDirectory:
2480 break;
2481
2482 case archTar:
2484 break;
2485
2486 default:
2487 pg_fatal("unrecognized file format \"%d\"", AH->format);
2488 }
2489
2490 return AH;
2491}
#define PG_BINARY_A
Definition c.h:1446
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 3611 of file pg_backup_archiver.c.

3612{
3613 RestoreOptions *ropt = AH->public.ropt;
3614
3615 if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
3616 return;
3617
3618 _becomeUser(AH, te->owner);
3619}
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 3588 of file pg_backup_archiver.c.

3589{
3590 if (!user)
3591 user = ""; /* avoid null pointers */
3592
3593 if (AH->currUser && strcmp(AH->currUser, user) == 0)
3594 return; /* no need to do anything */
3595
3597
3598 /*
3599 * NOTE: currUser keeps track of what the imaginary session user in our
3600 * script is
3601 */
3602 pg_free(AH->currUser);
3603 AH->currUser = pg_strdup(user);
3604}
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 2244 of file pg_backup_archiver.c.

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

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 3429 of file pg_backup_archiver.c.

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

3495{
3497
3498 appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3499
3500 /*
3501 * SQL requires a string literal here. Might as well be correct.
3502 */
3503 if (user && *user)
3504 appendStringLiteralAHX(cmd, user, AH);
3505 else
3506 appendPQExpBufferStr(cmd, "DEFAULT");
3507 appendPQExpBufferChar(cmd, ';');
3508
3509 if (RestoringToDB(AH))
3510 {
3511 PGresult *res;
3512
3513 res = PQexec(AH->connection, cmd->data);
3514
3515 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3516 /* NOT warn_or_exit_horribly... use -O instead to skip this. */
3517 pg_fatal("could not set session user to \"%s\": %s",
3519
3520 PQclear(res);
3521 }
3522 else
3523 ahprintf(AH, "%s\n\n", cmd->data);
3524
3525 destroyPQExpBuffer(cmd);
3526}
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 2232 of file pg_backup_archiver.c.

2233{
2234 struct stat st;
2235 char buf[MAXPGPATH];
2236
2237 if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
2238 pg_fatal("directory name too long: \"%s\"", dir);
2239
2240 return (stat(buf, &st) == 0 && S_ISREG(st.st_mode));
2241}
#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:318

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 3836 of file pg_backup_archiver.c.

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

1965{
1966 /* Unlink te from list */
1967 te->prev->next = te->next;
1968 te->next->prev = te->prev;
1969
1970 /* and insert it before "pos" */
1971 te->prev = pos->prev;
1972 te->next = pos;
1973 pos->prev->next = te;
1974 pos->prev = te;
1975}

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

Referenced by SortTocFromFile().

◆ _printTableAccessMethodNoStorage()

static void _printTableAccessMethodNoStorage ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 3788 of file pg_backup_archiver.c.

3789{
3790 RestoreOptions *ropt = AH->public.ropt;
3791 const char *tableam = te->tableam;
3792 PQExpBuffer cmd;
3793
3794 /* do nothing in --no-table-access-method mode */
3795 if (ropt->noTableAm)
3796 return;
3797
3798 if (!tableam)
3799 return;
3800
3802
3803 cmd = createPQExpBuffer();
3804
3805 appendPQExpBufferStr(cmd, "ALTER TABLE ");
3806 appendPQExpBuffer(cmd, "%s ", fmtQualifiedId(te->namespace, te->tag));
3807 appendPQExpBuffer(cmd, "SET ACCESS METHOD %s;",
3808 fmtId(tableam));
3809
3810 if (RestoringToDB(AH))
3811 {
3812 PGresult *res;
3813
3814 res = PQexec(AH->connection, cmd->data);
3815
3816 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3818 "could not alter table access method: %s",
3820 PQclear(res);
3821 }
3822 else
3823 ahprintf(AH, "%s\n\n", cmd->data);
3824
3825 destroyPQExpBuffer(cmd);
3826}
#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 3931 of file pg_backup_archiver.c.

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

3538{
3539 if (RestoringToDB(AH))
3541 else
3542 {
3544 RestoreOptions *ropt = AH->public.ropt;
3545
3546 /*
3547 * We must temporarily exit restricted mode for \connect, etc.
3548 * Anything added between this line and the following \restrict must
3549 * be careful to avoid any possible meta-command injection vectors.
3550 */
3551 ahprintf(AH, "\\unrestrict %s\n", ropt->restrict_key);
3552
3555 ahprintf(AH, "%s", connectbuf.data);
3557
3558 ahprintf(AH, "\\restrict %s\n\n", ropt->restrict_key);
3559 }
3560
3561 /*
3562 * NOTE: currUser keeps track of what the imaginary session user in our
3563 * script is. It's now effectively reset to the original userID.
3564 */
3565 free(AH->currUser);
3566 AH->currUser = NULL;
3567
3568 /* don't assume we still know the output schema, tablespace, etc either */
3569 free(AH->currSchema);
3570 AH->currSchema = NULL;
3571
3572 free(AH->currTableAm);
3573 AH->currTableAm = NULL;
3574
3575 free(AH->currTablespace);
3576 AH->currTablespace = NULL;
3577
3578 /* re-establish fixed state */
3580}
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 3627 of file pg_backup_archiver.c.

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

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 3738 of file pg_backup_archiver.c.

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

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 3678 of file pg_backup_archiver.c.

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

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

References _tocEntry::desc, and fb().

Referenced by _printTocEntry(), and _tocEntryRequired().

◆ _tocEntryRequired()

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

Definition at line 2987 of file pg_backup_archiver.c.

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

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

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

4316{
4317 pgoff_t tpos;
4318
4319 /* Check that ftello works on this file */
4320 tpos = ftello(fp);
4321 if (tpos < 0)
4322 return false;
4323
4324 /*
4325 * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
4326 * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
4327 * successful no-op even on files that are otherwise unseekable.
4328 */
4329 if (fseeko(fp, tpos, SEEK_SET) != 0)
4330 return false;
4331
4332 return true;
4333}
#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 5182 of file pg_backup_archiver.c.

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

5247{
5248 /* Should not have an open database connection */
5249 Assert(AH->connection == NULL);
5250
5251 /* Clear format-specific state */
5252 AH->DeClonePtr(AH);
5253
5254 /* Clear state allocated by CloneArchive */
5255 if (AH->sqlparse.curCmd)
5257
5258 /* Clear any connection-local state */
5259 free(AH->currUser);
5260 free(AH->currSchema);
5261 free(AH->currTablespace);
5262 free(AH->currTableAm);
5263 free(AH->savedPassword);
5264
5265 free(AH);
5266}
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:1329
#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 4340 of file pg_backup_archiver.c.

4341{
4342 char buf[64];
4343
4344 if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
4345 ahprintf(AH, "-- %s %s\n\n", msg, buf);
4346}
#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 4879 of file pg_backup_archiver.c.

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

2031{
2032 /* build index arrays if we didn't already */
2033 if (AH->tocsByDumpId == NULL)
2035
2036 if (id > 0 && id <= AH->maxDumpId)
2037 return AH->tocsByDumpId[id];
2038
2039 return NULL;
2040}
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 4633 of file pg_backup_archiver.c.

4634{
4635 int j,
4636 k;
4637
4638 for (j = 0; j < te1->nLockDeps; j++)
4639 {
4640 for (k = 0; k < te2->nDeps; k++)
4641 {
4642 if (te1->lockDeps[j] == te2->dependencies[k])
4643 return true;
4644 }
4645 }
4646 return false;
4647}
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 5043 of file pg_backup_archiver.c.

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

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

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 5147 of file pg_backup_archiver.c.

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

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 2563 of file pg_backup_archiver.c.

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

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 4838 of file pg_backup_archiver.c.

4842{
4843 binaryheap *ready_heap = (binaryheap *) callback_data;
4844
4845 pg_log_info("finished item %d %s %s",
4846 te->dumpId, te->desc, te->tag);
4847
4848 if (status == WORKER_CREATE_DONE)
4849 mark_create_done(AH, te);
4850 else if (status == WORKER_INHIBIT_DATA)
4851 {
4853 AH->public.n_errors++;
4854 }
4855 else if (status == WORKER_IGNORED_ERRORS)
4856 AH->public.n_errors++;
4857 else if (status != 0)
4858 pg_fatal("worker process failed: exit code %d",
4859 status);
4860
4862}
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 4723 of file pg_backup_archiver.c.

4726{
4727 TocEntry *te;
4729
4730 for (te = pending_list->pending_next; te != pending_list; te = next_te)
4731 {
4732 /* must save list link before possibly removing te from list */
4733 next_te = te->pending_next;
4734
4735 if (te->depCount == 0 &&
4737 {
4738 /* Remove it from pending_list ... */
4740 /* ... and add to ready_heap */
4742 }
4743 }
4744}
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 4815 of file pg_backup_archiver.c.

4816{
4817 int status;
4818
4819 Assert(AH->connection != NULL);
4820
4821 /* Count only errors associated with this TOC entry */
4822 AH->public.n_errors = 0;
4823
4824 /* Restore the TOC item */
4825 status = restore_toc_entry(AH, te, true);
4826
4827 return status;
4828}
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 4665 of file pg_backup_archiver.c.

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

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 4658 of file pg_backup_archiver.c.

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

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 4675 of file pg_backup_archiver.c.

4676{
4679 te->pending_prev = NULL;
4680 te->pending_next = NULL;
4681}

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 4758 of file pg_backup_archiver.c.

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

2882{
2883 /* te->defn should have the form SET client_encoding = 'foo'; */
2884 char *defn = pg_strdup(te->defn);
2885 char *ptr1;
2886 char *ptr2 = NULL;
2887 int encoding;
2888
2889 ptr1 = strchr(defn, '\'');
2890 if (ptr1)
2891 ptr2 = strchr(++ptr1, '\'');
2892 if (ptr2)
2893 {
2894 *ptr2 = '\0';
2896 if (encoding < 0)
2897 pg_fatal("unrecognized encoding \"%s\"",
2898 ptr1);
2899 AH->public.encoding = encoding;
2901 }
2902 else
2903 pg_fatal("invalid ENCODING item: %s",
2904 te->defn);
2905
2906 pg_free(defn);
2907}
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 2926 of file pg_backup_archiver.c.

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

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 2910 of file pg_backup_archiver.c.

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

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

Referenced by ReadToc().

◆ ReadHead()

void ReadHead ( ArchiveHandle AH)

Definition at line 4182 of file pg_backup_archiver.c.

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

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

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

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

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

◆ ReadToc()

void ReadToc ( ArchiveHandle AH)

Definition at line 2709 of file pg_backup_archiver.c.

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

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

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

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 4481 of file pg_backup_archiver.c.

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

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

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 4358 of file pg_backup_archiver.c.

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

2937{
2938 const char *missing_name;
2939
2940 Assert(ropt->strict_names);
2941
2942 if (ropt->schemaNames.head != NULL)
2943 {
2945 if (missing_name != NULL)
2946 pg_fatal("schema \"%s\" not found", missing_name);
2947 }
2948
2949 if (ropt->tableNames.head != NULL)
2950 {
2952 if (missing_name != NULL)
2953 pg_fatal("table \"%s\" not found", missing_name);
2954 }
2955
2956 if (ropt->indexNames.head != NULL)
2957 {
2959 if (missing_name != NULL)
2960 pg_fatal("index \"%s\" not found", missing_name);
2961 }
2962
2963 if (ropt->functionNames.head != NULL)
2964 {
2966 if (missing_name != NULL)
2967 pg_fatal("function \"%s\" not found", missing_name);
2968 }
2969
2970 if (ropt->triggerNames.head != NULL)
2971 {
2973 if (missing_name != NULL)
2974 pg_fatal("trigger \"%s\" not found", missing_name);
2975 }
2976}
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 4708 of file pg_backup_archiver.c.

4709{
4710 /* return opposite of qsort comparator for max-heap */
4711 return -TocEntrySizeCompareQsort(&p1, &p2);
4712}
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 4686 of file pg_backup_archiver.c.

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

References fb().

Referenced by TocEntrySizeCompareBinaryheap(), and WriteDataChunks().

◆ TocIDRequired()

int TocIDRequired ( ArchiveHandle AH,
DumpId  id 
)

Definition at line 2043 of file pg_backup_archiver.c.

2044{
2045 TocEntry *te = getTocEntryByDumpId(AH, id);
2046
2047 if (!te)
2048 return 0;
2049
2050 return te->reqs;
2051}

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 va_list ap;
1900
1901 switch (AH->stage)
1902 {
1903
1904 case STAGE_NONE:
1905 /* Do nothing special */
1906 break;
1907
1908 case STAGE_INITIALIZING:
1909 if (AH->stage != AH->lastErrorStage)
1910 pg_log_info("while INITIALIZING:");
1911 break;
1912
1913 case STAGE_PROCESSING:
1914 if (AH->stage != AH->lastErrorStage)
1915 pg_log_info("while PROCESSING TOC:");
1916 break;
1917
1918 case STAGE_FINALIZING:
1919 if (AH->stage != AH->lastErrorStage)
1920 pg_log_info("while FINALIZING:");
1921 break;
1922 }
1923 if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE)
1924 {
1925 pg_log_info("from TOC entry %d; %u %u %s %s %s",
1926 AH->currentTE->dumpId,
1928 AH->currentTE->catalogId.oid,
1929 AH->currentTE->desc ? AH->currentTE->desc : "(no desc)",
1930 AH->currentTE->tag ? AH->currentTE->tag : "(no tag)",
1931 AH->currentTE->owner ? AH->currentTE->owner : "(no owner)");
1932 }
1933 AH->lastErrorStage = AH->stage;
1934 AH->lastErrorTE = AH->currentTE;
1935
1936 va_start(ap, fmt);
1938 va_end(ap);
1939
1940 if (AH->public.exit_on_error)
1941 exit_nicely(1);
1942 else
1943 AH->public.n_errors++;
1944}
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)
ArchiverStage lastErrorStage

References _tocEntry::catalogId, _archiveHandle::currentTE, _tocEntry::desc, _tocEntry::dumpId, exit_nicely(), Archive::exit_on_error, fb(), _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 2497 of file pg_backup_archiver.c.

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

2579{
2582
2583 AH->currToc = te;
2584
2585 if (strcmp(te->desc, "BLOBS") == 0)
2586 {
2587 startPtr = AH->StartLOsPtr;
2588 endPtr = AH->EndLOsPtr;
2589 }
2590 else
2591 {
2592 startPtr = AH->StartDataPtr;
2593 endPtr = AH->EndDataPtr;
2594 }
2595
2596 if (startPtr != NULL)
2597 (*startPtr) (AH, te);
2598
2599 /*
2600 * The user-provided DataDumper routine needs to call AH->WriteData
2601 */
2602 te->dataDumper((Archive *) AH, te->dataDumperArg);
2603
2604 if (endPtr != NULL)
2605 (*endPtr) (AH, te);
2606
2607 AH->currToc = NULL;
2608}
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 4156 of file pg_backup_archiver.c.

4157{
4158 struct tm crtm;
4159
4160 AH->WriteBufPtr(AH, "PGDMP", 5); /* Magic code */
4161 AH->WriteBytePtr(AH, ARCHIVE_MAJOR(AH->version));
4162 AH->WriteBytePtr(AH, ARCHIVE_MINOR(AH->version));
4163 AH->WriteBytePtr(AH, ARCHIVE_REV(AH->version));
4164 AH->WriteBytePtr(AH, AH->intSize);
4165 AH->WriteBytePtr(AH, AH->offSize);
4166 AH->WriteBytePtr(AH, AH->format);
4168 crtm = *localtime(&AH->createDate);
4169 WriteInt(AH, crtm.tm_sec);
4170 WriteInt(AH, crtm.tm_min);
4171 WriteInt(AH, crtm.tm_hour);
4172 WriteInt(AH, crtm.tm_mday);
4173 WriteInt(AH, crtm.tm_mon);
4174 WriteInt(AH, crtm.tm_year);
4175 WriteInt(AH, crtm.tm_isdst);
4176 WriteStr(AH, PQdb(AH->connection));
4178 WriteStr(AH, PG_VERSION);
4179}
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 2135 of file pg_backup_archiver.c.

2136{
2137 int b;
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 (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 2054 of file pg_backup_archiver.c.

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

References fb(), and _archiveHandle::WriteBytePtr.

Referenced by _WriteExtraToc().

◆ WriteStr()

size_t WriteStr ( ArchiveHandle AH,
const char c 
)

Definition at line 2193 of file pg_backup_archiver.c.

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

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

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

◆ WriteToc()

void WriteToc ( ArchiveHandle AH)

Definition at line 2611 of file pg_backup_archiver.c.

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