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

◆ TEXT_DUMPALL_HEADER

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

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

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

3399 {
3400  RestoreOptions *ropt = AH->public.ropt;
3401 
3402  if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
3403  return;
3404 
3405  _becomeUser(AH, te->owner);
3406 }
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 3375 of file pg_backup_archiver.c.

3376 {
3377  if (!user)
3378  user = ""; /* avoid null pointers */
3379 
3380  if (AH->currUser && strcmp(AH->currUser, user) == 0)
3381  return; /* no need to do anything */
3382 
3383  _doSetSessionAuth(AH, user);
3384 
3385  /*
3386  * NOTE: currUser keeps track of what the imaginary session user in our
3387  * script is
3388  */
3389  free(AH->currUser);
3390  AH->currUser = pg_strdup(user);
3391 }
#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 1085 of file pg_backup_archiver.c.

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

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

3225 {
3226  RestoreOptions *ropt = AH->public.ropt;
3227 
3228  /*
3229  * Disable timeouts to allow for slow commands, idle parallel workers, etc
3230  */
3231  ahprintf(AH, "SET statement_timeout = 0;\n");
3232  ahprintf(AH, "SET lock_timeout = 0;\n");
3233  ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
3234  ahprintf(AH, "SET transaction_timeout = 0;\n");
3235 
3236  /* Select the correct character set encoding */
3237  ahprintf(AH, "SET client_encoding = '%s';\n",
3239 
3240  /* Select the correct string literal syntax */
3241  ahprintf(AH, "SET standard_conforming_strings = %s;\n",
3242  AH->public.std_strings ? "on" : "off");
3243 
3244  /* Select the role to be used during restore */
3245  if (ropt && ropt->use_role)
3246  ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));
3247 
3248  /* Select the dump-time search_path */
3249  if (AH->public.searchpath)
3250  ahprintf(AH, "%s", AH->public.searchpath);
3251 
3252  /* Make sure function checking is disabled */
3253  ahprintf(AH, "SET check_function_bodies = false;\n");
3254 
3255  /* Ensure that all valid XML data will be accepted */
3256  ahprintf(AH, "SET xmloption = content;\n");
3257 
3258  /* Avoid annoying notices etc */
3259  ahprintf(AH, "SET client_min_messages = warning;\n");
3260  if (!AH->public.std_strings)
3261  ahprintf(AH, "SET escape_string_warning = off;\n");
3262 
3263  /* Adjust row-security state */
3264  if (ropt && ropt->enable_row_security)
3265  ahprintf(AH, "SET row_security = on;\n");
3266  else
3267  ahprintf(AH, "SET row_security = off;\n");
3268 
3269  /*
3270  * In --transaction-size mode, we should always be in a transaction when
3271  * we begin to restore objects.
3272  */
3273  if (ropt && ropt->txn_size > 0)
3274  {
3275  if (AH->connection)
3276  StartTransaction(&AH->public);
3277  else
3278  ahprintf(AH, "\nBEGIN;\n");
3279  AH->txnCount = 0;
3280  }
3281 
3282  ahprintf(AH, "\n");
3283 }
#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:2014

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

