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"
 

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, bool isData)
 
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.

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

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

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

3410 {
3411  RestoreOptions *ropt = AH->public.ropt;
3412 
3413  if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
3414  return;
3415 
3416  _becomeUser(AH, te->owner);
3417 }
static void _becomeUser(ArchiveHandle *AH, const char *user)
RestoreOptions * ropt
Definition: pg_backup.h:215

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

3387 {
3388  if (!user)
3389  user = ""; /* avoid null pointers */
3390 
3391  if (AH->currUser && strcmp(AH->currUser, user) == 0)
3392  return; /* no need to do anything */
3393 
3394  _doSetSessionAuth(AH, user);
3395 
3396  /*
3397  * NOTE: currUser keeps track of what the imaginary session user in our
3398  * script is
3399  */
3400  free(AH->currUser);
3401  AH->currUser = pg_strdup(user);
3402 }
#define free(a)
Definition: header.h:65
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user)
static char * user
Definition: pg_regress.c:120

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

1089 {
1090  RestoreOptions *ropt = AH->public.ropt;
1091 
1092  /* This hack is only needed in a data-only restore */
1093  if (!ropt->dataOnly || !ropt->disable_triggers)
1094  return;
1095 
1096  pg_log_info("disabling triggers for %s", te->tag);
1097 
1098  /*
1099  * Become superuser if possible, since they are the only ones who can
1100  * disable constraint triggers. If -S was not given, assume the initial
1101  * user identity is a superuser. (XXX would it be better to become the
1102  * table owner?)
1103  */
1104  _becomeUser(AH, ropt->superuser);
1105 
1106  /*
1107  * Disable them.
1108  */
1109  ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
1110  fmtQualifiedId(te->namespace, te->tag));
1111 }
#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:145
char * superuser
Definition: pg_backup.h:104
int disable_triggers
Definition: pg_backup.h:100

References _becomeUser(), ahprintf(), _restoreOptions::dataOnly, _restoreOptions::disable_triggers, 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 2202 of file pg_backup_archiver.c.

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

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

3236 {
3237  RestoreOptions *ropt = AH->public.ropt;
3238 
3239  /*
3240  * Disable timeouts to allow for slow commands, idle parallel workers, etc
3241  */
3242  ahprintf(AH, "SET statement_timeout = 0;\n");
3243  ahprintf(AH, "SET lock_timeout = 0;\n");
3244  ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
3245  ahprintf(AH, "SET transaction_timeout = 0;\n");
3246 
3247  /* Select the correct character set encoding */
3248  ahprintf(AH, "SET client_encoding = '%s';\n",
3250 
3251  /* Select the correct string literal syntax */
3252  ahprintf(AH, "SET standard_conforming_strings = %s;\n",
3253  AH->public.std_strings ? "on" : "off");
3254 
3255  /* Select the role to be used during restore */
3256  if (ropt && ropt->use_role)
3257  ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));
3258 
3259  /* Select the dump-time search_path */
3260  if (AH->public.searchpath)
3261  ahprintf(AH, "%s", AH->public.searchpath);
3262 
3263  /* Make sure function checking is disabled */
3264  ahprintf(AH, "SET check_function_bodies = false;\n");
3265 
3266  /* Ensure that all valid XML data will be accepted */
3267  ahprintf(AH, "SET xmloption = content;\n");
3268 
3269  /* Avoid annoying notices etc */
3270  ahprintf(AH, "SET client_min_messages = warning;\n");
3271  if (!AH->public.std_strings)
3272  ahprintf(AH, "SET escape_string_warning = off;\n");
3273 
3274  /* Adjust row-security state */
3275  if (ropt && ropt->enable_row_security)
3276  ahprintf(AH, "SET row_security = on;\n");
3277  else
3278  ahprintf(AH, "SET row_security = off;\n");
3279 
3280  /*
3281  * In --transaction-size mode, we should always be in a transaction when
3282  * we begin to restore objects.
3283  */
3284  if (ropt && ropt->txn_size > 0)
3285  {
3286  if (AH->connection)
3287  StartTransaction(&AH->public);
3288  else
3289  ahprintf(AH, "\nBEGIN;\n");
3290  AH->txnCount = 0;
3291  }
3292 
3293  ahprintf(AH, "\n");
3294 }
#define pg_encoding_to_char
Definition: pg_wchar.h:630
const char * fmtId(const char *rawid)
Definition: string_utils.c:64
char * searchpath
Definition: pg_backup.h:233
char * use_role
Definition: pg_backup.h:105
int enable_row_security
Definition: pg_backup.h:157
static void StartTransaction(void)
Definition: xact.c:2052

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

3303 {
3305 
3306  appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3307 
3308  /*
3309  * SQL requires a string literal here. Might as well be correct.
3310  */
3311  if (user && *user)
3312  appendStringLiteralAHX(cmd, user, AH);
3313  else
3314  appendPQExpBufferStr(cmd, "DEFAULT");
3315  appendPQExpBufferChar(cmd, ';');
3316 
3317  if (RestoringToDB(AH))
3318  {
3319  PGresult *res;
3320 
3321  res = PQexec(AH->connection, cmd->data);
3322 
3323  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3324  /* NOT warn_or_exit_horribly... use -O instead to skip this. */
3325  pg_fatal("could not set session user to \"%s\": %s",
3327 
3328  PQclear(res);
3329  }
3330  else
3331  ahprintf(AH, "%s\n\n", cmd->data);
3332 
3333  destroyPQExpBuffer(cmd);
3334 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7171
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3411
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2262
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:99
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(), res, RestoringToDB(), and user.

Referenced by _becomeUser().

◆ _enableTriggersIfNecessary()

static void _enableTriggersIfNecessary ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 1114 of file pg_backup_archiver.c.

1115 {
1116  RestoreOptions *ropt = AH->public.ropt;
1117 
1118  /* This hack is only needed in a data-only restore */
1119  if (!ropt->dataOnly || !ropt->disable_triggers)
1120  return;
1121 
1122  pg_log_info("enabling triggers for %s", te->tag);
1123 
1124  /*
1125  * Become superuser if possible, since they are the only ones who can
1126  * disable constraint triggers. If -S was not given, assume the initial
1127  * user identity is a superuser. (XXX would it be better to become the
1128  * table owner?)
1129  */
1130  _becomeUser(AH, ropt->superuser);
1131 
1132  /*
1133  * Enable them.
1134  */
1135  ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
1136  fmtQualifiedId(te->namespace, te->tag));
1137 }

References _becomeUser(), ahprintf(), _restoreOptions::dataOnly, _restoreOptions::disable_triggers, 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 2190 of file pg_backup_archiver.c.

2191 {
2192  struct stat st;
2193  char buf[MAXPGPATH];
2194 
2195  if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
2196  pg_fatal("directory name too long: \"%s\"", dir);
2197 
2198  return (stat(buf, &st) == 0 && S_ISREG(st.st_mode));
2199 }
#define MAXPGPATH
static char * filename
Definition: pg_dumpall.c:119
static char * buf
Definition: pg_test_fsync.c:73
#define snprintf
Definition: port.h:238
#define S_ISREG(m)
Definition: win32_port.h:328

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

3635 {
3636  const char *type = te->desc;
3637 
3638  /* objects that don't require special decoration */
3639  if (strcmp(type, "COLLATION") == 0 ||
3640  strcmp(type, "CONVERSION") == 0 ||
3641  strcmp(type, "DOMAIN") == 0 ||
3642  strcmp(type, "FOREIGN TABLE") == 0 ||
3643  strcmp(type, "MATERIALIZED VIEW") == 0 ||
3644  strcmp(type, "SEQUENCE") == 0 ||
3645  strcmp(type, "STATISTICS") == 0 ||
3646  strcmp(type, "TABLE") == 0 ||
3647  strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
3648  strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 ||
3649  strcmp(type, "TYPE") == 0 ||
3650  strcmp(type, "VIEW") == 0 ||
3651  /* non-schema-specified objects */
3652  strcmp(type, "DATABASE") == 0 ||
3653  strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
3654  strcmp(type, "SCHEMA") == 0 ||
3655  strcmp(type, "EVENT TRIGGER") == 0 ||
3656  strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
3657  strcmp(type, "SERVER") == 0 ||
3658  strcmp(type, "PUBLICATION") == 0 ||
3659  strcmp(type, "SUBSCRIPTION") == 0)
3660  {
3661  appendPQExpBuffer(buf, "%s ", type);
3662  if (te->namespace && *te->namespace)
3663  appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
3665  }
3666  /* LOs just have a name, but it's numeric so must not use fmtId */
3667  else if (strcmp(type, "BLOB") == 0)
3668  {
3669  appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag);
3670  }
3671 
3672  /*
3673  * These object types require additional decoration. Fortunately, the
3674  * information needed is exactly what's in the DROP command.
3675  */
3676  else if (strcmp(type, "AGGREGATE") == 0 ||
3677  strcmp(type, "FUNCTION") == 0 ||
3678  strcmp(type, "OPERATOR") == 0 ||
3679  strcmp(type, "OPERATOR CLASS") == 0 ||
3680  strcmp(type, "OPERATOR FAMILY") == 0 ||
3681  strcmp(type, "PROCEDURE") == 0)
3682  {
3683  /* Chop "DROP " off the front and make a modifiable copy */
3684  char *first = pg_strdup(te->dropStmt + 5);
3685  char *last;
3686 
3687  /* point to last character in string */
3688  last = first + strlen(first) - 1;
3689 
3690  /* Strip off any ';' or '\n' at the end */
3691  while (last >= first && (*last == '\n' || *last == ';'))
3692  last--;
3693  *(last + 1) = '\0';
3694 
3695  appendPQExpBufferStr(buf, first);
3696 
3697  free(first);
3698  return;
3699  }
3700  /* these object types don't have separate owners */
3701  else if (strcmp(type, "CAST") == 0 ||
3702  strcmp(type, "CHECK CONSTRAINT") == 0 ||
3703  strcmp(type, "CONSTRAINT") == 0 ||
3704  strcmp(type, "DATABASE PROPERTIES") == 0 ||
3705  strcmp(type, "DEFAULT") == 0 ||
3706  strcmp(type, "FK CONSTRAINT") == 0 ||
3707  strcmp(type, "INDEX") == 0 ||
3708  strcmp(type, "RULE") == 0 ||
3709  strcmp(type, "TRIGGER") == 0 ||
3710  strcmp(type, "ROW SECURITY") == 0 ||
3711  strcmp(type, "POLICY") == 0 ||
3712  strcmp(type, "USER MAPPING") == 0)
3713  {
3714  /* do nothing */
3715  }
3716  else
3717  pg_fatal("don't know how to set owner for object type \"%s\"", type);
3718 }
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 1922 of file pg_backup_archiver.c.

1923 {
1924  /* Unlink te from list */
1925  te->prev->next = te->next;
1926  te->next->prev = te->prev;
1927 
1928  /* and insert it before "pos" */
1929  te->prev = pos->prev;
1930  te->next = pos;
1931  pos->prev->next = te;
1932  pos->prev = te;
1933 }

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

Referenced by SortTocFromFile().

◆ _printTableAccessMethodNoStorage()

static void _printTableAccessMethodNoStorage ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 3586 of file pg_backup_archiver.c.

3587 {
3588  RestoreOptions *ropt = AH->public.ropt;
3589  const char *tableam = te->tableam;
3590  PQExpBuffer cmd;
3591 
3592  /* do nothing in --no-table-access-method mode */
3593  if (ropt->noTableAm)
3594  return;
3595 
3596  if (!tableam)
3597  return;
3598 
3599  Assert(te->relkind == RELKIND_PARTITIONED_TABLE);
3600 
3601  cmd = createPQExpBuffer();
3602 
3603  appendPQExpBufferStr(cmd, "ALTER TABLE ");
3604  appendPQExpBuffer(cmd, "%s ", fmtQualifiedId(te->namespace, te->tag));
3605  appendPQExpBuffer(cmd, "SET ACCESS METHOD %s;",
3606  fmtId(tableam));
3607 
3608  if (RestoringToDB(AH))
3609  {
3610  PGresult *res;
3611 
3612  res = PQexec(AH->connection, cmd->data);
3613 
3614  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3616  "could not alter table access method: %s",
3617  PQerrorMessage(AH->connection));
3618  PQclear(res);
3619  }
3620  else
3621  ahprintf(AH, "%s\n\n", cmd->data);
3622 
3623  destroyPQExpBuffer(cmd);
3624 }
#define Assert(condition)
Definition: c.h:858
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, res, RestoringToDB(), Archive::ropt, _tocEntry::tableam, _tocEntry::tag, and warn_or_exit_horribly().

Referenced by _printTocEntry().

◆ _printTocEntry()

static void _printTocEntry ( ArchiveHandle AH,
TocEntry te,
bool  isData 
)
static

Definition at line 3728 of file pg_backup_archiver.c.

