PostgreSQL Source Code git master
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 "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 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 char * sanitize_line (const char *str, bool want_hyphen)
 
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)
 
char * ReadStr (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 46 of file pg_backup_archiver.c.

◆ TEXT_DUMPALL_HEADER

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

Definition at line 47 of file pg_backup_archiver.c.

◆ TOC_PREFIX_DATA

#define TOC_PREFIX_DATA   "Data for "

Definition at line 50 of file pg_backup_archiver.c.

◆ TOC_PREFIX_NONE

#define TOC_PREFIX_NONE   ""

Definition at line 49 of file pg_backup_archiver.c.

◆ TOC_PREFIX_STATS

#define TOC_PREFIX_STATS   "Statistics for "

Definition at line 51 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 2353 of file pg_backup_archiver.c.

2357{
2358 ArchiveHandle *AH;
2359 CompressFileHandle *CFH;
2360 pg_compress_specification out_compress_spec = {0};
2361
2362 pg_log_debug("allocating AH for %s, format %d",
2363 FileSpec ? FileSpec : "(stdio)", fmt);
2364
2365 AH = (ArchiveHandle *) pg_malloc0(sizeof(ArchiveHandle));
2366
2367 AH->version = K_VERS_SELF;
2368
2369 /* initialize for backwards compatible string processing */
2370 AH->public.encoding = 0; /* PG_SQL_ASCII */
2371 AH->public.std_strings = false;
2372
2373 /* sql error handling */
2374 AH->public.exit_on_error = true;
2375 AH->public.n_errors = 0;
2376
2377 AH->archiveDumpVersion = PG_VERSION;
2378
2379 AH->createDate = time(NULL);
2380
2381 AH->intSize = sizeof(int);
2382 AH->offSize = sizeof(pgoff_t);
2383 if (FileSpec)
2384 {
2385 AH->fSpec = pg_strdup(FileSpec);
2386
2387 /*
2388 * Not used; maybe later....
2389 *
2390 * AH->workDir = pg_strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
2391 * i--) if (AH->workDir[i-1] == '/')
2392 */
2393 }
2394 else
2395 AH->fSpec = NULL;
2396
2397 AH->currUser = NULL; /* unknown */
2398 AH->currSchema = NULL; /* ditto */
2399 AH->currTablespace = NULL; /* ditto */
2400 AH->currTableAm = NULL; /* ditto */
2401
2402 AH->toc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
2403
2404 AH->toc->next = AH->toc;
2405 AH->toc->prev = AH->toc;
2406
2407 AH->mode = mode;
2408 AH->compression_spec = compression_spec;
2409 AH->dosync = dosync;
2411
2412 memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse));
2413
2414 /* Open stdout with no compression for AH output handle */
2415 out_compress_spec.algorithm = PG_COMPRESSION_NONE;
2416 CFH = InitCompressFileHandle(out_compress_spec);
2417 if (!CFH->open_func(NULL, fileno(stdout), PG_BINARY_A, CFH))
2418 pg_fatal("could not open stdout for appending: %m");
2419 AH->OF = CFH;
2420
2421 /*
2422 * On Windows, we need to use binary mode to read/write non-text files,
2423 * which include all archive formats as well as compressed plain text.
2424 * Force stdin/stdout into binary mode if that is what we are using.
2425 */
2426#ifdef WIN32
2427 if ((fmt != archNull || compression_spec.algorithm != PG_COMPRESSION_NONE) &&
2428 (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
2429 {
2430 if (mode == archModeWrite)
2431 _setmode(fileno(stdout), O_BINARY);
2432 else
2433 _setmode(fileno(stdin), O_BINARY);
2434 }
2435#endif
2436
2437 AH->SetupWorkerPtr = setupWorkerPtr;
2438
2439 if (fmt == archUnknown)
2441 else
2442 AH->format = fmt;
2443
2444 switch (AH->format)
2445 {
2446 case archCustom:
2448 break;
2449
2450 case archNull:
2452 break;
2453
2454 case archDirectory:
2456 break;
2457
2458 case archTar:
2460 break;
2461
2462 default:
2463 pg_fatal("unrecognized file format \"%d\"", fmt);
2464 }
2465
2466 return AH;
2467}
#define PG_BINARY_A
Definition: c.h:1245
CompressFileHandle * InitCompressFileHandle(const pg_compress_specification compression_spec)
Definition: compress_io.c:194
@ PG_COMPRESSION_NONE
Definition: compression.h:23
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
static DataDirSyncMethod sync_method
Definition: initdb.c:170
#define pg_log_debug(...)
Definition: logging.h:133
@ 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
Definition: pg_checksums.c:55
static bool dosync
Definition: pg_dump.c:147
#define pgoff_t
Definition: port.h:401
bool exit_on_error
Definition: pg_backup.h:247
int n_errors
Definition: pg_backup.h:248
bool std_strings
Definition: pg_backup.h:240
int encoding
Definition: pg_backup.h:239
bool(* open_func)(const char *path, int fd, const char *mode, CompressFileHandle *CFH)
Definition: compress_io.h:111
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

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, _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, _archiveHandle::OF, _archiveHandle::offSize, CompressFileHandle::open_func, PG_BINARY_A, PG_COMPRESSION_NONE, pg_fatal, pg_log_debug, pg_malloc0(), pg_strdup(), pgoff_t, _tocEntry::prev, _archiveHandle::public, _archiveHandle::SetupWorkerPtr, _archiveHandle::sqlparse, Archive::std_strings, generate_unaccent_rules::stdout, 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 3444 of file pg_backup_archiver.c.

3445{
3446 RestoreOptions *ropt = AH->public.ropt;
3447
3448 if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
3449 return;
3450
3451 _becomeUser(AH, te->owner);
3452}
static void _becomeUser(ArchiveHandle *AH, const char *user)
RestoreOptions * ropt
Definition: pg_backup.h:225

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

3422{
3423 if (!user)
3424 user = ""; /* avoid null pointers */
3425
3426 if (AH->currUser && strcmp(AH->currUser, user) == 0)
3427 return; /* no need to do anything */
3428
3430
3431 /*
3432 * NOTE: currUser keeps track of what the imaginary session user in our
3433 * script is
3434 */
3435 free(AH->currUser);
3436 AH->currUser = pg_strdup(user);
3437}
#define free(a)
Definition: header.h:65
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user)
static char * user
Definition: pg_regress.c:119

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

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

◆ _disableTriggersIfNecessary()

static void _disableTriggersIfNecessary ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 1105 of file pg_backup_archiver.c.

1106{
1107 RestoreOptions *ropt = AH->public.ropt;
1108
1109 /* This hack is only needed in a data-only restore */
1110 if (ropt->dumpSchema || !ropt->disable_triggers)
1111 return;
1112
1113 pg_log_info("disabling triggers for %s", te->tag);
1114
1115 /*
1116 * Become superuser if possible, since they are the only ones who can
1117 * disable constraint triggers. If -S was not given, assume the initial
1118 * user identity is a superuser. (XXX would it be better to become the
1119 * table owner?)
1120 */
1121 _becomeUser(AH, ropt->superuser);
1122
1123 /*
1124 * Disable them.
1125 */
1126 ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
1127 fmtQualifiedId(te->namespace, te->tag));
1128}
#define pg_log_info(...)
Definition: logging.h:124
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
const char * fmtQualifiedId(const char *schema, const char *id)
Definition: string_utils.c:296
char * superuser
Definition: pg_backup.h:106
int disable_triggers
Definition: pg_backup.h:102

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

2220{
2221 FILE *fh;
2222 char sig[6]; /* More than enough */
2223 size_t cnt;
2224 int wantClose = 0;
2225
2226 pg_log_debug("attempting to ascertain archive format");
2227
2228 free(AH->lookahead);
2229
2230 AH->readHeader = 0;
2231 AH->lookaheadSize = 512;
2232 AH->lookahead = pg_malloc0(512);
2233 AH->lookaheadLen = 0;
2234 AH->lookaheadPos = 0;
2235
2236 if (AH->fSpec)
2237 {
2238 struct stat st;
2239
2240 wantClose = 1;
2241
2242 /*
2243 * Check if the specified archive is a directory. If so, check if
2244 * there's a "toc.dat" (or "toc.dat.{gz,lz4,zst}") file in it.
2245 */
2246 if (stat(AH->fSpec, &st) == 0 && S_ISDIR(st.st_mode))
2247 {
2248 AH->format = archDirectory;
2249 if (_fileExistsInDirectory(AH->fSpec, "toc.dat"))
2250 return AH->format;
2251#ifdef HAVE_LIBZ
2252 if (_fileExistsInDirectory(AH->fSpec, "toc.dat.gz"))
2253 return AH->format;
2254#endif
2255#ifdef USE_LZ4
2256 if (_fileExistsInDirectory(AH->fSpec, "toc.dat.lz4"))
2257 return AH->format;
2258#endif
2259#ifdef USE_ZSTD
2260 if (_fileExistsInDirectory(AH->fSpec, "toc.dat.zst"))
2261 return AH->format;
2262#endif
2263 pg_fatal("directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)",
2264 AH->fSpec);
2265 fh = NULL; /* keep compiler quiet */
2266 }
2267 else
2268 {
2269 fh = fopen(AH->fSpec, PG_BINARY_R);
2270 if (!fh)
2271 pg_fatal("could not open input file \"%s\": %m", AH->fSpec);
2272 }
2273 }
2274 else
2275 {
2276 fh = stdin;
2277 if (!fh)
2278 pg_fatal("could not open input file: %m");
2279 }
2280
2281 if ((cnt = fread(sig, 1, 5, fh)) != 5)
2282 {
2283 if (ferror(fh))
2284 pg_fatal("could not read input file: %m");
2285 else
2286 pg_fatal("input file is too short (read %lu, expected 5)",
2287 (unsigned long) cnt);
2288 }
2289
2290 /* Save it, just in case we need it later */
2291 memcpy(&AH->lookahead[0], sig, 5);
2292 AH->lookaheadLen = 5;
2293
2294 if (strncmp(sig, "PGDMP", 5) == 0)
2295 {
2296 /* It's custom format, stop here */
2297 AH->format = archCustom;
2298 AH->readHeader = 1;
2299 }
2300 else
2301 {
2302 /*
2303 * *Maybe* we have a tar archive format file or a text dump ... So,
2304 * read first 512 byte header...
2305 */
2306 cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh);
2307 /* read failure is checked below */
2308 AH->lookaheadLen += cnt;
2309
2310 if (AH->lookaheadLen >= strlen(TEXT_DUMPALL_HEADER) &&
2311 (strncmp(AH->lookahead, TEXT_DUMP_HEADER, strlen(TEXT_DUMP_HEADER)) == 0 ||
2312 strncmp(AH->lookahead, TEXT_DUMPALL_HEADER, strlen(TEXT_DUMPALL_HEADER)) == 0))
2313 {
2314 /*
2315 * looks like it's probably a text format dump. so suggest they
2316 * try psql
2317 */
2318 pg_fatal("input file appears to be a text format dump. Please use psql.");
2319 }
2320
2321 if (AH->lookaheadLen != 512)
2322 {
2323 if (feof(fh))
2324 pg_fatal("input file does not appear to be a valid archive (too short?)");
2325 else
2326 READ_ERROR_EXIT(fh);
2327 }
2328
2329 if (!isValidTarHeader(AH->lookahead))
2330 pg_fatal("input file does not appear to be a valid archive");
2331
2332 AH->format = archTar;
2333 }
2334
2335 /* Close the file if we opened it */
2336 if (wantClose)
2337 {
2338 if (fclose(fh) != 0)
2339 pg_fatal("could not close input file: %m");
2340 /* Forget lookahead, since we'll re-read header after re-opening */
2341 AH->readHeader = 0;
2342 AH->lookaheadLen = 0;
2343 }
2344
2345 return AH->format;
2346}
#define PG_BINARY_R
Definition: c.h:1246
#define TEXT_DUMPALL_HEADER
#define TEXT_DUMP_HEADER
static bool _fileExistsInDirectory(const char *dir, const char *filename)
bool isValidTarHeader(char *header)
#define READ_ERROR_EXIT(fd)
static int sig
Definition: pg_ctl.c:80
#define stat
Definition: win32_port.h:274
#define S_ISDIR(m)
Definition: win32_port.h:315

References _fileExistsInDirectory(), archCustom, archDirectory, archTar, _archiveHandle::format, free, _archiveHandle::fSpec, isValidTarHeader(), _archiveHandle::lookahead, _archiveHandle::lookaheadLen, _archiveHandle::lookaheadPos, _archiveHandle::lookaheadSize, PG_BINARY_R, pg_fatal, 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 3270 of file pg_backup_archiver.c.

3271{
3272 RestoreOptions *ropt = AH->public.ropt;
3273
3274 /*
3275 * Disable timeouts to allow for slow commands, idle parallel workers, etc
3276 */
3277 ahprintf(AH, "SET statement_timeout = 0;\n");
3278 ahprintf(AH, "SET lock_timeout = 0;\n");
3279 ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
3280 ahprintf(AH, "SET transaction_timeout = 0;\n");
3281
3282 /* Select the correct character set encoding */
3283 ahprintf(AH, "SET client_encoding = '%s';\n",
3285
3286 /* Select the correct string literal syntax */
3287 ahprintf(AH, "SET standard_conforming_strings = %s;\n",
3288 AH->public.std_strings ? "on" : "off");
3289
3290 /* Select the role to be used during restore */
3291 if (ropt && ropt->use_role)
3292 ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));
3293
3294 /* Select the dump-time search_path */
3295 if (AH->public.searchpath)
3296 ahprintf(AH, "%s", AH->public.searchpath);
3297
3298 /* Make sure function checking is disabled */
3299 ahprintf(AH, "SET check_function_bodies = false;\n");
3300
3301 /* Ensure that all valid XML data will be accepted */
3302 ahprintf(AH, "SET xmloption = content;\n");
3303
3304 /* Avoid annoying notices etc */
3305 ahprintf(AH, "SET client_min_messages = warning;\n");
3306 if (!AH->public.std_strings)
3307 ahprintf(AH, "SET escape_string_warning = off;\n");
3308
3309 /* Adjust row-security state */
3310 if (ropt && ropt->enable_row_security)
3311 ahprintf(AH, "SET row_security = on;\n");
3312 else
3313 ahprintf(AH, "SET row_security = off;\n");
3314
3315 /*
3316 * In --transaction-size mode, we should always be in a transaction when
3317 * we begin to restore objects.
3318 */
3319 if (ropt && ropt->txn_size > 0)
3320 {
3321 if (AH->connection)
3323 else
3324 ahprintf(AH, "\nBEGIN;\n");
3325 AH->txnCount = 0;
3326 }
3327
3328 ahprintf(AH, "\n");
3329}
#define pg_encoding_to_char
Definition: pg_wchar.h:630
const char * fmtId(const char *rawid)
Definition: string_utils.c:248
char * searchpath
Definition: pg_backup.h:243
char * use_role
Definition: pg_backup.h:107
int enable_row_security
Definition: pg_backup.h:158
static void StartTransaction(void)
Definition: xact.c:2064

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

3338{
3340
3341 appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3342
3343 /*
3344 * SQL requires a string literal here. Might as well be correct.
3345 */
3346 if (user && *user)
3347 appendStringLiteralAHX(cmd, user, AH);
3348 else
3349 appendPQExpBufferStr(cmd, "DEFAULT");
3350 appendPQExpBufferChar(cmd, ';');
3351
3352 if (RestoringToDB(AH))
3353 {
3354 PGresult *res;
3355
3356 res = PQexec(AH->connection, cmd->data);
3357
3358 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3359 /* NOT warn_or_exit_horribly... use -O instead to skip this. */
3360 pg_fatal("could not set session user to \"%s\": %s",
3362
3363 PQclear(res);
3364 }
3365 else
3366 ahprintf(AH, "%s\n\n", cmd->data);
3367
3368 destroyPQExpBuffer(cmd);
3369}
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7553
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3411
void PQclear(PGresult *res)
Definition: fe-exec.c:721
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2262
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:124
static int RestoringToDB(ArchiveHandle *AH)
#define appendStringLiteralAHX(buf, str, AH)
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:72
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:114
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367

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

1132{
1133 RestoreOptions *ropt = AH->public.ropt;
1134
1135 /* This hack is only needed in a data-only restore */
1136 if (ropt->dumpSchema || !ropt->disable_triggers)
1137 return;
1138
1139 pg_log_info("enabling triggers for %s", te->tag);
1140
1141 /*
1142 * Become superuser if possible, since they are the only ones who can
1143 * disable constraint triggers. If -S was not given, assume the initial
1144 * user identity is a superuser. (XXX would it be better to become the
1145 * table owner?)
1146 */
1147 _becomeUser(AH, ropt->superuser);
1148
1149 /*
1150 * Enable them.
1151 */
1152 ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
1153 fmtQualifiedId(te->namespace, te->tag));
1154}

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

2208{
2209 struct stat st;
2210 char buf[MAXPGPATH];
2211
2212 if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
2213 pg_fatal("directory name too long: \"%s\"", dir);
2214
2215 return (stat(buf, &st) == 0 && S_ISREG(st.st_mode));
2216}
#define MAXPGPATH
static char * filename
Definition: pg_dumpall.c:124
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:239
#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 3669 of file pg_backup_archiver.c.