3292 {
3294 
3295  appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3296 
3297  /*
3298  * SQL requires a string literal here. Might as well be correct.
3299  */
3300  if (user && *user)
3301  appendStringLiteralAHX(cmd, user, AH);
3302  else
3303  appendPQExpBufferStr(cmd, "DEFAULT");
3304  appendPQExpBufferChar(cmd, ';');
3305 
3306  if (RestoringToDB(AH))
3307  {
3308  PGresult *res;
3309 
3310  res = PQexec(AH->connection, cmd->data);
3311 
3312  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3313  /* NOT warn_or_exit_horribly... use -O instead to skip this. */
3314  pg_fatal("could not set session user to \"%s\": %s",
3316 
3317  PQclear(res);
3318  }
3319  else
3320  ahprintf(AH, "%s\n\n", cmd->data);
3321 
3322  destroyPQExpBuffer(cmd);
3323 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7141
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:100
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 1111 of file pg_backup_archiver.c.

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

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

2184 {
2185  struct stat st;
2186  char buf[MAXPGPATH];
2187 
2188  if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
2189  pg_fatal("directory name too long: \"%s\"", dir);
2190 
2191  return (stat(buf, &st) == 0 && S_ISREG(st.st_mode));
2192 }
#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 3578 of file pg_backup_archiver.c.

3579 {
3580  const char *type = te->desc;
3581 
3582  /* objects that don't require special decoration */
3583  if (strcmp(type, "COLLATION") == 0 ||
3584  strcmp(type, "CONVERSION") == 0 ||
3585  strcmp(type, "DOMAIN") == 0 ||
3586  strcmp(type, "FOREIGN TABLE") == 0 ||
3587  strcmp(type, "MATERIALIZED VIEW") == 0 ||
3588  strcmp(type, "SEQUENCE") == 0 ||
3589  strcmp(type, "STATISTICS") == 0 ||
3590  strcmp(type, "TABLE") == 0 ||
3591  strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
3592  strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 ||
3593  strcmp(type, "TYPE") == 0 ||
3594  strcmp(type, "VIEW") == 0 ||
3595  /* non-schema-specified objects */
3596  strcmp(type, "DATABASE") == 0 ||
3597  strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
3598  strcmp(type, "SCHEMA") == 0 ||
3599  strcmp(type, "EVENT TRIGGER") == 0 ||
3600  strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
3601  strcmp(type, "SERVER") == 0 ||
3602  strcmp(type, "PUBLICATION") == 0 ||
3603  strcmp(type, "SUBSCRIPTION") == 0)
3604  {
3605  appendPQExpBuffer(buf, "%s ", type);
3606  if (te->namespace && *te->namespace)
3607  appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
3609  }
3610  /* LOs just have a name, but it's numeric so must not use fmtId */
3611  else if (strcmp(type, "BLOB") == 0)
3612  {
3613  appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag);
3614  }
3615 
3616  /*
3617  * These object types require additional decoration. Fortunately, the
3618  * information needed is exactly what's in the DROP command.
3619  */
3620  else if (strcmp(type, "AGGREGATE") == 0 ||
3621  strcmp(type, "FUNCTION") == 0 ||
3622  strcmp(type, "OPERATOR") == 0 ||
3623  strcmp(type, "OPERATOR CLASS") == 0 ||
3624  strcmp(type, "OPERATOR FAMILY") == 0 ||
3625  strcmp(type, "PROCEDURE") == 0)
3626  {
3627  /* Chop "DROP " off the front and make a modifiable copy */
3628  char *first = pg_strdup(te->dropStmt + 5);
3629  char *last;
3630 
3631  /* point to last character in string */
3632  last = first + strlen(first) - 1;
3633 
3634  /* Strip off any ';' or '\n' at the end */
3635  while (last >= first && (*last == '\n' || *last == ';'))
3636  last--;
3637  *(last + 1) = '\0';
3638 
3639  appendPQExpBufferStr(buf, first);
3640 
3641  free(first);
3642  return;
3643  }
3644  /* these object types don't have separate owners */
3645  else if (strcmp(type, "CAST") == 0 ||
3646  strcmp(type, "CHECK CONSTRAINT") == 0 ||
3647  strcmp(type, "CONSTRAINT") == 0 ||
3648  strcmp(type, "DATABASE PROPERTIES") == 0 ||
3649  strcmp(type, "DEFAULT") == 0 ||
3650  strcmp(type, "FK CONSTRAINT") == 0 ||
3651  strcmp(type, "INDEX") == 0 ||
3652  strcmp(type, "RULE") == 0 ||
3653  strcmp(type, "TRIGGER") == 0 ||
3654  strcmp(type, "ROW SECURITY") == 0 ||
3655  strcmp(type, "POLICY") == 0 ||
3656  strcmp(type, "USER MAPPING") == 0)
3657  {
3658  /* do nothing */
3659  }
3660  else
3661  pg_fatal("don't know how to set owner for object type \"%s\"", type);
3662 }
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 1915 of file pg_backup_archiver.c.

1916 {
1917  /* Unlink te from list */
1918  te->prev->next = te->next;
1919  te->next->prev = te->prev;
1920 
1921  /* and insert it before "pos" */
1922  te->prev = pos->prev;
1923  te->next = pos;
1924  pos->prev->next = te;
1925  pos->prev = te;
1926 }

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

Referenced by SortTocFromFile().

◆ _printTocEntry()

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

Definition at line 3672 of file pg_backup_archiver.c.

3673 {
3674  RestoreOptions *ropt = AH->public.ropt;
3675 
3676  /* Select owner, schema, tablespace and default AM as necessary */
3677  _becomeOwner(AH, te);
3678  _selectOutputSchema(AH, te->namespace);
3679  _selectTablespace(AH, te->tablespace);
3681 
3682  /* Emit header comment for item */
3683  if (!AH->noTocComments)
3684  {
3685  const char *pfx;
3686  char *sanitized_name;
3687  char *sanitized_schema;
3688  char *sanitized_owner;
3689 
3690  if (isData)
3691  pfx = "Data for ";
3692  else
3693  pfx = "";
3694 
3695  ahprintf(AH, "--\n");
3696  if (AH->public.verbose)
3697  {
3698  ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
3699  te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
3700  if (te->nDeps > 0)
3701  {
3702  int i;
3703 
3704  ahprintf(AH, "-- Dependencies:");
3705  for (i = 0; i < te->nDeps; i++)
3706  ahprintf(AH, " %d", te->dependencies[i]);
3707  ahprintf(AH, "\n");
3708  }
3709  }
3710 
3711  sanitized_name = sanitize_line(te->tag, false);
3712  sanitized_schema = sanitize_line(te->namespace, true);
3713  sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
3714 
3715  ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
3716  pfx, sanitized_name, te->desc, sanitized_schema,
3717  sanitized_owner);
3718 
3719  free(sanitized_name);
3720  free(sanitized_schema);
3721  free(sanitized_owner);
3722 
3723  if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace)
3724  {
3725  char *sanitized_tablespace;
3726 
3727  sanitized_tablespace = sanitize_line(te->tablespace, false);
3728  ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
3729  free(sanitized_tablespace);
3730  }
3731  ahprintf(AH, "\n");
3732 
3733  if (AH->PrintExtraTocPtr != NULL)
3734  AH->PrintExtraTocPtr(AH, te);
3735  ahprintf(AH, "--\n\n");
3736  }
3737 
3738  /*
3739  * Actually print the definition. Normally we can just print the defn
3740  * string if any, but we have three special cases:
3741  *
3742  * 1. A crude hack for suppressing AUTHORIZATION clause that old pg_dump
3743  * versions put into CREATE SCHEMA. Don't mutate the variant for schema
3744  * "public" that is a comment. We have to do this when --no-owner mode is
3745  * selected. This is ugly, but I see no other good way ...
3746  *
3747  * 2. BLOB METADATA entries need special processing since their defn
3748  * strings are just lists of OIDs, not complete SQL commands.
3749  *
3750  * 3. ACL LARGE OBJECTS entries need special processing because they
3751  * contain only one copy of the ACL GRANT/REVOKE commands, which we must
3752  * apply to each large object listed in the associated BLOB METADATA.
3753  */
3754  if (ropt->noOwner &&
3755  strcmp(te->desc, "SCHEMA") == 0 && strncmp(te->defn, "--", 2) != 0)
3756  {
3757  ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
3758  }
3759  else if (strcmp(te->desc, "BLOB METADATA") == 0)
3760  {
3761  IssueCommandPerBlob(AH, te, "SELECT pg_catalog.lo_create('", "')");
3762  }
3763  else if (strcmp(te->desc, "ACL") == 0 &&
3764  strncmp(te->tag, "LARGE OBJECTS", 13) == 0)
3765  {
3766  IssueACLPerBlob(AH, te);
3767  }
3768  else
3769  {
3770  if (te->defn && strlen(te->defn) > 0)
3771  ahprintf(AH, "%s\n\n", te->defn);
3772  }
3773 
3774  /*
3775  * If we aren't using SET SESSION AUTH to determine ownership, we must
3776  * instead issue an ALTER OWNER command. Schema "public" is special; when
3777  * a dump emits a comment in lieu of creating it, we use ALTER OWNER even
3778  * when using SET SESSION for all other objects. We assume that anything
3779  * without a DROP command is not a separately ownable object.
3780  */
3781  if (!ropt->noOwner &&
3782  (!ropt->use_setsessauth ||
3783  (strcmp(te->desc, "SCHEMA") == 0 &&
3784  strncmp(te->defn, "--", 2) == 0)) &&
3785  te->owner && strlen(te->owner) > 0 &&
3786  te->dropStmt && strlen(te->dropStmt) > 0)
3787  {
3788  if (strcmp(te->desc, "BLOB METADATA") == 0)
3789  {
3790  /* BLOB METADATA needs special code to handle multiple LOs */
3791  char *cmdEnd = psprintf(" OWNER TO %s", fmtId(te->owner));
3792 
3793  IssueCommandPerBlob(AH, te, "ALTER LARGE OBJECT ", cmdEnd);
3794  pg_free(cmdEnd);
3795  }
3796  else
3797  {
3798  /* For all other cases, we can use _getObjectDescription */
3799  PQExpBufferData temp;
3800 
3801  initPQExpBuffer(&temp);
3802  _getObjectDescription(&temp, te);
3803 
3804  /*
3805  * If _getObjectDescription() didn't fill the buffer, then there
3806  * is no owner.
3807  */
3808  if (temp.data[0])
3809  ahprintf(AH, "ALTER %s OWNER TO %s;\n\n",
3810  temp.data, fmtId(te->owner));
3811  termPQExpBuffer(&temp);
3812  }
3813  }
3814 
3815  /*
3816  * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
3817  * commands, so we can no longer assume we know the current auth setting.
3818  */
3819  if (_tocEntryIsACL(te))
3820  {
3821  free(AH->currUser);
3822  AH->currUser = NULL;
3823  }
3824 }
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 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(), _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, 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 3334 of file pg_backup_archiver.c.

3335 {
3336  if (RestoringToDB(AH))
3338  else
3339  {
3340  PQExpBufferData connectbuf;
3341 
3342  initPQExpBuffer(&connectbuf);
3343  appendPsqlMetaConnect(&connectbuf, dbname);
3344  ahprintf(AH, "%s\n", connectbuf.data);
3345  termPQExpBuffer(&connectbuf);
3346  }
3347 
3348  /*
3349  * NOTE: currUser keeps track of what the imaginary session user in our
3350  * script is. It's now effectively reset to the original userID.
3351  */
3352  free(AH->currUser);
3353  AH->currUser = NULL;
3354 
3355  /* don't assume we still know the output schema, tablespace, etc either */
3356  free(AH->currSchema);
3357  AH->currSchema = NULL;
3358 
3359  free(AH->currTableAm);
3360  AH->currTableAm = NULL;
3361 
3362  free(AH->currTablespace);
3363  AH->currTablespace = NULL;
3364 
3365  /* re-establish fixed state */
3367 }
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 3414 of file pg_backup_archiver.c.

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

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

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

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