3729 {
3730  RestoreOptions *ropt = AH->public.ropt;
3731 
3732  /*
3733  * Select owner, schema, tablespace and default AM as necessary. The
3734  * default access method for partitioned tables is handled after
3735  * generating the object definition, as it requires an ALTER command
3736  * rather than SET.
3737  */
3738  _becomeOwner(AH, te);
3739  _selectOutputSchema(AH, te->namespace);
3740  _selectTablespace(AH, te->tablespace);
3741  if (te->relkind != RELKIND_PARTITIONED_TABLE)
3743 
3744  /* Emit header comment for item */
3745  if (!AH->noTocComments)
3746  {
3747  const char *pfx;
3748  char *sanitized_name;
3749  char *sanitized_schema;
3750  char *sanitized_owner;
3751 
3752  if (isData)
3753  pfx = "Data for ";
3754  else
3755  pfx = "";
3756 
3757  ahprintf(AH, "--\n");
3758  if (AH->public.verbose)
3759  {
3760  ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
3761  te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
3762  if (te->nDeps > 0)
3763  {
3764  int i;
3765 
3766  ahprintf(AH, "-- Dependencies:");
3767  for (i = 0; i < te->nDeps; i++)
3768  ahprintf(AH, " %d", te->dependencies[i]);
3769  ahprintf(AH, "\n");
3770  }
3771  }
3772 
3773  sanitized_name = sanitize_line(te->tag, false);
3774  sanitized_schema = sanitize_line(te->namespace, true);
3775  sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
3776 
3777  ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
3778  pfx, sanitized_name, te->desc, sanitized_schema,
3779  sanitized_owner);
3780 
3781  free(sanitized_name);
3782  free(sanitized_schema);
3783  free(sanitized_owner);
3784 
3785  if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace)
3786  {
3787  char *sanitized_tablespace;
3788 
3789  sanitized_tablespace = sanitize_line(te->tablespace, false);
3790  ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
3791  free(sanitized_tablespace);
3792  }
3793  ahprintf(AH, "\n");
3794 
3795  if (AH->PrintExtraTocPtr != NULL)
3796  AH->PrintExtraTocPtr(AH, te);
3797  ahprintf(AH, "--\n\n");
3798  }
3799 
3800  /*
3801  * Actually print the definition. Normally we can just print the defn
3802  * string if any, but we have three special cases:
3803  *
3804  * 1. A crude hack for suppressing AUTHORIZATION clause that old pg_dump
3805  * versions put into CREATE SCHEMA. Don't mutate the variant for schema
3806  * "public" that is a comment. We have to do this when --no-owner mode is
3807  * selected. This is ugly, but I see no other good way ...
3808  *
3809  * 2. BLOB METADATA entries need special processing since their defn
3810  * strings are just lists of OIDs, not complete SQL commands.
3811  *
3812  * 3. ACL LARGE OBJECTS entries need special processing because they
3813  * contain only one copy of the ACL GRANT/REVOKE commands, which we must
3814  * apply to each large object listed in the associated BLOB METADATA.
3815  */
3816  if (ropt->noOwner &&
3817  strcmp(te->desc, "SCHEMA") == 0 && strncmp(te->defn, "--", 2) != 0)
3818  {
3819  ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
3820  }
3821  else if (strcmp(te->desc, "BLOB METADATA") == 0)
3822  {
3823  IssueCommandPerBlob(AH, te, "SELECT pg_catalog.lo_create('", "')");
3824  }
3825  else if (strcmp(te->desc, "ACL") == 0 &&
3826  strncmp(te->tag, "LARGE OBJECTS", 13) == 0)
3827  {
3828  IssueACLPerBlob(AH, te);
3829  }
3830  else
3831  {
3832  if (te->defn && strlen(te->defn) > 0)
3833  ahprintf(AH, "%s\n\n", te->defn);
3834  }
3835 
3836  /*
3837  * If we aren't using SET SESSION AUTH to determine ownership, we must
3838  * instead issue an ALTER OWNER command. Schema "public" is special; when
3839  * a dump emits a comment in lieu of creating it, we use ALTER OWNER even
3840  * when using SET SESSION for all other objects. We assume that anything
3841  * without a DROP command is not a separately ownable object.
3842  */
3843  if (!ropt->noOwner &&
3844  (!ropt->use_setsessauth ||
3845  (strcmp(te->desc, "SCHEMA") == 0 &&
3846  strncmp(te->defn, "--", 2) == 0)) &&
3847  te->owner && strlen(te->owner) > 0 &&
3848  te->dropStmt && strlen(te->dropStmt) > 0)
3849  {
3850  if (strcmp(te->desc, "BLOB METADATA") == 0)
3851  {
3852  /* BLOB METADATA needs special code to handle multiple LOs */
3853  char *cmdEnd = psprintf(" OWNER TO %s", fmtId(te->owner));
3854 
3855  IssueCommandPerBlob(AH, te, "ALTER LARGE OBJECT ", cmdEnd);
3856  pg_free(cmdEnd);
3857  }
3858  else
3859  {
3860  /* For all other cases, we can use _getObjectDescription */
3861  PQExpBufferData temp;
3862 
3863  initPQExpBuffer(&temp);
3864  _getObjectDescription(&temp, te);
3865 
3866  /*
3867  * If _getObjectDescription() didn't fill the buffer, then there
3868  * is no owner.
3869  */
3870  if (temp.data[0])
3871  ahprintf(AH, "ALTER %s OWNER TO %s;\n\n",
3872  temp.data, fmtId(te->owner));
3873  termPQExpBuffer(&temp);
3874  }
3875  }
3876 
3877  /*
3878  * Select a partitioned table's default AM, once the table definition has
3879  * been generated.
3880  */
3881  if (te->relkind == RELKIND_PARTITIONED_TABLE)
3883 
3884  /*
3885  * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
3886  * commands, so we can no longer assume we know the current auth setting.
3887  */
3888  if (_tocEntryIsACL(te))
3889  {
3890  free(AH->currUser);
3891  AH->currUser = NULL;
3892  }
3893 }
void pg_free(void *ptr)
Definition: fe_memutils.c:105
int i
Definition: isn.c:73
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:599
void IssueCommandPerBlob(ArchiveHandle *AH, TocEntry *te, const char *cmdBegin, const char *cmdEnd)
Definition: pg_backup_db.c:552
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
int verbose
Definition: pg_backup.h:217
Oid tableoid
Definition: pg_backup.h:266
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::use_setsessauth, and Archive::verbose.

Referenced by restore_toc_entry().

◆ _reconnectToDB()

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

Definition at line 3345 of file pg_backup_archiver.c.

3346 {
3347  if (RestoringToDB(AH))
3349  else
3350  {
3351  PQExpBufferData connectbuf;
3352 
3353  initPQExpBuffer(&connectbuf);
3354  appendPsqlMetaConnect(&connectbuf, dbname);
3355  ahprintf(AH, "%s\n", connectbuf.data);
3356  termPQExpBuffer(&connectbuf);
3357  }
3358 
3359  /*
3360  * NOTE: currUser keeps track of what the imaginary session user in our
3361  * script is. It's now effectively reset to the original userID.
3362  */
3363  free(AH->currUser);
3364  AH->currUser = NULL;
3365 
3366  /* don't assume we still know the output schema, tablespace, etc either */
3367  free(AH->currSchema);
3368  AH->currSchema = NULL;
3369 
3370  free(AH->currTableAm);
3371  AH->currTableAm = NULL;
3372 
3373  free(AH->currTablespace);
3374  AH->currTablespace = NULL;
3375 
3376  /* re-establish fixed state */
3378 }
static void _doSetFixedOutputState(ArchiveHandle *AH)
void ReconnectToServer(ArchiveHandle *AH, const char *dbname)
Definition: pg_backup_db.c:74
char * dbname
Definition: streamutil.c:52
void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname)
Definition: string_utils.c:590

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

3426 {
3427  PQExpBuffer qry;
3428 
3429  /*
3430  * If there was a SEARCHPATH TOC entry, we're supposed to just stay with
3431  * that search_path rather than switching to entry-specific paths.
3432  * Otherwise, it's an old archive that will not restore correctly unless
3433  * we set the search_path as it's expecting.
3434  */
3435  if (AH->public.searchpath)
3436  return;
3437 
3438  if (!schemaName || *schemaName == '\0' ||
3439  (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0))
3440  return; /* no need to do anything */
3441 
3442  qry = createPQExpBuffer();
3443 
3444  appendPQExpBuffer(qry, "SET search_path = %s",
3445  fmtId(schemaName));
3446  if (strcmp(schemaName, "pg_catalog") != 0)
3447  appendPQExpBufferStr(qry, ", pg_catalog");
3448 
3449  if (RestoringToDB(AH))
3450  {
3451  PGresult *res;
3452 
3453  res = PQexec(AH->connection, qry->data);
3454 
3455  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3457  "could not set \"search_path\" to \"%s\": %s",
3458  schemaName, PQerrorMessage(AH->connection));
3459 
3460  PQclear(res);
3461  }
3462  else
3463  ahprintf(AH, "%s;\n\n", qry->data);
3464 
3465  free(AH->currSchema);
3466  AH->currSchema = pg_strdup(schemaName);
3467 
3468  destroyPQExpBuffer(qry);
3469 }

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, res, 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 3536 of file pg_backup_archiver.c.

3537 {
3538  RestoreOptions *ropt = AH->public.ropt;
3539  PQExpBuffer cmd;
3540  const char *want,
3541  *have;
3542 
3543  /* do nothing in --no-table-access-method mode */
3544  if (ropt->noTableAm)
3545  return;
3546 
3547  have = AH->currTableAm;
3548  want = tableam;
3549 
3550  if (!want)
3551  return;
3552 
3553  if (have && strcmp(want, have) == 0)
3554  return;
3555 
3556  cmd = createPQExpBuffer();
3557  appendPQExpBuffer(cmd, "SET default_table_access_method = %s;", fmtId(want));
3558 
3559  if (RestoringToDB(AH))
3560  {
3561  PGresult *res;
3562 
3563  res = PQexec(AH->connection, cmd->data);
3564 
3565  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3567  "could not set \"default_table_access_method\": %s",
3568  PQerrorMessage(AH->connection));
3569 
3570  PQclear(res);
3571  }
3572  else
3573  ahprintf(AH, "%s\n\n", cmd->data);
3574 
3575  destroyPQExpBuffer(cmd);
3576 
3577  free(AH->currTableAm);
3578  AH->currTableAm = pg_strdup(want);
3579 }

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, res, RestoringToDB(), Archive::ropt, and warn_or_exit_horribly().

Referenced by _printTocEntry().

◆ _selectTablespace()

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

Definition at line 3476 of file pg_backup_archiver.c.

3477 {
3478  RestoreOptions *ropt = AH->public.ropt;
3479  PQExpBuffer qry;
3480  const char *want,
3481  *have;
3482 
3483  /* do nothing in --no-tablespaces mode */
3484  if (ropt->noTablespace)
3485  return;
3486 
3487  have = AH->currTablespace;
3488  want = tablespace;
3489 
3490  /* no need to do anything for non-tablespace object */
3491  if (!want)
3492  return;
3493 
3494  if (have && strcmp(want, have) == 0)
3495  return; /* no need to do anything */
3496 
3497  qry = createPQExpBuffer();
3498 
3499  if (strcmp(want, "") == 0)
3500  {
3501  /* We want the tablespace to be the database's default */
3502  appendPQExpBufferStr(qry, "SET default_tablespace = ''");
3503  }
3504  else
3505  {
3506  /* We want an explicit tablespace */
3507  appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
3508  }
3509 
3510  if (RestoringToDB(AH))
3511  {
3512  PGresult *res;
3513 
3514  res = PQexec(AH->connection, qry->data);
3515 
3516  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3518  "could not set \"default_tablespace\" to %s: %s",
3519  fmtId(want), PQerrorMessage(AH->connection));
3520 
3521  PQclear(res);
3522  }
3523  else
3524  ahprintf(AH, "%s;\n\n", qry->data);
3525 
3526  free(AH->currTablespace);
3527  AH->currTablespace = pg_strdup(want);
3528 
3529  destroyPQExpBuffer(qry);
3530 }
static char * tablespace
Definition: pgbench.c:216

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, res, RestoringToDB(), Archive::ropt, tablespace, and warn_or_exit_horribly().

Referenced by _printTocEntry().

◆ _tocEntryIsACL()

static bool _tocEntryIsACL ( TocEntry te)
static

Definition at line 3220 of file pg_backup_archiver.c.

3221 {
3222  /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3223  if (strcmp(te->desc, "ACL") == 0 ||
3224  strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3225  strcmp(te->desc, "DEFAULT ACL") == 0)
3226  return true;
3227  return false;
3228 }

References _tocEntry::desc.

Referenced by _printTocEntry(), and _tocEntryRequired().

◆ _tocEntryRequired()

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