3670{
3671 const char *type = te->desc;
3672
3673 /* objects that don't require special decoration */
3674 if (strcmp(type, "COLLATION") == 0 ||
3675 strcmp(type, "CONVERSION") == 0 ||
3676 strcmp(type, "DOMAIN") == 0 ||
3677 strcmp(type, "FOREIGN TABLE") == 0 ||
3678 strcmp(type, "MATERIALIZED VIEW") == 0 ||
3679 strcmp(type, "SEQUENCE") == 0 ||
3680 strcmp(type, "STATISTICS") == 0 ||
3681 strcmp(type, "TABLE") == 0 ||
3682 strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
3683 strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 ||
3684 strcmp(type, "TYPE") == 0 ||
3685 strcmp(type, "VIEW") == 0 ||
3686 /* non-schema-specified objects */
3687 strcmp(type, "DATABASE") == 0 ||
3688 strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
3689 strcmp(type, "SCHEMA") == 0 ||
3690 strcmp(type, "EVENT TRIGGER") == 0 ||
3691 strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
3692 strcmp(type, "SERVER") == 0 ||
3693 strcmp(type, "PUBLICATION") == 0 ||
3694 strcmp(type, "SUBSCRIPTION") == 0)
3695 {
3696 appendPQExpBuffer(buf, "%s ", type);
3697 if (te->namespace && *te->namespace)
3698 appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
3700 }
3701 /* LOs just have a name, but it's numeric so must not use fmtId */
3702 else if (strcmp(type, "BLOB") == 0)
3703 {
3704 appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag);
3705 }
3706
3707 /*
3708 * These object types require additional decoration. Fortunately, the
3709 * information needed is exactly what's in the DROP command.
3710 */
3711 else if (strcmp(type, "AGGREGATE") == 0 ||
3712 strcmp(type, "FUNCTION") == 0 ||
3713 strcmp(type, "OPERATOR") == 0 ||
3714 strcmp(type, "OPERATOR CLASS") == 0 ||
3715 strcmp(type, "OPERATOR FAMILY") == 0 ||
3716 strcmp(type, "PROCEDURE") == 0)
3717 {
3718 /* Chop "DROP " off the front and make a modifiable copy */
3719 char *first = pg_strdup(te->dropStmt + 5);
3720 char *last;
3721
3722 /* point to last character in string */
3723 last = first + strlen(first) - 1;
3724
3725 /* Strip off any ';' or '\n' at the end */
3726 while (last >= first && (*last == '\n' || *last == ';'))
3727 last--;
3728 *(last + 1) = '\0';
3729
3730 appendPQExpBufferStr(buf, first);
3731
3732 free(first);
3733 return;
3734 }
3735 /* these object types don't have separate owners */
3736 else if (strcmp(type, "CAST") == 0 ||
3737 strcmp(type, "CHECK CONSTRAINT") == 0 ||
3738 strcmp(type, "CONSTRAINT") == 0 ||
3739 strcmp(type, "DATABASE PROPERTIES") == 0 ||
3740 strcmp(type, "DEFAULT") == 0 ||
3741 strcmp(type, "FK CONSTRAINT") == 0 ||
3742 strcmp(type, "INDEX") == 0 ||
3743 strcmp(type, "RULE") == 0 ||
3744 strcmp(type, "TRIGGER") == 0 ||
3745 strcmp(type, "ROW SECURITY") == 0 ||
3746 strcmp(type, "POLICY") == 0 ||
3747 strcmp(type, "USER MAPPING") == 0)
3748 {
3749 /* do nothing */
3750 }
3751 else
3752 pg_fatal("don't know how to set owner for object type \"%s\"", type);
3753}
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
const char * type

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

Referenced by _printTocEntry().

◆ _moveBefore()

static void _moveBefore ( TocEntry pos,
TocEntry te 
)
static

Definition at line 1939 of file pg_backup_archiver.c.

1940{
1941 /* Unlink te from list */
1942 te->prev->next = te->next;
1943 te->next->prev = te->prev;
1944
1945 /* and insert it before "pos" */
1946 te->prev = pos->prev;
1947 te->next = pos;
1948 pos->prev->next = te;
1949 pos->prev = te;
1950}

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

Referenced by SortTocFromFile().

◆ _printTableAccessMethodNoStorage()

static void _printTableAccessMethodNoStorage ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 3621 of file pg_backup_archiver.c.

3622{
3623 RestoreOptions *ropt = AH->public.ropt;
3624 const char *tableam = te->tableam;
3625 PQExpBuffer cmd;
3626
3627 /* do nothing in --no-table-access-method mode */
3628 if (ropt->noTableAm)
3629 return;
3630
3631 if (!tableam)
3632 return;
3633
3634 Assert(te->relkind == RELKIND_PARTITIONED_TABLE);
3635
3636 cmd = createPQExpBuffer();
3637
3638 appendPQExpBufferStr(cmd, "ALTER TABLE ");
3639 appendPQExpBuffer(cmd, "%s ", fmtQualifiedId(te->namespace, te->tag));
3640 appendPQExpBuffer(cmd, "SET ACCESS METHOD %s;",
3641 fmtId(tableam));
3642
3643 if (RestoringToDB(AH))
3644 {
3645 PGresult *res;
3646
3647 res = PQexec(AH->connection, cmd->data);
3648
3649 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3651 "could not alter table access method: %s",
3653 PQclear(res);
3654 }
3655 else
3656 ahprintf(AH, "%s\n\n", cmd->data);
3657
3658 destroyPQExpBuffer(cmd);
3659}
Assert(PointerIsAligned(start, uint64))
void warn_or_exit_horribly(ArchiveHandle *AH, const char *fmt,...)

References ahprintf(), appendPQExpBuffer(), appendPQExpBufferStr(), Assert(), _archiveHandle::connection, createPQExpBuffer(), PQExpBufferData::data, destroyPQExpBuffer(), 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 3763 of file pg_backup_archiver.c.

3764{
3765 RestoreOptions *ropt = AH->public.ropt;
3766
3767 /*
3768 * Select owner, schema, tablespace and default AM as necessary. The
3769 * default access method for partitioned tables is handled after
3770 * generating the object definition, as it requires an ALTER command
3771 * rather than SET.
3772 */
3773 _becomeOwner(AH, te);
3774 _selectOutputSchema(AH, te->namespace);
3776 if (te->relkind != RELKIND_PARTITIONED_TABLE)
3778
3779 /* Emit header comment for item */
3780 if (!AH->noTocComments)
3781 {
3782 char *sanitized_name;
3783 char *sanitized_schema;
3784 char *sanitized_owner;
3785
3786 ahprintf(AH, "--\n");
3787 if (AH->public.verbose)
3788 {
3789 ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
3790 te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
3791 if (te->nDeps > 0)
3792 {
3793 int i;
3794
3795 ahprintf(AH, "-- Dependencies:");
3796 for (i = 0; i < te->nDeps; i++)
3797 ahprintf(AH, " %d", te->dependencies[i]);
3798 ahprintf(AH, "\n");
3799 }
3800 }
3801
3802 sanitized_name = sanitize_line(te->tag, false);
3803 sanitized_schema = sanitize_line(te->namespace, true);
3804 sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
3805
3806 ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
3807 pfx, sanitized_name, te->desc, sanitized_schema,
3808 sanitized_owner);
3809
3810 free(sanitized_name);
3811 free(sanitized_schema);
3812 free(sanitized_owner);
3813
3814 if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace)
3815 {
3816 char *sanitized_tablespace;
3817
3818 sanitized_tablespace = sanitize_line(te->tablespace, false);
3819 ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
3820 free(sanitized_tablespace);
3821 }
3822 ahprintf(AH, "\n");
3823
3824 if (AH->PrintExtraTocPtr != NULL)
3825 AH->PrintExtraTocPtr(AH, te);
3826 ahprintf(AH, "--\n\n");
3827 }
3828
3829 /*
3830 * Actually print the definition. Normally we can just print the defn
3831 * string if any, but we have three special cases:
3832 *
3833 * 1. A crude hack for suppressing AUTHORIZATION clause that old pg_dump
3834 * versions put into CREATE SCHEMA. Don't mutate the variant for schema
3835 * "public" that is a comment. We have to do this when --no-owner mode is
3836 * selected. This is ugly, but I see no other good way ...
3837 *
3838 * 2. BLOB METADATA entries need special processing since their defn
3839 * strings are just lists of OIDs, not complete SQL commands.
3840 *
3841 * 3. ACL LARGE OBJECTS entries need special processing because they
3842 * contain only one copy of the ACL GRANT/REVOKE commands, which we must
3843 * apply to each large object listed in the associated BLOB METADATA.
3844 */
3845 if (ropt->noOwner &&
3846 strcmp(te->desc, "SCHEMA") == 0 && strncmp(te->defn, "--", 2) != 0)
3847 {
3848 ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
3849 }
3850 else if (strcmp(te->desc, "BLOB METADATA") == 0)
3851 {
3852 IssueCommandPerBlob(AH, te, "SELECT pg_catalog.lo_create('", "')");
3853 }
3854 else if (strcmp(te->desc, "ACL") == 0 &&
3855 strncmp(te->tag, "LARGE OBJECTS", 13) == 0)
3856 {
3857 IssueACLPerBlob(AH, te);
3858 }
3859 else if (te->defn && strlen(te->defn) > 0)
3860 {
3861 ahprintf(AH, "%s\n\n", te->defn);
3862
3863 /*
3864 * If the defn string contains multiple SQL commands, txn_size mode
3865 * should count it as N actions not one. But rather than build a full
3866 * SQL parser, approximate this by counting semicolons. One case
3867 * where that tends to be badly fooled is function definitions, so
3868 * ignore them. (restore_toc_entry will count one action anyway.)
3869 */
3870 if (ropt->txn_size > 0 &&
3871 strcmp(te->desc, "FUNCTION") != 0 &&
3872 strcmp(te->desc, "PROCEDURE") != 0)
3873 {
3874 const char *p = te->defn;
3875 int nsemis = 0;
3876
3877 while ((p = strchr(p, ';')) != NULL)
3878 {
3879 nsemis++;
3880 p++;
3881 }
3882 if (nsemis > 1)
3883 AH->txnCount += nsemis - 1;
3884 }
3885 }
3886
3887 /*
3888 * If we aren't using SET SESSION AUTH to determine ownership, we must
3889 * instead issue an ALTER OWNER command. Schema "public" is special; when
3890 * a dump emits a comment in lieu of creating it, we use ALTER OWNER even
3891 * when using SET SESSION for all other objects. We assume that anything
3892 * without a DROP command is not a separately ownable object.
3893 */
3894 if (!ropt->noOwner &&
3895 (!ropt->use_setsessauth ||
3896 (strcmp(te->desc, "SCHEMA") == 0 &&
3897 strncmp(te->defn, "--", 2) == 0)) &&
3898 te->owner && strlen(te->owner) > 0 &&
3899 te->dropStmt && strlen(te->dropStmt) > 0)
3900 {
3901 if (strcmp(te->desc, "BLOB METADATA") == 0)
3902 {
3903 /* BLOB METADATA needs special code to handle multiple LOs */
3904 char *cmdEnd = psprintf(" OWNER TO %s", fmtId(te->owner));
3905
3906 IssueCommandPerBlob(AH, te, "ALTER LARGE OBJECT ", cmdEnd);
3907 pg_free(cmdEnd);
3908 }
3909 else
3910 {
3911 /* For all other cases, we can use _getObjectDescription */
3912 PQExpBufferData temp;
3913
3914 initPQExpBuffer(&temp);
3915 _getObjectDescription(&temp, te);
3916
3917 /*
3918 * If _getObjectDescription() didn't fill the buffer, then there
3919 * is no owner.
3920 */
3921 if (temp.data[0])
3922 ahprintf(AH, "ALTER %s OWNER TO %s;\n\n",
3923 temp.data, fmtId(te->owner));
3924 termPQExpBuffer(&temp);
3925 }
3926 }
3927
3928 /*
3929 * Select a partitioned table's default AM, once the table definition has
3930 * been generated.
3931 */
3932 if (te->relkind == RELKIND_PARTITIONED_TABLE)
3934
3935 /*
3936 * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
3937 * commands, so we can no longer assume we know the current auth setting.
3938 */
3939 if (_tocEntryIsACL(te))
3940 {
3941 free(AH->currUser);
3942 AH->currUser = NULL;
3943 }
3944}
void pg_free(void *ptr)
Definition: fe_memutils.c:105
int i
Definition: isn.c:74
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 char * sanitize_line(const char *str, bool want_hyphen)
static void _selectTablespace(ArchiveHandle *AH, const char *tablespace)
void IssueACLPerBlob(ArchiveHandle *AH, TocEntry *te)
Definition: pg_backup_db.c:597
void IssueCommandPerBlob(ArchiveHandle *AH, TocEntry *te, const char *cmdBegin, const char *cmdEnd)
Definition: pg_backup_db.c:550
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
int verbose
Definition: pg_backup.h:227
Oid tableoid
Definition: pg_backup.h:276
PrintExtraTocPtrType PrintExtraTocPtr
CatalogId catalogId
DumpId * dependencies

References _becomeOwner(), _getObjectDescription(), _printTableAccessMethodNoStorage(), _selectOutputSchema(), _selectTableAccessMethod(), _selectTablespace(), _tocEntryIsACL(), ahprintf(), _tocEntry::catalogId, _archiveHandle::currUser, PQExpBufferData::data, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dropStmt, _tocEntry::dumpId, fmtId(), free, i, initPQExpBuffer(), IssueACLPerBlob(), IssueCommandPerBlob(), _tocEntry::nDeps, _restoreOptions::noOwner, _restoreOptions::noTablespace, _archiveHandle::noTocComments, CatalogId::oid, _tocEntry::owner, 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 3380 of file pg_backup_archiver.c.

3381{
3382 if (RestoringToDB(AH))
3384 else
3385 {
3386 PQExpBufferData connectbuf;
3387
3388 initPQExpBuffer(&connectbuf);
3389 appendPsqlMetaConnect(&connectbuf, dbname);
3390 ahprintf(AH, "%s\n", connectbuf.data);
3391 termPQExpBuffer(&connectbuf);
3392 }
3393
3394 /*
3395 * NOTE: currUser keeps track of what the imaginary session user in our
3396 * script is. It's now effectively reset to the original userID.
3397 */
3398 free(AH->currUser);
3399 AH->currUser = NULL;
3400
3401 /* don't assume we still know the output schema, tablespace, etc either */
3402 free(AH->currSchema);
3403 AH->currSchema = NULL;
3404
3405 free(AH->currTableAm);
3406 AH->currTableAm = NULL;
3407
3408 free(AH->currTablespace);
3409 AH->currTablespace = NULL;
3410
3411 /* re-establish fixed state */
3413}
static void _doSetFixedOutputState(ArchiveHandle *AH)
void ReconnectToServer(ArchiveHandle *AH, const char *dbname)
Definition: pg_backup_db.c:72
char * dbname
Definition: streamutil.c:49
void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname)
Definition: string_utils.c:743

References _doSetFixedOutputState(), ahprintf(), appendPsqlMetaConnect(), _archiveHandle::currSchema, _archiveHandle::currTableAm, _archiveHandle::currTablespace, _archiveHandle::currUser, PQExpBufferData::data, dbname, free, initPQExpBuffer(), ReconnectToServer(), RestoringToDB(), and termPQExpBuffer().

Referenced by restore_toc_entry().

◆ _selectOutputSchema()

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

Definition at line 3460 of file pg_backup_archiver.c.

3461{
3462 PQExpBuffer qry;
3463
3464 /*
3465 * If there was a SEARCHPATH TOC entry, we're supposed to just stay with
3466 * that search_path rather than switching to entry-specific paths.
3467 * Otherwise, it's an old archive that will not restore correctly unless
3468 * we set the search_path as it's expecting.
3469 */
3470 if (AH->public.searchpath)
3471 return;
3472
3473 if (!schemaName || *schemaName == '\0' ||
3474 (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0))
3475 return; /* no need to do anything */
3476
3477 qry = createPQExpBuffer();
3478
3479 appendPQExpBuffer(qry, "SET search_path = %s",
3480 fmtId(schemaName));
3481 if (strcmp(schemaName, "pg_catalog") != 0)
3482 appendPQExpBufferStr(qry, ", pg_catalog");
3483
3484 if (RestoringToDB(AH))
3485 {
3486 PGresult *res;
3487
3488 res = PQexec(AH->connection, qry->data);
3489
3490 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3492 "could not set \"search_path\" to \"%s\": %s",
3493 schemaName, PQerrorMessage(AH->connection));
3494
3495 PQclear(res);
3496 }
3497 else
3498 ahprintf(AH, "%s;\n\n", qry->data);
3499
3500 free(AH->currSchema);
3501 AH->currSchema = pg_strdup(schemaName);
3502
3503 destroyPQExpBuffer(qry);
3504}

References ahprintf(), appendPQExpBuffer(), appendPQExpBufferStr(), _archiveHandle::connection, createPQExpBuffer(), _archiveHandle::currSchema, PQExpBufferData::data, destroyPQExpBuffer(), fmtId(), 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 3571 of file pg_backup_archiver.c.

3572{
3573 RestoreOptions *ropt = AH->public.ropt;
3574 PQExpBuffer cmd;
3575 const char *want,
3576 *have;
3577
3578 /* do nothing in --no-table-access-method mode */
3579 if (ropt->noTableAm)
3580 return;
3581
3582 have = AH->currTableAm;
3583 want = tableam;
3584
3585 if (!want)
3586 return;
3587
3588 if (have && strcmp(want, have) == 0)
3589 return;
3590
3591 cmd = createPQExpBuffer();
3592 appendPQExpBuffer(cmd, "SET default_table_access_method = %s;", fmtId(want));
3593
3594 if (RestoringToDB(AH))
3595 {
3596 PGresult *res;
3597
3598 res = PQexec(AH->connection, cmd->data);
3599
3600 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3602 "could not set \"default_table_access_method\": %s",
3604
3605 PQclear(res);
3606 }
3607 else
3608 ahprintf(AH, "%s\n\n", cmd->data);
3609
3610 destroyPQExpBuffer(cmd);
3611
3612 free(AH->currTableAm);
3613 AH->currTableAm = pg_strdup(want);
3614}