3466 {
3467  RestoreOptions *ropt = AH->public.ropt;
3468  PQExpBuffer qry;
3469  const char *want,
3470  *have;
3471 
3472  /* do nothing in --no-tablespaces mode */
3473  if (ropt->noTablespace)
3474  return;
3475 
3476  have = AH->currTablespace;
3477  want = tablespace;
3478 
3479  /* no need to do anything for non-tablespace object */
3480  if (!want)
3481  return;
3482 
3483  if (have && strcmp(want, have) == 0)
3484  return; /* no need to do anything */
3485 
3486  qry = createPQExpBuffer();
3487 
3488  if (strcmp(want, "") == 0)
3489  {
3490  /* We want the tablespace to be the database's default */
3491  appendPQExpBufferStr(qry, "SET default_tablespace = ''");
3492  }
3493  else
3494  {
3495  /* We want an explicit tablespace */
3496  appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
3497  }
3498 
3499  if (RestoringToDB(AH))
3500  {
3501  PGresult *res;
3502 
3503  res = PQexec(AH->connection, qry->data);
3504 
3505  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3507  "could not set default_tablespace to %s: %s",
3508  fmtId(want), PQerrorMessage(AH->connection));
3509 
3510  PQclear(res);
3511  }
3512  else
3513  ahprintf(AH, "%s;\n\n", qry->data);
3514 
3515  free(AH->currTablespace);
3516  AH->currTablespace = pg_strdup(want);
3517 
3518  destroyPQExpBuffer(qry);
3519 }
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 3209 of file pg_backup_archiver.c.

3210 {
3211  /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3212  if (strcmp(te->desc, "ACL") == 0 ||
3213  strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3214  strcmp(te->desc, "DEFAULT ACL") == 0)
3215  return true;
3216  return false;
3217 }

References _tocEntry::desc.

Referenced by _printTocEntry(), and _tocEntryRequired().

◆ _tocEntryRequired()

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

Definition at line 2895 of file pg_backup_archiver.c.

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

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

1711 {
1712  int save_errno = errno;
1713  char *p;
1714  size_t len = 128; /* initial assumption about buffer size */
1715  size_t cnt;
1716 
1717  for (;;)
1718  {
1719  va_list args;
1720 
1721  /* Allocate work buffer. */
1722  p = (char *) pg_malloc(len);
1723 
1724  /* Try to format the data. */
1725  errno = save_errno;
1726  va_start(args, fmt);
1727  cnt = pvsnprintf(p, len, fmt, args);
1728  va_end(args);
1729 
1730  if (cnt < len)
1731  break; /* success */
1732 
1733  /* Release buffer and loop around to try again with larger len. */
1734  free(p);
1735  len = cnt;
1736  }
1737 
1738  ahwrite(p, 1, cnt, AH);
1739  free(p);
1740  return (int) cnt;
1741 }
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(), _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 1801 of file pg_backup_archiver.c.

1802 {
1803  int bytes_written = 0;
1804 
1805  if (AH->writingLO)
1806  {
1807  size_t remaining = size * nmemb;
1808 
1809  while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1810  {
1811  size_t avail = AH->lo_buf_size - AH->lo_buf_used;
1812 
1813  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1814  ptr = (const void *) ((const char *) ptr + avail);
1815  remaining -= avail;
1816  AH->lo_buf_used += avail;
1817  dump_lo_buf(AH);
1818  }
1819 
1820  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1821  AH->lo_buf_used += remaining;
1822 
1823  bytes_written = size * nmemb;
1824  }
1825  else if (AH->CustomOutPtr)
1826  bytes_written = AH->CustomOutPtr(AH, ptr, size * nmemb);
1827 
1828  /*
1829  * If we're doing a restore, and it's direct to DB, and we're connected
1830  * then send it to the DB.
1831  */
1832  else if (RestoringToDB(AH))
1833  bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb);
1834  else
1835  {
1836  CompressFileHandle *CFH = (CompressFileHandle *) AH->OF;
1837 
1838  if (CFH->write_func(ptr, size * nmemb, CFH))
1839  bytes_written = size * nmemb;
1840  }
1841 
1842  if (bytes_written != size * nmemb)
1844 }
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 1200 of file pg_backup_archiver.c.

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

1611 {
1612  int save_errno = errno;
1613  char *p;
1614  size_t len = 128; /* initial assumption about buffer size */
1615  size_t cnt;
1616 
1617  for (;;)
1618  {
1619  va_list args;
1620 
1621  /* Allocate work buffer. */
1622  p = (char *) pg_malloc(len);
1623 
1624  /* Try to format the data. */
1625  errno = save_errno;
1626  va_start(args, fmt);
1627  cnt = pvsnprintf(p, len, fmt, args);
1628  va_end(args);
1629 
1630  if (cnt < len)
1631  break; /* success */
1632 
1633  /* Release buffer and loop around to try again with larger len. */
1634  free(p);
1635  len = cnt;
1636  }
1637 
1638  WriteData(AH, p, cnt);
1639  free(p);
1640  return (int) cnt;
1641 }
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 1603 of file pg_backup_archiver.c.

1604 {
1605  WriteData(AH, s, strlen(s));
1606 }

References WriteData().

Referenced by dumpTableData_insert().

◆ buildTocEntryArrays()

static void buildTocEntryArrays ( ArchiveHandle AH)
static

Definition at line 1940 of file pg_backup_archiver.c.

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

4027 {
4028  pgoff_t tpos;
4029 
4030  /* Check that ftello works on this file */
4031  tpos = ftello(fp);
4032  if (tpos < 0)
4033  return false;
4034 
4035  /*
4036  * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
4037  * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
4038  * successful no-op even on files that are otherwise unseekable.
4039  */
4040  if (fseeko(fp, tpos, SEEK_SET) != 0)
4041  return false;
4042 
4043  return true;
4044 }
#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 4893 of file pg_backup_archiver.c.

4894 {
4895  ArchiveHandle *clone;
4896 
4897  /* Make a "flat" copy */
4898  clone = (ArchiveHandle *) pg_malloc(sizeof(ArchiveHandle));
4899  memcpy(clone, AH, sizeof(ArchiveHandle));
4900 
4901  /* Likewise flat-copy the RestoreOptions, so we can alter them locally */
4902  clone->public.ropt = (RestoreOptions *) pg_malloc(sizeof(RestoreOptions));
4903  memcpy(clone->public.ropt, AH->public.ropt, sizeof(RestoreOptions));
4904 
4905  /* Handle format-independent fields */
4906  memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse));
4907 
4908  /* The clone will have its own connection, so disregard connection state */
4909  clone->connection = NULL;
4910  clone->connCancel = NULL;
4911  clone->currUser = NULL;
4912  clone->currSchema = NULL;
4913  clone->currTableAm = NULL;
4914  clone->currTablespace = NULL;
4915 
4916  /* savedPassword must be local in case we change it while connecting */
4917  if (clone->savedPassword)
4918  clone->savedPassword = pg_strdup(clone->savedPassword);
4919 
4920  /* clone has its own error count, too */
4921  clone->public.n_errors = 0;
4922 
4923  /* clones should not share lo_buf */
4924  clone->lo_buf = NULL;
4925 
4926  /*
4927  * Clone connections disregard --transaction-size; they must commit after
4928  * each command so that the results are immediately visible to other
4929  * workers.
4930  */
4931  clone->public.ropt->txn_size = 0;
4932 
4933  /*
4934  * Connect our new clone object to the database, using the same connection
4935  * parameters used for the original connection.
4936  */
4937  ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true);
4938 
4939  /* re-establish fixed state */
4940  if (AH->mode == archModeRead)
4941  _doSetFixedOutputState(clone);
4942  /* in write case, setupDumpWorker will fix up connection state */
4943 
4944  /* Let the format-specific code have a chance too */
4945  clone->ClonePtr(clone);
4946 
4947  Assert(clone->connection != NULL);
4948  return clone;
4949 }
#define Assert(condition)
Definition: c.h:858
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 249 of file pg_backup_archiver.c.

250 {
251  ArchiveHandle *AH = (ArchiveHandle *) AHX;
252 
253  AH->ClosePtr(AH);
254 
255  /* Close the output */
256  errno = 0;
257  if (!EndCompressFileHandle(AH->OF))
258  pg_fatal("could not close output file: %m");
259 }
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 218 of file pg_backup_archiver.c.

224 {
225  ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression_spec,
227 
228  return (Archive *) AH;
229 }
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:1351

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

Referenced by main().

◆ DeCloneArchive()

void DeCloneArchive ( ArchiveHandle AH)

Definition at line 4957 of file pg_backup_archiver.c.