Definition at line 2906 of file pg_backup_archiver.c.

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

References _tocEntryIsACL(), _restoreOptions::aclsSkip, _restoreOptions::binary_upgrade, _restoreOptions::createDB, _restoreOptions::dataOnly, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, DUMP_DATA, DUMP_POST_DATA, DUMP_PRE_DATA, _tocEntry::dumpId, _restoreOptions::dumpSections, _restoreOptions::functionNames, getTocEntryByDumpId(), _tocEntry::hadDumper, SimpleStringList::head, i, _restoreOptions::idWanted, _restoreOptions::indexNames, _tocEntry::nDeps, _restoreOptions::no_comments, _restoreOptions::no_publications, _restoreOptions::no_security_labels, _restoreOptions::no_subscriptions, _archiveHandle::public, REQ_DATA, REQ_SCHEMA, REQ_SPECIAL, _tocEntry::reqs, res, Archive::ropt, _restoreOptions::schemaExcludeNames, _restoreOptions::schemaNames, _restoreOptions::schemaOnly, 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 3187 of file pg_backup_archiver.c.

3188 {
3189  /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3190  if (strcmp(te->desc, "ACL") == 0 ||
3191  strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3192  strcmp(te->desc, "DEFAULT ACL") == 0)
3193  return RESTORE_PASS_ACL;
3194  if (strcmp(te->desc, "EVENT TRIGGER") == 0 ||
3195  strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0)
3196  return RESTORE_PASS_POST_ACL;
3197 
3198  /*
3199  * Comments need to be emitted in the same pass as their parent objects.
3200  * ACLs haven't got comments, and neither do matview data objects, but
3201  * event triggers do. (Fortunately, event triggers haven't got ACLs, or
3202  * we'd need yet another weird special case.)
3203  */
3204  if (strcmp(te->desc, "COMMENT") == 0 &&
3205  strncmp(te->tag, "EVENT TRIGGER ", 14) == 0)
3206  return RESTORE_PASS_POST_ACL;
3207 
3208  /* All else can be handled in the main pass. */
3209  return RESTORE_PASS_MAIN;
3210 }
@ 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 1717 of file pg_backup_archiver.c.

1718 {
1719  int save_errno = errno;
1720  char *p;
1721  size_t len = 128; /* initial assumption about buffer size */
1722  size_t cnt;
1723 
1724  for (;;)
1725  {
1726  va_list args;
1727 
1728  /* Allocate work buffer. */
1729  p = (char *) pg_malloc(len);
1730 
1731  /* Try to format the data. */
1732  errno = save_errno;
1733  va_start(args, fmt);
1734  cnt = pvsnprintf(p, len, fmt, args);
1735  va_end(args);
1736 
1737  if (cnt < len)
1738  break; /* success */
1739 
1740  /* Release buffer and loop around to try again with larger len. */
1741  free(p);
1742  len = cnt;
1743  }
1744 
1745  ahwrite(p, 1, cnt, AH);
1746  free(p);
1747  return (int) cnt;
1748 }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
va_end(args)
va_start(args, fmt)
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:106

References ahwrite(), generate_unaccent_rules::args, fmt, free, len, pg_malloc(), pvsnprintf(), va_end(), and va_start().

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

1809 {
1810  int bytes_written = 0;
1811 
1812  if (AH->writingLO)
1813  {
1814  size_t remaining = size * nmemb;
1815 
1816  while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1817  {
1818  size_t avail = AH->lo_buf_size - AH->lo_buf_used;
1819 
1820  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1821  ptr = (const void *) ((const char *) ptr + avail);
1822  remaining -= avail;
1823  AH->lo_buf_used += avail;
1824  dump_lo_buf(AH);
1825  }
1826 
1827  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1828  AH->lo_buf_used += remaining;
1829 
1830  bytes_written = size * nmemb;
1831  }
1832  else if (AH->CustomOutPtr)
1833  bytes_written = AH->CustomOutPtr(AH, ptr, size * nmemb);
1834 
1835  /*
1836  * If we're doing a restore, and it's direct to DB, and we're connected
1837  * then send it to the DB.
1838  */
1839  else if (RestoringToDB(AH))
1840  bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb);
1841  else
1842  {
1843  CompressFileHandle *CFH = (CompressFileHandle *) AH->OF;
1844 
1845  if (CFH->write_func(ptr, size * nmemb, CFH))
1846  bytes_written = size * nmemb;
1847  }
1848 
1849  if (bytes_written != size * nmemb)
1851 }
int remaining
Definition: informix.c:673
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
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:445
static pg_noinline void Size size
Definition: slab.c:607
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(), size, 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 1203 of file pg_backup_archiver.c.

1205 {
1206  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1207  TocEntry *newToc;
1208 
1209  newToc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
1210 
1211  AH->tocCount++;
1212  if (dumpId > AH->maxDumpId)
1213  AH->maxDumpId = dumpId;
1214 
1215  newToc->prev = AH->toc->prev;
1216  newToc->next = AH->toc;
1217  AH->toc->prev->next = newToc;
1218  AH->toc->prev = newToc;
1219 
1220  newToc->catalogId = catalogId;
1221  newToc->dumpId = dumpId;
1222  newToc->section = opts->section;
1223 
1224  newToc->tag = pg_strdup(opts->tag);
1225  newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
1226  newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
1227  newToc->tableam = opts->tableam ? pg_strdup(opts->tableam) : NULL;
1228  newToc->relkind = opts->relkind;
1229  newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
1230  newToc->desc = pg_strdup(opts->description);
1231  newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
1232  newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
1233  newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
1234 
1235  if (opts->nDeps > 0)
1236  {
1237  newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId));
1238  memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
1239  newToc->nDeps = opts->nDeps;
1240  }
1241  else
1242  {
1243  newToc->dependencies = NULL;
1244  newToc->nDeps = 0;
1245  }
1246 
1247  newToc->dataDumper = opts->dumpFn;
1248  newToc->dataDumperArg = opts->dumpArg;
1249  newToc->hadDumper = opts->dumpFn ? true : false;
1250 
1251  newToc->formatData = NULL;
1252  newToc->dataLength = 0;
1253 
1254  if (AH->ArchiveEntryPtr != NULL)
1255  AH->ArchiveEntryPtr(AH, newToc);
1256 
1257  return newToc;
1258 }
return true
Definition: isn.c:126
static AmcheckOptions opts
Definition: pg_amcheck.c:111
int DumpId
Definition: pg_backup.h:270
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(), 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 1617 of file pg_backup_archiver.c.

1618 {
1619  int save_errno = errno;
1620  char *p;
1621  size_t len = 128; /* initial assumption about buffer size */
1622  size_t cnt;
1623 
1624  for (;;)
1625  {
1626  va_list args;
1627 
1628  /* Allocate work buffer. */
1629  p = (char *) pg_malloc(len);
1630 
1631  /* Try to format the data. */
1632  errno = save_errno;
1633  va_start(args, fmt);
1634  cnt = pvsnprintf(p, len, fmt, args);
1635  va_end(args);
1636 
1637  if (cnt < len)
1638  break; /* success */
1639 
1640  /* Release buffer and loop around to try again with larger len. */
1641  free(p);
1642  len = cnt;
1643  }
1644 
1645  WriteData(AH, p, cnt);
1646  free(p);
1647  return (int) cnt;
1648 }
void WriteData(Archive *AHX, const void *data, size_t dLen)

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

◆ archputs()

void archputs ( const char *  s,
Archive AH 
)

Definition at line 1610 of file pg_backup_archiver.c.

1611 {
1612  WriteData(AH, s, strlen(s));
1613 }

References WriteData().

Referenced by dumpTableData_insert().

◆ buildTocEntryArrays()

static void buildTocEntryArrays ( ArchiveHandle AH)
static

Definition at line 1947 of file pg_backup_archiver.c.

1948 {
1949  DumpId maxDumpId = AH->maxDumpId;
1950  TocEntry *te;
1951 
1952  AH->tocsByDumpId = (TocEntry **) pg_malloc0((maxDumpId + 1) * sizeof(TocEntry *));
1953  AH->tableDataId = (DumpId *) pg_malloc0((maxDumpId + 1) * sizeof(DumpId));
1954 
1955  for (te = AH->toc->next; te != AH->toc; te = te->next)
1956  {
1957  /* this check is purely paranoia, maxDumpId should be correct */
1958  if (te->dumpId <= 0 || te->dumpId > maxDumpId)
1959  pg_fatal("bad dumpId");
1960 
1961  /* tocsByDumpId indexes all TOCs by their dump ID */
1962  AH->tocsByDumpId[te->dumpId] = te;
1963 
1964  /*
1965  * tableDataId provides the TABLE DATA item's dump ID for each TABLE
1966  * TOC entry that has a DATA item. We compute this by reversing the
1967  * TABLE DATA item's dependency, knowing that a TABLE DATA item has
1968  * just one dependency and it is the TABLE item.
1969  */
1970  if (strcmp(te->desc, "TABLE DATA") == 0 && te->nDeps > 0)
1971  {
1972  DumpId tableId = te->dependencies[0];
1973 
1974  /*
1975  * The TABLE item might not have been in the archive, if this was
1976  * a data-only dump; but its dump ID should be less than its data
1977  * item's dump ID, so there should be a place for it in the array.
1978  */
1979  if (tableId <= 0 || tableId > maxDumpId)
1980  pg_fatal("bad table dumpId for TABLE DATA item");
1981 
1982  AH->tableDataId[tableId] = te->dumpId;
1983  }
1984  }
1985 }
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 4095 of file pg_backup_archiver.c.

4096 {
4097  pgoff_t tpos;
4098 
4099  /* Check that ftello works on this file */
4100  tpos = ftello(fp);
4101  if (tpos < 0)
4102  return false;
4103 
4104  /*
4105  * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
4106  * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
4107  * successful no-op even on files that are otherwise unseekable.
4108  */
4109  if (fseeko(fp, tpos, SEEK_SET) != 0)
4110  return false;
4111 
4112  return true;
4113 }
#define ftello(stream)
Definition: win32_port.h:219
#define fseeko(stream, offset, origin)
Definition: win32_port.h:216

References fseeko, ftello, and pgoff_t.

Referenced by InitArchiveFmt_Custom(), and InitArchiveFmt_Tar().

◆ CloneArchive()

ArchiveHandle* CloneArchive ( ArchiveHandle AH)

Definition at line 4962 of file pg_backup_archiver.c.

4963 {
4964  ArchiveHandle *clone;
4965 
4966  /* Make a "flat" copy */
4967  clone = (ArchiveHandle *) pg_malloc(sizeof(ArchiveHandle));
4968  memcpy(clone, AH, sizeof(ArchiveHandle));
4969 
4970  /* Likewise flat-copy the RestoreOptions, so we can alter them locally */
4971  clone->public.ropt = (RestoreOptions *) pg_malloc(sizeof(RestoreOptions));
4972  memcpy(clone->public.ropt, AH->public.ropt, sizeof(RestoreOptions));
4973 
4974  /* Handle format-independent fields */
4975  memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse));
4976 
4977  /* The clone will have its own connection, so disregard connection state */
4978  clone->connection = NULL;
4979  clone->connCancel = NULL;
4980  clone->currUser = NULL;
4981  clone->currSchema = NULL;
4982  clone->currTableAm = NULL;
4983  clone->currTablespace = NULL;
4984 
4985  /* savedPassword must be local in case we change it while connecting */
4986  if (clone->savedPassword)
4987  clone->savedPassword = pg_strdup(clone->savedPassword);
4988 
4989  /* clone has its own error count, too */
4990  clone->public.n_errors = 0;
4991 
4992  /* clones should not share lo_buf */
4993  clone->lo_buf = NULL;
4994 
4995  /*
4996  * Clone connections disregard --transaction-size; they must commit after
4997  * each command so that the results are immediately visible to other
4998  * workers.
4999  */
5000  clone->public.ropt->txn_size = 0;
5001 
5002  /*
5003  * Connect our new clone object to the database, using the same connection
5004  * parameters used for the original connection.
5005  */
5006  ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true);
5007 
5008  /* re-establish fixed state */
5009  if (AH->mode == archModeRead)
5010  _doSetFixedOutputState(clone);
5011  /* in write case, setupDumpWorker will fix up connection state */
5012 
5013  /* Let the format-specific code have a chance too */
5014  clone->ClonePtr(clone);
5015 
5016  Assert(clone->connection != NULL);
5017  return clone;
5018 }
void ConnectDatabase(Archive *AHX, const ConnParams *cparams, bool isReconnect)
Definition: pg_backup_db.c:110
@ archModeRead
Definition: pg_backup.h:52
PGcancel *volatile connCancel
ClonePtrType ClonePtr
ConnParams cparams
Definition: pg_backup.h:144

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