References ahprintf(), appendPQExpBuffer(), _archiveHandle::connection, createPQExpBuffer(), _archiveHandle::currTableAm, PQExpBufferData::data, destroyPQExpBuffer(), fmtId(), free, _restoreOptions::noTableAm, 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 3511 of file pg_backup_archiver.c.

3512{
3513 RestoreOptions *ropt = AH->public.ropt;
3514 PQExpBuffer qry;
3515 const char *want,
3516 *have;
3517
3518 /* do nothing in --no-tablespaces mode */
3519 if (ropt->noTablespace)
3520 return;
3521
3522 have = AH->currTablespace;
3523 want = tablespace;
3524
3525 /* no need to do anything for non-tablespace object */
3526 if (!want)
3527 return;
3528
3529 if (have && strcmp(want, have) == 0)
3530 return; /* no need to do anything */
3531
3532 qry = createPQExpBuffer();
3533
3534 if (strcmp(want, "") == 0)
3535 {
3536 /* We want the tablespace to be the database's default */
3537 appendPQExpBufferStr(qry, "SET default_tablespace = ''");
3538 }
3539 else
3540 {
3541 /* We want an explicit tablespace */
3542 appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
3543 }
3544
3545 if (RestoringToDB(AH))
3546 {
3547 PGresult *res;
3548
3549 res = PQexec(AH->connection, qry->data);
3550
3551 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3553 "could not set \"default_tablespace\" to %s: %s",
3554 fmtId(want), PQerrorMessage(AH->connection));
3555
3556 PQclear(res);
3557 }
3558 else
3559 ahprintf(AH, "%s;\n\n", qry->data);
3560
3561 free(AH->currTablespace);
3562 AH->currTablespace = pg_strdup(want);
3563
3564 destroyPQExpBuffer(qry);
3565}
static char * tablespace
Definition: pgbench.c:217

References ahprintf(), appendPQExpBuffer(), appendPQExpBufferStr(), _archiveHandle::connection, createPQExpBuffer(), _archiveHandle::currTablespace, PQExpBufferData::data, destroyPQExpBuffer(), fmtId(), free, _restoreOptions::noTablespace, 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 3255 of file pg_backup_archiver.c.

3256{
3257 /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3258 if (strcmp(te->desc, "ACL") == 0 ||
3259 strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3260 strcmp(te->desc, "DEFAULT ACL") == 0)
3261 return true;
3262 return false;
3263}

References _tocEntry::desc.

Referenced by _printTocEntry(), and _tocEntryRequired().

◆ _tocEntryRequired()

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

Definition at line 2925 of file pg_backup_archiver.c.

2926{
2927 int res = REQ_SCHEMA | REQ_DATA;
2928 RestoreOptions *ropt = AH->public.ropt;
2929
2930 /* These items are treated specially */
2931 if (strcmp(te->desc, "ENCODING") == 0 ||
2932 strcmp(te->desc, "STDSTRINGS") == 0 ||
2933 strcmp(te->desc, "SEARCHPATH") == 0)
2934 return REQ_SPECIAL;
2935
2936 if (strcmp(te->desc, "STATISTICS DATA") == 0)
2937 {
2938 if (!ropt->dumpStatistics)
2939 return 0;
2940
2941 res = REQ_STATS;
2942 }
2943
2944 /*
2945 * DATABASE and DATABASE PROPERTIES also have a special rule: they are
2946 * restored in createDB mode, and not restored otherwise, independently of
2947 * all else.
2948 */
2949 if (strcmp(te->desc, "DATABASE") == 0 ||
2950 strcmp(te->desc, "DATABASE PROPERTIES") == 0)
2951 {
2952 if (ropt->createDB)
2953 return REQ_SCHEMA;
2954 else
2955 return 0;
2956 }
2957
2958 /*
2959 * Process exclusions that affect certain classes of TOC entries.
2960 */
2961
2962 /* If it's an ACL, maybe ignore it */
2963 if (ropt->aclsSkip && _tocEntryIsACL(te))
2964 return 0;
2965
2966 /* If it's a comment, maybe ignore it */
2967 if (ropt->no_comments && strcmp(te->desc, "COMMENT") == 0)
2968 return 0;
2969
2970 /* If it's a policy, maybe ignore it */
2971 if (ropt->no_policies &&
2972 (strcmp(te->desc, "POLICY") == 0 ||
2973 strcmp(te->desc, "ROW SECURITY") == 0))
2974 return 0;
2975
2976 /*
2977 * If it's a publication or a table part of a publication, maybe ignore
2978 * it.
2979 */
2980 if (ropt->no_publications &&
2981 (strcmp(te->desc, "PUBLICATION") == 0 ||
2982 strcmp(te->desc, "PUBLICATION TABLE") == 0 ||
2983 strcmp(te->desc, "PUBLICATION TABLES IN SCHEMA") == 0))
2984 return 0;
2985
2986 /* If it's a security label, maybe ignore it */
2987 if (ropt->no_security_labels && strcmp(te->desc, "SECURITY LABEL") == 0)
2988 return 0;
2989
2990 /* If it's a subscription, maybe ignore it */
2991 if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0)
2992 return 0;
2993
2994 /* Ignore it if section is not to be dumped/restored */
2995 switch (curSection)
2996 {
2997 case SECTION_PRE_DATA:
2998 if (!(ropt->dumpSections & DUMP_PRE_DATA))
2999 return 0;
3000 break;
3001 case SECTION_DATA:
3002 if (!(ropt->dumpSections & DUMP_DATA))
3003 return 0;
3004 break;
3005 case SECTION_POST_DATA:
3006 if (!(ropt->dumpSections & DUMP_POST_DATA))
3007 return 0;
3008 break;
3009 default:
3010 /* shouldn't get here, really, but ignore it */
3011 return 0;
3012 }
3013
3014 /* Ignore it if rejected by idWanted[] (cf. SortTocFromFile) */
3015 if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
3016 return 0;
3017
3018 /*
3019 * Check options for selective dump/restore.
3020 */
3021 if (strcmp(te->desc, "ACL") == 0 ||
3022 strcmp(te->desc, "COMMENT") == 0 ||
3023 strcmp(te->desc, "STATISTICS DATA") == 0 ||
3024 strcmp(te->desc, "SECURITY LABEL") == 0)
3025 {
3026 /* Database properties react to createDB, not selectivity options. */
3027 if (strncmp(te->tag, "DATABASE ", 9) == 0)
3028 {
3029 if (!ropt->createDB)
3030 return 0;
3031 }
3032 else if (ropt->schemaNames.head != NULL ||
3033 ropt->schemaExcludeNames.head != NULL ||
3034 ropt->selTypes)
3035 {
3036 /*
3037 * In a selective dump/restore, we want to restore these dependent
3038 * TOC entry types only if their parent object is being restored.
3039 * Without selectivity options, we let through everything in the
3040 * archive. Note there may be such entries with no parent, eg
3041 * non-default ACLs for built-in objects. Also, we make
3042 * per-column ACLs additionally depend on the table's ACL if any
3043 * to ensure correct restore order, so those dependencies should
3044 * be ignored in this check.
3045 *
3046 * This code depends on the parent having been marked already,
3047 * which should be the case; if it isn't, perhaps due to
3048 * SortTocFromFile rearrangement, skipping the dependent entry
3049 * seems prudent anyway.
3050 *
3051 * Ideally we'd handle, eg, table CHECK constraints this way too.
3052 * But it's hard to tell which of their dependencies is the one to
3053 * consult.
3054 */
3055 bool dumpthis = false;
3056
3057 for (int i = 0; i < te->nDeps; i++)
3058 {
3059 TocEntry *pte = getTocEntryByDumpId(AH, te->dependencies[i]);
3060
3061 if (!pte)
3062 continue; /* probably shouldn't happen */
3063 if (strcmp(pte->desc, "ACL") == 0)
3064 continue; /* ignore dependency on another ACL */
3065 if (pte->reqs == 0)
3066 continue; /* this object isn't marked, so ignore it */
3067 /* Found a parent to be dumped, so we want to dump this too */
3068 dumpthis = true;
3069 break;
3070 }
3071 if (!dumpthis)
3072 return 0;
3073 }
3074 }
3075 else
3076 {
3077 /* Apply selective-restore rules for standalone TOC entries. */
3078 if (ropt->schemaNames.head != NULL)
3079 {
3080 /* If no namespace is specified, it means all. */
3081 if (!te->namespace)
3082 return 0;
3083 if (!simple_string_list_member(&ropt->schemaNames, te->namespace))
3084 return 0;
3085 }
3086
3087 if (ropt->schemaExcludeNames.head != NULL &&
3088 te->namespace &&
3089 simple_string_list_member(&ropt->schemaExcludeNames, te->namespace))
3090 return 0;
3091
3092 if (ropt->selTypes)
3093 {
3094 if (strcmp(te->desc, "TABLE") == 0 ||
3095 strcmp(te->desc, "TABLE DATA") == 0 ||
3096 strcmp(te->desc, "VIEW") == 0 ||
3097 strcmp(te->desc, "FOREIGN TABLE") == 0 ||
3098 strcmp(te->desc, "MATERIALIZED VIEW") == 0 ||
3099 strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 ||
3100 strcmp(te->desc, "SEQUENCE") == 0 ||
3101 strcmp(te->desc, "SEQUENCE SET") == 0)
3102 {
3103 if (!ropt->selTable)
3104 return 0;
3105 if (ropt->tableNames.head != NULL &&
3107 return 0;
3108 }
3109 else if (strcmp(te->desc, "INDEX") == 0)
3110 {
3111 if (!ropt->selIndex)
3112 return 0;
3113 if (ropt->indexNames.head != NULL &&
3115 return 0;
3116 }
3117 else if (strcmp(te->desc, "FUNCTION") == 0 ||
3118 strcmp(te->desc, "AGGREGATE") == 0 ||
3119 strcmp(te->desc, "PROCEDURE") == 0)
3120 {
3121 if (!ropt->selFunction)
3122 return 0;
3123 if (ropt->functionNames.head != NULL &&
3125 return 0;
3126 }
3127 else if (strcmp(te->desc, "TRIGGER") == 0)
3128 {
3129 if (!ropt->selTrigger)
3130 return 0;
3131 if (ropt->triggerNames.head != NULL &&
3133 return 0;
3134 }
3135 else
3136 return 0;
3137 }
3138 }
3139
3140
3141 /*
3142 * Determine whether the TOC entry contains schema and/or data components,
3143 * and mask off inapplicable REQ bits. If it had a dataDumper, assume
3144 * it's both schema and data. Otherwise it's probably schema-only, but
3145 * there are exceptions.
3146 */
3147 if (!te->hadDumper)
3148 {
3149 /*
3150 * Special Case: If 'SEQUENCE SET' or anything to do with LOs, then it
3151 * is considered a data entry. We don't need to check for BLOBS or
3152 * old-style BLOB COMMENTS entries, because they will have hadDumper =
3153 * true ... but we do need to check new-style BLOB ACLs, comments,
3154 * etc.
3155 */
3156 if (strcmp(te->desc, "SEQUENCE SET") == 0 ||
3157 strcmp(te->desc, "BLOB") == 0 ||
3158 strcmp(te->desc, "BLOB METADATA") == 0 ||
3159 (strcmp(te->desc, "ACL") == 0 &&
3160 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3161 (strcmp(te->desc, "COMMENT") == 0 &&
3162 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3163 (strcmp(te->desc, "SECURITY LABEL") == 0 &&
3164 strncmp(te->tag, "LARGE OBJECT", 12) == 0))
3165 res = res & REQ_DATA;
3166 else
3167 res = res & ~REQ_DATA;
3168 }
3169
3170 /*
3171 * If there's no definition command, there's no schema component. Treat
3172 * "load via partition root" comments as not schema.
3173 */
3174 if (!te->defn || !te->defn[0] ||
3175 strncmp(te->defn, "-- load via partition root ", 27) == 0)
3176 res = res & ~REQ_SCHEMA;
3177
3178 /*
3179 * Special case: <Init> type with <Max OID> tag; this is obsolete and we
3180 * always ignore it.
3181 */
3182 if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
3183 return 0;
3184
3185 /* Mask it if we don't want data */
3186 if (!ropt->dumpData)
3187 {
3188 /*
3189 * The sequence_data option overrides dumpData for SEQUENCE SET.
3190 *
3191 * In binary-upgrade mode, even with dumpData unset, we do not mask
3192 * out large objects. (Only large object definitions, comments and
3193 * other metadata should be generated in binary-upgrade mode, not the
3194 * actual data, but that need not concern us here.)
3195 */
3196 if (!(ropt->sequence_data && strcmp(te->desc, "SEQUENCE SET") == 0) &&
3197 !(ropt->binary_upgrade &&
3198 (strcmp(te->desc, "BLOB") == 0 ||
3199 strcmp(te->desc, "BLOB METADATA") == 0 ||
3200 (strcmp(te->desc, "ACL") == 0 &&
3201 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3202 (strcmp(te->desc, "COMMENT") == 0 &&
3203 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3204 (strcmp(te->desc, "SECURITY LABEL") == 0 &&
3205 strncmp(te->tag, "LARGE OBJECT", 12) == 0))))
3206 res = res & (REQ_SCHEMA | REQ_STATS);
3207 }
3208
3209 /* Mask it if we don't want schema */
3210 if (!ropt->dumpSchema)
3211 res = res & (REQ_DATA | REQ_STATS);
3212
3213 return res;
3214}
@ 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:140
bool * idWanted
Definition: pg_backup.h:157
SimpleStringList functionNames
Definition: pg_backup.h:138
SimpleStringList tableNames
Definition: pg_backup.h:142
SimpleStringList indexNames
Definition: pg_backup.h:137
int no_subscriptions
Definition: pg_backup.h:117
SimpleStringList triggerNames
Definition: pg_backup.h:141
bool dumpStatistics
Definition: pg_backup.h:165
SimpleStringList schemaNames
Definition: pg_backup.h:139
int no_security_labels
Definition: pg_backup.h:116

References _tocEntryIsACL(), _restoreOptions::aclsSkip, _restoreOptions::binary_upgrade, _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, _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, _archiveHandle::public, REQ_DATA, REQ_SCHEMA, REQ_SPECIAL, REQ_STATS, _tocEntry::reqs, 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 3222 of file pg_backup_archiver.c.

3223{
3224 /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3225 if (strcmp(te->desc, "ACL") == 0 ||
3226 strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3227 strcmp(te->desc, "DEFAULT ACL") == 0)
3228 return RESTORE_PASS_ACL;
3229 if (strcmp(te->desc, "EVENT TRIGGER") == 0 ||
3230 strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0)
3231 return RESTORE_PASS_POST_ACL;
3232
3233 /*
3234 * Comments need to be emitted in the same pass as their parent objects.
3235 * ACLs haven't got comments, and neither do matview data objects, but
3236 * event triggers do. (Fortunately, event triggers haven't got ACLs, or
3237 * we'd need yet another weird special case.)
3238 */
3239 if (strcmp(te->desc, "COMMENT") == 0 &&
3240 strncmp(te->tag, "EVENT TRIGGER ", 14) == 0)
3241 return RESTORE_PASS_POST_ACL;
3242
3243 /* All else can be handled in the main pass. */
3244 return RESTORE_PASS_MAIN;
3245}
@ RESTORE_PASS_POST_ACL
@ RESTORE_PASS_ACL
@ RESTORE_PASS_MAIN

References _tocEntry::desc, RESTORE_PASS_ACL, RESTORE_PASS_MAIN, RESTORE_PASS_POST_ACL, 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 1734 of file pg_backup_archiver.c.

1735{
1736 int save_errno = errno;
1737 char *p;
1738 size_t len = 128; /* initial assumption about buffer size */
1739 size_t cnt;
1740
1741 for (;;)
1742 {
1743 va_list args;
1744
1745 /* Allocate work buffer. */
1746 p = (char *) pg_malloc(len);
1747
1748 /* Try to format the data. */
1749 errno = save_errno;
1750 va_start(args, fmt);
1751 cnt = pvsnprintf(p, len, fmt, args);
1752 va_end(args);
1753
1754 if (cnt < len)
1755 break; /* success */
1756
1757 /* Release buffer and loop around to try again with larger len. */
1758 free(p);
1759 len = cnt;
1760 }
1761
1762 ahwrite(p, 1, cnt, AH);
1763 free(p);
1764 return (int) cnt;
1765}
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
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(), generate_unaccent_rules::args, free, len, pg_malloc(), and pvsnprintf().

Referenced by _disableTriggersIfNecessary(), _doSetFixedOutputState(), _doSetSessionAuth(), _enableTriggersIfNecessary(), _EndData(), _EndLO(), _EndLOs(), _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 1825 of file pg_backup_archiver.c.

1826{
1827 int bytes_written = 0;
1828
1829 if (AH->writingLO)
1830 {
1831 size_t remaining = size * nmemb;
1832
1833 while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1834 {
1835 size_t avail = AH->lo_buf_size - AH->lo_buf_used;
1836
1837 memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1838 ptr = (const char *) ptr + avail;
1839 remaining -= avail;
1840 AH->lo_buf_used += avail;
1841 dump_lo_buf(AH);
1842 }
1843
1844 memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1845 AH->lo_buf_used += remaining;
1846
1847 bytes_written = size * nmemb;
1848 }
1849 else if (AH->CustomOutPtr)
1850 bytes_written = AH->CustomOutPtr(AH, ptr, size * nmemb);
1851
1852 /*
1853 * If we're doing a restore, and it's direct to DB, and we're connected
1854 * then send it to the DB.
1855 */
1856 else if (RestoringToDB(AH))
1857 bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb);
1858 else
1859 {
1861
1862 if (CFH->write_func(ptr, size * nmemb, CFH))
1863 bytes_written = size * nmemb;
1864 }
1865
1866 if (bytes_written != size * nmemb)
1868}
int remaining
Definition: informix.c:692
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:78
static void dump_lo_buf(ArchiveHandle *AH)
#define WRITE_ERROR_EXIT
int ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen)
Definition: pg_backup_db.c:443
bool(* write_func)(const void *ptr, size_t size, struct CompressFileHandle *CFH)
Definition: compress_io.h:139
CustomOutPtrType CustomOutPtr

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

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

◆ ArchiveEntry()

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

Definition at line 1220 of file pg_backup_archiver.c.

1222{
1223 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1224 TocEntry *newToc;
1225
1226 newToc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
1227
1228 AH->tocCount++;
1229 if (dumpId > AH->maxDumpId)
1230 AH->maxDumpId = dumpId;
1231
1232 newToc->prev = AH->toc->prev;
1233 newToc->next = AH->toc;
1234 AH->toc->prev->next = newToc;
1235 AH->toc->prev = newToc;
1236
1237 newToc->catalogId = catalogId;
1238 newToc->dumpId = dumpId;
1239 newToc->section = opts->section;
1240
1241 newToc->tag = pg_strdup(opts->tag);
1242 newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
1243 newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
1244 newToc->tableam = opts->tableam ? pg_strdup(opts->tableam) : NULL;
1245 newToc->relkind = opts->relkind;
1246 newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
1247 newToc->desc = pg_strdup(opts->description);
1248 newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
1249 newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
1250 newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
1251
1252 if (opts->nDeps > 0)
1253 {
1254 newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId));
1255 memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
1256 newToc->nDeps = opts->nDeps;
1257 }
1258 else
1259 {
1260 newToc->dependencies = NULL;
1261 newToc->nDeps = 0;
1262 }
1263
1264 newToc->dataDumper = opts->dumpFn;
1265 newToc->dataDumperArg = opts->dumpArg;
1266 newToc->hadDumper = opts->dumpFn ? true : false;
1267
1268 newToc->formatData = NULL;
1269 newToc->dataLength = 0;
1270
1271 if (AH->ArchiveEntryPtr != NULL)
1272 AH->ArchiveEntryPtr(AH, newToc);
1273
1274 return newToc;
1275}
return true
Definition: isn.c:127
static AmcheckOptions opts
Definition: pg_amcheck.c:112
int DumpId
Definition: pg_backup.h:280
ArchiveEntryPtrType ArchiveEntryPtr
teSection section
DataDumperPtr dataDumper
pgoff_t dataLength
const void * dataDumperArg

References _archiveHandle::ArchiveEntryPtr, _tocEntry::catalogId, _tocEntry::copyStmt, _tocEntry::dataDumper, _tocEntry::dataDumperArg, _tocEntry::dataLength, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dropStmt, _tocEntry::dumpId, _tocEntry::formatData, _tocEntry::hadDumper, _archiveHandle::maxDumpId, _tocEntry::nDeps, _tocEntry::next, opts, _tocEntry::owner, pg_malloc(), pg_malloc0(), pg_strdup(), _tocEntry::prev, _tocEntry::relkind, _tocEntry::section, _tocEntry::tableam, _tocEntry::tablespace, _tocEntry::tag, _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(), 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 1634 of file pg_backup_archiver.c.

1635{
1636 int save_errno = errno;
1637 char *p;
1638 size_t len = 128; /* initial assumption about buffer size */
1639 size_t cnt;
1640
1641 for (;;)
1642 {
1643 va_list args;
1644
1645 /* Allocate work buffer. */
1646 p = (char *) pg_malloc(len);
1647
1648 /* Try to format the data. */
1649 errno = save_errno;
1650 va_start(args, fmt);
1651 cnt = pvsnprintf(p, len, fmt, args);
1652 va_end(args);
1653
1654 if (cnt < len)
1655 break; /* success */
1656
1657 /* Release buffer and loop around to try again with larger len. */
1658 free(p);
1659 len = cnt;
1660 }
1661
1662 WriteData(AH, p, cnt);
1663 free(p);
1664 return (int) cnt;
1665}
void WriteData(Archive *AHX, const void *data, size_t dLen)

References generate_unaccent_rules::args, free, len, pg_malloc(), pvsnprintf(), and WriteData().

◆ archputs()

void archputs ( const char *  s,
Archive AH 
)

Definition at line 1627 of file pg_backup_archiver.c.

1628{
1629 WriteData(AH, s, strlen(s));
1630}

References WriteData().

Referenced by dumpTableData_insert().

◆ buildTocEntryArrays()

static void buildTocEntryArrays ( ArchiveHandle AH)
static

Definition at line 1964 of file pg_backup_archiver.c.

1965{
1966 DumpId maxDumpId = AH->maxDumpId;
1967 TocEntry *te;
1968
1969 AH->tocsByDumpId = (TocEntry **) pg_malloc0((maxDumpId + 1) * sizeof(TocEntry *));
1970 AH->tableDataId = (DumpId *) pg_malloc0((maxDumpId + 1) * sizeof(DumpId));
1971
1972 for (te = AH->toc->next; te != AH->toc; te = te->next)
1973 {
1974 /* this check is purely paranoia, maxDumpId should be correct */
1975 if (te->dumpId <= 0 || te->dumpId > maxDumpId)
1976 pg_fatal("bad dumpId");
1977
1978 /* tocsByDumpId indexes all TOCs by their dump ID */
1979 AH->tocsByDumpId[te->dumpId] = te;
1980
1981 /*
1982 * tableDataId provides the TABLE DATA item's dump ID for each TABLE
1983 * TOC entry that has a DATA item. We compute this by reversing the
1984 * TABLE DATA item's dependency, knowing that a TABLE DATA item has
1985 * just one dependency and it is the TABLE item.
1986 */
1987 if (strcmp(te->desc, "TABLE DATA") == 0 && te->nDeps > 0)
1988 {
1989 DumpId tableId = te->dependencies[0];
1990
1991 /*
1992 * The TABLE item might not have been in the archive, if this was
1993 * a data-only dump; but its dump ID should be less than its data
1994 * item's dump ID, so there should be a place for it in the array.
1995 */
1996 if (tableId <= 0 || tableId > maxDumpId)
1997 pg_fatal("bad table dumpId for TABLE DATA item");
1998
1999 AH->tableDataId[tableId] = te->dumpId;
2000 }
2001 }
2002}
struct _tocEntry ** tocsByDumpId

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

Referenced by getTocEntryByDumpId(), and RestoreArchive().

◆ checkSeek()

bool checkSeek ( FILE *  fp)

Definition at line 4146 of file pg_backup_archiver.c.

4147{
4148 pgoff_t tpos;
4149
4150 /* Check that ftello works on this file */
4151 tpos = ftello(fp);
4152 if (tpos < 0)
4153 return false;
4154
4155 /*
4156 * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
4157 * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
4158 * successful no-op even on files that are otherwise unseekable.
4159 */
4160 if (fseeko(fp, tpos, SEEK_SET) != 0)
4161 return false;
4162
4163 return true;
4164}
#define ftello(stream)
Definition: win32_port.h:209
#define fseeko(stream, offset, origin)
Definition: win32_port.h:206

References fseeko, ftello, and pgoff_t.

Referenced by InitArchiveFmt_Custom(), and InitArchiveFmt_Tar().

◆ CloneArchive()

ArchiveHandle * CloneArchive ( ArchiveHandle AH)

Definition at line 5013 of file pg_backup_archiver.c.

5014{
5015 ArchiveHandle *clone;
5016
5017 /* Make a "flat" copy */
5018 clone = (ArchiveHandle *) pg_malloc(sizeof(ArchiveHandle));
5019 memcpy(clone, AH, sizeof(ArchiveHandle));
5020
5021 /* Likewise flat-copy the RestoreOptions, so we can alter them locally */
5022 clone->public.ropt = (RestoreOptions *) pg_malloc(sizeof(RestoreOptions));
5023 memcpy(clone->public.ropt, AH->public.ropt, sizeof(RestoreOptions));
5024
5025 /* Handle format-independent fields */
5026 memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse));
5027
5028 /* The clone will have its own connection, so disregard connection state */
5029 clone->connection = NULL;
5030 clone->connCancel = NULL;
5031 clone->currUser = NULL;
5032 clone->currSchema = NULL;
5033 clone->currTableAm = NULL;
5034 clone->currTablespace = NULL;
5035
5036 /* savedPassword must be local in case we change it while connecting */
5037 if (clone->savedPassword)
5038 clone->savedPassword = pg_strdup(clone->savedPassword);
5039
5040 /* clone has its own error count, too */
5041 clone->public.n_errors = 0;
5042
5043 /* clones should not share lo_buf */
5044 clone->lo_buf = NULL;
5045
5046 /*
5047 * Clone connections disregard --transaction-size; they must commit after
5048 * each command so that the results are immediately visible to other
5049 * workers.
5050 */
5051 clone->public.ropt->txn_size = 0;
5052
5053 /*
5054 * Connect our new clone object to the database, using the same connection
5055 * parameters used for the original connection.
5056 */
5057 ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true);
5058
5059 /* re-establish fixed state */
5060 if (AH->mode == archModeRead)
5062 /* in write case, setupDumpWorker will fix up connection state */
5063
5064 /* Let the format-specific code have a chance too */
5065 clone->ClonePtr(clone);
5066
5067 Assert(clone->connection != NULL);
5068 return clone;
5069}
void ConnectDatabase(Archive *AHX, const ConnParams *cparams, bool isReconnect)
Definition: pg_backup_db.c:108
@ archModeRead
Definition: pg_backup.h:52
PGcancel *volatile connCancel
ClonePtrType ClonePtr
ConnParams cparams
Definition: pg_backup.h:145