4958 {
4959  /* Should not have an open database connection */
4960  Assert(AH->connection == NULL);
4961 
4962  /* Clear format-specific state */
4963  AH->DeClonePtr(AH);
4964 
4965  /* Clear state allocated by CloneArchive */
4966  if (AH->sqlparse.curCmd)
4968 
4969  /* Clear any connection-local state */
4970  free(AH->currUser);
4971  free(AH->currSchema);
4972  free(AH->currTablespace);
4973  free(AH->currTableAm);
4974  free(AH->savedPassword);
4975 
4976  free(AH);
4977 }
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 1758 of file pg_backup_archiver.c.

1759 {
1760  if (AH->connection)
1761  {
1762  int res;
1763 
1764  res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1765  pg_log_debug(ngettext("wrote %zu byte of large object data (result = %d)",
1766  "wrote %zu bytes of large object data (result = %d)",
1767  AH->lo_buf_used),
1768  AH->lo_buf_used, res);
1769  /* We assume there are no short writes, only errors */
1770  if (res != AH->lo_buf_used)
1771  warn_or_exit_horribly(AH, "could not write to large object: %s",
1772  PQerrorMessage(AH->connection));
1773  }
1774  else
1775  {
1777 
1779  (const unsigned char *) AH->lo_buf,
1780  AH->lo_buf_used,
1781  AH);
1782 
1783  /* Hack: turn off writingLO so ahwrite doesn't recurse to here */
1784  AH->writingLO = false;
1785  ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
1786  AH->writingLO = true;
1787 
1789  }
1790  AH->lo_buf_used = 0;
1791 }
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 154 of file pg_backup_archiver.c.

155 {
156  DumpOptions *dopt = NewDumpOptions();
157 
158  /* this is the inverse of what's at the end of pg_dump.c's main() */
159  dopt->cparams.dbname = ropt->cparams.dbname ? pg_strdup(ropt->cparams.dbname) : NULL;
160  dopt->cparams.pgport = ropt->cparams.pgport ? pg_strdup(ropt->cparams.pgport) : NULL;
161  dopt->cparams.pghost = ropt->cparams.pghost ? pg_strdup(ropt->cparams.pghost) : NULL;
162  dopt->cparams.username = ropt->cparams.username ? pg_strdup(ropt->cparams.username) : NULL;
164  dopt->outputClean = ropt->dropSchema;
165  dopt->dataOnly = ropt->dataOnly;
166  dopt->schemaOnly = ropt->schemaOnly;
167  dopt->if_exists = ropt->if_exists;
168  dopt->column_inserts = ropt->column_inserts;
169  dopt->dumpSections = ropt->dumpSections;
170  dopt->aclsSkip = ropt->aclsSkip;
171  dopt->outputSuperuser = ropt->superuser;
172  dopt->outputCreateDB = ropt->createDB;
173  dopt->outputNoOwner = ropt->noOwner;
174  dopt->outputNoTableAm = ropt->noTableAm;
175  dopt->outputNoTablespaces = ropt->noTablespace;
176  dopt->disable_triggers = ropt->disable_triggers;
177  dopt->use_setsessauth = ropt->use_setsessauth;
179  dopt->dump_inserts = ropt->dump_inserts;
180  dopt->no_comments = ropt->no_comments;
181  dopt->no_publications = ropt->no_publications;
183  dopt->no_subscriptions = ropt->no_subscriptions;
184  dopt->lockWaitTimeout = ropt->lockWaitTimeout;
187  dopt->sequence_data = ropt->sequence_data;
188 
189  return dopt;
190 }
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 4051 of file pg_backup_archiver.c.

4052 {
4053  char buf[64];
4054 
4055  if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
4056  ahprintf(AH, "-- %s %s\n\n", msg, buf);
4057 }
#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 1381 of file pg_backup_archiver.c.

1382 {
1383  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1384 
1385  if (AH->EndLOPtr)
1386  AH->EndLOPtr(AH, AH->currToc, oid);
1387 
1388  return 1;
1389 }
EndLOPtrType EndLOPtr
struct _tocEntry * currToc

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

Referenced by dumpLOs().

◆ EndRestoreLO()

void EndRestoreLO ( ArchiveHandle AH,
Oid  oid 
)

Definition at line 1496 of file pg_backup_archiver.c.

1497 {
1498  if (AH->lo_buf_used > 0)
1499  {
1500  /* Write remaining bytes from the LO buffer */
1501  dump_lo_buf(AH);
1502  }
1503 
1504  AH->writingLO = false;
1505 
1506  if (AH->connection)
1507  {
1508  lo_close(AH->connection, AH->loFd);
1509  AH->loFd = -1;
1510  }
1511  else
1512  {
1513  ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
1514  }
1515 }
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 1423 of file pg_backup_archiver.c.

1424 {
1425  RestoreOptions *ropt = AH->public.ropt;
1426 
1427  if (!(ropt->single_txn || ropt->txn_size > 0))
1428  {
1429  if (AH->connection)
1430  CommitTransaction(&AH->public);
1431  else
1432  ahprintf(AH, "COMMIT;\n\n");
1433  }
1434 
1435  pg_log_info(ngettext("restored %d large object",
1436  "restored %d large objects",
1437  AH->loCount),
1438  AH->loCount);
1439 }
static void CommitTransaction(void)
Definition: xact.c:2178

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

4591 {
4592  TocEntry *te;
4593  int i;
4594 
4595  /*
4596  * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC
4597  * items are marked as not being in any parallel-processing list.
4598  */
4599  for (te = AH->toc->next; te != AH->toc; te = te->next)
4600  {
4601  te->depCount = te->nDeps;
4602  te->revDeps = NULL;
4603  te->nRevDeps = 0;
4604  te->pending_prev = NULL;
4605  te->pending_next = NULL;
4606  }
4607 
4608  /*
4609  * POST_DATA items that are shown as depending on a table need to be
4610  * re-pointed to depend on that table's data, instead. This ensures they
4611  * won't get scheduled until the data has been loaded.
4612  */
4614 
4615  /*
4616  * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB
4617  * COMMENTS to BLOBS. Cope. (We assume there's only one BLOBS and only
4618  * one BLOB COMMENTS in such files.)
4619  */
4620  if (AH->version < K_VERS_1_11)
4621  {
4622  for (te = AH->toc->next; te != AH->toc; te = te->next)
4623  {
4624  if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0)
4625  {
4626  TocEntry *te2;
4627 
4628  for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next)
4629  {
4630  if (strcmp(te2->desc, "BLOBS") == 0)
4631  {
4632  te->dependencies = (DumpId *) pg_malloc(sizeof(DumpId));
4633  te->dependencies[0] = te2->dumpId;
4634  te->nDeps++;
4635  te->depCount++;
4636  break;
4637  }
4638  }
4639  break;
4640  }
4641  }
4642  }
4643 
4644  /*
4645  * At this point we start to build the revDeps reverse-dependency arrays,
4646  * so all changes of dependencies must be complete.
4647  */
4648 
4649  /*
4650  * Count the incoming dependencies for each item. Also, it is possible
4651  * that the dependencies list items that are not in the archive at all
4652  * (that should not happen in 9.2 and later, but is highly likely in older
4653  * archives). Subtract such items from the depCounts.
4654  */
4655  for (te = AH->toc->next; te != AH->toc; te = te->next)
4656  {
4657  for (i = 0; i < te->nDeps; i++)
4658  {
4659  DumpId depid = te->dependencies[i];
4660 
4661  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4662  AH->tocsByDumpId[depid]->nRevDeps++;
4663  else
4664  te->depCount--;
4665  }
4666  }
4667 
4668  /*
4669  * Allocate space for revDeps[] arrays, and reset nRevDeps so we can use
4670  * it as a counter below.
4671  */
4672  for (te = AH->toc->next; te != AH->toc; te = te->next)
4673  {
4674  if (te->nRevDeps > 0)
4675  te->revDeps = (DumpId *) pg_malloc(te->nRevDeps * sizeof(DumpId));
4676  te->nRevDeps = 0;
4677  }
4678 
4679  /*
4680  * Build the revDeps[] arrays of incoming-dependency dumpIds. This had
4681  * better agree with the loops above.
4682  */
4683  for (te = AH->toc->next; te != AH->toc; te = te->next)
4684  {
4685  for (i = 0; i < te->nDeps; i++)
4686  {
4687  DumpId depid = te->dependencies[i];
4688 
4689  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4690  {
4691  TocEntry *otherte = AH->tocsByDumpId[depid];
4692 
4693  otherte->revDeps[otherte->nRevDeps++] = te->dumpId;
4694  }
4695  }
4696  }
4697 
4698  /*
4699  * Lastly, work out the locking dependencies.
4700  */
4701  for (te = AH->toc->next; te != AH->toc; te = te->next)
4702  {
4703  te->lockDeps = NULL;
4704  te->nLockDeps = 0;
4706  }
4707 }
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 1981 of file pg_backup_archiver.c.