253 {
254  ArchiveHandle *AH = (ArchiveHandle *) AHX;
255 
256  AH->ClosePtr(AH);
257 
258  /* Close the output */
259  errno = 0;
260  if (!EndCompressFileHandle(AH->OF))
261  pg_fatal("could not close output file: %m");
262 }
bool EndCompressFileHandle(CompressFileHandle *CFH)
Definition: compress_io.c:289
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 221 of file pg_backup_archiver.c.

227 {
228  ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression_spec,
230 
231  return (Archive *) AH;
232 }
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:1372

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

Referenced by main().

◆ DeCloneArchive()

void DeCloneArchive ( ArchiveHandle AH)

Definition at line 5026 of file pg_backup_archiver.c.

5027 {
5028  /* Should not have an open database connection */
5029  Assert(AH->connection == NULL);
5030 
5031  /* Clear format-specific state */
5032  AH->DeClonePtr(AH);
5033 
5034  /* Clear state allocated by CloneArchive */
5035  if (AH->sqlparse.curCmd)
5037 
5038  /* Clear any connection-local state */
5039  free(AH->currUser);
5040  free(AH->currSchema);
5041  free(AH->currTablespace);
5042  free(AH->currTableAm);
5043  free(AH->savedPassword);
5044 
5045  free(AH);
5046 }
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 1765 of file pg_backup_archiver.c.

1766 {
1767  if (AH->connection)
1768  {
1769  int res;
1770 
1771  res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1772  pg_log_debug(ngettext("wrote %zu byte of large object data (result = %d)",
1773  "wrote %zu bytes of large object data (result = %d)",
1774  AH->lo_buf_used),
1775  AH->lo_buf_used, res);
1776  /* We assume there are no short writes, only errors */
1777  if (res != AH->lo_buf_used)
1778  warn_or_exit_horribly(AH, "could not write to large object: %s",
1779  PQerrorMessage(AH->connection));
1780  }
1781  else
1782  {
1784 
1786  (const unsigned char *) AH->lo_buf,
1787  AH->lo_buf_used,
1788  AH);
1789 
1790  /* Hack: turn off writingLO so ahwrite doesn't recurse to here */
1791  AH->writingLO = false;
1792  ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
1793  AH->writingLO = true;
1794 
1796  }
1797  AH->lo_buf_used = 0;
1798 }
int lo_write(int fd, const char *buf, int len)
Definition: be-fsstubs.c:182
#define ngettext(s, p, n)
Definition: c.h:1181
#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(), res, warn_or_exit_horribly(), and _archiveHandle::writingLO.

Referenced by ahwrite(), and EndRestoreLO().

◆ dumpOptionsFromRestoreOptions()

DumpOptions* dumpOptionsFromRestoreOptions ( RestoreOptions ropt)

Definition at line 157 of file pg_backup_archiver.c.

158 {
159  DumpOptions *dopt = NewDumpOptions();
160 
161  /* this is the inverse of what's at the end of pg_dump.c's main() */
162  dopt->cparams.dbname = ropt->cparams.dbname ? pg_strdup(ropt->cparams.dbname) : NULL;
163  dopt->cparams.pgport = ropt->cparams.pgport ? pg_strdup(ropt->cparams.pgport) : NULL;
164  dopt->cparams.pghost = ropt->cparams.pghost ? pg_strdup(ropt->cparams.pghost) : NULL;
165  dopt->cparams.username = ropt->cparams.username ? pg_strdup(ropt->cparams.username) : NULL;
167  dopt->outputClean = ropt->dropSchema;
168  dopt->dataOnly = ropt->dataOnly;
169  dopt->schemaOnly = ropt->schemaOnly;
170  dopt->if_exists = ropt->if_exists;
171  dopt->column_inserts = ropt->column_inserts;
172  dopt->dumpSections = ropt->dumpSections;
173  dopt->aclsSkip = ropt->aclsSkip;
174  dopt->outputSuperuser = ropt->superuser;
175  dopt->outputCreateDB = ropt->createDB;
176  dopt->outputNoOwner = ropt->noOwner;
177  dopt->outputNoTableAm = ropt->noTableAm;
178  dopt->outputNoTablespaces = ropt->noTablespace;
179  dopt->disable_triggers = ropt->disable_triggers;
180  dopt->use_setsessauth = ropt->use_setsessauth;
182  dopt->dump_inserts = ropt->dump_inserts;
183  dopt->no_comments = ropt->no_comments;
184  dopt->no_publications = ropt->no_publications;
186  dopt->no_subscriptions = ropt->no_subscriptions;
187  dopt->lockWaitTimeout = ropt->lockWaitTimeout;
190  dopt->sequence_data = ropt->sequence_data;
191 
192  return dopt;
193 }
DumpOptions * NewDumpOptions(void)
char * pgport
Definition: pg_backup.h:85
char * pghost
Definition: pg_backup.h:86
trivalue promptPassword
Definition: pg_backup.h:88
char * username
Definition: pg_backup.h:87
char * dbname
Definition: pg_backup.h:84
bool dataOnly
Definition: pg_backup.h:170
int dump_inserts
Definition: pg_backup.h:174
int column_inserts
Definition: pg_backup.h:178
int use_setsessauth
Definition: pg_backup.h:190
int outputCreateDB
Definition: pg_backup.h:198
bool include_everything
Definition: pg_backup.h:195
int sequence_data
Definition: pg_backup.h:204
int disable_dollar_quoting
Definition: pg_backup.h:177
int no_comments
Definition: pg_backup.h:180
int outputNoTableAm
Definition: pg_backup.h:188
int enable_row_security
Definition: pg_backup.h:191
char * outputSuperuser
Definition: pg_backup.h:202
int dumpSections
Definition: pg_backup.h:171
int no_security_labels
Definition: pg_backup.h:181
int no_publications
Definition: pg_backup.h:182
ConnParams cparams
Definition: pg_backup.h:164
const char * lockWaitTimeout
Definition: pg_backup.h:173
int no_subscriptions
Definition: pg_backup.h:183
bool aclsSkip
Definition: pg_backup.h:172
int outputClean
Definition: pg_backup.h:197
int outputNoTablespaces
Definition: pg_backup.h:189
int disable_triggers
Definition: pg_backup.h:187
int outputNoOwner
Definition: pg_backup.h:201
bool schemaOnly
Definition: pg_backup.h:169
int include_everything
Definition: pg_backup.h:124
int disable_dollar_quoting
Definition: pg_backup.h:107
const char * lockWaitTimeout
Definition: pg_backup.h:123

References _restoreOptions::aclsSkip, _dumpOptions::aclsSkip, _restoreOptions::column_inserts, _dumpOptions::column_inserts, _restoreOptions::cparams, _dumpOptions::cparams, _restoreOptions::createDB, _restoreOptions::dataOnly, _dumpOptions::dataOnly, _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::dumpSections, _dumpOptions::dumpSections, _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_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::schemaOnly, _dumpOptions::schemaOnly, _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 4120 of file pg_backup_archiver.c.

4121 {
4122  char buf[64];
4123 
4124  if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
4125  ahprintf(AH, "-- %s %s\n\n", msg, buf);
4126 }
#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 1388 of file pg_backup_archiver.c.

1389 {
1390  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1391 
1392  if (AH->EndLOPtr)
1393  AH->EndLOPtr(AH, AH->currToc, oid);
1394 
1395  return 1;
1396 }
EndLOPtrType EndLOPtr
struct _tocEntry * currToc

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

Referenced by dumpLOs().

◆ EndRestoreLO()

void EndRestoreLO ( ArchiveHandle AH,
Oid  oid 
)

Definition at line 1503 of file pg_backup_archiver.c.

1504 {
1505  if (AH->lo_buf_used > 0)
1506  {
1507  /* Write remaining bytes from the LO buffer */
1508  dump_lo_buf(AH);
1509  }
1510 
1511  AH->writingLO = false;
1512 
1513  if (AH->connection)
1514  {
1515  lo_close(AH->connection, AH->loFd);
1516  AH->loFd = -1;
1517  }
1518  else
1519  {
1520  ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
1521  }
1522 }
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 1430 of file pg_backup_archiver.c.

1431 {
1432  RestoreOptions *ropt = AH->public.ropt;
1433 
1434  if (!(ropt->single_txn || ropt->txn_size > 0))
1435  {
1436  if (AH->connection)
1437  CommitTransaction(&AH->public);
1438  else
1439  ahprintf(AH, "COMMIT;\n\n");
1440  }
1441 
1442  pg_log_info(ngettext("restored %d large object",
1443  "restored %d large objects",
1444  AH->loCount),
1445  AH->loCount);
1446 }
static void CommitTransaction(void)
Definition: xact.c:2216

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

4660 {
4661  TocEntry *te;
4662  int i;
4663 
4664  /*
4665  * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC
4666  * items are marked as not being in any parallel-processing list.
4667  */
4668  for (te = AH->toc->next; te != AH->toc; te = te->next)
4669  {
4670  te->depCount = te->nDeps;
4671  te->revDeps = NULL;
4672  te->nRevDeps = 0;
4673  te->pending_prev = NULL;
4674  te->pending_next = NULL;
4675  }
4676 
4677  /*
4678  * POST_DATA items that are shown as depending on a table need to be
4679  * re-pointed to depend on that table's data, instead. This ensures they
4680  * won't get scheduled until the data has been loaded.
4681  */
4683 
4684  /*
4685  * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB
4686  * COMMENTS to BLOBS. Cope. (We assume there's only one BLOBS and only
4687  * one BLOB COMMENTS in such files.)
4688  */
4689  if (AH->version < K_VERS_1_11)
4690  {
4691  for (te = AH->toc->next; te != AH->toc; te = te->next)
4692  {
4693  if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0)
4694  {
4695  TocEntry *te2;
4696 
4697  for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next)
4698  {
4699  if (strcmp(te2->desc, "BLOBS") == 0)
4700  {
4701  te->dependencies = (DumpId *) pg_malloc(sizeof(DumpId));
4702  te->dependencies[0] = te2->dumpId;
4703  te->nDeps++;
4704  te->depCount++;
4705  break;
4706  }
4707  }
4708  break;
4709  }
4710  }
4711  }
4712 
4713  /*
4714  * At this point we start to build the revDeps reverse-dependency arrays,
4715  * so all changes of dependencies must be complete.
4716  */
4717 
4718  /*
4719  * Count the incoming dependencies for each item. Also, it is possible
4720  * that the dependencies list items that are not in the archive at all
4721  * (that should not happen in 9.2 and later, but is highly likely in older
4722  * archives). Subtract such items from the depCounts.
4723  */
4724  for (te = AH->toc->next; te != AH->toc; te = te->next)
4725  {
4726  for (i = 0; i < te->nDeps; i++)
4727  {
4728  DumpId depid = te->dependencies[i];
4729 
4730  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4731  AH->tocsByDumpId[depid]->nRevDeps++;
4732  else
4733  te->depCount--;
4734  }
4735  }
4736 
4737  /*
4738  * Allocate space for revDeps[] arrays, and reset nRevDeps so we can use
4739  * it as a counter below.
4740  */
4741  for (te = AH->toc->next; te != AH->toc; te = te->next)
4742  {
4743  if (te->nRevDeps > 0)
4744  te->revDeps = (DumpId *) pg_malloc(te->nRevDeps * sizeof(DumpId));
4745  te->nRevDeps = 0;
4746  }
4747 
4748  /*
4749  * Build the revDeps[] arrays of incoming-dependency dumpIds. This had
4750  * better agree with the loops above.
4751  */
4752  for (te = AH->toc->next; te != AH->toc; te = te->next)
4753  {
4754  for (i = 0; i < te->nDeps; i++)
4755  {
4756  DumpId depid = te->dependencies[i];
4757 
4758  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4759  {
4760  TocEntry *otherte = AH->tocsByDumpId[depid];
4761 
4762  otherte->revDeps[otherte->nRevDeps++] = te->dumpId;
4763  }
4764  }
4765  }
4766 
4767  /*
4768  * Lastly, work out the locking dependencies.
4769  */
4770  for (te = AH->toc->next; te != AH->toc; te = te->next)
4771  {
4772  te->lockDeps = NULL;
4773  te->nLockDeps = 0;
4775  }
4776 }
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 1988 of file pg_backup_archiver.c.

1989 {
1990  /* build index arrays if we didn't already */
1991  if (AH->tocsByDumpId == NULL)
1992  buildTocEntryArrays(AH);
1993 
1994  if (id > 0 && id <= AH->maxDumpId)
1995  return AH->tocsByDumpId[id];
1996 
1997  return NULL;
1998 }
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 4413 of file pg_backup_archiver.c.

4414 {
4415  int j,
4416  k;
4417 
4418  for (j = 0; j < te1->nLockDeps; j++)
4419  {
4420  for (k = 0; k < te2->nDeps; k++)
4421  {
4422  if (te1->lockDeps[j] == te2->dependencies[k])
4423  return true;
4424  }
4425  }
4426  return false;
4427 }
int j
Definition: isn.c:74

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