References _doSetFixedOutputState(), archModeRead, Assert(), _archiveHandle::ClonePtr, _archiveHandle::connCancel, ConnectDatabase(), _archiveHandle::connection, _restoreOptions::cparams, _archiveHandle::currSchema, _archiveHandle::currTableAm, _archiveHandle::currTablespace, _archiveHandle::currUser, _archiveHandle::lo_buf, _archiveHandle::mode, Archive::n_errors, pg_malloc(), pg_strdup(), _archiveHandle::public, Archive::ropt, _archiveHandle::savedPassword, _archiveHandle::sqlparse, and _restoreOptions::txn_size.

Referenced by RunWorker().

◆ CloseArchive()

void CloseArchive ( Archive AHX)

Definition at line 260 of file pg_backup_archiver.c.

261{
262 ArchiveHandle *AH = (ArchiveHandle *) AHX;
263
264 AH->ClosePtr(AH);
265
266 /* Close the output */
267 errno = 0;
268 if (!EndCompressFileHandle(AH->OF))
269 pg_fatal("could not close output file: %m");
270}
bool EndCompressFileHandle(CompressFileHandle *CFH)
Definition: compress_io.c:288
ClosePtrType ClosePtr

References _archiveHandle::ClosePtr, EndCompressFileHandle(), _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 229 of file pg_backup_archiver.c.

235{
236 ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression_spec,
238
239 return (Archive *) AH;
240}
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:1475

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

Referenced by main().

◆ DeCloneArchive()

void DeCloneArchive ( ArchiveHandle AH)

Definition at line 5077 of file pg_backup_archiver.c.

5078{
5079 /* Should not have an open database connection */
5080 Assert(AH->connection == NULL);
5081
5082 /* Clear format-specific state */
5083 AH->DeClonePtr(AH);
5084
5085 /* Clear state allocated by CloneArchive */
5086 if (AH->sqlparse.curCmd)
5088
5089 /* Clear any connection-local state */
5090 free(AH->currUser);
5091 free(AH->currSchema);
5092 free(AH->currTablespace);
5093 free(AH->currTableAm);
5094 free(AH->savedPassword);
5095
5096 free(AH);
5097}
DeClonePtrType DeClonePtr
PQExpBuffer curCmd

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

Referenced by RunWorker().

◆ dump_lo_buf()

static void dump_lo_buf ( ArchiveHandle AH)
static

Definition at line 1782 of file pg_backup_archiver.c.

1783{
1784 if (AH->connection)
1785 {
1786 int res;
1787
1788 res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1789 pg_log_debug(ngettext("wrote %zu byte of large object data (result = %d)",
1790 "wrote %zu bytes of large object data (result = %d)",
1791 AH->lo_buf_used),
1792 AH->lo_buf_used, res);
1793 /* We assume there are no short writes, only errors */
1794 if (res != AH->lo_buf_used)
1795 warn_or_exit_horribly(AH, "could not write to large object: %s",
1797 }
1798 else
1799 {
1801
1803 (const unsigned char *) AH->lo_buf,
1804 AH->lo_buf_used,
1805 AH);
1806
1807 /* Hack: turn off writingLO so ahwrite doesn't recurse to here */
1808 AH->writingLO = false;
1809 ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
1810 AH->writingLO = true;
1811
1813 }
1814 AH->lo_buf_used = 0;
1815}
int lo_write(int fd, const char *buf, int len)
Definition: be-fsstubs.c:182
#define ngettext(s, p, n)
Definition: c.h:1152
#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 163 of file pg_backup_archiver.c.

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

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, _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::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 4171 of file pg_backup_archiver.c.

4172{
4173 char buf[64];
4174
4175 if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
4176 ahprintf(AH, "-- %s %s\n\n", msg, buf);
4177}
#define PGDUMP_STRFTIME_FMT
Definition: dumputils.h:33

References ahprintf(), buf, and PGDUMP_STRFTIME_FMT.

Referenced by RestoreArchive().

◆ EndLO()

int EndLO ( Archive AHX,
Oid  oid 
)

Definition at line 1405 of file pg_backup_archiver.c.

1406{
1407 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1408
1409 if (AH->EndLOPtr)
1410 AH->EndLOPtr(AH, AH->currToc, oid);
1411
1412 return 1;
1413}
EndLOPtrType EndLOPtr
struct _tocEntry * currToc

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

Referenced by dumpLOs().

◆ EndRestoreLO()

void EndRestoreLO ( ArchiveHandle AH,
Oid  oid 
)

Definition at line 1520 of file pg_backup_archiver.c.

1521{
1522 if (AH->lo_buf_used > 0)
1523 {
1524 /* Write remaining bytes from the LO buffer */
1525 dump_lo_buf(AH);
1526 }
1527
1528 AH->writingLO = false;
1529
1530 if (AH->connection)
1531 {
1532 lo_close(AH->connection, AH->loFd);
1533 AH->loFd = -1;
1534 }
1535 else
1536 {
1537 ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
1538 }
1539}
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().

◆ EndRestoreLOs()

void EndRestoreLOs ( ArchiveHandle AH)

Definition at line 1447 of file pg_backup_archiver.c.

1448{
1449 RestoreOptions *ropt = AH->public.ropt;
1450
1451 if (!(ropt->single_txn || ropt->txn_size > 0))
1452 {
1453 if (AH->connection)
1455 else
1456 ahprintf(AH, "COMMIT;\n\n");
1457 }
1458
1459 pg_log_info(ngettext("restored %d large object",
1460 "restored %d large objects",
1461 AH->loCount),
1462 AH->loCount);
1463}
static void CommitTransaction(void)
Definition: xact.c:2228

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().

◆ fix_dependencies()

static void fix_dependencies ( ArchiveHandle AH)
static

Definition at line 4710 of file pg_backup_archiver.c.