1982 {
1983  /* build index arrays if we didn't already */
1984  if (AH->tocsByDumpId == NULL)
1985  buildTocEntryArrays(AH);
1986 
1987  if (id > 0 && id <= AH->maxDumpId)
1988  return AH->tocsByDumpId[id];
1989 
1990  return NULL;
1991 }
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 4344 of file pg_backup_archiver.c.

4345 {
4346  int j,
4347  k;
4348 
4349  for (j = 0; j < te1->nLockDeps; j++)
4350  {
4351  for (k = 0; k < te2->nDeps; k++)
4352  {
4353  if (te1->lockDeps[j] == te2->dependencies[k])
4354  return true;
4355  }
4356  }
4357  return false;
4358 }
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 4754 of file pg_backup_archiver.c.

4755 {
4756  DumpId *lockids;
4757  int nlockids;
4758  int i;
4759 
4760  /*
4761  * We only care about this for POST_DATA items. PRE_DATA items are not
4762  * run in parallel, and DATA items are all independent by assumption.
4763  */
4764  if (te->section != SECTION_POST_DATA)
4765  return;
4766 
4767  /* Quick exit if no dependencies at all */
4768  if (te->nDeps == 0)
4769  return;
4770 
4771  /*
4772  * Most POST_DATA items are ALTER TABLEs or some moral equivalent of that,
4773  * and hence require exclusive lock. However, we know that CREATE INDEX
4774  * does not. (Maybe someday index-creating CONSTRAINTs will fall in that
4775  * category too ... but today is not that day.)
4776  */
4777  if (strcmp(te->desc, "INDEX") == 0)
4778  return;
4779 
4780  /*
4781  * We assume the entry requires exclusive lock on each TABLE or TABLE DATA
4782  * item listed among its dependencies. Originally all of these would have
4783  * been TABLE items, but repoint_table_dependencies would have repointed
4784  * them to the TABLE DATA items if those are present (which they might not
4785  * be, eg in a schema-only dump). Note that all of the entries we are
4786  * processing here are POST_DATA; otherwise there might be a significant
4787  * difference between a dependency on a table and a dependency on its
4788  * data, so that closer analysis would be needed here.
4789  */
4790  lockids = (DumpId *) pg_malloc(te->nDeps * sizeof(DumpId));
4791  nlockids = 0;
4792  for (i = 0; i < te->nDeps; i++)
4793  {
4794  DumpId depid = te->dependencies[i];
4795 
4796  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL &&
4797  ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) ||
4798  strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0))
4799  lockids[nlockids++] = depid;
4800  }
4801 
4802  if (nlockids == 0)
4803  {
4804  free(lockids);
4805  return;
4806  }
4807 
4808  te->lockDeps = pg_realloc(lockids, nlockids * sizeof(DumpId));
4809  te->nLockDeps = nlockids;
4810 }
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 4873 of file pg_backup_archiver.c.

4874 {
4875  pg_log_info("table \"%s\" could not be created, will not restore its data",
4876  te->tag);
4877 
4878  if (AH->tableDataId[te->dumpId] != 0)
4879  {
4880  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4881 
4882  ted->reqs = 0;
4883  }
4884 }

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

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

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

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

4859 {
4860  if (AH->tableDataId[te->dumpId] != 0)
4861  {
4862  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4863 
4864  ted->created = true;
4865  }
4866 }

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

2519 {
2520  pg_log_info("finished item %d %s %s",
2521  te->dumpId, te->desc, te->tag);
2522 
2523  if (status != 0)
2524  pg_fatal("worker process failed: exit code %d",
2525  status);
2526 }

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

4553 {
4554  binaryheap *ready_heap = (binaryheap *) callback_data;
4555 
4556  pg_log_info("finished item %d %s %s",
4557  te->dumpId, te->desc, te->tag);
4558 
4559  if (status == WORKER_CREATE_DONE)
4560  mark_create_done(AH, te);
4561  else if (status == WORKER_INHIBIT_DATA)
4562  {
4564  AH->public.n_errors++;
4565  }
4566  else if (status == WORKER_IGNORED_ERRORS)
4567  AH->public.n_errors++;
4568  else if (status != 0)
4569  pg_fatal("worker process failed: exit code %d",
4570  status);
4571 
4572  reduce_dependencies(AH, te, ready_heap);
4573 }
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 4434 of file pg_backup_archiver.c.

4437 {
4438  TocEntry *te;
4439  TocEntry *next_te;
4440 
4441  for (te = pending_list->pending_next; te != pending_list; te = next_te)
4442  {
4443  /* must save list link before possibly removing te from list */
4444  next_te = te->pending_next;
4445 
4446  if (te->depCount == 0 &&
4447  _tocEntryRestorePass(te) == pass)
4448  {
4449  /* Remove it from pending_list ... */
4450  pending_list_remove(te);
4451  /* ... and add to ready_heap */
4452  binaryheap_add(ready_heap, te);
4453  }
4454  }
4455 }
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 128 of file pg_backup_archiver.c.

129 {
131 
133  return opts;
134 }
void InitDumpOptions(DumpOptions *opts)

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

Referenced by dumpOptionsFromRestoreOptions().

◆ NewRestoreOptions()

RestoreOptions* NewRestoreOptions ( void  )

Definition at line 1068 of file pg_backup_archiver.c.

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

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