4824 {
4825  DumpId *lockids;
4826  int nlockids;
4827  int i;
4828 
4829  /*
4830  * We only care about this for POST_DATA items. PRE_DATA items are not
4831  * run in parallel, and DATA items are all independent by assumption.
4832  */
4833  if (te->section != SECTION_POST_DATA)
4834  return;
4835 
4836  /* Quick exit if no dependencies at all */
4837  if (te->nDeps == 0)
4838  return;
4839 
4840  /*
4841  * Most POST_DATA items are ALTER TABLEs or some moral equivalent of that,
4842  * and hence require exclusive lock. However, we know that CREATE INDEX
4843  * does not. (Maybe someday index-creating CONSTRAINTs will fall in that
4844  * category too ... but today is not that day.)
4845  */
4846  if (strcmp(te->desc, "INDEX") == 0)
4847  return;
4848 
4849  /*
4850  * We assume the entry requires exclusive lock on each TABLE or TABLE DATA
4851  * item listed among its dependencies. Originally all of these would have
4852  * been TABLE items, but repoint_table_dependencies would have repointed
4853  * them to the TABLE DATA items if those are present (which they might not
4854  * be, eg in a schema-only dump). Note that all of the entries we are
4855  * processing here are POST_DATA; otherwise there might be a significant
4856  * difference between a dependency on a table and a dependency on its
4857  * data, so that closer analysis would be needed here.
4858  */
4859  lockids = (DumpId *) pg_malloc(te->nDeps * sizeof(DumpId));
4860  nlockids = 0;
4861  for (i = 0; i < te->nDeps; i++)
4862  {
4863  DumpId depid = te->dependencies[i];
4864 
4865  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL &&
4866  ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) ||
4867  strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0))
4868  lockids[nlockids++] = depid;
4869  }
4870 
4871  if (nlockids == 0)
4872  {
4873  free(lockids);
4874  return;
4875  }
4876 
4877  te->lockDeps = pg_realloc(lockids, nlockids * sizeof(DumpId));
4878  te->nLockDeps = nlockids;
4879 }
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 4942 of file pg_backup_archiver.c.

4943 {
4944  pg_log_info("table \"%s\" could not be created, will not restore its data",
4945  te->tag);
4946 
4947  if (AH->tableDataId[te->dumpId] != 0)
4948  {
4949  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4950 
4951  ted->reqs = 0;
4952  }
4953 }

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

144 {
145  memset(opts, 0, sizeof(DumpOptions));
146  /* set any fields that shouldn't default to zeroes */
147  opts->include_everything = true;
148  opts->cparams.promptPassword = TRI_DEFAULT;
149  opts->dumpSections = DUMP_UNSECTIONED;
150 }
#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 1151 of file pg_backup_archiver.c.

1152 {
1153  if (te->defn &&
1154  strncmp(te->defn, "-- load via partition root ", 27) == 0)
1155  return true;
1156  if (te->copyStmt && *te->copyStmt)
1157  {
1158  PQExpBuffer copyStmt = createPQExpBuffer();
1159  bool result;
1160 
1161  /*
1162  * Build the initial part of the COPY as it would appear if the
1163  * nominal target table is the actual target. If we see anything
1164  * else, it must be a load-via-partition-root case.
1165  */
1166  appendPQExpBuffer(copyStmt, "COPY %s ",
1167  fmtQualifiedId(te->namespace, te->tag));
1168  result = strncmp(te->copyStmt, copyStmt->data, copyStmt->len) != 0;
1169  destroyPQExpBuffer(copyStmt);
1170  return result;
1171  }
1172  /* Assume it's not load-via-partition-root */
1173  return false;
1174 }

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

4928 {
4929  if (AH->tableDataId[te->dumpId] != 0)
4930  {
4931  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4932 
4933  ted->created = true;
4934  }
4935 }

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

2526 {
2527  pg_log_info("finished item %d %s %s",
2528  te->dumpId, te->desc, te->tag);
2529 
2530  if (status != 0)
2531  pg_fatal("worker process failed: exit code %d",
2532  status);
2533 }

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

4622 {
4623  binaryheap *ready_heap = (binaryheap *) callback_data;
4624 
4625  pg_log_info("finished item %d %s %s",
4626  te->dumpId, te->desc, te->tag);
4627 
4628  if (status == WORKER_CREATE_DONE)
4629  mark_create_done(AH, te);
4630  else if (status == WORKER_INHIBIT_DATA)
4631  {
4633  AH->public.n_errors++;
4634  }
4635  else if (status == WORKER_IGNORED_ERRORS)
4636  AH->public.n_errors++;
4637  else if (status != 0)
4638  pg_fatal("worker process failed: exit code %d",
4639  status);
4640 
4641  reduce_dependencies(AH, te, ready_heap);
4642 }
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 4503 of file pg_backup_archiver.c.

4506 {
4507  TocEntry *te;
4508  TocEntry *next_te;
4509 
4510  for (te = pending_list->pending_next; te != pending_list; te = next_te)
4511  {
4512  /* must save list link before possibly removing te from list */
4513  next_te = te->pending_next;
4514 
4515  if (te->depCount == 0 &&
4516  _tocEntryRestorePass(te) == pass)
4517  {
4518  /* Remove it from pending_list ... */
4519  pending_list_remove(te);
4520  /* ... and add to ready_heap */
4521  binaryheap_add(ready_heap, te);
4522  }
4523  }
4524 }
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 131 of file pg_backup_archiver.c.

132 {
134 
136  return opts;
137 }
void InitDumpOptions(DumpOptions *opts)

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

Referenced by dumpOptionsFromRestoreOptions().

◆ NewRestoreOptions()

RestoreOptions* NewRestoreOptions ( void  )

Definition at line 1071 of file pg_backup_archiver.c.

1072 {
1074 
1076 
1077  /* set any fields that shouldn't default to zeroes */
1078  opts->format = archUnknown;
1079  opts->cparams.promptPassword = TRI_DEFAULT;
1080  opts->dumpSections = DUMP_UNSECTIONED;
1081  opts->compression_spec.algorithm = PG_COMPRESSION_NONE;
1082  opts->compression_spec.level = 0;
1083 
1084  return opts;
1085 }

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

238 {
239  ArchiveHandle *AH;
240  pg_compress_specification compression_spec = {0};
241 
242  compression_spec.algorithm = PG_COMPRESSION_NONE;
243  AH = _allocAH(FileSpec, fmt, compression_spec, true,
246 
247  return (Archive *) AH;
248 }
@ 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, fmt, PG_COMPRESSION_NONE, and setupRestoreWorker().

Referenced by main().

◆ parallel_restore()

int parallel_restore ( ArchiveHandle AH,
TocEntry te 
)

Definition at line 4595 of file pg_backup_archiver.c.

4596 {
4597  int status;
4598 
4599  Assert(AH->connection != NULL);
4600 
4601  /* Count only errors associated with this TOC entry */
4602  AH->public.n_errors = 0;
4603 
4604  /* Restore the TOC item */
4605  status = restore_toc_entry(AH, te, true);
4606 
4607  return status;
4608 }
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 4445 of file pg_backup_archiver.c.

4446 {
4447  te->pending_prev = l->pending_prev;
4448  l->pending_prev->pending_next = te;
4449  l->pending_prev = te;
4450  te->pending_next = l;
4451 }

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

4439 {
4440  l->pending_prev = l->pending_next = l;
4441 }

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

4456 {
4459  te->pending_prev = NULL;
4460  te->pending_next = NULL;
4461 }

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

4540 {
4541  /*
4542  * Search the ready_heap until we find a suitable item. Note that we do a
4543  * sequential scan through the heap nodes, so even though we will first
4544  * try to choose the highest-priority item, we might end up picking
4545  * something with a much lower priority. However, we expect that we will
4546  * typically be able to pick one of the first few items, which should
4547  * usually have a relatively high priority.
4548  */
4549  for (int i = 0; i < binaryheap_size(ready_heap); i++)
4550  {
4551  TocEntry *te = (TocEntry *) binaryheap_get_node(ready_heap, i);
4552  bool conflicts = false;
4553 
4554  /*
4555  * Check to see if the item would need exclusive lock on something
4556  * that a currently running item also needs lock on, or vice versa. If
4557  * so, we don't want to schedule them together.
4558  */
4559  for (int k = 0; k < pstate->numWorkers; k++)
4560  {
4561  TocEntry *running_te = pstate->te[k];
4562 
4563  if (running_te == NULL)
4564  continue;
4565  if (has_lock_conflicts(te, running_te) ||
4566  has_lock_conflicts(running_te, te))
4567  {
4568  conflicts = true;
4569  break;
4570  }
4571  }
4572 
4573  if (conflicts)
4574  continue;
4575 
4576  /* passed all tests, so this item can run */
4577  binaryheap_remove_node(ready_heap, i);
4578  return te;
4579  }
4580 
4581  pg_log_debug("no item ready");
4582  return NULL;
4583 }
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 1262 of file pg_backup_archiver.c.

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

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

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

2803 {
2804  /* te->defn should have the form SET client_encoding = 'foo'; */
2805  char *defn = pg_strdup(te->defn);
2806  char *ptr1;
2807  char *ptr2 = NULL;
2808  int encoding;
2809 
2810  ptr1 = strchr(defn, '\'');
2811  if (ptr1)
2812  ptr2 = strchr(++ptr1, '\'');
2813  if (ptr2)
2814  {
2815  *ptr2 = '\0';
2816  encoding = pg_char_to_encoding(ptr1);
2817  if (encoding < 0)
2818  pg_fatal("unrecognized encoding \"%s\"",
2819  ptr1);
2820  AH->public.encoding = encoding;
2821  }
2822  else
2823  pg_fatal("invalid ENCODING item: %s",
2824  te->defn);
2825 
2826  free(defn);
2827 }
int32 encoding
Definition: pg_database.h:41
#define pg_char_to_encoding
Definition: pg_wchar.h:629

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

Referenced by ReadToc().

◆ processSearchPathEntry()

static void processSearchPathEntry ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 2846 of file pg_backup_archiver.c.

2847 {
2848  /*
2849  * te->defn should contain a command to set search_path. We just copy it
2850  * verbatim for use later.
2851  */
2852  AH->public.searchpath = pg_strdup(te->defn);
2853 }

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

2831 {
2832  /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2833  char *ptr1;
2834 
2835  ptr1 = strchr(te->defn, '\'');
2836  if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2837  AH->public.std_strings = true;
2838  else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2839  AH->public.std_strings = false;
2840  else
2841  pg_fatal("invalid STDSTRINGS item: %s",
2842  te->defn);
2843 }

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

Referenced by ReadToc().

◆ ReadHead()

void ReadHead ( ArchiveHandle AH)

Definition at line 3961 of file pg_backup_archiver.c.

3962 {
3963  char *errmsg;
3964  char vmaj,
3965  vmin,
3966  vrev;
3967  int fmt;
3968 
3969  /*
3970  * If we haven't already read the header, do so.
3971  *
3972  * NB: this code must agree with _discoverArchiveFormat(). Maybe find a
3973  * way to unify the cases?
3974  */
3975  if (!AH->readHeader)
3976  {
3977  char tmpMag[7];
3978 
3979  AH->ReadBufPtr(AH, tmpMag, 5);
3980 
3981  if (strncmp(tmpMag, "PGDMP", 5) != 0)
3982  pg_fatal("did not find magic string in file header");
3983  }
3984 
3985  vmaj = AH->ReadBytePtr(AH);
3986  vmin = AH->ReadBytePtr(AH);
3987 
3988  if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
3989  vrev = AH->ReadBytePtr(AH);
3990  else
3991  vrev = 0;
3992 
3993  AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev);
3994 
3995  if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
3996  pg_fatal("unsupported version (%d.%d) in file header",
3997  vmaj, vmin);
3998 
3999  AH->intSize = AH->ReadBytePtr(AH);
4000  if (AH->intSize > 32)
4001  pg_fatal("sanity check on integer size (%lu) failed",
4002  (unsigned long) AH->intSize);
4003 
4004  if (AH->intSize > sizeof(int))
4005  pg_log_warning("archive was made on a machine with larger integers, some operations might fail");
4006 
4007  if (AH->version >= K_VERS_1_7)
4008  AH->offSize = AH->ReadBytePtr(AH);
4009  else
4010  AH->offSize = AH->intSize;
4011 
4012  fmt = AH->ReadBytePtr(AH);
4013 
4014  if (AH->format != fmt)
4015  pg_fatal("expected format (%d) differs from format found in file (%d)",
4016  AH->format, fmt);
4017 
4018  if (AH->version >= K_VERS_1_15)
4019  AH->compression_spec.algorithm = AH->ReadBytePtr(AH);
4020  else if (AH->version >= K_VERS_1_2)
4021  {
4022  /* Guess the compression method based on the level */
4023  if (AH->version < K_VERS_1_4)
4024  AH->compression_spec.level = AH->ReadBytePtr(AH);
4025  else
4026  AH->compression_spec.level = ReadInt(AH);
4027 
4028  if (AH->compression_spec.level != 0)
4030  }
4031  else
4033 
4035  if (errmsg)
4036  {
4037  pg_log_warning("archive is compressed, but this installation does not support compression (%s) -- no data will be available",
4038  errmsg);
4039  pg_free(errmsg);
4040  }
4041 
4042  if (AH->version >= K_VERS_1_4)
4043  {
4044  struct tm crtm;
4045 
4046  crtm.tm_sec = ReadInt(AH);
4047  crtm.tm_min = ReadInt(AH);
4048  crtm.tm_hour = ReadInt(AH);
4049  crtm.tm_mday = ReadInt(AH);
4050  crtm.tm_mon = ReadInt(AH);
4051  crtm.tm_year = ReadInt(AH);
4052  crtm.tm_isdst = ReadInt(AH);
4053 
4054  /*
4055  * Newer versions of glibc have mktime() report failure if tm_isdst is
4056  * inconsistent with the prevailing timezone, e.g. tm_isdst = 1 when
4057  * TZ=UTC. This is problematic when restoring an archive under a
4058  * different timezone setting. If we get a failure, try again with
4059  * tm_isdst set to -1 ("don't know").
4060  *
4061  * XXX with or without this hack, we reconstruct createDate
4062  * incorrectly when the prevailing timezone is different from
4063  * pg_dump's. Next time we bump the archive version, we should flush
4064  * this representation and store a plain seconds-since-the-Epoch
4065  * timestamp instead.
4066  */
4067  AH->createDate = mktime(&crtm);
4068  if (AH->createDate == (time_t) -1)
4069  {
4070  crtm.tm_isdst = -1;
4071  AH->createDate = mktime(&crtm);
4072  if (AH->createDate == (time_t) -1)
4073  pg_log_warning("invalid creation date in header");
4074  }
4075  }
4076 
4077  if (AH->version >= K_VERS_1_4)
4078  {
4079  AH->archdbname = ReadStr(AH);
4080  }
4081 
4082  if (AH->version >= K_VERS_1_10)
4083  {
4084  AH->archiveRemoteVersion = ReadStr(AH);
4085  AH->archiveDumpVersion = ReadStr(AH);
4086  }
4087 }
char * supports_compression(const pg_compress_specification compression_spec)
Definition: compress_io.c:88
@ 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(), fmt, _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 2124 of file pg_backup_archiver.c.