4711{
4712 TocEntry *te;
4713 int i;
4714
4715 /*
4716 * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC
4717 * items are marked as not being in any parallel-processing list.
4718 */
4719 for (te = AH->toc->next; te != AH->toc; te = te->next)
4720 {
4721 te->depCount = te->nDeps;
4722 te->revDeps = NULL;
4723 te->nRevDeps = 0;
4724 te->pending_prev = NULL;
4725 te->pending_next = NULL;
4726 }
4727
4728 /*
4729 * POST_DATA items that are shown as depending on a table need to be
4730 * re-pointed to depend on that table's data, instead. This ensures they
4731 * won't get scheduled until the data has been loaded.
4732 */
4734
4735 /*
4736 * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB
4737 * COMMENTS to BLOBS. Cope. (We assume there's only one BLOBS and only
4738 * one BLOB COMMENTS in such files.)
4739 */
4740 if (AH->version < K_VERS_1_11)
4741 {
4742 for (te = AH->toc->next; te != AH->toc; te = te->next)
4743 {
4744 if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0)
4745 {
4746 TocEntry *te2;
4747
4748 for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next)
4749 {
4750 if (strcmp(te2->desc, "BLOBS") == 0)
4751 {
4752 te->dependencies = (DumpId *) pg_malloc(sizeof(DumpId));
4753 te->dependencies[0] = te2->dumpId;
4754 te->nDeps++;
4755 te->depCount++;
4756 break;
4757 }
4758 }
4759 break;
4760 }
4761 }
4762 }
4763
4764 /*
4765 * At this point we start to build the revDeps reverse-dependency arrays,
4766 * so all changes of dependencies must be complete.
4767 */
4768
4769 /*
4770 * Count the incoming dependencies for each item. Also, it is possible
4771 * that the dependencies list items that are not in the archive at all
4772 * (that should not happen in 9.2 and later, but is highly likely in older
4773 * archives). Subtract such items from the depCounts.
4774 */
4775 for (te = AH->toc->next; te != AH->toc; te = te->next)
4776 {
4777 for (i = 0; i < te->nDeps; i++)
4778 {
4779 DumpId depid = te->dependencies[i];
4780
4781 if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4782 AH->tocsByDumpId[depid]->nRevDeps++;
4783 else
4784 te->depCount--;
4785 }
4786 }
4787
4788 /*
4789 * Allocate space for revDeps[] arrays, and reset nRevDeps so we can use
4790 * it as a counter below.
4791 */
4792 for (te = AH->toc->next; te != AH->toc; te = te->next)
4793 {
4794 if (te->nRevDeps > 0)
4795 te->revDeps = (DumpId *) pg_malloc(te->nRevDeps * sizeof(DumpId));
4796 te->nRevDeps = 0;
4797 }
4798
4799 /*
4800 * Build the revDeps[] arrays of incoming-dependency dumpIds. This had
4801 * better agree with the loops above.
4802 */
4803 for (te = AH->toc->next; te != AH->toc; te = te->next)
4804 {
4805 for (i = 0; i < te->nDeps; i++)
4806 {
4807 DumpId depid = te->dependencies[i];
4808
4809 if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4810 {
4811 TocEntry *otherte = AH->tocsByDumpId[depid];
4812
4813 otherte->revDeps[otherte->nRevDeps++] = te->dumpId;
4814 }
4815 }
4816 }
4817
4818 /*
4819 * Lastly, work out the locking dependencies.
4820 */
4821 for (te = AH->toc->next; te != AH->toc; te = te->next)
4822 {
4823 te->lockDeps = NULL;
4824 te->nLockDeps = 0;
4826 }
4827}
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
DumpId * revDeps
DumpId * lockDeps

References _tocEntry::depCount, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dumpId, 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(), 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 2005 of file pg_backup_archiver.c.

2006{
2007 /* build index arrays if we didn't already */
2008 if (AH->tocsByDumpId == NULL)
2010
2011 if (id > 0 && id <= AH->maxDumpId)
2012 return AH->tocsByDumpId[id];
2013
2014 return NULL;
2015}
static void buildTocEntryArrays(ArchiveHandle *AH)

References buildTocEntryArrays(), 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 4464 of file pg_backup_archiver.c.

4465{
4466 int j,
4467 k;
4468
4469 for (j = 0; j < te1->nLockDeps; j++)
4470 {
4471 for (k = 0; k < te2->nDeps; k++)
4472 {
4473 if (te1->lockDeps[j] == te2->dependencies[k])
4474 return true;
4475 }
4476 }
4477 return false;
4478}
int j
Definition: isn.c:75

References _tocEntry::dependencies, j, _tocEntry::lockDeps, _tocEntry::nDeps, and _tocEntry::nLockDeps.

Referenced by pop_next_work_item().

◆ identify_locking_dependencies()

static void identify_locking_dependencies ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 4874 of file pg_backup_archiver.c.

4875{
4876 DumpId *lockids;
4877 int nlockids;
4878 int i;
4879
4880 /*
4881 * We only care about this for POST_DATA items. PRE_DATA items are not
4882 * run in parallel, and DATA items are all independent by assumption.
4883 */
4884 if (te->section != SECTION_POST_DATA)
4885 return;
4886
4887 /* Quick exit if no dependencies at all */
4888 if (te->nDeps == 0)
4889 return;
4890
4891 /*
4892 * Most POST_DATA items are ALTER TABLEs or some moral equivalent of that,
4893 * and hence require exclusive lock. However, we know that CREATE INDEX
4894 * does not. (Maybe someday index-creating CONSTRAINTs will fall in that
4895 * category too ... but today is not that day.)
4896 */
4897 if (strcmp(te->desc, "INDEX") == 0)
4898 return;
4899
4900 /*
4901 * We assume the entry requires exclusive lock on each TABLE or TABLE DATA
4902 * item listed among its dependencies. Originally all of these would have
4903 * been TABLE items, but repoint_table_dependencies would have repointed
4904 * them to the TABLE DATA items if those are present (which they might not
4905 * be, eg in a schema-only dump). Note that all of the entries we are
4906 * processing here are POST_DATA; otherwise there might be a significant
4907 * difference between a dependency on a table and a dependency on its
4908 * data, so that closer analysis would be needed here.
4909 */
4910 lockids = (DumpId *) pg_malloc(te->nDeps * sizeof(DumpId));
4911 nlockids = 0;
4912 for (i = 0; i < te->nDeps; i++)
4913 {
4914 DumpId depid = te->dependencies[i];
4915
4916 if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL &&
4917 ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) ||
4918 strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0))
4919 lockids[nlockids++] = depid;
4920 }
4921
4922 if (nlockids == 0)
4923 {
4924 free(lockids);
4925 return;
4926 }
4927
4928 te->lockDeps = pg_realloc(lockids, nlockids * sizeof(DumpId));
4929 te->nLockDeps = nlockids;
4930}
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65

References _tocEntry::dependencies, _tocEntry::desc, free, i, _tocEntry::lockDeps, _tocEntry::nDeps, _tocEntry::nLockDeps, pg_malloc(), pg_realloc(), _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 4993 of file pg_backup_archiver.c.

4994{
4995 pg_log_info("table \"%s\" could not be created, will not restore its data",
4996 te->tag);
4997
4998 if (AH->tableDataId[te->dumpId] != 0)
4999 {
5000 TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
5001
5002 ted->reqs = 0;
5003 }
5004}

References _tocEntry::dumpId, 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 146 of file pg_backup_archiver.c.

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

References DUMP_UNSECTIONED, 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 1168 of file pg_backup_archiver.c.

1169{
1170 if (te->defn &&
1171 strncmp(te->defn, "-- load via partition root ", 27) == 0)
1172 return true;
1173 if (te->copyStmt && *te->copyStmt)
1174 {
1175 PQExpBuffer copyStmt = createPQExpBuffer();
1176 bool result;
1177
1178 /*
1179 * Build the initial part of the COPY as it would appear if the
1180 * nominal target table is the actual target. If we see anything
1181 * else, it must be a load-via-partition-root case.
1182 */
1183 appendPQExpBuffer(copyStmt, "COPY %s ",
1184 fmtQualifiedId(te->namespace, te->tag));
1185 result = strncmp(te->copyStmt, copyStmt->data, copyStmt->len) != 0;
1186 destroyPQExpBuffer(copyStmt);
1187 return result;
1188 }
1189 /* Assume it's not load-via-partition-root */
1190 return false;
1191}

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

Referenced by restore_toc_entry().

◆ mark_create_done()

static void mark_create_done ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 4978 of file pg_backup_archiver.c.

4979{
4980 if (AH->tableDataId[te->dumpId] != 0)
4981 {
4982 TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4983
4984 ted->created = true;
4985 }
4986}

References _tocEntry::created, _tocEntry::dumpId, _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 2539 of file pg_backup_archiver.c.

2543{
2544 pg_log_info("finished item %d %s %s",
2545 te->dumpId, te->desc, te->tag);
2546
2547 if (status != 0)
2548 pg_fatal("worker process failed: exit code %d",
2549 status);
2550}

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

4673{
4674 binaryheap *ready_heap = (binaryheap *) callback_data;
4675
4676 pg_log_info("finished item %d %s %s",
4677 te->dumpId, te->desc, te->tag);
4678
4679 if (status == WORKER_CREATE_DONE)
4680 mark_create_done(AH, te);
4681 else if (status == WORKER_INHIBIT_DATA)
4682 {
4684 AH->public.n_errors++;
4685 }
4686 else if (status == WORKER_IGNORED_ERRORS)
4687 AH->public.n_errors++;
4688 else if (status != 0)
4689 pg_fatal("worker process failed: exit code %d",
4690 status);
4691
4692 reduce_dependencies(AH, te, ready_heap);
4693}
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, 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 4554 of file pg_backup_archiver.c.

4557{
4558 TocEntry *te;
4559 TocEntry *next_te;
4560
4561 for (te = pending_list->pending_next; te != pending_list; te = next_te)
4562 {
4563 /* must save list link before possibly removing te from list */
4564 next_te = te->pending_next;
4565
4566 if (te->depCount == 0 &&
4567 _tocEntryRestorePass(te) == pass)
4568 {
4569 /* Remove it from pending_list ... */
4571 /* ... and add to ready_heap */
4572 binaryheap_add(ready_heap, te);
4573 }
4574 }
4575}
void binaryheap_add(binaryheap *heap, bh_node_type d)
Definition: binaryheap.c:154
static RestorePass _tocEntryRestorePass(TocEntry *te)
static void pending_list_remove(TocEntry *te)

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

Referenced by restore_toc_entries_parallel().

◆ NewDumpOptions()

DumpOptions * NewDumpOptions ( void  )

Definition at line 134 of file pg_backup_archiver.c.

135{
137
139 return opts;
140}
void InitDumpOptions(DumpOptions *opts)

References InitDumpOptions(), opts, and pg_malloc().

Referenced by dumpOptionsFromRestoreOptions().

◆ NewRestoreOptions()

RestoreOptions * NewRestoreOptions ( void  )

Definition at line 1085 of file pg_backup_archiver.c.

1086{
1088
1090
1091 /* set any fields that shouldn't default to zeroes */
1092 opts->format = archUnknown;
1093 opts->cparams.promptPassword = TRI_DEFAULT;
1094 opts->dumpSections = DUMP_UNSECTIONED;
1095 opts->compression_spec.algorithm = PG_COMPRESSION_NONE;
1096 opts->compression_spec.level = 0;
1097 opts->dumpSchema = true;
1098 opts->dumpData = true;
1099 opts->dumpStatistics = true;
1100
1101 return opts;
1102}

References archUnknown, DUMP_UNSECTIONED, opts, PG_COMPRESSION_NONE, pg_malloc0(), and TRI_DEFAULT.

Referenced by _CloseArchive(), and main().

◆ OpenArchive()

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

Definition at line 245 of file pg_backup_archiver.c.

246{
247 ArchiveHandle *AH;
248 pg_compress_specification compression_spec = {0};
249
250 compression_spec.algorithm = PG_COMPRESSION_NONE;
251 AH = _allocAH(FileSpec, fmt, compression_spec, true,
254
255 return (Archive *) AH;
256}
@ 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, PG_COMPRESSION_NONE, and setupRestoreWorker().

Referenced by main().

◆ parallel_restore()

int parallel_restore ( ArchiveHandle AH,
TocEntry te 
)

Definition at line 4646 of file pg_backup_archiver.c.

4647{
4648 int status;
4649
4650 Assert(AH->connection != NULL);
4651
4652 /* Count only errors associated with this TOC entry */
4653 AH->public.n_errors = 0;
4654
4655 /* Restore the TOC item */
4656 status = restore_toc_entry(AH, te, true);
4657
4658 return status;
4659}
static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)

References Assert(), _archiveHandle::connection, 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 4496 of file pg_backup_archiver.c.

4497{
4498 te->pending_prev = l->pending_prev;
4499 l->pending_prev->pending_next = te;
4500 l->pending_prev = te;
4501 te->pending_next = l;
4502}

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

4490{
4491 l->pending_prev = l->pending_next = l;
4492}

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

4507{
4510 te->pending_prev = NULL;
4511 te->pending_next = NULL;
4512}

References _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 4589 of file pg_backup_archiver.c.

4591{
4592 /*
4593 * Search the ready_heap until we find a suitable item. Note that we do a
4594 * sequential scan through the heap nodes, so even though we will first
4595 * try to choose the highest-priority item, we might end up picking
4596 * something with a much lower priority. However, we expect that we will
4597 * typically be able to pick one of the first few items, which should
4598 * usually have a relatively high priority.
4599 */
4600 for (int i = 0; i < binaryheap_size(ready_heap); i++)
4601 {
4602 TocEntry *te = (TocEntry *) binaryheap_get_node(ready_heap, i);
4603 bool conflicts = false;
4604
4605 /*
4606 * Check to see if the item would need exclusive lock on something
4607 * that a currently running item also needs lock on, or vice versa. If
4608 * so, we don't want to schedule them together.
4609 */
4610 for (int k = 0; k < pstate->numWorkers; k++)
4611 {
4612 TocEntry *running_te = pstate->te[k];
4613
4614 if (running_te == NULL)
4615 continue;
4616 if (has_lock_conflicts(te, running_te) ||
4617 has_lock_conflicts(running_te, te))
4618 {
4619 conflicts = true;
4620 break;
4621 }
4622 }
4623
4624 if (conflicts)
4625 continue;
4626
4627 /* passed all tests, so this item can run */
4628 binaryheap_remove_node(ready_heap, i);
4629 return te;
4630 }
4631
4632 pg_log_debug("no item ready");
4633 return NULL;
4634}
void binaryheap_remove_node(binaryheap *heap, int n)
Definition: binaryheap.c:225
#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
int numWorkers
Definition: parallel.h:57

References binaryheap_get_node, binaryheap_remove_node(), binaryheap_size, 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 1279 of file pg_backup_archiver.c.