235 {
236  ArchiveHandle *AH;
237  pg_compress_specification compression_spec = {0};
238 
239  compression_spec.algorithm = PG_COMPRESSION_NONE;
240  AH = _allocAH(FileSpec, fmt, compression_spec, true,
243 
244  return (Archive *) AH;
245 }
@ 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 4526 of file pg_backup_archiver.c.

4527 {
4528  int status;
4529 
4530  Assert(AH->connection != NULL);
4531 
4532  /* Count only errors associated with this TOC entry */
4533  AH->public.n_errors = 0;
4534 
4535  /* Restore the TOC item */
4536  status = restore_toc_entry(AH, te, true);
4537 
4538  return status;
4539 }
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 4376 of file pg_backup_archiver.c.

4377 {
4378  te->pending_prev = l->pending_prev;
4379  l->pending_prev->pending_next = te;
4380  l->pending_prev = te;
4381  te->pending_next = l;
4382 }

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

4370 {
4371  l->pending_prev = l->pending_next = l;
4372 }

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

4387 {
4390  te->pending_prev = NULL;
4391  te->pending_next = NULL;
4392 }

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

4471 {
4472  /*
4473  * Search the ready_heap until we find a suitable item. Note that we do a
4474  * sequential scan through the heap nodes, so even though we will first
4475  * try to choose the highest-priority item, we might end up picking
4476  * something with a much lower priority. However, we expect that we will
4477  * typically be able to pick one of the first few items, which should
4478  * usually have a relatively high priority.
4479  */
4480  for (int i = 0; i < binaryheap_size(ready_heap); i++)
4481  {
4482  TocEntry *te = (TocEntry *) binaryheap_get_node(ready_heap, i);
4483  bool conflicts = false;
4484 
4485  /*
4486  * Check to see if the item would need exclusive lock on something
4487  * that a currently running item also needs lock on, or vice versa. If
4488  * so, we don't want to schedule them together.
4489  */
4490  for (int k = 0; k < pstate->numWorkers; k++)
4491  {
4492  TocEntry *running_te = pstate->te[k];
4493 
4494  if (running_te == NULL)
4495  continue;
4496  if (has_lock_conflicts(te, running_te) ||
4497  has_lock_conflicts(running_te, te))
4498  {
4499  conflicts = true;
4500  break;
4501  }
4502  }
4503 
4504  if (conflicts)
4505  continue;
4506 
4507  /* passed all tests, so this item can run */
4508  binaryheap_remove_node(ready_heap, i);
4509  return te;
4510  }
4511 
4512  pg_log_debug("no item ready");
4513  return NULL;
4514 }
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 1258 of file pg_backup_archiver.c.

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

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

2792 {
2793  /* te->defn should have the form SET client_encoding = 'foo'; */
2794  char *defn = pg_strdup(te->defn);
2795  char *ptr1;
2796  char *ptr2 = NULL;
2797  int encoding;
2798 
2799  ptr1 = strchr(defn, '\'');
2800  if (ptr1)
2801  ptr2 = strchr(++ptr1, '\'');
2802  if (ptr2)
2803  {
2804  *ptr2 = '\0';
2805  encoding = pg_char_to_encoding(ptr1);
2806  if (encoding < 0)
2807  pg_fatal("unrecognized encoding \"%s\"",
2808  ptr1);
2809  AH->public.encoding = encoding;
2810  }
2811  else
2812  pg_fatal("invalid ENCODING item: %s",
2813  te->defn);
2814 
2815  free(defn);
2816 }
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 2835 of file pg_backup_archiver.c.

2836 {
2837  /*
2838  * te->defn should contain a command to set search_path. We just copy it
2839  * verbatim for use later.
2840  */
2841  AH->public.searchpath = pg_strdup(te->defn);
2842 }

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

2820 {
2821  /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2822  char *ptr1;
2823 
2824  ptr1 = strchr(te->defn, '\'');
2825  if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2826  AH->public.std_strings = true;
2827  else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2828  AH->public.std_strings = false;
2829  else
2830  pg_fatal("invalid STDSTRINGS item: %s",
2831  te->defn);
2832 }

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

Referenced by ReadToc().

◆ ReadHead()

void ReadHead ( ArchiveHandle AH)

Definition at line 3892 of file pg_backup_archiver.c.

3893 {
3894  char *errmsg;
3895  char vmaj,
3896  vmin,
3897  vrev;
3898  int fmt;
3899 
3900  /*
3901  * If we haven't already read the header, do so.
3902  *
3903  * NB: this code must agree with _discoverArchiveFormat(). Maybe find a
3904  * way to unify the cases?
3905  */
3906  if (!AH->readHeader)
3907  {
3908  char tmpMag[7];
3909 
3910  AH->ReadBufPtr(AH, tmpMag, 5);
3911 
3912  if (strncmp(tmpMag, "PGDMP", 5) != 0)
3913  pg_fatal("did not find magic string in file header");
3914  }
3915 
3916  vmaj = AH->ReadBytePtr(AH);
3917  vmin = AH->ReadBytePtr(AH);
3918 
3919  if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
3920  vrev = AH->ReadBytePtr(AH);
3921  else
3922  vrev = 0;
3923 
3924  AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev);
3925 
3926  if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
3927  pg_fatal("unsupported version (%d.%d) in file header",
3928  vmaj, vmin);
3929 
3930  AH->intSize = AH->ReadBytePtr(AH);
3931  if (AH->intSize > 32)
3932  pg_fatal("sanity check on integer size (%lu) failed",
3933  (unsigned long) AH->intSize);
3934 
3935  if (AH->intSize > sizeof(int))
3936  pg_log_warning("archive was made on a machine with larger integers, some operations might fail");
3937 
3938  if (AH->version >= K_VERS_1_7)
3939  AH->offSize = AH->ReadBytePtr(AH);
3940  else
3941  AH->offSize = AH->intSize;
3942 
3943  fmt = AH->ReadBytePtr(AH);
3944 
3945  if (AH->format != fmt)
3946  pg_fatal("expected format (%d) differs from format found in file (%d)",
3947  AH->format, fmt);
3948 
3949  if (AH->version >= K_VERS_1_15)
3950  AH->compression_spec.algorithm = AH->ReadBytePtr(AH);
3951  else if (AH->version >= K_VERS_1_2)
3952  {
3953  /* Guess the compression method based on the level */
3954  if (AH->version < K_VERS_1_4)
3955  AH->compression_spec.level = AH->ReadBytePtr(AH);
3956  else
3957  AH->compression_spec.level = ReadInt(AH);
3958 
3959  if (AH->compression_spec.level != 0)
3961  }
3962  else
3964 
3966  if (errmsg)
3967  {
3968  pg_log_warning("archive is compressed, but this installation does not support compression (%s) -- no data will be available",
3969  errmsg);
3970  pg_free(errmsg);
3971  }
3972 
3973  if (AH->version >= K_VERS_1_4)
3974  {
3975  struct tm crtm;
3976 
3977  crtm.tm_sec = ReadInt(AH);
3978  crtm.tm_min = ReadInt(AH);
3979  crtm.tm_hour = ReadInt(AH);
3980  crtm.tm_mday = ReadInt(AH);
3981  crtm.tm_mon = ReadInt(AH);
3982  crtm.tm_year = ReadInt(AH);
3983  crtm.tm_isdst = ReadInt(AH);
3984 
3985  /*
3986  * Newer versions of glibc have mktime() report failure if tm_isdst is
3987  * inconsistent with the prevailing timezone, e.g. tm_isdst = 1 when
3988  * TZ=UTC. This is problematic when restoring an archive under a
3989  * different timezone setting. If we get a failure, try again with
3990  * tm_isdst set to -1 ("don't know").
3991  *
3992  * XXX with or without this hack, we reconstruct createDate
3993  * incorrectly when the prevailing timezone is different from
3994  * pg_dump's. Next time we bump the archive version, we should flush
3995  * this representation and store a plain seconds-since-the-Epoch
3996  * timestamp instead.
3997  */
3998  AH->createDate = mktime(&crtm);
3999  if (AH->createDate == (time_t) -1)
4000  {
4001  crtm.tm_isdst = -1;
4002  AH->createDate = mktime(&crtm);
4003  if (AH->createDate == (time_t) -1)
4004  pg_log_warning("invalid creation date in header");
4005  }
4006  }
4007 
4008  if (AH->version >= K_VERS_1_4)
4009  {
4010  AH->archdbname = ReadStr(AH);
4011  }
4012 
4013  if (AH->version >= K_VERS_1_10)
4014  {
4015  AH->archiveRemoteVersion = ReadStr(AH);
4016  AH->archiveDumpVersion = ReadStr(AH);
4017  }
4018 }
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:1072
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 2117 of file pg_backup_archiver.c.

2118 {
2119  int res = 0;
2120  int bv,
2121  b;
2122  int sign = 0; /* Default positive */
2123  int bitShift = 0;
2124 
2125  if (AH->version > K_VERS_1_0)
2126  /* Read a sign byte */
2127  sign = AH->ReadBytePtr(AH);
2128 
2129  for (b = 0; b < AH->intSize; b++)
2130  {
2131  bv = AH->ReadBytePtr(AH) & 0xFF;
2132  if (bv != 0)
2133  res = res + (bv << bitShift);
2134  bitShift += 8;
2135  }
2136 
2137  if (sign)
2138  res = -res;
2139 
2140  return res;
2141 }
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 2022 of file pg_backup_archiver.c.

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