2125 {
2126  int res = 0;
2127  int bv,
2128  b;
2129  int sign = 0; /* Default positive */
2130  int bitShift = 0;
2131 
2132  if (AH->version > K_VERS_1_0)
2133  /* Read a sign byte */
2134  sign = AH->ReadBytePtr(AH);
2135 
2136  for (b = 0; b < AH->intSize; b++)
2137  {
2138  bv = AH->ReadBytePtr(AH) & 0xFF;
2139  if (bv != 0)
2140  res = res + (bv << bitShift);
2141  bitShift += 8;
2142  }
2143 
2144  if (sign)
2145  res = -res;
2146 
2147  return res;
2148 }
char sign
Definition: informix.c:674
int b
Definition: isn.c:70

References b, _archiveHandle::intSize, K_VERS_1_0, _archiveHandle::ReadBytePtr, res, 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 2029 of file pg_backup_archiver.c.

2030 {
2031  int i;
2032  int off;
2033  int offsetFlg;
2034 
2035  /* Initialize to zero */
2036  *o = 0;
2037 
2038  /* Check for old version */
2039  if (AH->version < K_VERS_1_7)
2040  {
2041  /* Prior versions wrote offsets using WriteInt */
2042  i = ReadInt(AH);
2043  /* -1 means not set */
2044  if (i < 0)
2045  return K_OFFSET_POS_NOT_SET;
2046  else if (i == 0)
2047  return K_OFFSET_NO_DATA;
2048 
2049  /* Cast to pgoff_t because it was written as an int. */
2050  *o = (pgoff_t) i;
2051  return K_OFFSET_POS_SET;
2052  }
2053 
2054  /*
2055  * Read the flag indicating the state of the data pointer. Check if valid
2056  * and die if not.
2057  *
2058  * This used to be handled by a negative or zero pointer, now we use an
2059  * extra byte specifically for the state.
2060  */
2061  offsetFlg = AH->ReadBytePtr(AH) & 0xFF;
2062 
2063  switch (offsetFlg)
2064  {
2065  case K_OFFSET_POS_NOT_SET:
2066  case K_OFFSET_NO_DATA:
2067  case K_OFFSET_POS_SET:
2068 
2069  break;
2070 
2071  default:
2072  pg_fatal("unexpected data offset flag %d", offsetFlg);
2073  }
2074 
2075  /*
2076  * Read the bytes
2077  */
2078  for (off = 0; off < AH->offSize; off++)
2079  {
2080  if (off < sizeof(pgoff_t))
2081  *o |= ((pgoff_t) (AH->ReadBytePtr(AH))) << (off * 8);
2082  else
2083  {
2084  if (AH->ReadBytePtr(AH) != 0)
2085  pg_fatal("file offset in dump file is too large");
2086  }
2087  }
2088 
2089  return offsetFlg;
2090 }
#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 2170 of file pg_backup_archiver.c.

2171 {
2172  char *buf;
2173  int l;
2174 
2175  l = ReadInt(AH);
2176  if (l < 0)
2177  buf = NULL;
2178  else
2179  {
2180  buf = (char *) pg_malloc(l + 1);
2181  AH->ReadBufPtr(AH, (void *) buf, l);
2182 
2183  buf[l] = '\0';
2184  }
2185 
2186  return buf;
2187 }

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

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

◆ ReadToc()

void ReadToc ( ArchiveHandle AH)

Definition at line 2630 of file pg_backup_archiver.c.

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

4889 {
4890  int i;
4891 
4892  pg_log_debug("reducing dependencies for %d", te->dumpId);
4893 
4894  for (i = 0; i < te->nRevDeps; i++)
4895  {
4896  TocEntry *otherte = AH->tocsByDumpId[te->revDeps[i]];
4897 
4898  Assert(otherte->depCount > 0);
4899  otherte->depCount--;
4900 
4901  /*
4902  * It's ready if it has no remaining dependencies, and it belongs in
4903  * the current restore pass, and it is currently a member of the
4904  * pending list (that check is needed to prevent double restore in
4905  * some cases where a list-file forces out-of-order restoring).
4906  * However, if ready_heap == NULL then caller doesn't want any list
4907  * memberships changed.
4908  */
4909  if (otherte->depCount == 0 &&
4910  _tocEntryRestorePass(otherte) == AH->restorePass &&
4911  otherte->pending_prev != NULL &&
4912  ready_heap != NULL)
4913  {
4914  /* Remove it from pending list ... */
4915  pending_list_remove(otherte);
4916  /* ... and add to ready_heap */
4917  binaryheap_add(ready_heap, otherte);
4918  }
4919  }
4920 }
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 4789 of file pg_backup_archiver.c.

4790 {
4791  TocEntry *te;
4792  int i;
4793  DumpId olddep;
4794 
4795  for (te = AH->toc->next; te != AH->toc; te = te->next)
4796  {
4797  if (te->section != SECTION_POST_DATA)
4798  continue;
4799  for (i = 0; i < te->nDeps; i++)
4800  {
4801  olddep = te->dependencies[i];
4802  if (olddep <= AH->maxDumpId &&
4803  AH->tableDataId[olddep] != 0)
4804  {
4805  DumpId tabledataid = AH->tableDataId[olddep];
4806  TocEntry *tabledatate = AH->tocsByDumpId[tabledataid];
4807 
4808  te->dependencies[i] = tabledataid;
4809  te->dataLength = Max(te->dataLength, tabledatate->dataLength);
4810  pg_log_debug("transferring dependency %d -> %d to %d",
4811  te->dumpId, olddep, tabledataid);
4812  }
4813  }
4814  }
4815 }
#define Max(x, y)
Definition: c.h:998

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

4263 {
4264  binaryheap *ready_heap;
4265  TocEntry *next_work_item;
4266 
4267  pg_log_debug("entering restore_toc_entries_parallel");
4268 
4269  /* Set up ready_heap with enough room for all known TocEntrys */
4270  ready_heap = binaryheap_allocate(AH->tocCount,
4272  NULL);
4273 
4274  /*
4275  * The pending_list contains all items that we need to restore. Move all
4276  * items that are available to process immediately into the ready_heap.
4277  * After this setup, the pending list is everything that needs to be done
4278  * but is blocked by one or more dependencies, while the ready heap
4279  * contains items that have no remaining dependencies and are OK to
4280  * process in the current restore pass.
4281  */
4283  move_to_ready_heap(pending_list, ready_heap, AH->restorePass);
4284 
4285  /*
4286  * main parent loop
4287  *
4288  * Keep going until there is no worker still running AND there is no work
4289  * left to be done. Note invariant: at top of loop, there should always
4290  * be at least one worker available to dispatch a job to.
4291  */
4292  pg_log_info("entering main parallel loop");
4293 
4294  for (;;)
4295  {
4296  /* Look for an item ready to be dispatched to a worker */
4297  next_work_item = pop_next_work_item(ready_heap, pstate);
4298  if (next_work_item != NULL)
4299  {
4300  /* If not to be restored, don't waste time launching a worker */
4301  if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA)) == 0)
4302  {
4303  pg_log_info("skipping item %d %s %s",
4304  next_work_item->dumpId,
4305  next_work_item->desc, next_work_item->tag);
4306  /* Update its dependencies as though we'd completed it */
4307  reduce_dependencies(AH, next_work_item, ready_heap);
4308  /* Loop around to see if anything else can be dispatched */
4309  continue;
4310  }
4311 
4312  pg_log_info("launching item %d %s %s",
4313  next_work_item->dumpId,
4314  next_work_item->desc, next_work_item->tag);
4315 
4316  /* Dispatch to some worker */
4317  DispatchJobForTocEntry(AH, pstate, next_work_item, ACT_RESTORE,
4318  mark_restore_job_done, ready_heap);
4319  }
4320  else if (IsEveryWorkerIdle(pstate))
4321  {
4322  /*
4323  * Nothing is ready and no worker is running, so we're done with
4324  * the current pass or maybe with the whole process.
4325  */
4326  if (AH->restorePass == RESTORE_PASS_LAST)
4327  break; /* No more parallel processing is possible */
4328 
4329  /* Advance to next restore pass */
4330  AH->restorePass++;
4331  /* That probably allows some stuff to be made ready */
4332  move_to_ready_heap(pending_list, ready_heap, AH->restorePass);
4333  /* Loop around to see if anything's now ready */
4334  continue;
4335  }
4336  else
4337  {
4338  /*
4339  * We have nothing ready, but at least one child is working, so
4340  * wait for some subjob to finish.
4341  */
4342  }
4343 
4344  /*
4345  * Before dispatching another job, check to see if anything has
4346  * finished. We should check every time through the loop so as to
4347  * reduce dependencies as soon as possible. If we were unable to
4348  * dispatch any job this time through, wait until some worker finishes
4349  * (and, hopefully, unblocks some pending item). If we did dispatch
4350  * something, continue as soon as there's at least one idle worker.
4351  * Note that in either case, there's guaranteed to be at least one
4352  * idle worker when we return to the top of the loop. This ensures we
4353  * won't block inside DispatchJobForTocEntry, which would be
4354  * undesirable: we'd rather postpone dispatching until we see what's
4355  * been unblocked by finished jobs.
4356  */
4357  WaitForWorkers(AH, pstate,
4358  next_work_item ? WFW_ONE_IDLE : WFW_GOT_STATUS);
4359  }
4360 
4361  /* There should now be nothing in ready_heap. */
4362  Assert(binaryheap_empty(ready_heap));
4363 
4364  binaryheap_free(ready_heap);
4365 
4366  pg_log_info("finished main parallel loop");
4367 }
void WaitForWorkers(ArchiveHandle *AH, ParallelState *pstate, WFW_WaitOption mode)
Definition: parallel.c:1451
void DispatchJobForTocEntry(ArchiveHandle *AH, ParallelState *pstate, TocEntry *te, T_Action act, ParallelCompletionPtr callback, void *callback_data)
Definition: parallel.c:1205
bool IsEveryWorkerIdle(ParallelState *pstate)
Definition: parallel.c:1268
@ WFW_GOT_STATUS
Definition: parallel.h:33
@ WFW_ONE_IDLE
Definition: parallel.h:34
binaryheap * binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
Definition: binaryheap.c:39
void binaryheap_free(binaryheap *heap)
Definition: binaryheap.c:75
#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, _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 4379 of file pg_backup_archiver.c.