1280{
1281 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1282 RestoreOptions *ropt = AH->public.ropt;
1283 TocEntry *te;
1284 pg_compress_specification out_compression_spec = {0};
1285 teSection curSection;
1286 CompressFileHandle *sav;
1287 const char *fmtName;
1288 char stamp_str[64];
1289
1290 /* TOC is always uncompressed */
1291 out_compression_spec.algorithm = PG_COMPRESSION_NONE;
1292
1293 sav = SaveOutput(AH);
1294 if (ropt->filename)
1295 SetOutput(AH, ropt->filename, out_compression_spec);
1296
1297 if (strftime(stamp_str, sizeof(stamp_str), PGDUMP_STRFTIME_FMT,
1298 localtime(&AH->createDate)) == 0)
1299 strcpy(stamp_str, "[unknown]");
1300
1301 ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
1302 ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %s\n",
1303 sanitize_line(AH->archdbname, false),
1304 AH->tocCount,
1306
1307 switch (AH->format)
1308 {
1309 case archCustom:
1310 fmtName = "CUSTOM";
1311 break;
1312 case archDirectory:
1313 fmtName = "DIRECTORY";
1314 break;
1315 case archTar:
1316 fmtName = "TAR";
1317 break;
1318 default:
1319 fmtName = "UNKNOWN";
1320 }
1321
1322 ahprintf(AH, "; Dump Version: %d.%d-%d\n",
1324 ahprintf(AH, "; Format: %s\n", fmtName);
1325 ahprintf(AH, "; Integer: %d bytes\n", (int) AH->intSize);
1326 ahprintf(AH, "; Offset: %d bytes\n", (int) AH->offSize);
1327 if (AH->archiveRemoteVersion)
1328 ahprintf(AH, "; Dumped from database version: %s\n",
1330 if (AH->archiveDumpVersion)
1331 ahprintf(AH, "; Dumped by pg_dump version: %s\n",
1332 AH->archiveDumpVersion);
1333
1334 ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");
1335
1336 curSection = SECTION_PRE_DATA;
1337 for (te = AH->toc->next; te != AH->toc; te = te->next)
1338 {
1339 /* This bit must match ProcessArchiveRestoreOptions' marking logic */
1340 if (te->section != SECTION_NONE)
1341 curSection = te->section;
1342 te->reqs = _tocEntryRequired(te, curSection, AH);
1343 /* Now, should we print it? */
1344 if (ropt->verbose ||
1345 (te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0)
1346 {
1347 char *sanitized_name;
1348 char *sanitized_schema;
1349 char *sanitized_owner;
1350
1351 /*
1352 */
1353 sanitized_name = sanitize_line(te->tag, false);
1354 sanitized_schema = sanitize_line(te->namespace, true);
1355 sanitized_owner = sanitize_line(te->owner, false);
1356
1357 ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
1359 te->desc, sanitized_schema, sanitized_name,
1360 sanitized_owner);
1361
1362 free(sanitized_name);
1363 free(sanitized_schema);
1364 free(sanitized_owner);
1365 }
1366 if (ropt->verbose && te->nDeps > 0)
1367 {
1368 int i;
1369
1370 ahprintf(AH, ";\tdepends on:");
1371 for (i = 0; i < te->nDeps; i++)
1372 ahprintf(AH, " %d", te->dependencies[i]);
1373 ahprintf(AH, "\n");
1374 }
1375 }
1376
1377 /* Enforce strict names checking */
1378 if (ropt->strict_names)
1379 StrictNamesCheck(ropt);
1380
1381 if (ropt->filename)
1382 RestoreOutput(AH, sav);
1383}
const char * get_compress_algorithm_name(pg_compress_algorithm algorithm)
Definition: compression.c:69
@ 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:120

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, _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 287 of file pg_backup_archiver.c.

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

References _tocEntryRequired(), archModeRead, _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 2819 of file pg_backup_archiver.c.

2820{
2821 /* te->defn should have the form SET client_encoding = 'foo'; */
2822 char *defn = pg_strdup(te->defn);
2823 char *ptr1;
2824 char *ptr2 = NULL;
2825 int encoding;
2826
2827 ptr1 = strchr(defn, '\'');
2828 if (ptr1)
2829 ptr2 = strchr(++ptr1, '\'');
2830 if (ptr2)
2831 {
2832 *ptr2 = '\0';
2834 if (encoding < 0)
2835 pg_fatal("unrecognized encoding \"%s\"",
2836 ptr1);
2837 AH->public.encoding = encoding;
2839 }
2840 else
2841 pg_fatal("invalid ENCODING item: %s",
2842 te->defn);
2843
2844 free(defn);
2845}
int32 encoding
Definition: pg_database.h:41
#define pg_char_to_encoding
Definition: pg_wchar.h:629
void setFmtEncoding(int encoding)
Definition: string_utils.c:69

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

Referenced by ReadToc().

◆ processSearchPathEntry()

static void processSearchPathEntry ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 2864 of file pg_backup_archiver.c.

2865{
2866 /*
2867 * te->defn should contain a command to set search_path. We just copy it
2868 * verbatim for use later.
2869 */
2870 AH->public.searchpath = pg_strdup(te->defn);
2871}

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

2849{
2850 /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2851 char *ptr1;
2852
2853 ptr1 = strchr(te->defn, '\'');
2854 if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2855 AH->public.std_strings = true;
2856 else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2857 AH->public.std_strings = false;
2858 else
2859 pg_fatal("invalid STDSTRINGS item: %s",
2860 te->defn);
2861}

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

Referenced by ReadToc().

◆ ReadHead()

void ReadHead ( ArchiveHandle AH)

Definition at line 4012 of file pg_backup_archiver.c.

4013{
4014 char *errmsg;
4015 char vmaj,
4016 vmin,
4017 vrev;
4018 int fmt;
4019
4020 /*
4021 * If we haven't already read the header, do so.
4022 *
4023 * NB: this code must agree with _discoverArchiveFormat(). Maybe find a
4024 * way to unify the cases?
4025 */
4026 if (!AH->readHeader)
4027 {
4028 char tmpMag[7];
4029
4030 AH->ReadBufPtr(AH, tmpMag, 5);
4031
4032 if (strncmp(tmpMag, "PGDMP", 5) != 0)
4033 pg_fatal("did not find magic string in file header");
4034 }
4035
4036 vmaj = AH->ReadBytePtr(AH);
4037 vmin = AH->ReadBytePtr(AH);
4038
4039 if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
4040 vrev = AH->ReadBytePtr(AH);
4041 else
4042 vrev = 0;
4043
4044 AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev);
4045
4046 if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
4047 pg_fatal("unsupported version (%d.%d) in file header",
4048 vmaj, vmin);
4049
4050 AH->intSize = AH->ReadBytePtr(AH);
4051 if (AH->intSize > 32)
4052 pg_fatal("sanity check on integer size (%lu) failed",
4053 (unsigned long) AH->intSize);
4054
4055 if (AH->intSize > sizeof(int))
4056 pg_log_warning("archive was made on a machine with larger integers, some operations might fail");
4057
4058 if (AH->version >= K_VERS_1_7)
4059 AH->offSize = AH->ReadBytePtr(AH);
4060 else
4061 AH->offSize = AH->intSize;
4062
4063 fmt = AH->ReadBytePtr(AH);
4064
4065 if (AH->format != fmt)
4066 pg_fatal("expected format (%d) differs from format found in file (%d)",
4067 AH->format, fmt);
4068
4069 if (AH->version >= K_VERS_1_15)
4071 else if (AH->version >= K_VERS_1_2)
4072 {
4073 /* Guess the compression method based on the level */
4074 if (AH->version < K_VERS_1_4)
4075 AH->compression_spec.level = AH->ReadBytePtr(AH);
4076 else
4077 AH->compression_spec.level = ReadInt(AH);
4078
4079 if (AH->compression_spec.level != 0)
4081 }
4082 else
4084
4086 if (errmsg)
4087 {
4088 pg_log_warning("archive is compressed, but this installation does not support compression (%s) -- no data will be available",
4089 errmsg);
4090 pg_free(errmsg);
4091 }
4092
4093 if (AH->version >= K_VERS_1_4)
4094 {
4095 struct tm crtm;
4096
4097 crtm.tm_sec = ReadInt(AH);
4098 crtm.tm_min = ReadInt(AH);
4099 crtm.tm_hour = ReadInt(AH);
4100 crtm.tm_mday = ReadInt(AH);
4101 crtm.tm_mon = ReadInt(AH);
4102 crtm.tm_year = ReadInt(AH);
4103 crtm.tm_isdst = ReadInt(AH);
4104
4105 /*
4106 * Newer versions of glibc have mktime() report failure if tm_isdst is
4107 * inconsistent with the prevailing timezone, e.g. tm_isdst = 1 when
4108 * TZ=UTC. This is problematic when restoring an archive under a
4109 * different timezone setting. If we get a failure, try again with
4110 * tm_isdst set to -1 ("don't know").
4111 *
4112 * XXX with or without this hack, we reconstruct createDate
4113 * incorrectly when the prevailing timezone is different from
4114 * pg_dump's. Next time we bump the archive version, we should flush
4115 * this representation and store a plain seconds-since-the-Epoch
4116 * timestamp instead.
4117 */
4118 AH->createDate = mktime(&crtm);
4119 if (AH->createDate == (time_t) -1)
4120 {
4121 crtm.tm_isdst = -1;
4122 AH->createDate = mktime(&crtm);
4123 if (AH->createDate == (time_t) -1)
4124 pg_log_warning("invalid creation date in header");
4125 }
4126 }
4127
4128 if (AH->version >= K_VERS_1_4)
4129 {
4130 AH->archdbname = ReadStr(AH);
4131 }
4132
4133 if (AH->version >= K_VERS_1_10)
4134 {
4135 AH->archiveRemoteVersion = ReadStr(AH);
4136 AH->archiveDumpVersion = ReadStr(AH);
4137 }
4138}
char * supports_compression(const pg_compress_specification compression_spec)
Definition: compress_io.c:87
@ PG_COMPRESSION_GZIP
Definition: compression.h:24
int errmsg(const char *fmt,...)
Definition: elog.c:1070
static struct pg_tm tm
Definition: localtime.c:104
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(), _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 2141 of file pg_backup_archiver.c.

2142{
2143 int res = 0;
2144 int bv,
2145 b;
2146 int sign = 0; /* Default positive */
2147 int bitShift = 0;
2148
2149 if (AH->version > K_VERS_1_0)
2150 /* Read a sign byte */
2151 sign = AH->ReadBytePtr(AH);
2152
2153 for (b = 0; b < AH->intSize; b++)
2154 {
2155 bv = AH->ReadBytePtr(AH) & 0xFF;
2156 if (bv != 0)
2157 res = res + (bv << bitShift);
2158 bitShift += 8;
2159 }
2160
2161 if (sign)
2162 res = -res;
2163
2164 return res;
2165}
char sign
Definition: informix.c:693
int b
Definition: isn.c:71

References b, _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 2046 of file pg_backup_archiver.c.

2047{
2048 int i;
2049 int off;
2050 int offsetFlg;
2051
2052 /* Initialize to zero */
2053 *o = 0;
2054
2055 /* Check for old version */
2056 if (AH->version < K_VERS_1_7)
2057 {
2058 /* Prior versions wrote offsets using WriteInt */
2059 i = ReadInt(AH);
2060 /* -1 means not set */
2061 if (i < 0)
2062 return K_OFFSET_POS_NOT_SET;
2063 else if (i == 0)
2064 return K_OFFSET_NO_DATA;
2065
2066 /* Cast to pgoff_t because it was written as an int. */
2067 *o = (pgoff_t) i;
2068 return K_OFFSET_POS_SET;
2069 }
2070
2071 /*
2072 * Read the flag indicating the state of the data pointer. Check if valid
2073 * and die if not.
2074 *
2075 * This used to be handled by a negative or zero pointer, now we use an
2076 * extra byte specifically for the state.
2077 */
2078 offsetFlg = AH->ReadBytePtr(AH) & 0xFF;
2079
2080 switch (offsetFlg)
2081 {
2083 case K_OFFSET_NO_DATA:
2084 case K_OFFSET_POS_SET:
2085
2086 break;
2087
2088 default:
2089 pg_fatal("unexpected data offset flag %d", offsetFlg);
2090 }
2091
2092 /*
2093 * Read the bytes
2094 */
2095 for (off = 0; off < AH->offSize; off++)
2096 {
2097 if (off < sizeof(pgoff_t))
2098 *o |= ((pgoff_t) (AH->ReadBytePtr(AH))) << (off * 8);
2099 else
2100 {
2101 if (AH->ReadBytePtr(AH) != 0)
2102 pg_fatal("file offset in dump file is too large");
2103 }
2104 }
2105
2106 return offsetFlg;
2107}
#define K_OFFSET_NO_DATA
#define K_OFFSET_POS_NOT_SET
#define K_OFFSET_POS_SET

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

Referenced by _ReadExtraToc().

◆ ReadStr()

char * ReadStr ( ArchiveHandle AH)

Definition at line 2187 of file pg_backup_archiver.c.

2188{
2189 char *buf;
2190 int l;
2191
2192 l = ReadInt(AH);
2193 if (l < 0)
2194 buf = NULL;
2195 else
2196 {
2197 buf = (char *) pg_malloc(l + 1);
2198 AH->ReadBufPtr(AH, buf, l);
2199
2200 buf[l] = '\0';
2201 }
2202
2203 return buf;
2204}

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

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

◆ ReadToc()

void ReadToc ( ArchiveHandle AH)

Definition at line 2647 of file pg_backup_archiver.c.

2648{
2649 int i;
2650 char *tmp;
2651 DumpId *deps;
2652 int depIdx;
2653 int depSize;
2654 TocEntry *te;
2655 bool is_supported;
2656
2657 AH->tocCount = ReadInt(AH);
2658 AH->maxDumpId = 0;
2659
2660 for (i = 0; i < AH->tocCount; i++)
2661 {
2662 te = (TocEntry *) pg_malloc0(sizeof(TocEntry));
2663 te->dumpId = ReadInt(AH);
2664
2665 if (te->dumpId > AH->maxDumpId)
2666 AH->maxDumpId = te->dumpId;
2667
2668 /* Sanity check */
2669 if (te->dumpId <= 0)
2670 pg_fatal("entry ID %d out of range -- perhaps a corrupt TOC",
2671 te->dumpId);
2672
2673 te->hadDumper = ReadInt(AH);
2674
2675 if (AH->version >= K_VERS_1_8)
2676 {
2677 tmp = ReadStr(AH);
2678 sscanf(tmp, "%u", &te->catalogId.tableoid);
2679 free(tmp);
2680 }
2681 else
2683 tmp = ReadStr(AH);
2684 sscanf(tmp, "%u", &te->catalogId.oid);
2685 free(tmp);
2686
2687 te->tag = ReadStr(AH);
2688 te->desc = ReadStr(AH);
2689
2690 if (AH->version >= K_VERS_1_11)
2691 {
2692 te->section = ReadInt(AH);
2693 }
2694 else
2695 {
2696 /*
2697 * Rules for pre-8.4 archives wherein pg_dump hasn't classified
2698 * the entries into sections. This list need not cover entry
2699 * types added later than 8.4.
2700 */
2701 if (strcmp(te->desc, "COMMENT") == 0 ||
2702 strcmp(te->desc, "ACL") == 0 ||
2703 strcmp(te->desc, "ACL LANGUAGE") == 0)
2704 te->section = SECTION_NONE;
2705 else if (strcmp(te->desc, "TABLE DATA") == 0 ||
2706 strcmp(te->desc, "BLOBS") == 0 ||
2707 strcmp(te->desc, "BLOB COMMENTS") == 0)
2708 te->section = SECTION_DATA;
2709 else if (strcmp(te->desc, "CONSTRAINT") == 0 ||
2710 strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2711 strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2712 strcmp(te->desc, "INDEX") == 0 ||
2713 strcmp(te->desc, "RULE") == 0 ||
2714 strcmp(te->desc, "TRIGGER") == 0)
2716 else
2718 }
2719
2720 te->defn = ReadStr(AH);
2721 te->dropStmt = ReadStr(AH);
2722
2723 if (AH->version >= K_VERS_1_3)
2724 te->copyStmt = ReadStr(AH);
2725
2726 if (AH->version >= K_VERS_1_6)
2727 te->namespace = ReadStr(AH);
2728
2729 if (AH->version >= K_VERS_1_10)
2730 te->tablespace = ReadStr(AH);
2731
2732 if (AH->version >= K_VERS_1_14)
2733 te->tableam = ReadStr(AH);
2734
2735 if (AH->version >= K_VERS_1_16)
2736 te->relkind = ReadInt(AH);
2737
2738 te->owner = ReadStr(AH);
2739 is_supported = true;
2740 if (AH->version < K_VERS_1_9)
2741 is_supported = false;
2742 else
2743 {
2744 tmp = ReadStr(AH);
2745
2746 if (strcmp(tmp, "true") == 0)
2747 is_supported = false;
2748
2749 free(tmp);
2750 }
2751
2752 if (!is_supported)
2753 pg_log_warning("restoring tables WITH OIDS is not supported anymore");
2754
2755 /* Read TOC entry dependencies */
2756 if (AH->version >= K_VERS_1_5)
2757 {
2758 depSize = 100;
2759 deps = (DumpId *) pg_malloc(sizeof(DumpId) * depSize);
2760 depIdx = 0;
2761 for (;;)
2762 {
2763 tmp = ReadStr(AH);
2764 if (!tmp)
2765 break; /* end of list */
2766 if (depIdx >= depSize)
2767 {
2768 depSize *= 2;
2769 deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depSize);
2770 }
2771 sscanf(tmp, "%d", &deps[depIdx]);
2772 free(tmp);
2773 depIdx++;
2774 }
2775
2776 if (depIdx > 0) /* We have a non-null entry */
2777 {
2778 deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depIdx);
2779 te->dependencies = deps;
2780 te->nDeps = depIdx;
2781 }
2782 else
2783 {
2784 free(deps);
2785 te->dependencies = NULL;
2786 te->nDeps = 0;
2787 }
2788 }
2789 else
2790 {
2791 te->dependencies = NULL;
2792 te->nDeps = 0;
2793 }
2794 te->dataLength = 0;
2795
2796 if (AH->ReadExtraTocPtr)
2797 AH->ReadExtraTocPtr(AH, te);
2798
2799 pg_log_debug("read TOC entry %d (ID %d) for %s %s",
2800 i, te->dumpId, te->desc, te->tag);
2801
2802 /* link completed entry into TOC circular list */
2803 te->prev = AH->toc->prev;
2804 AH->toc->prev->next = te;
2805 AH->toc->prev = te;
2806 te->next = AH->toc;
2807
2808 /* special processing immediately upon read for some items */
2809 if (strcmp(te->desc, "ENCODING") == 0)
2810 processEncodingEntry(AH, te);
2811 else if (strcmp(te->desc, "STDSTRINGS") == 0)
2812 processStdStringsEntry(AH, te);
2813 else if (strcmp(te->desc, "SEARCHPATH") == 0)
2814 processSearchPathEntry(AH, te);
2815 }
2816}
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
Definition: postgres_ext.h:37
ReadExtraTocPtrType ReadExtraTocPtr

References _tocEntry::catalogId, _tocEntry::copyStmt, _tocEntry::dataLength, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dropStmt, _tocEntry::dumpId, 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_log_debug, pg_log_warning, pg_malloc(), pg_malloc0(), pg_realloc(), _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 4938 of file pg_backup_archiver.c.

4940{
4941 int i;
4942
4943 pg_log_debug("reducing dependencies for %d", te->dumpId);
4944
4945 for (i = 0; i < te->nRevDeps; i++)
4946 {
4947 TocEntry *otherte = AH->tocsByDumpId[te->revDeps[i]];
4948
4949 Assert(otherte->depCount > 0);
4950 otherte->depCount--;
4951
4952 /*
4953 * It's ready if it has no remaining dependencies, and it belongs in
4954 * the current restore pass, and it is currently a member of the
4955 * pending list (that check is needed to prevent double restore in
4956 * some cases where a list-file forces out-of-order restoring).
4957 * However, if ready_heap == NULL then caller doesn't want any list
4958 * memberships changed.
4959 */
4960 if (otherte->depCount == 0 &&
4961 _tocEntryRestorePass(otherte) == AH->restorePass &&
4962 otherte->pending_prev != NULL &&
4963 ready_heap != NULL)
4964 {
4965 /* Remove it from pending list ... */
4966 pending_list_remove(otherte);
4967 /* ... and add to ready_heap */
4968 binaryheap_add(ready_heap, otherte);
4969 }
4970 }
4971}
RestorePass restorePass

References _tocEntryRestorePass(), Assert(), binaryheap_add(), _tocEntry::depCount, _tocEntry::dumpId, i, _tocEntry::nRevDeps, pending_list_remove(), _tocEntry::pending_prev, 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 4840 of file pg_backup_archiver.c.

4841{
4842 TocEntry *te;
4843 int i;
4844 DumpId olddep;
4845
4846 for (te = AH->toc->next; te != AH->toc; te = te->next)
4847 {
4848 if (te->section != SECTION_POST_DATA)
4849 continue;
4850 for (i = 0; i < te->nDeps; i++)
4851 {
4852 olddep = te->dependencies[i];
4853 if (olddep <= AH->maxDumpId &&
4854 AH->tableDataId[olddep] != 0)
4855 {
4856 DumpId tabledataid = AH->tableDataId[olddep];
4857 TocEntry *tabledatate = AH->tocsByDumpId[tabledataid];
4858
4859 te->dependencies[i] = tabledataid;
4860 te->dataLength = Max(te->dataLength, tabledatate->dataLength);
4861 pg_log_debug("transferring dependency %d -> %d to %d",
4862 te->dumpId, olddep, tabledataid);
4863 }
4864 }
4865 }
4866}
#define Max(x, y)
Definition: c.h:969