2164 {
2165  char *buf;
2166  int l;
2167 
2168  l = ReadInt(AH);
2169  if (l < 0)
2170  buf = NULL;
2171  else
2172  {
2173  buf = (char *) pg_malloc(l + 1);
2174  AH->ReadBufPtr(AH, (void *) buf, l);
2175 
2176  buf[l] = '\0';
2177  }
2178 
2179  return buf;
2180 }

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

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

◆ ReadToc()

void ReadToc ( ArchiveHandle AH)

Definition at line 2622 of file pg_backup_archiver.c.

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

4820 {
4821  int i;
4822 
4823  pg_log_debug("reducing dependencies for %d", te->dumpId);
4824 
4825  for (i = 0; i < te->nRevDeps; i++)
4826  {
4827  TocEntry *otherte = AH->tocsByDumpId[te->revDeps[i]];
4828 
4829  Assert(otherte->depCount > 0);
4830  otherte->depCount--;
4831 
4832  /*
4833  * It's ready if it has no remaining dependencies, and it belongs in
4834  * the current restore pass, and it is currently a member of the
4835  * pending list (that check is needed to prevent double restore in
4836  * some cases where a list-file forces out-of-order restoring).
4837  * However, if ready_heap == NULL then caller doesn't want any list
4838  * memberships changed.
4839  */
4840  if (otherte->depCount == 0 &&
4841  _tocEntryRestorePass(otherte) == AH->restorePass &&
4842  otherte->pending_prev != NULL &&
4843  ready_heap != NULL)
4844  {
4845  /* Remove it from pending list ... */
4846  pending_list_remove(otherte);
4847  /* ... and add to ready_heap */
4848  binaryheap_add(ready_heap, otherte);
4849  }
4850  }
4851 }
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 4720 of file pg_backup_archiver.c.

4721 {
4722  TocEntry *te;
4723  int i;
4724  DumpId olddep;
4725 
4726  for (te = AH->toc->next; te != AH->toc; te = te->next)
4727  {
4728  if (te->section != SECTION_POST_DATA)
4729  continue;
4730  for (i = 0; i < te->nDeps; i++)
4731  {
4732  olddep = te->dependencies[i];
4733  if (olddep <= AH->maxDumpId &&
4734  AH->tableDataId[olddep] != 0)
4735  {
4736  DumpId tabledataid = AH->tableDataId[olddep];
4737  TocEntry *tabledatate = AH->tocsByDumpId[tabledataid];
4738 
4739  te->dependencies[i] = tabledataid;
4740  te->dataLength = Max(te->dataLength, tabledatate->dataLength);
4741  pg_log_debug("transferring dependency %d -> %d to %d",
4742  te->dumpId, olddep, tabledataid);
4743  }
4744  }
4745  }
4746 }
#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 4192 of file pg_backup_archiver.c.

4194 {
4195  binaryheap *ready_heap;
4196  TocEntry *next_work_item;
4197 
4198  pg_log_debug("entering restore_toc_entries_parallel");
4199 
4200  /* Set up ready_heap with enough room for all known TocEntrys */
4201  ready_heap = binaryheap_allocate(AH->tocCount,
4203  NULL);
4204 
4205  /*
4206  * The pending_list contains all items that we need to restore. Move all
4207  * items that are available to process immediately into the ready_heap.
4208  * After this setup, the pending list is everything that needs to be done
4209  * but is blocked by one or more dependencies, while the ready heap
4210  * contains items that have no remaining dependencies and are OK to
4211  * process in the current restore pass.
4212  */
4214  move_to_ready_heap(pending_list, ready_heap, AH->restorePass);
4215 
4216  /*
4217  * main parent loop
4218  *
4219  * Keep going until there is no worker still running AND there is no work
4220  * left to be done. Note invariant: at top of loop, there should always
4221  * be at least one worker available to dispatch a job to.
4222  */
4223  pg_log_info("entering main parallel loop");
4224 
4225  for (;;)
4226  {
4227  /* Look for an item ready to be dispatched to a worker */
4228  next_work_item = pop_next_work_item(ready_heap, pstate);
4229  if (next_work_item != NULL)
4230  {
4231  /* If not to be restored, don't waste time launching a worker */
4232  if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA)) == 0)
4233  {
4234  pg_log_info("skipping item %d %s %s",
4235  next_work_item->dumpId,
4236  next_work_item->desc, next_work_item->tag);
4237  /* Update its dependencies as though we'd completed it */
4238  reduce_dependencies(AH, next_work_item, ready_heap);
4239  /* Loop around to see if anything else can be dispatched */
4240  continue;
4241  }
4242 
4243  pg_log_info("launching item %d %s %s",
4244  next_work_item->dumpId,
4245  next_work_item->desc, next_work_item->tag);
4246 
4247  /* Dispatch to some worker */
4248  DispatchJobForTocEntry(AH, pstate, next_work_item, ACT_RESTORE,
4249  mark_restore_job_done, ready_heap);
4250  }
4251  else if (IsEveryWorkerIdle(pstate))
4252  {
4253  /*
4254  * Nothing is ready and no worker is running, so we're done with
4255  * the current pass or maybe with the whole process.
4256  */
4257  if (AH->restorePass == RESTORE_PASS_LAST)
4258  break; /* No more parallel processing is possible */
4259 
4260  /* Advance to next restore pass */
4261  AH->restorePass++;
4262  /* That probably allows some stuff to be made ready */
4263  move_to_ready_heap(pending_list, ready_heap, AH->restorePass);
4264  /* Loop around to see if anything's now ready */
4265  continue;
4266  }
4267  else
4268  {
4269  /*
4270  * We have nothing ready, but at least one child is working, so
4271  * wait for some subjob to finish.
4272  */
4273  }
4274 
4275  /*
4276  * Before dispatching another job, check to see if anything has
4277  * finished. We should check every time through the loop so as to
4278  * reduce dependencies as soon as possible. If we were unable to
4279  * dispatch any job this time through, wait until some worker finishes
4280  * (and, hopefully, unblocks some pending item). If we did dispatch
4281  * something, continue as soon as there's at least one idle worker.
4282  * Note that in either case, there's guaranteed to be at least one
4283  * idle worker when we return to the top of the loop. This ensures we
4284  * won't block inside DispatchJobForTocEntry, which would be
4285  * undesirable: we'd rather postpone dispatching until we see what's
4286  * been unblocked by finished jobs.
4287  */
4288  WaitForWorkers(AH, pstate,
4289  next_work_item ? WFW_ONE_IDLE : WFW_GOT_STATUS);
4290  }
4291 
4292  /* There should now be nothing in ready_heap. */
4293  Assert(binaryheap_empty(ready_heap));
4294 
4295  binaryheap_free(ready_heap);
4296 
4297  pg_log_info("finished main parallel loop");
4298 }
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 4310 of file pg_backup_archiver.c.

4311 {
4312  RestoreOptions *ropt = AH->public.ropt;
4313  TocEntry *te;
4314 
4315  pg_log_debug("entering restore_toc_entries_postfork");
4316 
4317  /*
4318  * Now reconnect the single parent connection.
4319  */
4320  ConnectDatabase((Archive *) AH, &ropt->cparams, true);
4321 
4322  /* re-establish fixed state */
4324 
4325  /*
4326  * Make sure there is no work left due to, say, circular dependencies, or
4327  * some other pathological condition. If so, do it in the single parent
4328  * connection. We don't sweat about RestorePass ordering; it's likely we
4329  * already violated that.
4330  */
4331  for (te = pending_list->pending_next; te != pending_list; te = te->pending_next)
4332  {
4333  pg_log_info("processing missed item %d %s %s",
4334  te->dumpId, te->desc, te->tag);
4335  (void) restore_toc_entry(AH, te, false);
4336  }
4337 }

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