4380 {
4381  RestoreOptions *ropt = AH->public.ropt;
4382  TocEntry *te;
4383 
4384  pg_log_debug("entering restore_toc_entries_postfork");
4385 
4386  /*
4387  * Now reconnect the single parent connection.
4388  */
4389  ConnectDatabase((Archive *) AH, &ropt->cparams, true);
4390 
4391  /* re-establish fixed state */
4393 
4394  /*
4395  * Make sure there is no work left due to, say, circular dependencies, or
4396  * some other pathological condition. If so, do it in the single parent
4397  * connection. We don't sweat about RestorePass ordering; it's likely we
4398  * already violated that.
4399  */
4400  for (te = pending_list->pending_next; te != pending_list; te = te->pending_next)
4401  {
4402  pg_log_info("processing missed item %d %s %s",
4403  te->dumpId, te->desc, te->tag);
4404  (void) restore_toc_entry(AH, te, false);
4405  }
4406 }

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

4139 {
4140  bool skipped_some;
4141  TocEntry *next_work_item;
4142 
4143  pg_log_debug("entering restore_toc_entries_prefork");
4144 
4145  /* Adjust dependency information */
4146  fix_dependencies(AH);
4147 
4148  /*
4149  * Do all the early stuff in a single connection in the parent. There's no
4150  * great point in running it in parallel, in fact it will actually run
4151  * faster in a single connection because we avoid all the connection and
4152  * setup overhead. Also, pre-9.2 pg_dump versions were not very good
4153  * about showing all the dependencies of SECTION_PRE_DATA items, so we do
4154  * not risk trying to process them out-of-order.
4155  *
4156  * Stuff that we can't do immediately gets added to the pending_list.
4157  * Note: we don't yet filter out entries that aren't going to be restored.
4158  * They might participate in dependency chains connecting entries that
4159  * should be restored, so we treat them as live until we actually process
4160  * them.
4161  *
4162  * Note: as of 9.2, it should be guaranteed that all PRE_DATA items appear
4163  * before DATA items, and all DATA items before POST_DATA items. That is
4164  * not certain to be true in older archives, though, and in any case use
4165  * of a list file would destroy that ordering (cf. SortTocFromFile). So
4166  * this loop cannot assume that it holds.
4167  */
4169  skipped_some = false;
4170  for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
4171  {
4172  bool do_now = true;
4173 
4174  if (next_work_item->section != SECTION_PRE_DATA)
4175  {
4176  /* DATA and POST_DATA items are just ignored for now */
4177  if (next_work_item->section == SECTION_DATA ||
4178  next_work_item->section == SECTION_POST_DATA)
4179  {
4180  do_now = false;
4181  skipped_some = true;
4182  }
4183  else
4184  {
4185  /*
4186  * SECTION_NONE items, such as comments, can be processed now
4187  * if we are still in the PRE_DATA part of the archive. Once
4188  * we've skipped any items, we have to consider whether the
4189  * comment's dependencies are satisfied, so skip it for now.
4190  */
4191  if (skipped_some)
4192  do_now = false;
4193  }
4194  }
4195 
4196  /*
4197  * Also skip items that need to be forced into later passes. We need
4198  * not set skipped_some in this case, since by assumption no main-pass
4199  * items could depend on these.
4200  */
4201  if (_tocEntryRestorePass(next_work_item) != RESTORE_PASS_MAIN)
4202  do_now = false;
4203 
4204  if (do_now)
4205  {
4206  /* OK, restore the item and update its dependencies */
4207  pg_log_info("processing item %d %s %s",
4208  next_work_item->dumpId,
4209  next_work_item->desc, next_work_item->tag);
4210 
4211  (void) restore_toc_entry(AH, next_work_item, false);
4212 
4213  /* Reduce dependencies, but don't move anything to ready_heap */
4214  reduce_dependencies(AH, next_work_item, NULL);
4215  }
4216  else
4217  {
4218  /* Nope, so add it to pending_list */
4219  pending_list_append(pending_list, next_work_item);
4220  }
4221  }
4222 
4223  /*
4224  * In --transaction-size mode, we must commit the open transaction before
4225  * dropping the database connection. This also ensures that child workers
4226  * can see the objects we've created so far.
4227  */
4228  if (AH->public.ropt->txn_size > 0)
4229  CommitTransaction(&AH->public);
4230 
4231  /*
4232  * Now close parent connection in prep for parallel steps. We do this
4233  * mainly to ensure that we don't exceed the specified number of parallel
4234  * connections.
4235  */
4236  DisconnectDatabase(&AH->public);
4237 
4238  /* blow away any transient state from the old connection */
4239  free(AH->currUser);
4240  AH->currUser = NULL;
4241  free(AH->currSchema);
4242  AH->currSchema = NULL;
4243  free(AH->currTablespace);
4244  AH->currTablespace = NULL;
4245  free(AH->currTableAm);
4246  AH->currTableAm = NULL;
4247 }
void DisconnectDatabase(Archive *AHX)
Definition: pg_backup_db.c:225
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 815 of file pg_backup_archiver.c.

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

References _becomeOwner(), _disableTriggersIfNecessary(), _enableTriggersIfNecessary(), _printTocEntry(), _reconnectToDB(), _selectOutputSchema(), ahprintf(), CommitTransaction(), _archiveHandle::connection, _tocEntry::copyStmt, _tocEntry::created, _archiveHandle::currentTE, _restoreOptions::dataOnly, _tocEntry::defn, _tocEntry::desc, 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, _tocEntry::reqs, RestoringToDB(), Archive::ropt, StartTransaction(), _restoreOptions::suppressDumpWarnings, _tocEntry::tag, _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 334 of file pg_backup_archiver.c.

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

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, _restoreOptions::dataOnly, _tocEntry::desc, destroyPQExpBuffer(), DisconnectDatabase(), DropLOIfExists(), _restoreOptions::dropSchema, _tocEntry::dropStmt, 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, _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 1702 of file pg_backup_archiver.c.

1703 {
1704  errno = 0;
1705  if (!EndCompressFileHandle(AH->OF))
1706  pg_fatal("could not close output file: %m");
1707 
1708  AH->OF = savedOutput;
1709 }

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

Referenced by PrintTOCSummary(), and RestoreArchive().

◆ RestoringToDB()

static int RestoringToDB ( ArchiveHandle AH)
static

◆ sanitize_line()

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

Definition at line 3912 of file pg_backup_archiver.c.

3913 {
3914  char *result;
3915  char *s;
3916 
3917  if (!str)
3918  return pg_strdup(want_hyphen ? "-" : "");
3919 
3920  result = pg_strdup(str);
3921 
3922  for (s = result; *s != '\0'; s++)
3923  {
3924  if (*s == '\n' || *s == '\r')
3925  *s = ' ';
3926  }
3927 
3928  return result;
3929 }
const char * str

References pg_strdup(), and str.

Referenced by _printTocEntry(), and PrintTOCSummary().

◆ SaveOutput()

static CompressFileHandle * SaveOutput ( ArchiveHandle AH)
static

Definition at line 1696 of file pg_backup_archiver.c.

1697 {
1698  return (CompressFileHandle *) AH->OF;
1699 }

References _archiveHandle::OF.

Referenced by PrintTOCSummary(), and RestoreArchive().

◆ SetArchiveOptions()

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

Definition at line 266 of file pg_backup_archiver.c.

267 {
268  /* Caller can omit dump options, in which case we synthesize them */
269  if (dopt == NULL && ropt != NULL)
270  dopt = dumpOptionsFromRestoreOptions(ropt);
271 
272  /* Save options for later access */
273  AH->dopt = dopt;
274  AH->ropt = ropt;
275 }
DumpOptions * dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
DumpOptions * dopt
Definition: pg_backup.h:214

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

1658 {
1659  CompressFileHandle *CFH;
1660  const char *mode;
1661  int fn = -1;
1662 
1663  if (filename)
1664  {
1665  if (strcmp(filename, "-") == 0)
1666  fn = fileno(stdout);
1667  }
1668  else if (AH->FH)
1669  fn = fileno(AH->FH);
1670  else if (AH->fSpec)
1671  {
1672  filename = AH->fSpec;
1673  }
1674  else
1675  fn = fileno(stdout);
1676 
1677  if (AH->mode == archModeAppend)
1678  mode = PG_BINARY_A;
1679  else
1680  mode = PG_BINARY_W;
1681 
1682  CFH = InitCompressFileHandle(compression_spec);
1683 
1684  if (!CFH->open_func(filename, fn, mode, CFH))
1685  {
1686  if (filename)
1687  pg_fatal("could not open output file \"%s\": %m", filename);
1688  else
1689  pg_fatal("could not open output file: %m");
1690  }
1691 
1692  AH->OF = CFH;
1693 }
#define PG_BINARY_W
Definition: c.h:1276
@ 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 210 of file pg_backup_archiver.c.

211 {
212  ArchiveHandle *AH = (ArchiveHandle *) AHX;
213 
214  AH->ReopenPtr(AH);
215 }

References _archiveHandle::ReopenPtr.

Referenced by OpenArchive().

◆ SortTocFromFile()

void SortTocFromFile ( Archive AHX)

Definition at line 1529 of file pg_backup_archiver.c.

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

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

1375 {
1376  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1377 
1378  if (!AH->StartLOPtr)
1379  pg_fatal("large-object output not supported in chosen format");
1380 
1381  AH->StartLOPtr(AH, AH->currToc, oid);
1382 
1383  return 1;
1384 }
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 1453 of file pg_backup_archiver.c.

1454 {
1455  bool old_lo_style = (AH->version < K_VERS_1_12);
1456  Oid loOid;
1457 
1458  AH->loCount++;
1459 
1460  /* Initialize the LO Buffer */
1461  if (AH->lo_buf == NULL)
1462  {
1463  /* First time through (in this process) so allocate the buffer */
1464  AH->lo_buf_size = LOBBUFSIZE;
1465  AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE);
1466  }
1467  AH->lo_buf_used = 0;
1468 
1469  pg_log_info("restoring large object with OID %u", oid);
1470 
1471  /* With an old archive we must do drop and create logic here */
1472  if (old_lo_style && drop)
1473  DropLOIfExists(AH, oid);
1474 
1475  if (AH->connection)
1476  {
1477  if (old_lo_style)
1478  {
1479  loOid = lo_create(AH->connection, oid);
1480  if (loOid == 0 || loOid != oid)
1481  pg_fatal("could not create large object %u: %s",
1482  oid, PQerrorMessage(AH->connection));
1483  }
1484  AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
1485  if (AH->loFd == -1)
1486  pg_fatal("could not open large object %u: %s",
1487  oid, PQerrorMessage(AH->connection));
1488  }
1489  else
1490  {
1491  if (old_lo_style)
1492  ahprintf(AH, "SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n",
1493  oid, INV_WRITE);
1494  else
1495  ahprintf(AH, "SELECT pg_catalog.lo_open('%u', %d);\n",
1496  oid, INV_WRITE);
1497  }
1498 
1499  AH->writingLO = true;
1500 }
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:31

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

1407 {
1408  RestoreOptions *ropt = AH->public.ropt;
1409 
1410  /*
1411  * LOs must be restored within a transaction block, since we need the LO
1412  * handle to stay open while we write it. Establish a transaction unless
1413  * there's one being used globally.
1414  */
1415  if (!(ropt->single_txn || ropt->txn_size > 0))
1416  {
1417  if (AH->connection)
1418  StartTransaction(&AH->public);
1419  else
1420  ahprintf(AH, "BEGIN;\n\n");
1421  }
1422 
1423  AH->loCount = 0;
1424 }

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

2857 {
2858  const char *missing_name;
2859 
2860  Assert(ropt->strict_names);
2861 
2862  if (ropt->schemaNames.head != NULL)
2863  {
2864  missing_name = simple_string_list_not_touched(&ropt->schemaNames);
2865  if (missing_name != NULL)
2866  pg_fatal("schema \"%s\" not found", missing_name);
2867  }
2868 
2869  if (ropt->tableNames.head != NULL)
2870  {
2871  missing_name = simple_string_list_not_touched(&ropt->tableNames);
2872  if (missing_name != NULL)
2873  pg_fatal("table \"%s\" not found", missing_name);
2874  }
2875 
2876  if (ropt->indexNames.head != NULL)
2877  {
2878  missing_name = simple_string_list_not_touched(&ropt->indexNames);
2879  if (missing_name != NULL)
2880  pg_fatal("index \"%s\" not found", missing_name);
2881  }
2882 
2883  if (ropt->functionNames.head != NULL)
2884  {
2885  missing_name = simple_string_list_not_touched(&ropt->functionNames);
2886  if (missing_name != NULL)
2887  pg_fatal("function \"%s\" not found", missing_name);
2888  }
2889 
2890  if (ropt->triggerNames.head != NULL)
2891  {
2892  missing_name = simple_string_list_not_touched(&ropt->triggerNames);
2893  if (missing_name != NULL)
2894  pg_fatal("trigger \"%s\" not found", missing_name);
2895  }
2896 }
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 4488 of file pg_backup_archiver.c.