References _tocEntry::dataLength, _tocEntry::dependencies, _tocEntry::dumpId, 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 4312 of file pg_backup_archiver.c.

4314{
4315 binaryheap *ready_heap;
4316 TocEntry *next_work_item;
4317
4318 pg_log_debug("entering restore_toc_entries_parallel");
4319
4320 /* Set up ready_heap with enough room for all known TocEntrys */
4321 ready_heap = binaryheap_allocate(AH->tocCount,
4323 NULL);
4324
4325 /*
4326 * The pending_list contains all items that we need to restore. Move all
4327 * items that are available to process immediately into the ready_heap.
4328 * After this setup, the pending list is everything that needs to be done
4329 * but is blocked by one or more dependencies, while the ready heap
4330 * contains items that have no remaining dependencies and are OK to
4331 * process in the current restore pass.
4332 */
4334 move_to_ready_heap(pending_list, ready_heap, AH->restorePass);
4335
4336 /*
4337 * main parent loop
4338 *
4339 * Keep going until there is no worker still running AND there is no work
4340 * left to be done. Note invariant: at top of loop, there should always
4341 * be at least one worker available to dispatch a job to.
4342 */
4343 pg_log_info("entering main parallel loop");
4344
4345 for (;;)
4346 {
4347 /* Look for an item ready to be dispatched to a worker */
4348 next_work_item = pop_next_work_item(ready_heap, pstate);
4349 if (next_work_item != NULL)
4350 {
4351 /* If not to be restored, don't waste time launching a worker */
4352 if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) == 0)
4353 {
4354 pg_log_info("skipping item %d %s %s",
4355 next_work_item->dumpId,
4356 next_work_item->desc, next_work_item->tag);
4357 /* Update its dependencies as though we'd completed it */
4358 reduce_dependencies(AH, next_work_item, ready_heap);
4359 /* Loop around to see if anything else can be dispatched */
4360 continue;
4361 }
4362
4363 pg_log_info("launching item %d %s %s",
4364 next_work_item->dumpId,
4365 next_work_item->desc, next_work_item->tag);
4366
4367 /* Dispatch to some worker */
4368 DispatchJobForTocEntry(AH, pstate, next_work_item, ACT_RESTORE,
4369 mark_restore_job_done, ready_heap);
4370 }
4371 else if (IsEveryWorkerIdle(pstate))
4372 {
4373 /*
4374 * Nothing is ready and no worker is running, so we're done with
4375 * the current pass or maybe with the whole process.
4376 */
4377 if (AH->restorePass == RESTORE_PASS_LAST)
4378 break; /* No more parallel processing is possible */
4379
4380 /* Advance to next restore pass */
4381 AH->restorePass++;
4382 /* That probably allows some stuff to be made ready */
4383 move_to_ready_heap(pending_list, ready_heap, AH->restorePass);
4384 /* Loop around to see if anything's now ready */
4385 continue;
4386 }
4387 else
4388 {
4389 /*
4390 * We have nothing ready, but at least one child is working, so
4391 * wait for some subjob to finish.
4392 */
4393 }
4394
4395 /*
4396 * Before dispatching another job, check to see if anything has
4397 * finished. We should check every time through the loop so as to
4398 * reduce dependencies as soon as possible. If we were unable to
4399 * dispatch any job this time through, wait until some worker finishes
4400 * (and, hopefully, unblocks some pending item). If we did dispatch
4401 * something, continue as soon as there's at least one idle worker.
4402 * Note that in either case, there's guaranteed to be at least one
4403 * idle worker when we return to the top of the loop. This ensures we
4404 * won't block inside DispatchJobForTocEntry, which would be
4405 * undesirable: we'd rather postpone dispatching until we see what's
4406 * been unblocked by finished jobs.
4407 */
4408 WaitForWorkers(AH, pstate,
4409 next_work_item ? WFW_ONE_IDLE : WFW_GOT_STATUS);
4410 }
4411
4412 /* There should now be nothing in ready_heap. */
4413 Assert(binaryheap_empty(ready_heap));
4414
4415 binaryheap_free(ready_heap);
4416
4417 pg_log_info("finished main parallel loop");
4418}
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:75
binaryheap * binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
Definition: binaryheap.c:39
#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(), _tocEntry::desc, DispatchJobForTocEntry(), _tocEntry::dumpId, 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, _tocEntry::reqs, RESTORE_PASS_LAST, RESTORE_PASS_MAIN, _archiveHandle::restorePass, _tocEntry::tag, _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 4430 of file pg_backup_archiver.c.

4431{
4432 RestoreOptions *ropt = AH->public.ropt;
4433 TocEntry *te;
4434
4435 pg_log_debug("entering restore_toc_entries_postfork");
4436
4437 /*
4438 * Now reconnect the single parent connection.
4439 */
4440 ConnectDatabase((Archive *) AH, &ropt->cparams, true);
4441
4442 /* re-establish fixed state */
4444
4445 /*
4446 * Make sure there is no work left due to, say, circular dependencies, or
4447 * some other pathological condition. If so, do it in the single parent
4448 * connection. We don't sweat about RestorePass ordering; it's likely we
4449 * already violated that.
4450 */
4451 for (te = pending_list->pending_next; te != pending_list; te = te->pending_next)
4452 {
4453 pg_log_info("processing missed item %d %s %s",
4454 te->dumpId, te->desc, te->tag);
4455 (void) restore_toc_entry(AH, te, false);
4456 }
4457}

References _doSetFixedOutputState(), ConnectDatabase(), _restoreOptions::cparams, _tocEntry::desc, _tocEntry::dumpId, _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 4189 of file pg_backup_archiver.c.

4190{
4191 bool skipped_some;
4192 TocEntry *next_work_item;
4193
4194 pg_log_debug("entering restore_toc_entries_prefork");
4195
4196 /* Adjust dependency information */
4197 fix_dependencies(AH);
4198
4199 /*
4200 * Do all the early stuff in a single connection in the parent. There's no
4201 * great point in running it in parallel, in fact it will actually run
4202 * faster in a single connection because we avoid all the connection and
4203 * setup overhead. Also, pre-9.2 pg_dump versions were not very good
4204 * about showing all the dependencies of SECTION_PRE_DATA items, so we do
4205 * not risk trying to process them out-of-order.
4206 *
4207 * Stuff that we can't do immediately gets added to the pending_list.
4208 * Note: we don't yet filter out entries that aren't going to be restored.
4209 * They might participate in dependency chains connecting entries that
4210 * should be restored, so we treat them as live until we actually process
4211 * them.
4212 *
4213 * Note: as of 9.2, it should be guaranteed that all PRE_DATA items appear
4214 * before DATA items, and all DATA items before POST_DATA items. That is
4215 * not certain to be true in older archives, though, and in any case use
4216 * of a list file would destroy that ordering (cf. SortTocFromFile). So
4217 * this loop cannot assume that it holds.
4218 */
4220 skipped_some = false;
4221 for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
4222 {
4223 bool do_now = true;
4224
4225 if (next_work_item->section != SECTION_PRE_DATA)
4226 {
4227 /* DATA and POST_DATA items are just ignored for now */
4228 if (next_work_item->section == SECTION_DATA ||
4229 next_work_item->section == SECTION_POST_DATA)
4230 {
4231 do_now = false;
4232 skipped_some = true;
4233 }
4234 else
4235 {
4236 /*
4237 * SECTION_NONE items, such as comments, can be processed now
4238 * if we are still in the PRE_DATA part of the archive. Once
4239 * we've skipped any items, we have to consider whether the
4240 * comment's dependencies are satisfied, so skip it for now.
4241 */
4242 if (skipped_some)
4243 do_now = false;
4244 }
4245 }
4246
4247 /*
4248 * Also skip items that need to be forced into later passes. We need
4249 * not set skipped_some in this case, since by assumption no main-pass
4250 * items could depend on these.
4251 */
4252 if (_tocEntryRestorePass(next_work_item) != RESTORE_PASS_MAIN)
4253 do_now = false;
4254
4255 if (do_now)
4256 {
4257 /* OK, restore the item and update its dependencies */
4258 pg_log_info("processing item %d %s %s",
4259 next_work_item->dumpId,
4260 next_work_item->desc, next_work_item->tag);
4261
4262 (void) restore_toc_entry(AH, next_work_item, false);
4263
4264 /* Reduce dependencies, but don't move anything to ready_heap */
4265 reduce_dependencies(AH, next_work_item, NULL);
4266 }
4267 else
4268 {
4269 /* Nope, so add it to pending_list */
4270 pending_list_append(pending_list, next_work_item);
4271 }
4272 }
4273
4274 /*
4275 * In --transaction-size mode, we must commit the open transaction before
4276 * dropping the database connection. This also ensures that child workers
4277 * can see the objects we've created so far.
4278 */
4279 if (AH->public.ropt->txn_size > 0)
4281
4282 /*
4283 * Now close parent connection in prep for parallel steps. We do this
4284 * mainly to ensure that we don't exceed the specified number of parallel
4285 * connections.
4286 */
4288
4289 /* blow away any transient state from the old connection */
4290 free(AH->currUser);
4291 AH->currUser = NULL;
4292 free(AH->currSchema);
4293 AH->currSchema = NULL;
4294 free(AH->currTablespace);
4295 AH->currTablespace = NULL;
4296 free(AH->currTableAm);
4297 AH->currTableAm = NULL;
4298}
void DisconnectDatabase(Archive *AHX)
Definition: pg_backup_db.c:223
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, _tocEntry::desc, DisconnectDatabase(), _tocEntry::dumpId, 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, _tocEntry::section, SECTION_DATA, SECTION_POST_DATA, SECTION_PRE_DATA, _tocEntry::tag, _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 823 of file pg_backup_archiver.c.

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

References _becomeOwner(), _disableTriggersIfNecessary(), _enableTriggersIfNecessary(), _printTocEntry(), _reconnectToDB(), _selectOutputSchema(), ahprintf(), CommitTransaction(), _archiveHandle::connection, _tocEntry::copyStmt, _tocEntry::created, _archiveHandle::currentTE, _tocEntry::defn, _tocEntry::desc, _restoreOptions::dumpSchema, EndDBCopyMode(), 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 342 of file pg_backup_archiver.c.

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

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, ConnectDatabase(), _archiveHandle::connection, _restoreOptions::cparams, _archiveHandle::createDate, _restoreOptions::createDB, createPQExpBuffer(), _archiveHandle::currentTE, _archiveHandle::currSchema, PQExpBufferData::data, _tocEntry::desc, destroyPQExpBuffer(), DisconnectDatabase(), DropLOIfExists(), _restoreOptions::dropSchema, _tocEntry::dropStmt, _restoreOptions::dumpSchema, dumpTimestamp(), errmsg(), _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(), 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 1719 of file pg_backup_archiver.c.

1720{
1721 errno = 0;
1722 if (!EndCompressFileHandle(AH->OF))
1723 pg_fatal("could not close output file: %m");
1724
1725 AH->OF = savedOutput;
1726}

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

Referenced by PrintTOCSummary(), and RestoreArchive().

◆ RestoringToDB()

◆ sanitize_line()

static char * sanitize_line ( const char *  str,
bool  want_hyphen 
)
static

Definition at line 3963 of file pg_backup_archiver.c.

3964{
3965 char *result;
3966 char *s;
3967
3968 if (!str)
3969 return pg_strdup(want_hyphen ? "-" : "");
3970
3971 result = pg_strdup(str);
3972
3973 for (s = result; *s != '\0'; s++)
3974 {
3975 if (*s == '\n' || *s == '\r')
3976 *s = ' ';
3977 }
3978
3979 return result;
3980}
const char * str

References pg_strdup(), and str.

Referenced by _printTocEntry(), and PrintTOCSummary().

◆ SaveOutput()

static CompressFileHandle * SaveOutput ( ArchiveHandle AH)
static

Definition at line 1713 of file pg_backup_archiver.c.

1714{
1715 return (CompressFileHandle *) AH->OF;
1716}

References _archiveHandle::OF.

Referenced by PrintTOCSummary(), and RestoreArchive().

◆ SetArchiveOptions()

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

Definition at line 274 of file pg_backup_archiver.c.

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

References Archive::dopt, dumpOptionsFromRestoreOptions(), 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 1673 of file pg_backup_archiver.c.

1675{
1676 CompressFileHandle *CFH;
1677 const char *mode;
1678 int fn = -1;
1679
1680 if (filename)
1681 {
1682 if (strcmp(filename, "-") == 0)
1683 fn = fileno(stdout);
1684 }
1685 else if (AH->FH)
1686 fn = fileno(AH->FH);
1687 else if (AH->fSpec)
1688 {
1689 filename = AH->fSpec;
1690 }
1691 else
1692 fn = fileno(stdout);
1693
1694 if (AH->mode == archModeAppend)
1695 mode = PG_BINARY_A;
1696 else
1697 mode = PG_BINARY_W;
1698
1699 CFH = InitCompressFileHandle(compression_spec);
1700
1701 if (!CFH->open_func(filename, fn, mode, CFH))
1702 {
1703 if (filename)
1704 pg_fatal("could not open output file \"%s\": %m", filename);
1705 else
1706 pg_fatal("could not open output file: %m");
1707 }
1708
1709 AH->OF = CFH;
1710}
#define PG_BINARY_W
Definition: c.h:1247
@ archModeAppend
Definition: pg_backup.h:50
static void * fn(void *arg)
Definition: thread-alloc.c:119

References archModeAppend, _archiveHandle::FH, filename, fn(), _archiveHandle::fSpec, InitCompressFileHandle(), mode, _archiveHandle::mode, _archiveHandle::OF, CompressFileHandle::open_func, PG_BINARY_A, PG_BINARY_W, pg_fatal, and generate_unaccent_rules::stdout.

Referenced by PrintTOCSummary(), and RestoreArchive().

◆ setupRestoreWorker()

static void setupRestoreWorker ( Archive AHX)
static

Definition at line 218 of file pg_backup_archiver.c.

219{
220 ArchiveHandle *AH = (ArchiveHandle *) AHX;
221
222 AH->ReopenPtr(AH);
223}

References _archiveHandle::ReopenPtr.

Referenced by OpenArchive().

◆ SortTocFromFile()

void SortTocFromFile ( Archive AHX)

Definition at line 1546 of file pg_backup_archiver.c.

1547{
1548 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1549 RestoreOptions *ropt = AH->public.ropt;
1550 FILE *fh;
1551 StringInfoData linebuf;
1552
1553 /* Allocate space for the 'wanted' array, and init it */
1554 ropt->idWanted = (bool *) pg_malloc0(sizeof(bool) * AH->maxDumpId);
1555
1556 /* Setup the file */
1557 fh = fopen(ropt->tocFile, PG_BINARY_R);
1558 if (!fh)
1559 pg_fatal("could not open TOC file \"%s\": %m", ropt->tocFile);
1560
1561 initStringInfo(&linebuf);
1562
1563 while (pg_get_line_buf(fh, &linebuf))
1564 {
1565 char *cmnt;
1566 char *endptr;
1567 DumpId id;
1568 TocEntry *te;
1569
1570 /* Truncate line at comment, if any */
1571 cmnt = strchr(linebuf.data, ';');
1572 if (cmnt != NULL)
1573 {
1574 cmnt[0] = '\0';
1575 linebuf.len = cmnt - linebuf.data;
1576 }
1577
1578 /* Ignore if all blank */
1579 if (strspn(linebuf.data, " \t\r\n") == linebuf.len)
1580 continue;
1581
1582 /* Get an ID, check it's valid and not already seen */
1583 id = strtol(linebuf.data, &endptr, 10);
1584 if (endptr == linebuf.data || id <= 0 || id > AH->maxDumpId ||
1585 ropt->idWanted[id - 1])
1586 {
1587 pg_log_warning("line ignored: %s", linebuf.data);
1588 continue;
1589 }
1590
1591 /* Find TOC entry */
1592 te = getTocEntryByDumpId(AH, id);
1593 if (!te)
1594 pg_fatal("could not find entry for ID %d",
1595 id);
1596
1597 /* Mark it wanted */
1598 ropt->idWanted[id - 1] = true;
1599
1600 /*
1601 * Move each item to the end of the list as it is selected, so that
1602 * they are placed in the desired order. Any unwanted items will end
1603 * up at the front of the list, which may seem unintuitive but it's
1604 * what we need. In an ordinary serial restore that makes no
1605 * difference, but in a parallel restore we need to mark unrestored
1606 * items' dependencies as satisfied before we start examining
1607 * restorable items. Otherwise they could have surprising
1608 * side-effects on the order in which restorable items actually get
1609 * restored.
1610 */
1611 _moveBefore(AH->toc, te);
1612 }
1613
1614 pg_free(linebuf.data);
1615
1616 if (fclose(fh) != 0)
1617 pg_fatal("could not close TOC file: %m");
1618}
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
char * tocFile
Definition: pg_backup.h:128

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

Referenced by main().

◆ StartLO()

int StartLO ( Archive AHX,
Oid  oid 
)

Definition at line 1391 of file pg_backup_archiver.c.

1392{
1393 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1394
1395 if (!AH->StartLOPtr)
1396 pg_fatal("large-object output not supported in chosen format");
1397
1398 AH->StartLOPtr(AH, AH->currToc, oid);
1399
1400 return 1;
1401}
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 1470 of file pg_backup_archiver.c.