4070 {
4071  bool skipped_some;
4072  TocEntry *next_work_item;
4073 
4074  pg_log_debug("entering restore_toc_entries_prefork");
4075 
4076  /* Adjust dependency information */
4077  fix_dependencies(AH);
4078 
4079  /*
4080  * Do all the early stuff in a single connection in the parent. There's no
4081  * great point in running it in parallel, in fact it will actually run
4082  * faster in a single connection because we avoid all the connection and
4083  * setup overhead. Also, pre-9.2 pg_dump versions were not very good
4084  * about showing all the dependencies of SECTION_PRE_DATA items, so we do
4085  * not risk trying to process them out-of-order.
4086  *
4087  * Stuff that we can't do immediately gets added to the pending_list.
4088  * Note: we don't yet filter out entries that aren't going to be restored.
4089  * They might participate in dependency chains connecting entries that
4090  * should be restored, so we treat them as live until we actually process
4091  * them.
4092  *
4093  * Note: as of 9.2, it should be guaranteed that all PRE_DATA items appear
4094  * before DATA items, and all DATA items before POST_DATA items. That is
4095  * not certain to be true in older archives, though, and in any case use
4096  * of a list file would destroy that ordering (cf. SortTocFromFile). So
4097  * this loop cannot assume that it holds.
4098  */
4100  skipped_some = false;
4101  for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
4102  {
4103  bool do_now = true;
4104 
4105  if (next_work_item->section != SECTION_PRE_DATA)
4106  {
4107  /* DATA and POST_DATA items are just ignored for now */
4108  if (next_work_item->section == SECTION_DATA ||
4109  next_work_item->section == SECTION_POST_DATA)
4110  {
4111  do_now = false;
4112  skipped_some = true;
4113  }
4114  else
4115  {
4116  /*
4117  * SECTION_NONE items, such as comments, can be processed now
4118  * if we are still in the PRE_DATA part of the archive. Once
4119  * we've skipped any items, we have to consider whether the
4120  * comment's dependencies are satisfied, so skip it for now.
4121  */
4122  if (skipped_some)
4123  do_now = false;
4124  }
4125  }
4126 
4127  /*
4128  * Also skip items that need to be forced into later passes. We need
4129  * not set skipped_some in this case, since by assumption no main-pass
4130  * items could depend on these.
4131  */
4132  if (_tocEntryRestorePass(next_work_item) != RESTORE_PASS_MAIN)
4133  do_now = false;
4134 
4135  if (do_now)
4136  {
4137  /* OK, restore the item and update its dependencies */
4138  pg_log_info("processing item %d %s %s",
4139  next_work_item->dumpId,
4140  next_work_item->desc, next_work_item->tag);
4141 
4142  (void) restore_toc_entry(AH, next_work_item, false);
4143 
4144  /* Reduce dependencies, but don't move anything to ready_heap */
4145  reduce_dependencies(AH, next_work_item, NULL);
4146  }
4147  else
4148  {
4149  /* Nope, so add it to pending_list */
4150  pending_list_append(pending_list, next_work_item);
4151  }
4152  }
4153 
4154  /*
4155  * In --transaction-size mode, we must commit the open transaction before
4156  * dropping the database connection. This also ensures that child workers
4157  * can see the objects we've created so far.
4158  */
4159  if (AH->public.ropt->txn_size > 0)
4160  CommitTransaction(&AH->public);
4161 
4162  /*
4163  * Now close parent connection in prep for parallel steps. We do this
4164  * mainly to ensure that we don't exceed the specified number of parallel
4165  * connections.
4166  */
4167  DisconnectDatabase(&AH->public);
4168 
4169  /* blow away any transient state from the old connection */
4170  free(AH->currUser);
4171  AH->currUser = NULL;
4172  free(AH->currSchema);
4173  AH->currSchema = NULL;
4174  free(AH->currTablespace);
4175  AH->currTablespace = NULL;
4176  free(AH->currTableAm);
4177  AH->currTableAm = NULL;
4178 }
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 812 of file pg_backup_archiver.c.

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

332 {
333  ArchiveHandle *AH = (ArchiveHandle *) AHX;
334  RestoreOptions *ropt = AH->public.ropt;
335  bool parallel_mode;
336  TocEntry *te;
337  CompressFileHandle *sav;
338 
340 
341  /*
342  * If we're going to do parallel restore, there are some restrictions.
343  */
344  parallel_mode = (AH->public.numWorkers > 1 && ropt->useDB);
345  if (parallel_mode)
346  {
347  /* We haven't got round to making this work for all archive formats */
348  if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
349  pg_fatal("parallel restore is not supported with this archive file format");
350 
351  /* Doesn't work if the archive represents dependencies as OIDs */
352  if (AH->version < K_VERS_1_8)
353  pg_fatal("parallel restore is not supported with archives made by pre-8.0 pg_dump");
354 
355  /*
356  * It's also not gonna work if we can't reopen the input file, so
357  * let's try that immediately.
358  */
359  AH->ReopenPtr(AH);
360  }
361 
362  /*
363  * Make sure we won't need (de)compression we haven't got
364  */
365  if (AH->PrintTocDataPtr != NULL)
366  {
367  for (te = AH->toc->next; te != AH->toc; te = te->next)
368  {
369  if (te->hadDumper && (te->reqs & REQ_DATA) != 0)
370  {
372 
373  if (errmsg)
374  pg_fatal("cannot restore from compressed archive (%s)",
375  errmsg);
376  else
377  break;
378  }
379  }
380  }
381 
382  /*
383  * Prepare index arrays, so we can assume we have them throughout restore.
384  * It's possible we already did this, though.
385  */
386  if (AH->tocsByDumpId == NULL)
388 
389  /*
390  * If we're using a DB connection, then connect it.
391  */
392  if (ropt->useDB)
393  {
394  pg_log_info("connecting to database for restore");
395  if (AH->version < K_VERS_1_3)
396  pg_fatal("direct database connections are not supported in pre-1.3 archives");
397 
398  /*
399  * We don't want to guess at whether the dump will successfully
400  * restore; allow the attempt regardless of the version of the restore
401  * target.
402  */
403  AHX->minRemoteVersion = 0;
404  AHX->maxRemoteVersion = 9999999;
405 
406  ConnectDatabase(AHX, &ropt->cparams, false);
407 
408  /*
409  * If we're talking to the DB directly, don't send comments since they
410  * obscure SQL when displaying errors
411  */
412  AH->noTocComments = 1;
413  }
414 
415  /*
416  * Work out if we have an implied data-only restore. This can happen if
417  * the dump was data only or if the user has used a toc list to exclude
418  * all of the schema data. All we do is look for schema entries - if none
419  * are found then we set the dataOnly flag.
420  *
421  * We could scan for wanted TABLE entries, but that is not the same as
422  * dataOnly. At this stage, it seems unnecessary (6-Mar-2001).
423  */
424  if (!ropt->dataOnly)
425  {
426  int impliedDataOnly = 1;
427 
428  for (te = AH->toc->next; te != AH->toc; te = te->next)
429  {
430  if ((te->reqs & REQ_SCHEMA) != 0)
431  { /* It's schema, and it's wanted */
432  impliedDataOnly = 0;
433  break;
434  }
435  }
436  if (impliedDataOnly)
437  {
438  ropt->dataOnly = impliedDataOnly;
439  pg_log_info("implied data-only restore");
440  }
441  }
442 
443  /*
444  * Setup the output file if necessary.
445  */
446  sav = SaveOutput(AH);
448  SetOutput(AH, ropt->filename, ropt->compression_spec);
449 
450  ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n");
451 
452  if (AH->archiveRemoteVersion)
453  ahprintf(AH, "-- Dumped from database version %s\n",
455  if (AH->archiveDumpVersion)
456  ahprintf(AH, "-- Dumped by pg_dump version %s\n",
457  AH->archiveDumpVersion);
458 
459  ahprintf(AH, "\n");
460 
461  if (AH->public.verbose)
462  dumpTimestamp(AH, "Started on", AH->createDate);
463 
464  if (ropt->single_txn)
465  {
466  if (AH->connection)
467  StartTransaction(AHX);
468  else
469  ahprintf(AH, "BEGIN;\n\n");
470  }
471 
472  /*
473  * Establish important parameter values right away.
474  */