4489 {
4490  /* return opposite of qsort comparator for max-heap */
4491  return -TocEntrySizeCompareQsort(&p1, &p2);
4492 }
static int TocEntrySizeCompareQsort(const void *p1, const void *p2)

References p2, and TocEntrySizeCompareQsort().

Referenced by restore_toc_entries_parallel().

◆ TocEntrySizeCompareQsort()

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

Definition at line 4466 of file pg_backup_archiver.c.

4467 {
4468  const TocEntry *te1 = *(const TocEntry *const *) p1;
4469  const TocEntry *te2 = *(const TocEntry *const *) p2;
4470 
4471  /* Sort by decreasing dataLength */
4472  if (te1->dataLength > te2->dataLength)
4473  return -1;
4474  if (te1->dataLength < te2->dataLength)
4475  return 1;
4476 
4477  /* For equal dataLengths, sort by dumpId, just to be stable */
4478  if (te1->dumpId < te2->dumpId)
4479  return -1;
4480  if (te1->dumpId > te2->dumpId)
4481  return 1;
4482 
4483  return 0;
4484 }

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

Referenced by TocEntrySizeCompareBinaryheap(), and WriteDataChunks().

◆ TocIDRequired()

int TocIDRequired ( ArchiveHandle AH,
DumpId  id 
)

Definition at line 2001 of file pg_backup_archiver.c.

2002 {
2003  TocEntry *te = getTocEntryByDumpId(AH, id);
2004 
2005  if (!te)
2006  return 0;
2007 
2008  return te->reqs;
2009 }

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

1856 {
1857  va_list ap;
1858 
1859  switch (AH->stage)
1860  {
1861 
1862  case STAGE_NONE:
1863  /* Do nothing special */
1864  break;
1865 
1866  case STAGE_INITIALIZING:
1867  if (AH->stage != AH->lastErrorStage)
1868  pg_log_info("while INITIALIZING:");
1869  break;
1870 
1871  case STAGE_PROCESSING:
1872  if (AH->stage != AH->lastErrorStage)
1873  pg_log_info("while PROCESSING TOC:");
1874  break;
1875 
1876  case STAGE_FINALIZING:
1877  if (AH->stage != AH->lastErrorStage)
1878  pg_log_info("while FINALIZING:");
1879  break;
1880  }
1881  if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE)
1882  {
1883  pg_log_info("from TOC entry %d; %u %u %s %s %s",
1884  AH->currentTE->dumpId,
1886  AH->currentTE->catalogId.oid,
1887  AH->currentTE->desc ? AH->currentTE->desc : "(no desc)",
1888  AH->currentTE->tag ? AH->currentTE->tag : "(no tag)",
1889  AH->currentTE->owner ? AH->currentTE->owner : "(no owner)");
1890  }
1891  AH->lastErrorStage = AH->stage;
1892  AH->lastErrorTE = AH->currentTE;
1893 
1894  va_start(ap, fmt);
1896  va_end(ap);
1897 
1898  if (AH->public.exit_on_error)
1899  exit_nicely(1);
1900  else
1901  AH->public.n_errors++;
1902 }
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:218
@ PG_LOG_PRIMARY
Definition: logging.h:67
@ PG_LOG_ERROR
Definition: logging.h:43
@ STAGE_NONE
#define exit_nicely(code)
Definition: pg_dumpall.c:124
ArchiverStage lastErrorStage

References _tocEntry::catalogId, _archiveHandle::currentTE, _tocEntry::desc, _tocEntry::dumpId, exit_nicely, Archive::exit_on_error, fmt, _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, _tocEntry::tag, va_end(), and va_start().

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

1183 {
1184  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1185 
1186  if (!AH->currToc)
1187  pg_fatal("internal error -- WriteData cannot be called outside the context of a DataDumper routine");
1188 
1189  AH->WriteDataPtr(AH, data, dLen);
1190 }
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 2456 of file pg_backup_archiver.c.

2457 {
2458  TocEntry *te;
2459 
2460  if (pstate && pstate->numWorkers > 1)
2461  {
2462  /*
2463  * In parallel mode, this code runs in the leader process. We
2464  * construct an array of candidate TEs, then sort it into decreasing
2465  * size order, then dispatch each TE to a data-transfer worker. By
2466  * dumping larger tables first, we avoid getting into a situation
2467  * where we're down to one job and it's big, losing parallelism.
2468  */
2469  TocEntry **tes;
2470  int ntes;
2471 
2472  tes = (TocEntry **) pg_malloc(AH->tocCount * sizeof(TocEntry *));
2473  ntes = 0;
2474  for (te = AH->toc->next; te != AH->toc; te = te->next)
2475  {
2476  /* Consider only TEs with dataDumper functions ... */
2477  if (!te->dataDumper)
2478  continue;
2479  /* ... and ignore ones not enabled for dump */
2480  if ((te->reqs & REQ_DATA) == 0)
2481  continue;
2482 
2483  tes[ntes++] = te;
2484  }
2485 
2486  if (ntes > 1)
2487  qsort(tes, ntes, sizeof(TocEntry *), TocEntrySizeCompareQsort);
2488 
2489  for (int i = 0; i < ntes; i++)
2490  DispatchJobForTocEntry(AH, pstate, tes[i], ACT_DUMP,
2491  mark_dump_job_done, NULL);
2492 
2493  pg_free(tes);
2494 
2495  /* Now wait for workers to finish. */
2496  WaitForWorkers(AH, pstate, WFW_ALL_IDLE);
2497  }
2498  else
2499  {
2500  /* Non-parallel mode: just dump all candidate TEs sequentially. */
2501  for (te = AH->toc->next; te != AH->toc; te = te->next)
2502  {
2503  /* Must have same filter conditions as above */
2504  if (!te->dataDumper)
2505  continue;
2506  if ((te->reqs & REQ_DATA) == 0)
2507  continue;
2508 
2510  }
2511  }
2512 }
@ 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:453

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

2538 {
2539  StartDataPtrType startPtr;
2540  EndDataPtrType endPtr;
2541 
2542  AH->currToc = te;
2543 
2544  if (strcmp(te->desc, "BLOBS") == 0)
2545  {
2546  startPtr = AH->StartLOsPtr;
2547  endPtr = AH->EndLOsPtr;
2548  }
2549  else
2550  {
2551  startPtr = AH->StartDataPtr;
2552  endPtr = AH->EndDataPtr;
2553  }
2554 
2555  if (startPtr != NULL)
2556  (*startPtr) (AH, te);
2557 
2558  /*
2559  * The user-provided DataDumper routine needs to call AH->WriteData
2560  */
2561  te->dataDumper((Archive *) AH, te->dataDumperArg);
2562 
2563  if (endPtr != NULL)
2564  (*endPtr) (AH, te);
2565 
2566  AH->currToc = NULL;
2567 }
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 3935 of file pg_backup_archiver.c.

3936 {
3937  struct tm crtm;
3938 
3939  AH->WriteBufPtr(AH, "PGDMP", 5); /* Magic code */
3940  AH->WriteBytePtr(AH, ARCHIVE_MAJOR(AH->version));
3941  AH->WriteBytePtr(AH, ARCHIVE_MINOR(AH->version));
3942  AH->WriteBytePtr(AH, ARCHIVE_REV(AH->version));
3943  AH->WriteBytePtr(AH, AH->intSize);
3944  AH->WriteBytePtr(AH, AH->offSize);
3945  AH->WriteBytePtr(AH, AH->format);
3947  crtm = *localtime(&AH->createDate);
3948  WriteInt(AH, crtm.tm_sec);
3949  WriteInt(AH, crtm.tm_min);
3950  WriteInt(AH, crtm.tm_hour);
3951  WriteInt(AH, crtm.tm_mday);
3952  WriteInt(AH, crtm.tm_mon);
3953  WriteInt(AH, crtm.tm_year);
3954  WriteInt(AH, crtm.tm_isdst);
3955  WriteStr(AH, PQdb(AH->connection));
3956  WriteStr(AH, AH->public.remoteVersionStr);
3957  WriteStr(AH, PG_VERSION);
3958 }
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:7017
size_t WriteInt(ArchiveHandle *AH, int i)
size_t WriteStr(ArchiveHandle *AH, const char *c)
char * remoteVersionStr
Definition: pg_backup.h:218
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 2093 of file pg_backup_archiver.c.

2094 {
2095  int b;
2096 
2097  /*
2098  * This is a bit yucky, but I don't want to make the binary format very
2099  * dependent on representation, and not knowing much about it, I write out
2100  * a sign byte. If you change this, don't forget to change the file
2101  * version #, and modify ReadInt to read the new format AS WELL AS the old
2102  * formats.
2103  */
2104 
2105  /* SIGN byte */
2106  if (i < 0)
2107  {
2108  AH->WriteBytePtr(AH, 1);
2109  i = -i;
2110  }
2111  else
2112  AH->WriteBytePtr(AH, 0);
2113 
2114  for (b = 0; b < AH->intSize; b++)
2115  {
2116  AH->WriteBytePtr(AH, i & 0xFF);
2117  i >>= 8;
2118  }
2119 
2120  return AH->intSize + 1;
2121 }

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

2013 {
2014  int off;
2015 
2016  /* Save the flag */
2017  AH->WriteBytePtr(AH, wasSet);
2018 
2019  /* Write out pgoff_t smallest byte first, prevents endian mismatch */
2020  for (off = 0; off < sizeof(pgoff_t); off++)
2021  {
2022  AH->WriteBytePtr(AH, o & 0xFF);
2023  o >>= 8;
2024  }
2025  return sizeof(pgoff_t) + 1;
2026 }

References pgoff_t, and _archiveHandle::WriteBytePtr.

Referenced by _WriteExtraToc().

◆ WriteStr()

size_t WriteStr ( ArchiveHandle AH,
const char *  c 
)

Definition at line 2151 of file pg_backup_archiver.c.

2152 {
2153  size_t res;
2154 
2155  if (c)
2156  {
2157  int len = strlen(c);
2158 
2159  res = WriteInt(AH, len);
2160  AH->WriteBufPtr(AH, c, len);
2161  res += len;
2162  }
2163  else
2164  res = WriteInt(AH, -1);
2165 
2166  return res;
2167 }
char * c

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

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

◆ WriteToc()

void WriteToc ( ArchiveHandle AH)

Definition at line 2570 of file pg_backup_archiver.c.

2571 {
2572  TocEntry *te;
2573  char workbuf[32];
2574  int tocCount;
2575  int i;
2576 
2577  /* count entries that will actually be dumped */
2578  tocCount = 0;
2579  for (te = AH->toc->next; te != AH->toc; te = te->next)
2580  {
2581  if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) != 0)
2582  tocCount++;
2583  }
2584 
2585  /* printf("%d TOC Entries to save\n", tocCount); */
2586 
2587  WriteInt(AH, tocCount);
2588 
2589  for (te = AH->toc->next; te != AH->toc; te = te->next)
2590  {
2591  if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) == 0)
2592  continue;
2593 
2594  WriteInt(AH, te->dumpId);
2595  WriteInt(AH, te->dataDumper ? 1 : 0);
2596 
2597  /* OID is recorded as a string for historical reasons */
2598  sprintf(workbuf, "%u", te->catalogId.tableoid);
2599  WriteStr(AH, workbuf);
2600  sprintf(workbuf, "%u", te->catalogId.oid);
2601  WriteStr(AH, workbuf);
2602 
2603  WriteStr(AH, te->tag);
2604  WriteStr(AH, te->desc);
2605  WriteInt(AH, te->section);
2606  WriteStr(AH, te->defn);
2607  WriteStr(AH, te->dropStmt);
2608  WriteStr(AH, te->copyStmt);
2609  WriteStr(AH, te->namespace);
2610  WriteStr(AH, te->tablespace);
2611  WriteStr(AH, te->tableam);
2612  WriteInt(AH, te->relkind);
2613  WriteStr(AH, te->owner);
2614  WriteStr(AH, "false");
2615 
2616  /* Dump list of dependencies */
2617  for (i = 0; i < te->nDeps; i++)
2618  {
2619  sprintf(workbuf, "%d", te->dependencies[i]);
2620  WriteStr(AH, workbuf);
2621  }
2622  WriteStr(AH, NULL); /* Terminate List */
2623 
2624  if (AH->WriteExtraTocPtr)
2625  AH->WriteExtraTocPtr(AH, te);
2626  }
2627 }
#define sprintf
Definition: port.h:240
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, _tocEntry::reqs, _tocEntry::section, sprintf, _tocEntry::tableam, CatalogId::tableoid, _tocEntry::tablespace, _tocEntry::tag, _archiveHandle::toc, _archiveHandle::WriteExtraTocPtr, WriteInt(), and WriteStr().

Referenced by _CloseArchive().