1471{
1472 bool old_lo_style = (AH->version < K_VERS_1_12);
1473 Oid loOid;
1474
1475 AH->loCount++;
1476
1477 /* Initialize the LO Buffer */
1478 if (AH->lo_buf == NULL)
1479 {
1480 /* First time through (in this process) so allocate the buffer */
1481 AH->lo_buf_size = LOBBUFSIZE;
1483 }
1484 AH->lo_buf_used = 0;
1485
1486 pg_log_info("restoring large object with OID %u", oid);
1487
1488 /* With an old archive we must do drop and create logic here */
1489 if (old_lo_style && drop)
1490 DropLOIfExists(AH, oid);
1491
1492 if (AH->connection)
1493 {
1494 if (old_lo_style)
1495 {
1496 loOid = lo_create(AH->connection, oid);
1497 if (loOid == 0 || loOid != oid)
1498 pg_fatal("could not create large object %u: %s",
1499 oid, PQerrorMessage(AH->connection));
1500 }
1501 AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
1502 if (AH->loFd == -1)
1503 pg_fatal("could not open large object %u: %s",
1504 oid, PQerrorMessage(AH->connection));
1505 }
1506 else
1507 {
1508 if (old_lo_style)
1509 ahprintf(AH, "SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n",
1510 oid, INV_WRITE);
1511 else
1512 ahprintf(AH, "SELECT pg_catalog.lo_open('%u', %d);\n",
1513 oid, INV_WRITE);
1514 }
1515
1516 AH->writingLO = true;
1517}
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
Definition: postgres_ext.h:32

References ahprintf(), _archiveHandle::connection, DropLOIfExists(), 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().

◆ StartRestoreLOs()

void StartRestoreLOs ( ArchiveHandle AH)

Definition at line 1423 of file pg_backup_archiver.c.

1424{
1425 RestoreOptions *ropt = AH->public.ropt;
1426
1427 /*
1428 * LOs must be restored within a transaction block, since we need the LO
1429 * handle to stay open while we write it. Establish a transaction unless
1430 * there's one being used globally.
1431 */
1432 if (!(ropt->single_txn || ropt->txn_size > 0))
1433 {
1434 if (AH->connection)
1436 else
1437 ahprintf(AH, "BEGIN;\n\n");
1438 }
1439
1440 AH->loCount = 0;
1441}

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

Referenced by _LoadLOs().

◆ StrictNamesCheck()

static void StrictNamesCheck ( RestoreOptions ropt)
static

Definition at line 2874 of file pg_backup_archiver.c.

2875{
2876 const char *missing_name;
2877
2878 Assert(ropt->strict_names);
2879
2880 if (ropt->schemaNames.head != NULL)
2881 {
2882 missing_name = simple_string_list_not_touched(&ropt->schemaNames);
2883 if (missing_name != NULL)
2884 pg_fatal("schema \"%s\" not found", missing_name);
2885 }
2886
2887 if (ropt->tableNames.head != NULL)
2888 {
2889 missing_name = simple_string_list_not_touched(&ropt->tableNames);
2890 if (missing_name != NULL)
2891 pg_fatal("table \"%s\" not found", missing_name);
2892 }
2893
2894 if (ropt->indexNames.head != NULL)
2895 {
2896 missing_name = simple_string_list_not_touched(&ropt->indexNames);
2897 if (missing_name != NULL)
2898 pg_fatal("index \"%s\" not found", missing_name);
2899 }
2900
2901 if (ropt->functionNames.head != NULL)
2902 {
2903 missing_name = simple_string_list_not_touched(&ropt->functionNames);
2904 if (missing_name != NULL)
2905 pg_fatal("function \"%s\" not found", missing_name);
2906 }
2907
2908 if (ropt->triggerNames.head != NULL)
2909 {
2910 missing_name = simple_string_list_not_touched(&ropt->triggerNames);
2911 if (missing_name != NULL)
2912 pg_fatal("trigger \"%s\" not found", missing_name);
2913 }
2914}
const char * simple_string_list_not_touched(SimpleStringList *list)
Definition: simple_list.c:144

References Assert(), _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 4539 of file pg_backup_archiver.c.

4540{
4541 /* return opposite of qsort comparator for max-heap */
4542 return -TocEntrySizeCompareQsort(&p1, &p2);
4543}
static int TocEntrySizeCompareQsort(const void *p1, const void *p2)

References TocEntrySizeCompareQsort().

Referenced by restore_toc_entries_parallel().

◆ TocEntrySizeCompareQsort()

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

Definition at line 4517 of file pg_backup_archiver.c.

4518{
4519 const TocEntry *te1 = *(const TocEntry *const *) p1;
4520 const TocEntry *te2 = *(const TocEntry *const *) p2;
4521
4522 /* Sort by decreasing dataLength */
4523 if (te1->dataLength > te2->dataLength)
4524 return -1;
4525 if (te1->dataLength < te2->dataLength)
4526 return 1;
4527
4528 /* For equal dataLengths, sort by dumpId, just to be stable */
4529 if (te1->dumpId < te2->dumpId)
4530 return -1;
4531 if (te1->dumpId > te2->dumpId)
4532 return 1;
4533
4534 return 0;
4535}

References _tocEntry::dataLength, and _tocEntry::dumpId.

Referenced by TocEntrySizeCompareBinaryheap(), and WriteDataChunks().

◆ TocIDRequired()

int TocIDRequired ( ArchiveHandle AH,
DumpId  id 
)

Definition at line 2018 of file pg_backup_archiver.c.

2019{
2020 TocEntry *te = getTocEntryByDumpId(AH, id);
2021
2022 if (!te)
2023 return 0;
2024
2025 return te->reqs;
2026}

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

1873{
1874 va_list ap;
1875
1876 switch (AH->stage)
1877 {
1878
1879 case STAGE_NONE:
1880 /* Do nothing special */
1881 break;
1882
1883 case STAGE_INITIALIZING:
1884 if (AH->stage != AH->lastErrorStage)
1885 pg_log_info("while INITIALIZING:");
1886 break;
1887
1888 case STAGE_PROCESSING:
1889 if (AH->stage != AH->lastErrorStage)
1890 pg_log_info("while PROCESSING TOC:");
1891 break;
1892
1893 case STAGE_FINALIZING:
1894 if (AH->stage != AH->lastErrorStage)
1895 pg_log_info("while FINALIZING:");
1896 break;
1897 }
1898 if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE)
1899 {
1900 pg_log_info("from TOC entry %d; %u %u %s %s %s",
1901 AH->currentTE->dumpId,
1903 AH->currentTE->catalogId.oid,
1904 AH->currentTE->desc ? AH->currentTE->desc : "(no desc)",
1905 AH->currentTE->tag ? AH->currentTE->tag : "(no tag)",
1906 AH->currentTE->owner ? AH->currentTE->owner : "(no owner)");
1907 }
1908 AH->lastErrorStage = AH->stage;
1909 AH->lastErrorTE = AH->currentTE;
1910
1911 va_start(ap, fmt);
1913 va_end(ap);
1914
1915 if (AH->public.exit_on_error)
1916 exit_nicely(1);
1917 else
1918 AH->public.n_errors++;
1919}
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:219
@ PG_LOG_PRIMARY
Definition: logging.h:67
@ PG_LOG_ERROR
Definition: logging.h:43
@ STAGE_NONE
#define exit_nicely(code)
Definition: pg_dumpall.c:129
ArchiverStage lastErrorStage

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

1200{
1201 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1202
1203 if (!AH->currToc)
1204 pg_fatal("internal error -- WriteData cannot be called outside the context of a DataDumper routine");
1205
1206 AH->WriteDataPtr(AH, data, dLen);
1207}
const void * data
WriteDataPtrType WriteDataPtr

References _archiveHandle::currToc, data, pg_fatal, and _archiveHandle::WriteDataPtr.

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

◆ WriteDataChunks()

void WriteDataChunks ( ArchiveHandle AH,
ParallelState pstate 
)

Definition at line 2473 of file pg_backup_archiver.c.

2474{
2475 TocEntry *te;
2476
2477 if (pstate && pstate->numWorkers > 1)
2478 {
2479 /*
2480 * In parallel mode, this code runs in the leader process. We
2481 * construct an array of candidate TEs, then sort it into decreasing
2482 * size order, then dispatch each TE to a data-transfer worker. By
2483 * dumping larger tables first, we avoid getting into a situation
2484 * where we're down to one job and it's big, losing parallelism.
2485 */
2486 TocEntry **tes;
2487 int ntes;
2488
2489 tes = (TocEntry **) pg_malloc(AH->tocCount * sizeof(TocEntry *));
2490 ntes = 0;
2491 for (te = AH->toc->next; te != AH->toc; te = te->next)
2492 {
2493 /* Consider only TEs with dataDumper functions ... */
2494 if (!te->dataDumper)
2495 continue;
2496 /* ... and ignore ones not enabled for dump */
2497 if ((te->reqs & REQ_DATA) == 0)
2498 continue;
2499
2500 tes[ntes++] = te;
2501 }
2502
2503 if (ntes > 1)
2504 qsort(tes, ntes, sizeof(TocEntry *), TocEntrySizeCompareQsort);
2505
2506 for (int i = 0; i < ntes; i++)
2507 DispatchJobForTocEntry(AH, pstate, tes[i], ACT_DUMP,
2508 mark_dump_job_done, NULL);
2509
2510 pg_free(tes);
2511
2512 /* Now wait for workers to finish. */
2513 WaitForWorkers(AH, pstate, WFW_ALL_IDLE);
2514 }
2515 else
2516 {
2517 /* Non-parallel mode: just dump all candidate TEs sequentially. */
2518 for (te = AH->toc->next; te != AH->toc; te = te->next)
2519 {
2520 /* Must have same filter conditions as above */
2521 if (!te->dataDumper)
2522 continue;
2523 if ((te->reqs & REQ_DATA) == 0)
2524 continue;
2525
2527 }
2528 }
2529}
@ 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)
@ ACT_DUMP
#define qsort(a, b, c, d)
Definition: port.h:475

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

Referenced by _CloseArchive().

◆ WriteDataChunksForTocEntry()

void WriteDataChunksForTocEntry ( ArchiveHandle AH,
TocEntry te 
)

Definition at line 2554 of file pg_backup_archiver.c.

2555{
2556 StartDataPtrType startPtr;
2557 EndDataPtrType endPtr;
2558
2559 AH->currToc = te;
2560
2561 if (strcmp(te->desc, "BLOBS") == 0)
2562 {
2563 startPtr = AH->StartLOsPtr;
2564 endPtr = AH->EndLOsPtr;
2565 }
2566 else
2567 {
2568 startPtr = AH->StartDataPtr;
2569 endPtr = AH->EndDataPtr;
2570 }
2571
2572 if (startPtr != NULL)
2573 (*startPtr) (AH, te);
2574
2575 /*
2576 * The user-provided DataDumper routine needs to call AH->WriteData
2577 */
2578 te->dataDumper((Archive *) AH, te->dataDumperArg);
2579
2580 if (endPtr != NULL)
2581 (*endPtr) (AH, te);
2582
2583 AH->currToc = NULL;
2584}
void(* EndDataPtrType)(ArchiveHandle *AH, TocEntry *te)
void(* StartDataPtrType)(ArchiveHandle *AH, TocEntry *te)
EndLOsPtrType EndLOsPtr
StartLOsPtrType StartLOsPtr
StartDataPtrType StartDataPtr
EndDataPtrType EndDataPtr

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

Referenced by _WorkerJobDumpDirectory(), and WriteDataChunks().

◆ WriteHead()

void WriteHead ( ArchiveHandle AH)

Definition at line 3986 of file pg_backup_archiver.c.

3987{
3988 struct tm crtm;
3989
3990 AH->WriteBufPtr(AH, "PGDMP", 5); /* Magic code */
3991 AH->WriteBytePtr(AH, ARCHIVE_MAJOR(AH->version));
3992 AH->WriteBytePtr(AH, ARCHIVE_MINOR(AH->version));
3993 AH->WriteBytePtr(AH, ARCHIVE_REV(AH->version));
3994 AH->WriteBytePtr(AH, AH->intSize);
3995 AH->WriteBytePtr(AH, AH->offSize);
3996 AH->WriteBytePtr(AH, AH->format);
3998 crtm = *localtime(&AH->createDate);
3999 WriteInt(AH, crtm.tm_sec);
4000 WriteInt(AH, crtm.tm_min);
4001 WriteInt(AH, crtm.tm_hour);
4002 WriteInt(AH, crtm.tm_mday);
4003 WriteInt(AH, crtm.tm_mon);
4004 WriteInt(AH, crtm.tm_year);
4005 WriteInt(AH, crtm.tm_isdst);
4006 WriteStr(AH, PQdb(AH->connection));
4008 WriteStr(AH, PG_VERSION);
4009}
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:7381
size_t WriteInt(ArchiveHandle *AH, int i)
size_t WriteStr(ArchiveHandle *AH, const char *c)
char * remoteVersionStr
Definition: pg_backup.h:228
WriteBufPtrType WriteBufPtr
WriteBytePtrType WriteBytePtr

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

Referenced by _CloseArchive().

◆ WriteInt()

size_t WriteInt ( ArchiveHandle AH,
int  i 
)

Definition at line 2110 of file pg_backup_archiver.c.

2111{
2112 int b;
2113
2114 /*
2115 * This is a bit yucky, but I don't want to make the binary format very
2116 * dependent on representation, and not knowing much about it, I write out
2117 * a sign byte. If you change this, don't forget to change the file
2118 * version #, and modify ReadInt to read the new format AS WELL AS the old
2119 * formats.
2120 */
2121
2122 /* SIGN byte */
2123 if (i < 0)
2124 {
2125 AH->WriteBytePtr(AH, 1);
2126 i = -i;
2127 }
2128 else
2129 AH->WriteBytePtr(AH, 0);
2130
2131 for (b = 0; b < AH->intSize; b++)
2132 {
2133 AH->WriteBytePtr(AH, i & 0xFF);
2134 i >>= 8;
2135 }
2136
2137 return AH->intSize + 1;
2138}

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

2030{
2031 int off;
2032
2033 /* Save the flag */
2034 AH->WriteBytePtr(AH, wasSet);
2035
2036 /* Write out pgoff_t smallest byte first, prevents endian mismatch */
2037 for (off = 0; off < sizeof(pgoff_t); off++)
2038 {
2039 AH->WriteBytePtr(AH, o & 0xFF);
2040 o >>= 8;
2041 }
2042 return sizeof(pgoff_t) + 1;
2043}

References pgoff_t, and _archiveHandle::WriteBytePtr.

Referenced by _WriteExtraToc().

◆ WriteStr()

size_t WriteStr ( ArchiveHandle AH,
const char *  c 
)

Definition at line 2168 of file pg_backup_archiver.c.

2169{
2170 size_t res;
2171
2172 if (c)
2173 {
2174 int len = strlen(c);
2175
2176 res = WriteInt(AH, len);
2177 AH->WriteBufPtr(AH, c, len);
2178 res += len;
2179 }
2180 else
2181 res = WriteInt(AH, -1);
2182
2183 return res;
2184}
char * c

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

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

◆ WriteToc()

void WriteToc ( ArchiveHandle AH)

Definition at line 2587 of file pg_backup_archiver.c.

2588{
2589 TocEntry *te;
2590 char workbuf[32];
2591 int tocCount;
2592 int i;
2593
2594 /* count entries that will actually be dumped */
2595 tocCount = 0;
2596 for (te = AH->toc->next; te != AH->toc; te = te->next)
2597 {
2598 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS | REQ_SPECIAL)) != 0)
2599 tocCount++;
2600 }
2601
2602 /* printf("%d TOC Entries to save\n", tocCount); */
2603
2604 WriteInt(AH, tocCount);
2605
2606 for (te = AH->toc->next; te != AH->toc; te = te->next)
2607 {
2608 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS | REQ_SPECIAL)) == 0)
2609 continue;
2610
2611 WriteInt(AH, te->dumpId);
2612 WriteInt(AH, te->dataDumper ? 1 : 0);
2613
2614 /* OID is recorded as a string for historical reasons */
2615 sprintf(workbuf, "%u", te->catalogId.tableoid);
2616 WriteStr(AH, workbuf);
2617 sprintf(workbuf, "%u", te->catalogId.oid);
2618 WriteStr(AH, workbuf);
2619
2620 WriteStr(AH, te->tag);
2621 WriteStr(AH, te->desc);
2622 WriteInt(AH, te->section);
2623 WriteStr(AH, te->defn);
2624 WriteStr(AH, te->dropStmt);
2625 WriteStr(AH, te->copyStmt);
2626 WriteStr(AH, te->namespace);
2627 WriteStr(AH, te->tablespace);
2628 WriteStr(AH, te->tableam);
2629 WriteInt(AH, te->relkind);
2630 WriteStr(AH, te->owner);
2631 WriteStr(AH, "false");
2632
2633 /* Dump list of dependencies */
2634 for (i = 0; i < te->nDeps; i++)
2635 {
2636 sprintf(workbuf, "%d", te->dependencies[i]);
2637 WriteStr(AH, workbuf);
2638 }
2639 WriteStr(AH, NULL); /* Terminate List */
2640
2641 if (AH->WriteExtraTocPtr)
2642 AH->WriteExtraTocPtr(AH, te);
2643 }
2644}
#define sprintf
Definition: port.h:241
WriteExtraTocPtrType WriteExtraTocPtr

References _tocEntry::catalogId, _tocEntry::copyStmt, _tocEntry::dataDumper, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dropStmt, _tocEntry::dumpId, i, _tocEntry::nDeps, _tocEntry::next, CatalogId::oid, _tocEntry::owner, _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().