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 "dumputils.h"
#include "fe_utils/string_utils.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.

Data Structures

struct  _outputContext
 
struct  _parallelReadyList
 

Macros

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

Typedefs

typedef struct _outputContext OutputContext
 
typedef struct _parallelReadyList ParallelReadyList
 

Functions

static ArchiveHandle_allocAH (const char *FileSpec, const ArchiveFormat fmt, const pg_compress_specification compression_spec, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupWorkerPtr)
 
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 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 OutputContext SaveOutput (ArchiveHandle *AH)
 
static void RestoreOutput (ArchiveHandle *AH, OutputContext savedContext)
 
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 void ready_list_init (ParallelReadyList *ready_list, int tocCount)
 
static void ready_list_free (ParallelReadyList *ready_list)
 
static void ready_list_insert (ParallelReadyList *ready_list, TocEntry *te)
 
static void ready_list_remove (ParallelReadyList *ready_list, int i)
 
static void ready_list_sort (ParallelReadyList *ready_list)
 
static int TocEntrySizeCompare (const void *p1, const void *p2)
 
static void move_to_ready_list (TocEntry *pending_list, ParallelReadyList *ready_list, RestorePass pass)
 
static TocEntrypop_next_work_item (ParallelReadyList *ready_list, 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, ParallelReadyList *ready_list)
 
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)
 
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)
 
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 43 of file pg_backup_archiver.c.

◆ TEXT_DUMPALL_HEADER

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

Definition at line 44 of file pg_backup_archiver.c.

Typedef Documentation

◆ OutputContext

typedef struct _outputContext OutputContext

◆ ParallelReadyList

Function Documentation

◆ _allocAH()

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

Definition at line 2216 of file pg_backup_archiver.c.

2220 {
2221  ArchiveHandle *AH;
2222 
2223  pg_log_debug("allocating AH for %s, format %d",
2224  FileSpec ? FileSpec : "(stdio)", fmt);
2225 
2226  AH = (ArchiveHandle *) pg_malloc0(sizeof(ArchiveHandle));
2227 
2228  AH->version = K_VERS_SELF;
2229 
2230  /* initialize for backwards compatible string processing */
2231  AH->public.encoding = 0; /* PG_SQL_ASCII */
2232  AH->public.std_strings = false;
2233 
2234  /* sql error handling */
2235  AH->public.exit_on_error = true;
2236  AH->public.n_errors = 0;
2237 
2238  AH->archiveDumpVersion = PG_VERSION;
2239 
2240  AH->createDate = time(NULL);
2241 
2242  AH->intSize = sizeof(int);
2243  AH->offSize = sizeof(pgoff_t);
2244  if (FileSpec)
2245  {
2246  AH->fSpec = pg_strdup(FileSpec);
2247 
2248  /*
2249  * Not used; maybe later....
2250  *
2251  * AH->workDir = pg_strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
2252  * i--) if (AH->workDir[i-1] == '/')
2253  */
2254  }
2255  else
2256  AH->fSpec = NULL;
2257 
2258  AH->currUser = NULL; /* unknown */
2259  AH->currSchema = NULL; /* ditto */
2260  AH->currTablespace = NULL; /* ditto */
2261  AH->currTableAm = NULL; /* ditto */
2262 
2263  AH->toc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
2264 
2265  AH->toc->next = AH->toc;
2266  AH->toc->prev = AH->toc;
2267 
2268  AH->mode = mode;
2269  AH->compression_spec = compression_spec;
2270  AH->dosync = dosync;
2271 
2272  memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse));
2273 
2274  /* Open stdout with no compression for AH output handle */
2275  AH->gzOut = 0;
2276  AH->OF = stdout;
2277 
2278  /*
2279  * On Windows, we need to use binary mode to read/write non-text files,
2280  * which include all archive formats as well as compressed plain text.
2281  * Force stdin/stdout into binary mode if that is what we are using.
2282  */
2283 #ifdef WIN32
2284  if ((fmt != archNull || compression_spec.algorithm != PG_COMPRESSION_NONE) &&
2285  (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
2286  {
2287  if (mode == archModeWrite)
2288  _setmode(fileno(stdout), O_BINARY);
2289  else
2290  _setmode(fileno(stdin), O_BINARY);
2291  }
2292 #endif
2293 
2294  AH->SetupWorkerPtr = setupWorkerPtr;
2295 
2296  if (fmt == archUnknown)
2297  AH->format = _discoverArchiveFormat(AH);
2298  else
2299  AH->format = fmt;
2300 
2301  switch (AH->format)
2302  {
2303  case archCustom:
2305  break;
2306 
2307  case archNull:
2308  InitArchiveFmt_Null(AH);
2309  break;
2310 
2311  case archDirectory:
2313  break;
2314 
2315  case archTar:
2316  InitArchiveFmt_Tar(AH);
2317  break;
2318 
2319  default:
2320  pg_fatal("unrecognized file format \"%d\"", fmt);
2321  }
2322 
2323  return AH;
2324 }
@ PG_COMPRESSION_NONE
Definition: compression.h:19
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static void const char * fmt
#define pg_log_debug(...)
Definition: logging.h:133
@ archModeWrite
Definition: pg_backup.h:50
@ archUnknown
Definition: pg_backup.h:40
@ archTar
Definition: pg_backup.h:42
@ archCustom
Definition: pg_backup.h:41
@ archDirectory
Definition: pg_backup.h:44
@ archNull
Definition: pg_backup.h:43
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:65
static bool dosync
Definition: pg_dump.c:101
bool exit_on_error
Definition: pg_backup.h:234
int n_errors
Definition: pg_backup.h:235
bool std_strings
Definition: pg_backup.h:227
int encoding
Definition: pg_backup.h:226
ArchiveFormat format
struct _tocEntry * toc
pg_compress_specification compression_spec
sqlparseInfo sqlparse
SetupWorkerPtrType SetupWorkerPtr
struct _tocEntry * prev
struct _tocEntry * next
pg_compress_algorithm algorithm
Definition: compression.h:29
#define pgoff_t
Definition: win32_port.h:211

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, _archiveHandle::gzOut, InitArchiveFmt_Custom(), InitArchiveFmt_Directory(), InitArchiveFmt_Null(), InitArchiveFmt_Tar(), _archiveHandle::intSize, K_VERS_SELF, mode, _archiveHandle::mode, Archive::n_errors, _tocEntry::next, _archiveHandle::OF, _archiveHandle::offSize, 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, _archiveHandle::toc, and _archiveHandle::version.

Referenced by CreateArchive(), and OpenArchive().

◆ _becomeOwner()

static void _becomeOwner ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 3242 of file pg_backup_archiver.c.

3243 {
3244  RestoreOptions *ropt = AH->public.ropt;
3245 
3246  if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
3247  return;
3248 
3249  _becomeUser(AH, te->owner);
3250 }
static void _becomeUser(ArchiveHandle *AH, const char *user)
RestoreOptions * ropt
Definition: pg_backup.h:212

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

3220 {
3221  if (!user)
3222  user = ""; /* avoid null pointers */
3223 
3224  if (AH->currUser && strcmp(AH->currUser, user) == 0)
3225  return; /* no need to do anything */
3226 
3227  _doSetSessionAuth(AH, user);
3228 
3229  /*
3230  * NOTE: currUser keeps track of what the imaginary session user in our
3231  * script is
3232  */
3233  free(AH->currUser);
3234  AH->currUser = pg_strdup(user);
3235 }
#define free(a)
Definition: header.h:65
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user)
static char * user
Definition: pg_regress.c:93

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

989 {
990  RestoreOptions *ropt = AH->public.ropt;
991 
992  /* This hack is only needed in a data-only restore */
993  if (!ropt->dataOnly || !ropt->disable_triggers)
994  return;
995 
996  pg_log_info("disabling triggers for %s", te->tag);
997 
998  /*
999  * Become superuser if possible, since they are the only ones who can
1000  * disable constraint triggers. If -S was not given, assume the initial
1001  * user identity is a superuser. (XXX would it be better to become the
1002  * table owner?)
1003  */
1004  _becomeUser(AH, ropt->superuser);
1005 
1006  /*
1007  * Disable them.
1008  */
1009  ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
1010  fmtQualifiedId(te->namespace, te->tag));
1011 }
#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:103
int disable_triggers
Definition: pg_backup.h:99

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

2077 {
2078  FILE *fh;
2079  char sig[6]; /* More than enough */
2080  size_t cnt;
2081  int wantClose = 0;
2082 
2083  pg_log_debug("attempting to ascertain archive format");
2084 
2085  free(AH->lookahead);
2086 
2087  AH->readHeader = 0;
2088  AH->lookaheadSize = 512;
2089  AH->lookahead = pg_malloc0(512);
2090  AH->lookaheadLen = 0;
2091  AH->lookaheadPos = 0;
2092 
2093  if (AH->fSpec)
2094  {
2095  struct stat st;
2096 
2097  wantClose = 1;
2098 
2099  /*
2100  * Check if the specified archive is a directory. If so, check if
2101  * there's a "toc.dat" (or "toc.dat.gz") file in it.
2102  */
2103  if (stat(AH->fSpec, &st) == 0 && S_ISDIR(st.st_mode))
2104  {
2105  char buf[MAXPGPATH];
2106 
2107  if (snprintf(buf, MAXPGPATH, "%s/toc.dat", AH->fSpec) >= MAXPGPATH)
2108  pg_fatal("directory name too long: \"%s\"",
2109  AH->fSpec);
2110  if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
2111  {
2112  AH->format = archDirectory;
2113  return AH->format;
2114  }
2115 
2116 #ifdef HAVE_LIBZ
2117  if (snprintf(buf, MAXPGPATH, "%s/toc.dat.gz", AH->fSpec) >= MAXPGPATH)
2118  pg_fatal("directory name too long: \"%s\"",
2119  AH->fSpec);
2120  if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
2121  {
2122  AH->format = archDirectory;
2123  return AH->format;
2124  }
2125 #endif
2126  pg_fatal("directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)",
2127  AH->fSpec);
2128  fh = NULL; /* keep compiler quiet */
2129  }
2130  else
2131  {
2132  fh = fopen(AH->fSpec, PG_BINARY_R);
2133  if (!fh)
2134  pg_fatal("could not open input file \"%s\": %m", AH->fSpec);
2135  }
2136  }
2137  else
2138  {
2139  fh = stdin;
2140  if (!fh)
2141  pg_fatal("could not open input file: %m");
2142  }
2143 
2144  if ((cnt = fread(sig, 1, 5, fh)) != 5)
2145  {
2146  if (ferror(fh))
2147  pg_fatal("could not read input file: %m");
2148  else
2149  pg_fatal("input file is too short (read %lu, expected 5)",
2150  (unsigned long) cnt);
2151  }
2152 
2153  /* Save it, just in case we need it later */
2154  memcpy(&AH->lookahead[0], sig, 5);
2155  AH->lookaheadLen = 5;
2156 
2157  if (strncmp(sig, "PGDMP", 5) == 0)
2158  {
2159  /* It's custom format, stop here */
2160  AH->format = archCustom;
2161  AH->readHeader = 1;
2162  }
2163  else
2164  {
2165  /*
2166  * *Maybe* we have a tar archive format file or a text dump ... So,
2167  * read first 512 byte header...
2168  */
2169  cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh);
2170  /* read failure is checked below */
2171  AH->lookaheadLen += cnt;
2172 
2173  if (AH->lookaheadLen >= strlen(TEXT_DUMPALL_HEADER) &&
2174  (strncmp(AH->lookahead, TEXT_DUMP_HEADER, strlen(TEXT_DUMP_HEADER)) == 0 ||
2175  strncmp(AH->lookahead, TEXT_DUMPALL_HEADER, strlen(TEXT_DUMPALL_HEADER)) == 0))
2176  {
2177  /*
2178  * looks like it's probably a text format dump. so suggest they
2179  * try psql
2180  */
2181  pg_fatal("input file appears to be a text format dump. Please use psql.");
2182  }
2183 
2184  if (AH->lookaheadLen != 512)
2185  {
2186  if (feof(fh))
2187  pg_fatal("input file does not appear to be a valid archive (too short?)");
2188  else
2189  READ_ERROR_EXIT(fh);
2190  }
2191 
2192  if (!isValidTarHeader(AH->lookahead))
2193  pg_fatal("input file does not appear to be a valid archive");
2194 
2195  AH->format = archTar;
2196  }
2197 
2198  /* Close the file if we opened it */
2199  if (wantClose)
2200  {
2201  if (fclose(fh) != 0)
2202  pg_fatal("could not close input file: %m");
2203  /* Forget lookahead, since we'll re-read header after re-opening */
2204  AH->readHeader = 0;
2205  AH->lookaheadLen = 0;
2206  }
2207 
2208  return AH->format;
2209 }
#define PG_BINARY_R
Definition: c.h:1211
#define TEXT_DUMPALL_HEADER
#define TEXT_DUMP_HEADER
bool isValidTarHeader(char *header)
#define READ_ERROR_EXIT(fd)
#define MAXPGPATH
static int sig
Definition: pg_ctl.c:79
static char * buf
Definition: pg_test_fsync.c:67
#define snprintf
Definition: port.h:238
#define stat
Definition: win32_port.h:286
#define S_ISDIR(m)
Definition: win32_port.h:327
#define S_ISREG(m)
Definition: win32_port.h:330

References archCustom, archDirectory, archTar, buf, _archiveHandle::format, free, _archiveHandle::fSpec, isValidTarHeader(), _archiveHandle::lookahead, _archiveHandle::lookaheadLen, _archiveHandle::lookaheadPos, _archiveHandle::lookaheadSize, MAXPGPATH, PG_BINARY_R, pg_fatal, pg_log_debug, pg_malloc0(), READ_ERROR_EXIT, _archiveHandle::readHeader, S_ISDIR, S_ISREG, sig, snprintf, stat::st_mode, stat, TEXT_DUMP_HEADER, and TEXT_DUMPALL_HEADER.

Referenced by _allocAH().

◆ _doSetFixedOutputState()

static void _doSetFixedOutputState ( ArchiveHandle AH)
static

Definition at line 3082 of file pg_backup_archiver.c.

3083 {
3084  RestoreOptions *ropt = AH->public.ropt;
3085 
3086  /*
3087  * Disable timeouts to allow for slow commands, idle parallel workers, etc
3088  */
3089  ahprintf(AH, "SET statement_timeout = 0;\n");
3090  ahprintf(AH, "SET lock_timeout = 0;\n");
3091  ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
3092 
3093  /* Select the correct character set encoding */
3094  ahprintf(AH, "SET client_encoding = '%s';\n",
3096 
3097  /* Select the correct string literal syntax */
3098  ahprintf(AH, "SET standard_conforming_strings = %s;\n",
3099  AH->public.std_strings ? "on" : "off");
3100 
3101  /* Select the role to be used during restore */
3102  if (ropt && ropt->use_role)
3103  ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));
3104 
3105  /* Select the dump-time search_path */
3106  if (AH->public.searchpath)
3107  ahprintf(AH, "%s", AH->public.searchpath);
3108 
3109  /* Make sure function checking is disabled */
3110  ahprintf(AH, "SET check_function_bodies = false;\n");
3111 
3112  /* Ensure that all valid XML data will be accepted */
3113  ahprintf(AH, "SET xmloption = content;\n");
3114 
3115  /* Avoid annoying notices etc */
3116  ahprintf(AH, "SET client_min_messages = warning;\n");
3117  if (!AH->public.std_strings)
3118  ahprintf(AH, "SET escape_string_warning = off;\n");
3119 
3120  /* Adjust row-security state */
3121  if (ropt && ropt->enable_row_security)
3122  ahprintf(AH, "SET row_security = on;\n");
3123  else
3124  ahprintf(AH, "SET row_security = off;\n");
3125 
3126  ahprintf(AH, "\n");
3127 }
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:588
const char * fmtId(const char *rawid)
Definition: string_utils.c:64
char * searchpath
Definition: pg_backup.h:230
char * use_role
Definition: pg_backup.h:104
int enable_row_security
Definition: pg_backup.h:154

References ahprintf(), _restoreOptions::enable_row_security, Archive::encoding, fmtId(), pg_encoding_to_char(), _archiveHandle::public, Archive::ropt, Archive::searchpath, Archive::std_strings, 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 3135 of file pg_backup_archiver.c.

3136 {
3138 
3139  appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3140 
3141  /*
3142  * SQL requires a string literal here. Might as well be correct.
3143  */
3144  if (user && *user)
3145  appendStringLiteralAHX(cmd, user, AH);
3146  else
3147  appendPQExpBufferStr(cmd, "DEFAULT");
3148  appendPQExpBufferChar(cmd, ';');
3149 
3150  if (RestoringToDB(AH))
3151  {
3152  PGresult *res;
3153 
3154  res = PQexec(AH->connection, cmd->data);
3155 
3156  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3157  /* NOT warn_or_exit_horribly... use -O instead to skip this. */
3158  pg_fatal("could not set session user to \"%s\": %s",
3160 
3161  PQclear(res);
3162  }
3163  else
3164  ahprintf(AH, "%s\n\n", cmd->data);
3165 
3166  destroyPQExpBuffer(cmd);
3167 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6743
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3240
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2225
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:97
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 1014 of file pg_backup_archiver.c.

1015 {
1016  RestoreOptions *ropt = AH->public.ropt;
1017 
1018  /* This hack is only needed in a data-only restore */
1019  if (!ropt->dataOnly || !ropt->disable_triggers)
1020  return;
1021 
1022  pg_log_info("enabling triggers for %s", te->tag);
1023 
1024  /*
1025  * Become superuser if possible, since they are the only ones who can
1026  * disable constraint triggers. If -S was not given, assume the initial
1027  * user identity is a superuser. (XXX would it be better to become the
1028  * table owner?)
1029  */
1030  _becomeUser(AH, ropt->superuser);
1031 
1032  /*
1033  * Enable them.
1034  */
1035  ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
1036  fmtQualifiedId(te->namespace, te->tag));
1037 }

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

◆ _getObjectDescription()

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

Definition at line 3422 of file pg_backup_archiver.c.

3423 {
3424  const char *type = te->desc;
3425 
3426  /* objects that don't require special decoration */
3427  if (strcmp(type, "COLLATION") == 0 ||
3428  strcmp(type, "CONVERSION") == 0 ||
3429  strcmp(type, "DOMAIN") == 0 ||
3430  strcmp(type, "FOREIGN TABLE") == 0 ||
3431  strcmp(type, "MATERIALIZED VIEW") == 0 ||
3432  strcmp(type, "SEQUENCE") == 0 ||
3433  strcmp(type, "STATISTICS") == 0 ||
3434  strcmp(type, "TABLE") == 0 ||
3435  strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
3436  strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 ||
3437  strcmp(type, "TYPE") == 0 ||
3438  strcmp(type, "VIEW") == 0 ||
3439  /* non-schema-specified objects */
3440  strcmp(type, "DATABASE") == 0 ||
3441  strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
3442  strcmp(type, "SCHEMA") == 0 ||
3443  strcmp(type, "EVENT TRIGGER") == 0 ||
3444  strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
3445  strcmp(type, "SERVER") == 0 ||
3446  strcmp(type, "PUBLICATION") == 0 ||
3447  strcmp(type, "SUBSCRIPTION") == 0)
3448  {
3449  appendPQExpBuffer(buf, "%s ", type);
3450  if (te->namespace && *te->namespace)
3451  appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
3453  }
3454  /* LOs just have a name, but it's numeric so must not use fmtId */
3455  else if (strcmp(type, "BLOB") == 0)
3456  {
3457  appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag);
3458  }
3459  /*
3460  * These object types require additional decoration. Fortunately, the
3461  * information needed is exactly what's in the DROP command.
3462  */
3463  else if (strcmp(type, "AGGREGATE") == 0 ||
3464  strcmp(type, "FUNCTION") == 0 ||
3465  strcmp(type, "OPERATOR") == 0 ||
3466  strcmp(type, "OPERATOR CLASS") == 0 ||
3467  strcmp(type, "OPERATOR FAMILY") == 0 ||
3468  strcmp(type, "PROCEDURE") == 0)
3469  {
3470  /* Chop "DROP " off the front and make a modifiable copy */
3471  char *first = pg_strdup(te->dropStmt + 5);
3472  char *last;
3473 
3474  /* point to last character in string */
3475  last = first + strlen(first) - 1;
3476 
3477  /* Strip off any ';' or '\n' at the end */
3478  while (last >= first && (*last == '\n' || *last == ';'))
3479  last--;
3480  *(last + 1) = '\0';
3481 
3482  appendPQExpBufferStr(buf, first);
3483 
3484  free(first);
3485  return;
3486  }
3487  /* these object types don't have separate owners */
3488  else if (strcmp(type, "CAST") == 0 ||
3489  strcmp(type, "CHECK CONSTRAINT") == 0 ||
3490  strcmp(type, "CONSTRAINT") == 0 ||
3491  strcmp(type, "DATABASE PROPERTIES") == 0 ||
3492  strcmp(type, "DEFAULT") == 0 ||
3493  strcmp(type, "FK CONSTRAINT") == 0 ||
3494  strcmp(type, "INDEX") == 0 ||
3495  strcmp(type, "RULE") == 0 ||
3496  strcmp(type, "TRIGGER") == 0 ||
3497  strcmp(type, "ROW SECURITY") == 0 ||
3498  strcmp(type, "POLICY") == 0 ||
3499  strcmp(type, "USER MAPPING") == 0)
3500  {
3501  /* do nothing */
3502  }
3503  else
3504  pg_fatal("don't know how to set owner for object type \"%s\"", type);
3505 }
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265

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

Referenced by _printTocEntry().

◆ _moveBefore()

static void _moveBefore ( TocEntry pos,
TocEntry te 
)
static

Definition at line 1808 of file pg_backup_archiver.c.

1809 {
1810  /* Unlink te from list */
1811  te->prev->next = te->next;
1812  te->next->prev = te->prev;
1813 
1814  /* and insert it before "pos" */
1815  te->prev = pos->prev;
1816  te->next = pos;
1817  pos->prev->next = te;
1818  pos->prev = te;
1819 }

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

Referenced by SortTocFromFile().

◆ _printTocEntry()

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

Definition at line 3515 of file pg_backup_archiver.c.

3516 {
3517  RestoreOptions *ropt = AH->public.ropt;
3518 
3519  /* Select owner, schema, tablespace and default AM as necessary */
3520  _becomeOwner(AH, te);
3521  _selectOutputSchema(AH, te->namespace);
3522  _selectTablespace(AH, te->tablespace);
3524 
3525  /* Emit header comment for item */
3526  if (!AH->noTocComments)
3527  {
3528  const char *pfx;
3529  char *sanitized_name;
3530  char *sanitized_schema;
3531  char *sanitized_owner;
3532 
3533  if (isData)
3534  pfx = "Data for ";
3535  else
3536  pfx = "";
3537 
3538  ahprintf(AH, "--\n");
3539  if (AH->public.verbose)
3540  {
3541  ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
3542  te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
3543  if (te->nDeps > 0)
3544  {
3545  int i;
3546 
3547  ahprintf(AH, "-- Dependencies:");
3548  for (i = 0; i < te->nDeps; i++)
3549  ahprintf(AH, " %d", te->dependencies[i]);
3550  ahprintf(AH, "\n");
3551  }
3552  }
3553 
3554  sanitized_name = sanitize_line(te->tag, false);
3555  sanitized_schema = sanitize_line(te->namespace, true);
3556  sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
3557 
3558  ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
3559  pfx, sanitized_name, te->desc, sanitized_schema,
3560  sanitized_owner);
3561 
3562  free(sanitized_name);
3563  free(sanitized_schema);
3564  free(sanitized_owner);
3565 
3566  if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace)
3567  {
3568  char *sanitized_tablespace;
3569 
3570  sanitized_tablespace = sanitize_line(te->tablespace, false);
3571  ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
3572  free(sanitized_tablespace);
3573  }
3574  ahprintf(AH, "\n");
3575 
3576  if (AH->PrintExtraTocPtr != NULL)
3577  AH->PrintExtraTocPtr(AH, te);
3578  ahprintf(AH, "--\n\n");
3579  }
3580 
3581  /*
3582  * Actually print the definition.
3583  *
3584  * Really crude hack for suppressing AUTHORIZATION clause that old pg_dump
3585  * versions put into CREATE SCHEMA. Don't mutate the variant for schema
3586  * "public" that is a comment. We have to do this when --no-owner mode is
3587  * selected. This is ugly, but I see no other good way ...
3588  */
3589  if (ropt->noOwner &&
3590  strcmp(te->desc, "SCHEMA") == 0 && strncmp(te->defn, "--", 2) != 0)
3591  {
3592  ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
3593  }
3594  else
3595  {
3596  if (te->defn && strlen(te->defn) > 0)
3597  ahprintf(AH, "%s\n\n", te->defn);
3598  }
3599 
3600  /*
3601  * If we aren't using SET SESSION AUTH to determine ownership, we must
3602  * instead issue an ALTER OWNER command. Schema "public" is special; when
3603  * a dump emits a comment in lieu of creating it, we use ALTER OWNER even
3604  * when using SET SESSION for all other objects. We assume that anything
3605  * without a DROP command is not a separately ownable object.
3606  */
3607  if (!ropt->noOwner &&
3608  (!ropt->use_setsessauth ||
3609  (strcmp(te->desc, "SCHEMA") == 0 &&
3610  strncmp(te->defn, "--", 2) == 0)) &&
3611  te->owner && strlen(te->owner) > 0 &&
3612  te->dropStmt && strlen(te->dropStmt) > 0)
3613  {
3614  PQExpBufferData temp;
3615 
3616  initPQExpBuffer(&temp);
3617  _getObjectDescription(&temp, te);
3618  /*
3619  * If _getObjectDescription() didn't fill the buffer, then there is no
3620  * owner.
3621  */
3622  if (temp.data[0])
3623  ahprintf(AH, "ALTER %s OWNER TO %s;\n\n", temp.data, fmtId(te->owner));
3624  termPQExpBuffer(&temp);
3625  }
3626 
3627  /*
3628  * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
3629  * commands, so we can no longer assume we know the current auth setting.
3630  */
3631  if (_tocEntryIsACL(te))
3632  {
3633  free(AH->currUser);
3634  AH->currUser = NULL;
3635  }
3636 }
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 initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
int verbose
Definition: pg_backup.h:214
Oid tableoid
Definition: pg_backup.h:263
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(), _tocEntry::nDeps, _restoreOptions::noOwner, _restoreOptions::noTablespace, _archiveHandle::noTocComments, CatalogId::oid, _tocEntry::owner, _archiveHandle::PrintExtraTocPtr, _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 3178 of file pg_backup_archiver.c.

3179 {
3180  if (RestoringToDB(AH))
3182  else
3183  {
3184  PQExpBufferData connectbuf;
3185 
3186  initPQExpBuffer(&connectbuf);
3187  appendPsqlMetaConnect(&connectbuf, dbname);
3188  ahprintf(AH, "%s\n", connectbuf.data);
3189  termPQExpBuffer(&connectbuf);
3190  }
3191 
3192  /*
3193  * NOTE: currUser keeps track of what the imaginary session user in our
3194  * script is. It's now effectively reset to the original userID.
3195  */
3196  free(AH->currUser);
3197  AH->currUser = NULL;
3198 
3199  /* don't assume we still know the output schema, tablespace, etc either */
3200  free(AH->currSchema);
3201  AH->currSchema = NULL;
3202 
3203  free(AH->currTableAm);
3204  AH->currTableAm = NULL;
3205 
3206  free(AH->currTablespace);
3207  AH->currTablespace = NULL;
3208 
3209  /* re-establish fixed state */
3211 }
static void _doSetFixedOutputState(ArchiveHandle *AH)
void ReconnectToServer(ArchiveHandle *AH, const char *dbname)
Definition: pg_backup_db.c:74
char * dbname
Definition: streamutil.c:51
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 3258 of file pg_backup_archiver.c.

3259 {
3260  PQExpBuffer qry;
3261 
3262  /*
3263  * If there was a SEARCHPATH TOC entry, we're supposed to just stay with
3264  * that search_path rather than switching to entry-specific paths.
3265  * Otherwise, it's an old archive that will not restore correctly unless
3266  * we set the search_path as it's expecting.
3267  */
3268  if (AH->public.searchpath)
3269  return;
3270 
3271  if (!schemaName || *schemaName == '\0' ||
3272  (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0))
3273  return; /* no need to do anything */
3274 
3275  qry = createPQExpBuffer();
3276 
3277  appendPQExpBuffer(qry, "SET search_path = %s",
3278  fmtId(schemaName));
3279  if (strcmp(schemaName, "pg_catalog") != 0)
3280  appendPQExpBufferStr(qry, ", pg_catalog");
3281 
3282  if (RestoringToDB(AH))
3283  {
3284  PGresult *res;
3285 
3286  res = PQexec(AH->connection, qry->data);
3287 
3288  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3290  "could not set search_path to \"%s\": %s",
3291  schemaName, PQerrorMessage(AH->connection));
3292 
3293  PQclear(res);
3294  }
3295  else
3296  ahprintf(AH, "%s;\n\n", qry->data);
3297 
3298  free(AH->currSchema);
3299  AH->currSchema = pg_strdup(schemaName);
3300 
3301  destroyPQExpBuffer(qry);
3302 }
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 3369 of file pg_backup_archiver.c.

3370 {
3371  RestoreOptions *ropt = AH->public.ropt;
3372  PQExpBuffer cmd;
3373  const char *want,
3374  *have;
3375 
3376  /* do nothing in --no-table-access-method mode */
3377  if (ropt->noTableAm)
3378  return;
3379 
3380  have = AH->currTableAm;
3381  want = tableam;
3382 
3383  if (!want)
3384  return;
3385 
3386  if (have && strcmp(want, have) == 0)
3387  return;
3388 
3389  cmd = createPQExpBuffer();
3390  appendPQExpBuffer(cmd, "SET default_table_access_method = %s;", fmtId(want));
3391 
3392  if (RestoringToDB(AH))
3393  {
3394  PGresult *res;
3395 
3396  res = PQexec(AH->connection, cmd->data);
3397 
3398  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3400  "could not set default_table_access_method: %s",
3401  PQerrorMessage(AH->connection));
3402 
3403  PQclear(res);
3404  }
3405  else
3406  ahprintf(AH, "%s\n\n", cmd->data);
3407 
3408  destroyPQExpBuffer(cmd);
3409 
3410  free(AH->currTableAm);
3411  AH->currTableAm = pg_strdup(want);
3412 }

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

3310 {
3311  RestoreOptions *ropt = AH->public.ropt;
3312  PQExpBuffer qry;
3313  const char *want,
3314  *have;
3315 
3316  /* do nothing in --no-tablespaces mode */
3317  if (ropt->noTablespace)
3318  return;
3319 
3320  have = AH->currTablespace;
3321  want = tablespace;
3322 
3323  /* no need to do anything for non-tablespace object */
3324  if (!want)
3325  return;
3326 
3327  if (have && strcmp(want, have) == 0)
3328  return; /* no need to do anything */
3329 
3330  qry = createPQExpBuffer();
3331 
3332  if (strcmp(want, "") == 0)
3333  {
3334  /* We want the tablespace to be the database's default */
3335  appendPQExpBufferStr(qry, "SET default_tablespace = ''");
3336  }
3337  else
3338  {
3339  /* We want an explicit tablespace */
3340  appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
3341  }
3342 
3343  if (RestoringToDB(AH))
3344  {
3345  PGresult *res;
3346 
3347  res = PQexec(AH->connection, qry->data);
3348 
3349  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3351  "could not set default_tablespace to %s: %s",
3352  fmtId(want), PQerrorMessage(AH->connection));
3353 
3354  PQclear(res);
3355  }
3356  else
3357  ahprintf(AH, "%s;\n\n", qry->data);
3358 
3359  free(AH->currTablespace);
3360  AH->currTablespace = pg_strdup(want);
3361 
3362  destroyPQExpBuffer(qry);
3363 }
char * tablespace
Definition: pgbench.c:225

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

3068 {
3069  /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3070  if (strcmp(te->desc, "ACL") == 0 ||
3071  strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3072  strcmp(te->desc, "DEFAULT ACL") == 0)
3073  return true;
3074  return false;
3075 }

References _tocEntry::desc.

Referenced by _printTocEntry(), and _tocEntryRequired().

◆ _tocEntryRequired()

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

Definition at line 2777 of file pg_backup_archiver.c.

2778 {
2779  int res = REQ_SCHEMA | REQ_DATA;
2780  RestoreOptions *ropt = AH->public.ropt;
2781 
2782  /* These items are treated specially */
2783  if (strcmp(te->desc, "ENCODING") == 0 ||
2784  strcmp(te->desc, "STDSTRINGS") == 0 ||
2785  strcmp(te->desc, "SEARCHPATH") == 0)
2786  return REQ_SPECIAL;
2787 
2788  /*
2789  * DATABASE and DATABASE PROPERTIES also have a special rule: they are
2790  * restored in createDB mode, and not restored otherwise, independently of
2791  * all else.
2792  */
2793  if (strcmp(te->desc, "DATABASE") == 0 ||
2794  strcmp(te->desc, "DATABASE PROPERTIES") == 0)
2795  {
2796  if (ropt->createDB)
2797  return REQ_SCHEMA;
2798  else
2799  return 0;
2800  }
2801 
2802  /*
2803  * Process exclusions that affect certain classes of TOC entries.
2804  */
2805 
2806  /* If it's an ACL, maybe ignore it */
2807  if (ropt->aclsSkip && _tocEntryIsACL(te))
2808  return 0;
2809 
2810  /* If it's a comment, maybe ignore it */
2811  if (ropt->no_comments && strcmp(te->desc, "COMMENT") == 0)
2812  return 0;
2813 
2814  /*
2815  * If it's a publication or a table part of a publication, maybe ignore
2816  * it.
2817  */
2818  if (ropt->no_publications &&
2819  (strcmp(te->desc, "PUBLICATION") == 0 ||
2820  strcmp(te->desc, "PUBLICATION TABLE") == 0 ||
2821  strcmp(te->desc, "PUBLICATION TABLES IN SCHEMA") == 0))
2822  return 0;
2823 
2824  /* If it's a security label, maybe ignore it */
2825  if (ropt->no_security_labels && strcmp(te->desc, "SECURITY LABEL") == 0)
2826  return 0;
2827 
2828  /* If it's a subscription, maybe ignore it */
2829  if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0)
2830  return 0;
2831 
2832  /* Ignore it if section is not to be dumped/restored */
2833  switch (curSection)
2834  {
2835  case SECTION_PRE_DATA:
2836  if (!(ropt->dumpSections & DUMP_PRE_DATA))
2837  return 0;
2838  break;
2839  case SECTION_DATA:
2840  if (!(ropt->dumpSections & DUMP_DATA))
2841  return 0;
2842  break;
2843  case SECTION_POST_DATA:
2844  if (!(ropt->dumpSections & DUMP_POST_DATA))
2845  return 0;
2846  break;
2847  default:
2848  /* shouldn't get here, really, but ignore it */
2849  return 0;
2850  }
2851 
2852  /* Ignore it if rejected by idWanted[] (cf. SortTocFromFile) */
2853  if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
2854  return 0;
2855 
2856  /*
2857  * Check options for selective dump/restore.
2858  */
2859  if (strcmp(te->desc, "ACL") == 0 ||
2860  strcmp(te->desc, "COMMENT") == 0 ||
2861  strcmp(te->desc, "SECURITY LABEL") == 0)
2862  {
2863  /* Database properties react to createDB, not selectivity options. */
2864  if (strncmp(te->tag, "DATABASE ", 9) == 0)
2865  {
2866  if (!ropt->createDB)
2867  return 0;
2868  }
2869  else if (ropt->schemaNames.head != NULL ||
2870  ropt->schemaExcludeNames.head != NULL ||
2871  ropt->selTypes)
2872  {
2873  /*
2874  * In a selective dump/restore, we want to restore these dependent
2875  * TOC entry types only if their parent object is being restored.
2876  * Without selectivity options, we let through everything in the
2877  * archive. Note there may be such entries with no parent, eg
2878  * non-default ACLs for built-in objects.
2879  *
2880  * This code depends on the parent having been marked already,
2881  * which should be the case; if it isn't, perhaps due to
2882  * SortTocFromFile rearrangement, skipping the dependent entry
2883  * seems prudent anyway.
2884  *
2885  * Ideally we'd handle, eg, table CHECK constraints this way too.
2886  * But it's hard to tell which of their dependencies is the one to
2887  * consult.
2888  */
2889  if (te->nDeps != 1 ||
2890  TocIDRequired(AH, te->dependencies[0]) == 0)
2891  return 0;
2892  }
2893  }
2894  else
2895  {
2896  /* Apply selective-restore rules for standalone TOC entries. */
2897  if (ropt->schemaNames.head != NULL)
2898  {
2899  /* If no namespace is specified, it means all. */
2900  if (!te->namespace)
2901  return 0;
2902  if (!simple_string_list_member(&ropt->schemaNames, te->namespace))
2903  return 0;
2904  }
2905 
2906  if (ropt->schemaExcludeNames.head != NULL &&
2907  te->namespace &&
2908  simple_string_list_member(&ropt->schemaExcludeNames, te->namespace))
2909  return 0;
2910 
2911  if (ropt->selTypes)
2912  {
2913  if (strcmp(te->desc, "TABLE") == 0 ||
2914  strcmp(te->desc, "TABLE DATA") == 0 ||
2915  strcmp(te->desc, "VIEW") == 0 ||
2916  strcmp(te->desc, "FOREIGN TABLE") == 0 ||
2917  strcmp(te->desc, "MATERIALIZED VIEW") == 0 ||
2918  strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 ||
2919  strcmp(te->desc, "SEQUENCE") == 0 ||
2920  strcmp(te->desc, "SEQUENCE SET") == 0)
2921  {
2922  if (!ropt->selTable)
2923  return 0;
2924  if (ropt->tableNames.head != NULL &&
2926  return 0;
2927  }
2928  else if (strcmp(te->desc, "INDEX") == 0)
2929  {
2930  if (!ropt->selIndex)
2931  return 0;
2932  if (ropt->indexNames.head != NULL &&
2934  return 0;
2935  }
2936  else if (strcmp(te->desc, "FUNCTION") == 0 ||
2937  strcmp(te->desc, "AGGREGATE") == 0 ||
2938  strcmp(te->desc, "PROCEDURE") == 0)
2939  {
2940  if (!ropt->selFunction)
2941  return 0;
2942  if (ropt->functionNames.head != NULL &&
2944  return 0;
2945  }
2946  else if (strcmp(te->desc, "TRIGGER") == 0)
2947  {
2948  if (!ropt->selTrigger)
2949  return 0;
2950  if (ropt->triggerNames.head != NULL &&
2952  return 0;
2953  }
2954  else
2955  return 0;
2956  }
2957  }
2958 
2959  /*
2960  * Determine whether the TOC entry contains schema and/or data components,
2961  * and mask off inapplicable REQ bits. If it had a dataDumper, assume
2962  * it's both schema and data. Otherwise it's probably schema-only, but
2963  * there are exceptions.
2964  */
2965  if (!te->hadDumper)
2966  {
2967  /*
2968  * Special Case: If 'SEQUENCE SET' or anything to do with LOs, then
2969  * it is considered a data entry. We don't need to check for the
2970  * BLOBS entry or old-style BLOB COMMENTS, because they will have
2971  * hadDumper = true ... but we do need to check new-style BLOB ACLs,
2972  * comments, etc.
2973  */
2974  if (strcmp(te->desc, "SEQUENCE SET") == 0 ||
2975  strcmp(te->desc, "BLOB") == 0 ||
2976  (strcmp(te->desc, "ACL") == 0 &&
2977  strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
2978  (strcmp(te->desc, "COMMENT") == 0 &&
2979  strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
2980  (strcmp(te->desc, "SECURITY LABEL") == 0 &&
2981  strncmp(te->tag, "LARGE OBJECT ", 13) == 0))
2982  res = res & REQ_DATA;
2983  else
2984  res = res & ~REQ_DATA;
2985  }
2986 
2987  /* If there's no definition command, there's no schema component */
2988  if (!te->defn || !te->defn[0])
2989  res = res & ~REQ_SCHEMA;
2990 
2991  /*
2992  * Special case: <Init> type with <Max OID> tag; this is obsolete and we
2993  * always ignore it.
2994  */
2995  if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
2996  return 0;
2997 
2998  /* Mask it if we only want schema */
2999  if (ropt->schemaOnly)
3000  {
3001  /*
3002  * The sequence_data option overrides schemaOnly for SEQUENCE SET.
3003  *
3004  * In binary-upgrade mode, even with schemaOnly set, we do not mask
3005  * out large objects. (Only large object definitions, comments and
3006  * other metadata should be generated in binary-upgrade mode, not the
3007  * actual data, but that need not concern us here.)
3008  */
3009  if (!(ropt->sequence_data && strcmp(te->desc, "SEQUENCE SET") == 0) &&
3010  !(ropt->binary_upgrade &&
3011  (strcmp(te->desc, "BLOB") == 0 ||
3012  (strcmp(te->desc, "ACL") == 0 &&
3013  strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
3014  (strcmp(te->desc, "COMMENT") == 0 &&
3015  strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
3016  (strcmp(te->desc, "SECURITY LABEL") == 0 &&
3017  strncmp(te->tag, "LARGE OBJECT ", 13) == 0))))
3018  res = res & REQ_SCHEMA;
3019  }
3020 
3021  /* Mask it if we only want data */
3022  if (ropt->dataOnly)
3023  res = res & REQ_DATA;
3024 
3025  return res;
3026 }
@ SECTION_POST_DATA
Definition: pg_backup.h:59
@ SECTION_PRE_DATA
Definition: pg_backup.h:57
@ SECTION_DATA
Definition: pg_backup.h:58
int TocIDRequired(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:138
bool * idWanted
Definition: pg_backup.h:153
SimpleStringList functionNames
Definition: pg_backup.h:136
SimpleStringList tableNames
Definition: pg_backup.h:140
SimpleStringList indexNames
Definition: pg_backup.h:135
int no_subscriptions
Definition: pg_backup.h:113
SimpleStringList triggerNames
Definition: pg_backup.h:139
SimpleStringList schemaNames
Definition: pg_backup.h:137
int no_security_labels
Definition: pg_backup.h:112

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, _tocEntry::hadDumper, SimpleStringList::head, _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, 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, TocIDRequired(), and _restoreOptions::triggerNames.

Referenced by PrintTOCSummary(), and ProcessArchiveRestoreOptions().

◆ _tocEntryRestorePass()

static RestorePass _tocEntryRestorePass ( TocEntry te)
static

Definition at line 3034 of file pg_backup_archiver.c.

3035 {
3036  /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3037  if (strcmp(te->desc, "ACL") == 0 ||
3038  strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3039  strcmp(te->desc, "DEFAULT ACL") == 0)
3040  return RESTORE_PASS_ACL;
3041  if (strcmp(te->desc, "EVENT TRIGGER") == 0 ||
3042  strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0)
3043  return RESTORE_PASS_POST_ACL;
3044 
3045  /*
3046  * Comments need to be emitted in the same pass as their parent objects.
3047  * ACLs haven't got comments, and neither do matview data objects, but
3048  * event triggers do. (Fortunately, event triggers haven't got ACLs, or
3049  * we'd need yet another weird special case.)
3050  */
3051  if (strcmp(te->desc, "COMMENT") == 0 &&
3052  strncmp(te->tag, "EVENT TRIGGER ", 14) == 0)
3053  return RESTORE_PASS_POST_ACL;
3054 
3055  /* All else can be handled in the main pass. */
3056  return RESTORE_PASS_MAIN;
3057 }
@ RESTORE_PASS_ACL
@ RESTORE_PASS_MAIN

References _tocEntry::desc, RESTORE_PASS_ACL, RESTORE_PASS_MAIN, and _tocEntry::tag.

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

◆ ahprintf()

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

Definition at line 1603 of file pg_backup_archiver.c.

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

1695 {
1696  int bytes_written = 0;
1697 
1698  if (AH->writingLO)
1699  {
1700  size_t remaining = size * nmemb;
1701 
1702  while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1703  {
1704  size_t avail = AH->lo_buf_size - AH->lo_buf_used;
1705 
1706  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1707  ptr = (const void *) ((const char *) ptr + avail);
1708  remaining -= avail;
1709  AH->lo_buf_used += avail;
1710  dump_lo_buf(AH);
1711  }
1712 
1713  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1714  AH->lo_buf_used += remaining;
1715 
1716  bytes_written = size * nmemb;
1717  }
1718  else if (AH->gzOut)
1719  bytes_written = GZWRITE(ptr, size, nmemb, AH->OF);
1720  else if (AH->CustomOutPtr)
1721  bytes_written = AH->CustomOutPtr(AH, ptr, size * nmemb);
1722 
1723  else
1724  {
1725  /*
1726  * If we're doing a restore, and it's direct to DB, and we're
1727  * connected then send it to the DB.
1728  */
1729  if (RestoringToDB(AH))
1730  bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb);
1731  else
1732  bytes_written = fwrite(ptr, size, nmemb, AH->OF) * size;
1733  }
1734 
1735  if (bytes_written != size * nmemb)
1737 }
int remaining
Definition: informix.c:667
static void dump_lo_buf(ArchiveHandle *AH)
#define GZWRITE(p, s, n, fh)
#define WRITE_ERROR_EXIT
int ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen)
Definition: pg_backup_db.c:445
CustomOutPtrType CustomOutPtr

References _archiveHandle::CustomOutPtr, dump_lo_buf(), ExecuteSqlCommandBuf(), _archiveHandle::gzOut, GZWRITE, _archiveHandle::lo_buf, _archiveHandle::lo_buf_size, _archiveHandle::lo_buf_used, _archiveHandle::OF, _archiveHandle::public, remaining, RestoringToDB(), WRITE_ERROR_EXIT, 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 1066 of file pg_backup_archiver.c.

1068 {
1069  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1070  TocEntry *newToc;
1071 
1072  newToc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
1073 
1074  AH->tocCount++;
1075  if (dumpId > AH->maxDumpId)
1076  AH->maxDumpId = dumpId;
1077 
1078  newToc->prev = AH->toc->prev;
1079  newToc->next = AH->toc;
1080  AH->toc->prev->next = newToc;
1081  AH->toc->prev = newToc;
1082 
1083  newToc->catalogId = catalogId;
1084  newToc->dumpId = dumpId;
1085  newToc->section = opts->section;
1086 
1087  newToc->tag = pg_strdup(opts->tag);
1088  newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
1089  newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
1090  newToc->tableam = opts->tableam ? pg_strdup(opts->tableam) : NULL;
1091  newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
1092  newToc->desc = pg_strdup(opts->description);
1093  newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
1094  newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
1095  newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
1096 
1097  if (opts->nDeps > 0)
1098  {
1099  newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId));
1100  memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
1101  newToc->nDeps = opts->nDeps;
1102  }
1103  else
1104  {
1105  newToc->dependencies = NULL;
1106  newToc->nDeps = 0;
1107  }
1108 
1109  newToc->dataDumper = opts->dumpFn;
1110  newToc->dataDumperArg = opts->dumpArg;
1111  newToc->hadDumper = opts->dumpFn ? true : false;
1112 
1113  newToc->formatData = NULL;
1114  newToc->dataLength = 0;
1115 
1116  if (AH->ArchiveEntryPtr != NULL)
1117  AH->ArchiveEntryPtr(AH, newToc);
1118 
1119  return newToc;
1120 }
return true
Definition: isn.c:126
static AmcheckOptions opts
Definition: pg_amcheck.c:110
int DumpId
Definition: pg_backup.h:267
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(), 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 1464 of file pg_backup_archiver.c.

1465 {
1466  int save_errno = errno;
1467  char *p;
1468  size_t len = 128; /* initial assumption about buffer size */
1469  size_t cnt;
1470 
1471  for (;;)
1472  {
1473  va_list args;
1474 
1475  /* Allocate work buffer. */
1476  p = (char *) pg_malloc(len);
1477 
1478  /* Try to format the data. */
1479  errno = save_errno;
1480  va_start(args, fmt);
1481  cnt = pvsnprintf(p, len, fmt, args);
1482  va_end(args);
1483 
1484  if (cnt < len)
1485  break; /* success */
1486 
1487  /* Release buffer and loop around to try again with larger len. */
1488  free(p);
1489  len = cnt;
1490  }
1491 
1492  WriteData(AH, p, cnt);
1493  free(p);
1494  return (int) cnt;
1495 }
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 1457 of file pg_backup_archiver.c.

1458 {
1459  WriteData(AH, s, strlen(s));
1460 }

References WriteData().

Referenced by dumpTableData_insert().

◆ buildTocEntryArrays()

static void buildTocEntryArrays ( ArchiveHandle AH)
static

Definition at line 1833 of file pg_backup_archiver.c.

1834 {
1835  DumpId maxDumpId = AH->maxDumpId;
1836  TocEntry *te;
1837 
1838  AH->tocsByDumpId = (TocEntry **) pg_malloc0((maxDumpId + 1) * sizeof(TocEntry *));
1839  AH->tableDataId = (DumpId *) pg_malloc0((maxDumpId + 1) * sizeof(DumpId));
1840 
1841  for (te = AH->toc->next; te != AH->toc; te = te->next)
1842  {
1843  /* this check is purely paranoia, maxDumpId should be correct */
1844  if (te->dumpId <= 0 || te->dumpId > maxDumpId)
1845  pg_fatal("bad dumpId");
1846 
1847  /* tocsByDumpId indexes all TOCs by their dump ID */
1848  AH->tocsByDumpId[te->dumpId] = te;
1849 
1850  /*
1851  * tableDataId provides the TABLE DATA item's dump ID for each TABLE
1852  * TOC entry that has a DATA item. We compute this by reversing the
1853  * TABLE DATA item's dependency, knowing that a TABLE DATA item has
1854  * just one dependency and it is the TABLE item.
1855  */
1856  if (strcmp(te->desc, "TABLE DATA") == 0 && te->nDeps > 0)
1857  {
1858  DumpId tableId = te->dependencies[0];
1859 
1860  /*
1861  * The TABLE item might not have been in the archive, if this was
1862  * a data-only dump; but its dump ID should be less than its data
1863  * item's dump ID, so there should be a place for it in the array.
1864  */
1865  if (tableId <= 0 || tableId > maxDumpId)
1866  pg_fatal("bad table dumpId for TABLE DATA item");
1867 
1868  AH->tableDataId[tableId] = te->dumpId;
1869  }
1870  }
1871 }
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 3838 of file pg_backup_archiver.c.

3839 {
3840  pgoff_t tpos;
3841 
3842  /* Check that ftello works on this file */
3843  tpos = ftello(fp);
3844  if (tpos < 0)
3845  return false;
3846 
3847  /*
3848  * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
3849  * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
3850  * successful no-op even on files that are otherwise unseekable.
3851  */
3852  if (fseeko(fp, tpos, SEEK_SET) != 0)
3853  return false;
3854 
3855  return true;
3856 }
#define ftello(stream)
Definition: win32_port.h:221
#define fseeko(stream, offset, origin)
Definition: win32_port.h:218

References fseeko, ftello, and pgoff_t.

Referenced by InitArchiveFmt_Custom(), and InitArchiveFmt_Tar().

◆ CloneArchive()

ArchiveHandle* CloneArchive ( ArchiveHandle AH)

Definition at line 4758 of file pg_backup_archiver.c.

4759 {
4760  ArchiveHandle *clone;
4761 
4762  /* Make a "flat" copy */
4763  clone = (ArchiveHandle *) pg_malloc(sizeof(ArchiveHandle));
4764  memcpy(clone, AH, sizeof(ArchiveHandle));
4765 
4766  /* Handle format-independent fields */
4767  memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse));
4768 
4769  /* The clone will have its own connection, so disregard connection state */
4770  clone->connection = NULL;
4771  clone->connCancel = NULL;
4772  clone->currUser = NULL;
4773  clone->currSchema = NULL;
4774  clone->currTableAm = NULL;
4775  clone->currTablespace = NULL;
4776 
4777  /* savedPassword must be local in case we change it while connecting */
4778  if (clone->savedPassword)
4779  clone->savedPassword = pg_strdup(clone->savedPassword);
4780 
4781  /* clone has its own error count, too */
4782  clone->public.n_errors = 0;
4783 
4784  /*
4785  * Connect our new clone object to the database, using the same connection
4786  * parameters used for the original connection.
4787  */
4788  ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true);
4789 
4790  /* re-establish fixed state */
4791  if (AH->mode == archModeRead)
4792  _doSetFixedOutputState(clone);
4793  /* in write case, setupDumpWorker will fix up connection state */
4794 
4795  /* Let the format-specific code have a chance too */
4796  clone->ClonePtr(clone);
4797 
4798  Assert(clone->connection != NULL);
4799  return clone;
4800 }
Assert(fmt[strlen(fmt) - 1] !='\n')
void ConnectDatabase(Archive *AHX, const ConnParams *cparams, bool isReconnect)
Definition: pg_backup_db.c:110
@ archModeRead
Definition: pg_backup.h:51
PGcancel *volatile connCancel
ClonePtrType ClonePtr
ConnParams cparams
Definition: pg_backup.h:143

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

Referenced by RunWorker().

◆ CloseArchive()

void CloseArchive ( Archive AHX)

Definition at line 272 of file pg_backup_archiver.c.

273 {
274  int res = 0;
275  ArchiveHandle *AH = (ArchiveHandle *) AHX;
276 
277  AH->ClosePtr(AH);
278 
279  /* Close the output */
280  errno = 0; /* in case gzclose() doesn't set it */
281  if (AH->gzOut)
282  res = GZCLOSE(AH->OF);
283  else if (AH->OF != stdout)
284  res = fclose(AH->OF);
285 
286  if (res != 0)
287  pg_fatal("could not close output file: %m");
288 }
#define GZCLOSE(fh)
ClosePtrType ClosePtr

References _archiveHandle::ClosePtr, GZCLOSE, _archiveHandle::gzOut, _archiveHandle::OF, pg_fatal, res, and generate_unaccent_rules::stdout.

Referenced by main().

◆ CreateArchive()

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

Definition at line 243 of file pg_backup_archiver.c.

248 {
249  ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression_spec,
251 
252  return (Archive *) AH;
253 }
static ArchiveHandle * _allocAH(const char *FileSpec, const ArchiveFormat fmt, const pg_compress_specification compression_spec, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupWorkerPtr)
static void setupDumpWorker(Archive *AH)
Definition: pg_dump.c:1268

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

Referenced by main().

◆ DeCloneArchive()

void DeCloneArchive ( ArchiveHandle AH)

Definition at line 4808 of file pg_backup_archiver.c.

4809 {
4810  /* Should not have an open database connection */
4811  Assert(AH->connection == NULL);
4812 
4813  /* Clear format-specific state */
4814  AH->DeClonePtr(AH);
4815 
4816  /* Clear state allocated by CloneArchive */
4817  if (AH->sqlparse.curCmd)
4819 
4820  /* Clear any connection-local state */
4821  free(AH->currUser);
4822  free(AH->currSchema);
4823  free(AH->currTablespace);
4824  free(AH->currTableAm);
4825  free(AH->savedPassword);
4826 
4827  free(AH);
4828 }
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 1651 of file pg_backup_archiver.c.

1652 {
1653  if (AH->connection)
1654  {
1655  int res;
1656 
1657  res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1658  pg_log_debug(ngettext("wrote %zu byte of large object data (result = %d)",
1659  "wrote %zu bytes of large object data (result = %d)",
1660  AH->lo_buf_used),
1661  AH->lo_buf_used, res);
1662  /* We assume there are no short writes, only errors */
1663  if (res != AH->lo_buf_used)
1664  warn_or_exit_horribly(AH, "could not write to large object: %s",
1665  PQerrorMessage(AH->connection));
1666  }
1667  else
1668  {
1670 
1672  (const unsigned char *) AH->lo_buf,
1673  AH->lo_buf_used,
1674  AH);
1675 
1676  /* Hack: turn off writingLO so ahwrite doesn't recurse to here */
1677  AH->writingLO = false;
1678  ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
1679  AH->writingLO = true;
1680 
1682  }
1683  AH->lo_buf_used = 0;
1684 }
int lo_write(int fd, const char *buf, int len)
Definition: be-fsstubs.c:181
#define ngettext(s, p, n)
Definition: c.h:1120
#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 179 of file pg_backup_archiver.c.

180 {
181  DumpOptions *dopt = NewDumpOptions();
182 
183  /* this is the inverse of what's at the end of pg_dump.c's main() */
184  dopt->cparams.dbname = ropt->cparams.dbname ? pg_strdup(ropt->cparams.dbname) : NULL;
185  dopt->cparams.pgport = ropt->cparams.pgport ? pg_strdup(ropt->cparams.pgport) : NULL;
186  dopt->cparams.pghost = ropt->cparams.pghost ? pg_strdup(ropt->cparams.pghost) : NULL;
187  dopt->cparams.username = ropt->cparams.username ? pg_strdup(ropt->cparams.username) : NULL;
189  dopt->outputClean = ropt->dropSchema;
190  dopt->dataOnly = ropt->dataOnly;
191  dopt->schemaOnly = ropt->schemaOnly;
192  dopt->if_exists = ropt->if_exists;
193  dopt->column_inserts = ropt->column_inserts;
194  dopt->dumpSections = ropt->dumpSections;
195  dopt->aclsSkip = ropt->aclsSkip;
196  dopt->outputSuperuser = ropt->superuser;
197  dopt->outputCreateDB = ropt->createDB;
198  dopt->outputNoOwner = ropt->noOwner;
199  dopt->outputNoTableAm = ropt->noTableAm;
200  dopt->outputNoTablespaces = ropt->noTablespace;
201  dopt->disable_triggers = ropt->disable_triggers;
202  dopt->use_setsessauth = ropt->use_setsessauth;
204  dopt->dump_inserts = ropt->dump_inserts;
205  dopt->no_comments = ropt->no_comments;
206  dopt->no_publications = ropt->no_publications;
208  dopt->no_subscriptions = ropt->no_subscriptions;
209  dopt->lockWaitTimeout = ropt->lockWaitTimeout;
212  dopt->sequence_data = ropt->sequence_data;
213 
214  return dopt;
215 }
DumpOptions * NewDumpOptions(void)
char * pgport
Definition: pg_backup.h:84
char * pghost
Definition: pg_backup.h:85
trivalue promptPassword
Definition: pg_backup.h:87
char * username
Definition: pg_backup.h:86
char * dbname
Definition: pg_backup.h:83
bool dataOnly
Definition: pg_backup.h:167
int dump_inserts
Definition: pg_backup.h:171
int column_inserts
Definition: pg_backup.h:175
int use_setsessauth
Definition: pg_backup.h:187
int outputCreateDB
Definition: pg_backup.h:195
bool include_everything
Definition: pg_backup.h:192
int sequence_data
Definition: pg_backup.h:201
int disable_dollar_quoting
Definition: pg_backup.h:174
int no_comments
Definition: pg_backup.h:177
int outputNoTableAm
Definition: pg_backup.h:185
int enable_row_security
Definition: pg_backup.h:188
char * outputSuperuser
Definition: pg_backup.h:199
int dumpSections
Definition: pg_backup.h:168
int no_security_labels
Definition: pg_backup.h:178
int no_publications
Definition: pg_backup.h:179
ConnParams cparams
Definition: pg_backup.h:161
const char * lockWaitTimeout
Definition: pg_backup.h:170
int no_subscriptions
Definition: pg_backup.h:180
bool aclsSkip
Definition: pg_backup.h:169
int outputClean
Definition: pg_backup.h:194
int outputNoTablespaces
Definition: pg_backup.h:186
int disable_triggers
Definition: pg_backup.h:184
int outputNoOwner
Definition: pg_backup.h:198
bool schemaOnly
Definition: pg_backup.h:166
int include_everything
Definition: pg_backup.h:123
int disable_dollar_quoting
Definition: pg_backup.h:106
const char * lockWaitTimeout
Definition: pg_backup.h:122

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

3864 {
3865  char buf[64];
3866 
3867  if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
3868  ahprintf(AH, "-- %s %s\n\n", msg, buf);
3869 }
#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 1246 of file pg_backup_archiver.c.

1247 {
1248  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1249 
1250  if (AH->EndLOPtr)
1251  AH->EndLOPtr(AH, AH->currToc, oid);
1252 
1253  return 1;
1254 }
EndLOPtrType EndLOPtr
struct _tocEntry * currToc

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

Referenced by dumpLOs().

◆ EndRestoreLO()

void EndRestoreLO ( ArchiveHandle AH,
Oid  oid 
)

Definition at line 1350 of file pg_backup_archiver.c.

1351 {
1352  if (AH->lo_buf_used > 0)
1353  {
1354  /* Write remaining bytes from the LO buffer */
1355  dump_lo_buf(AH);
1356  }
1357 
1358  AH->writingLO = false;
1359 
1360  if (AH->connection)
1361  {
1362  lo_close(AH->connection, AH->loFd);
1363  AH->loFd = -1;
1364  }
1365  else
1366  {
1367  ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
1368  }
1369 }
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 1283 of file pg_backup_archiver.c.

1284 {
1285  RestoreOptions *ropt = AH->public.ropt;
1286 
1287  if (!ropt->single_txn)
1288  {
1289  if (AH->connection)
1290  CommitTransaction(&AH->public);
1291  else
1292  ahprintf(AH, "COMMIT;\n\n");
1293  }
1294 
1295  pg_log_info(ngettext("restored %d large object",
1296  "restored %d large objects",
1297  AH->loCount),
1298  AH->loCount);
1299 }
static void CommitTransaction(void)
Definition: xact.c:2141

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

Referenced by _LoadLOs().

◆ fix_dependencies()

static void fix_dependencies ( ArchiveHandle AH)
static

Definition at line 4455 of file pg_backup_archiver.c.

4456 {
4457  TocEntry *te;
4458  int i;
4459 
4460  /*
4461  * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC
4462  * items are marked as not being in any parallel-processing list.
4463  */
4464  for (te = AH->toc->next; te != AH->toc; te = te->next)
4465  {
4466  te->depCount = te->nDeps;
4467  te->revDeps = NULL;
4468  te->nRevDeps = 0;
4469  te->pending_prev = NULL;
4470  te->pending_next = NULL;
4471  }
4472 
4473  /*
4474  * POST_DATA items that are shown as depending on a table need to be
4475  * re-pointed to depend on that table's data, instead. This ensures they
4476  * won't get scheduled until the data has been loaded.
4477  */
4479 
4480  /*
4481  * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB
4482  * COMMENTS to BLOBS. Cope. (We assume there's only one BLOBS and only
4483  * one BLOB COMMENTS in such files.)
4484  */
4485  if (AH->version < K_VERS_1_11)
4486  {
4487  for (te = AH->toc->next; te != AH->toc; te = te->next)
4488  {
4489  if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0)
4490  {
4491  TocEntry *te2;
4492 
4493  for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next)
4494  {
4495  if (strcmp(te2->desc, "BLOBS") == 0)
4496  {
4497  te->dependencies = (DumpId *) pg_malloc(sizeof(DumpId));
4498  te->dependencies[0] = te2->dumpId;
4499  te->nDeps++;
4500  te->depCount++;
4501  break;
4502  }
4503  }
4504  break;
4505  }
4506  }
4507  }
4508 
4509  /*
4510  * At this point we start to build the revDeps reverse-dependency arrays,
4511  * so all changes of dependencies must be complete.
4512  */
4513 
4514  /*
4515  * Count the incoming dependencies for each item. Also, it is possible
4516  * that the dependencies list items that are not in the archive at all
4517  * (that should not happen in 9.2 and later, but is highly likely in older
4518  * archives). Subtract such items from the depCounts.
4519  */
4520  for (te = AH->toc->next; te != AH->toc; te = te->next)
4521  {
4522  for (i = 0; i < te->nDeps; i++)
4523  {
4524  DumpId depid = te->dependencies[i];
4525 
4526  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4527  AH->tocsByDumpId[depid]->nRevDeps++;
4528  else
4529  te->depCount--;
4530  }
4531  }
4532 
4533  /*
4534  * Allocate space for revDeps[] arrays, and reset nRevDeps so we can use
4535  * it as a counter below.
4536  */
4537  for (te = AH->toc->next; te != AH->toc; te = te->next)
4538  {
4539  if (te->nRevDeps > 0)
4540  te->revDeps = (DumpId *) pg_malloc(te->nRevDeps * sizeof(DumpId));
4541  te->nRevDeps = 0;
4542  }
4543 
4544  /*
4545  * Build the revDeps[] arrays of incoming-dependency dumpIds. This had
4546  * better agree with the loops above.
4547  */
4548  for (te = AH->toc->next; te != AH->toc; te = te->next)
4549  {
4550  for (i = 0; i < te->nDeps; i++)
4551  {
4552  DumpId depid = te->dependencies[i];
4553 
4554  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4555  {
4556  TocEntry *otherte = AH->tocsByDumpId[depid];
4557 
4558  otherte->revDeps[otherte->nRevDeps++] = te->dumpId;
4559  }
4560  }
4561  }
4562 
4563  /*
4564  * Lastly, work out the locking dependencies.
4565  */
4566  for (te = AH->toc->next; te != AH->toc; te = te->next)
4567  {
4568  te->lockDeps = NULL;
4569  te->nLockDeps = 0;
4571  }
4572 }
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 1874 of file pg_backup_archiver.c.

1875 {
1876  /* build index arrays if we didn't already */
1877  if (AH->tocsByDumpId == NULL)
1878  buildTocEntryArrays(AH);
1879 
1880  if (id > 0 && id <= AH->maxDumpId)
1881  return AH->tocsByDumpId[id];
1882 
1883  return NULL;
1884 }
static void buildTocEntryArrays(ArchiveHandle *AH)

References buildTocEntryArrays(), and _archiveHandle::tocsByDumpId.

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

◆ has_lock_conflicts()

static bool has_lock_conflicts ( TocEntry te1,
TocEntry te2 
)
static

Definition at line 4146 of file pg_backup_archiver.c.

4147 {
4148  int j,
4149  k;
4150 
4151  for (j = 0; j < te1->nLockDeps; j++)
4152  {
4153  for (k = 0; k < te2->nDeps; k++)
4154  {
4155  if (te1->lockDeps[j] == te2->dependencies[k])
4156  return true;
4157  }
4158  }
4159  return false;
4160 }
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 4619 of file pg_backup_archiver.c.

4620 {
4621  DumpId *lockids;
4622  int nlockids;
4623  int i;
4624 
4625  /*
4626  * We only care about this for POST_DATA items. PRE_DATA items are not
4627  * run in parallel, and DATA items are all independent by assumption.
4628  */
4629  if (te->section != SECTION_POST_DATA)
4630  return;
4631 
4632  /* Quick exit if no dependencies at all */
4633  if (te->nDeps == 0)
4634  return;
4635 
4636  /*
4637  * Most POST_DATA items are ALTER TABLEs or some moral equivalent of that,
4638  * and hence require exclusive lock. However, we know that CREATE INDEX
4639  * does not. (Maybe someday index-creating CONSTRAINTs will fall in that
4640  * category too ... but today is not that day.)
4641  */
4642  if (strcmp(te->desc, "INDEX") == 0)
4643  return;
4644 
4645  /*
4646  * We assume the entry requires exclusive lock on each TABLE or TABLE DATA
4647  * item listed among its dependencies. Originally all of these would have
4648  * been TABLE items, but repoint_table_dependencies would have repointed
4649  * them to the TABLE DATA items if those are present (which they might not
4650  * be, eg in a schema-only dump). Note that all of the entries we are
4651  * processing here are POST_DATA; otherwise there might be a significant
4652  * difference between a dependency on a table and a dependency on its
4653  * data, so that closer analysis would be needed here.
4654  */
4655  lockids = (DumpId *) pg_malloc(te->nDeps * sizeof(DumpId));
4656  nlockids = 0;
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  ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) ||
4663  strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0))
4664  lockids[nlockids++] = depid;
4665  }
4666 
4667  if (nlockids == 0)
4668  {
4669  free(lockids);
4670  return;
4671  }
4672 
4673  te->lockDeps = pg_realloc(lockids, nlockids * sizeof(DumpId));
4674  te->nLockDeps = nlockids;
4675 }
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 4738 of file pg_backup_archiver.c.

4739 {
4740  pg_log_info("table \"%s\" could not be created, will not restore its data",
4741  te->tag);
4742 
4743  if (AH->tableDataId[te->dumpId] != 0)
4744  {
4745  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4746 
4747  ted->reqs = 0;
4748  }
4749 }

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

166 {
167  memset(opts, 0, sizeof(DumpOptions));
168  /* set any fields that shouldn't default to zeroes */
169  opts->include_everything = true;
170  opts->cparams.promptPassword = TRI_DEFAULT;
171  opts->dumpSections = DUMP_UNSECTIONED;
172 }
#define DUMP_UNSECTIONED
@ TRI_DEFAULT
Definition: vacuumlo.c:36

References DUMP_UNSECTIONED, opts, and TRI_DEFAULT.

Referenced by main(), and NewDumpOptions().

◆ mark_create_done()

static void mark_create_done ( ArchiveHandle AH,
TocEntry te 
)
static

Definition at line 4723 of file pg_backup_archiver.c.

4724 {
4725  if (AH->tableDataId[te->dumpId] != 0)
4726  {
4727  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4728 
4729  ted->created = true;
4730  }
4731 }

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

2401 {
2402  pg_log_info("finished item %d %s %s",
2403  te->dumpId, te->desc, te->tag);
2404 
2405  if (status != 0)
2406  pg_fatal("worker process failed: exit code %d",
2407  status);
2408 }
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

References _tocEntry::desc, _tocEntry::dumpId, pg_fatal, pg_log_info, status(), 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 4414 of file pg_backup_archiver.c.

4418 {
4419  ParallelReadyList *ready_list = (ParallelReadyList *) callback_data;
4420 
4421  pg_log_info("finished item %d %s %s",
4422  te->dumpId, te->desc, te->tag);
4423 
4424  if (status == WORKER_CREATE_DONE)
4425  mark_create_done(AH, te);
4426  else if (status == WORKER_INHIBIT_DATA)
4427  {
4429  AH->public.n_errors++;
4430  }
4431  else if (status == WORKER_IGNORED_ERRORS)
4432  AH->public.n_errors++;
4433  else if (status != 0)
4434  pg_fatal("worker process failed: exit code %d",
4435  status);
4436 
4437  reduce_dependencies(AH, te, ready_list);
4438 }
static void mark_create_done(ArchiveHandle *AH, TocEntry *te)
static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te, ParallelReadyList *ready_list)
static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te)
#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(), status(), _tocEntry::tag, WORKER_CREATE_DONE, WORKER_IGNORED_ERRORS, and WORKER_INHIBIT_DATA.

Referenced by restore_toc_entries_parallel().

◆ move_to_ready_list()

static void move_to_ready_list ( TocEntry pending_list,
ParallelReadyList ready_list,
RestorePass  pass 
)
static

Definition at line 4299 of file pg_backup_archiver.c.

4302 {
4303  TocEntry *te;
4304  TocEntry *next_te;
4305 
4306  for (te = pending_list->pending_next; te != pending_list; te = next_te)
4307  {
4308  /* must save list link before possibly removing te from list */
4309  next_te = te->pending_next;
4310 
4311  if (te->depCount == 0 &&
4312  _tocEntryRestorePass(te) == pass)
4313  {
4314  /* Remove it from pending_list ... */
4315  pending_list_remove(te);
4316  /* ... and add to ready_list */
4317  ready_list_insert(ready_list, te);
4318  }
4319  }
4320 }
static void ready_list_insert(ParallelReadyList *ready_list, TocEntry *te)
static RestorePass _tocEntryRestorePass(TocEntry *te)
static void pending_list_remove(TocEntry *te)

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

Referenced by restore_toc_entries_parallel().

◆ NewDumpOptions()

DumpOptions* NewDumpOptions ( void  )

Definition at line 153 of file pg_backup_archiver.c.

154 {
156 
158  return opts;
159 }
void InitDumpOptions(DumpOptions *opts)

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

Referenced by dumpOptionsFromRestoreOptions().

◆ NewRestoreOptions()

RestoreOptions* NewRestoreOptions ( void  )

Definition at line 971 of file pg_backup_archiver.c.

972 {
974 
976 
977  /* set any fields that shouldn't default to zeroes */
978  opts->format = archUnknown;
979  opts->cparams.promptPassword = TRI_DEFAULT;
980  opts->dumpSections = DUMP_UNSECTIONED;
981  opts->compression_spec.algorithm = PG_COMPRESSION_NONE;
982  opts->compression_spec.level = 0;
983 
984  return opts;
985 }

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

259 {
260  ArchiveHandle *AH;
261  pg_compress_specification compression_spec = {0};
262 
263  compression_spec.algorithm = PG_COMPRESSION_NONE;
264  AH = _allocAH(FileSpec, fmt, compression_spec, true,
266 
267  return (Archive *) AH;
268 }
static void setupRestoreWorker(Archive *AHX)

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

Referenced by main().

◆ parallel_restore()

int parallel_restore ( ArchiveHandle AH,
TocEntry te 
)

Definition at line 4391 of file pg_backup_archiver.c.

4392 {
4393  int status;
4394 
4395  Assert(AH->connection != NULL);
4396 
4397  /* Count only errors associated with this TOC entry */
4398  AH->public.n_errors = 0;
4399 
4400  /* Restore the TOC item */
4401  status = restore_toc_entry(AH, te, true);
4402 
4403  return status;
4404 }
static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)

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

Referenced by _WorkerJobRestoreCustom(), and _WorkerJobRestoreDirectory().

◆ pending_list_append()

static void pending_list_append ( TocEntry l,
TocEntry te 
)
static

Definition at line 4178 of file pg_backup_archiver.c.

4179 {
4180  te->pending_prev = l->pending_prev;
4181  l->pending_prev->pending_next = te;
4182  l->pending_prev = te;
4183  te->pending_next = l;
4184 }

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

4172 {
4173  l->pending_prev = l->pending_next = l;
4174 }

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

4189 {
4192  te->pending_prev = NULL;
4193  te->pending_next = NULL;
4194 }

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

Referenced by move_to_ready_list(), and reduce_dependencies().

◆ pop_next_work_item()

static TocEntry * pop_next_work_item ( ParallelReadyList ready_list,
ParallelState pstate 
)
static

Definition at line 4334 of file pg_backup_archiver.c.

4336 {
4337  /*
4338  * Sort the ready_list so that we'll tackle larger jobs first.
4339  */
4340  ready_list_sort(ready_list);
4341 
4342  /*
4343  * Search the ready_list until we find a suitable item.
4344  */
4345  for (int i = ready_list->first_te; i <= ready_list->last_te; i++)
4346  {
4347  TocEntry *te = ready_list->tes[i];
4348  bool conflicts = false;
4349 
4350  /*
4351  * Check to see if the item would need exclusive lock on something
4352  * that a currently running item also needs lock on, or vice versa. If
4353  * so, we don't want to schedule them together.
4354  */
4355  for (int k = 0; k < pstate->numWorkers; k++)
4356  {
4357  TocEntry *running_te = pstate->te[k];
4358 
4359  if (running_te == NULL)
4360  continue;
4361  if (has_lock_conflicts(te, running_te) ||
4362  has_lock_conflicts(running_te, te))
4363  {
4364  conflicts = true;
4365  break;
4366  }
4367  }
4368 
4369  if (conflicts)
4370  continue;
4371 
4372  /* passed all tests, so this item can run */
4373  ready_list_remove(ready_list, i);
4374  return te;
4375  }
4376 
4377  pg_log_debug("no item ready");
4378  return NULL;
4379 }
static void ready_list_sort(ParallelReadyList *ready_list)
static void ready_list_remove(ParallelReadyList *ready_list, int i)
static bool has_lock_conflicts(TocEntry *te1, TocEntry *te2)
TocEntry ** te
Definition: parallel.h:59
int numWorkers
Definition: parallel.h:57

References _parallelReadyList::first_te, has_lock_conflicts(), i, ParallelState::numWorkers, pg_log_debug, ready_list_remove(), ready_list_sort(), ParallelState::te, and _parallelReadyList::tes.

Referenced by restore_toc_entries_parallel().

◆ PrintTOCSummary()

void PrintTOCSummary ( Archive AHX)

Definition at line 1124 of file pg_backup_archiver.c.

1125 {
1126  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1127  RestoreOptions *ropt = AH->public.ropt;
1128  TocEntry *te;
1129  pg_compress_specification out_compression_spec = {0};
1130  teSection curSection;
1131  OutputContext sav;
1132  const char *fmtName;
1133  char stamp_str[64];
1134 
1135  /* TOC is always uncompressed */
1136  out_compression_spec.algorithm = PG_COMPRESSION_NONE;
1137 
1138  sav = SaveOutput(AH);
1139  if (ropt->filename)
1140  SetOutput(AH, ropt->filename, out_compression_spec);
1141 
1142  if (strftime(stamp_str, sizeof(stamp_str), PGDUMP_STRFTIME_FMT,
1143  localtime(&AH->createDate)) == 0)
1144  strcpy(stamp_str, "[unknown]");
1145 
1146  ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
1147  ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %d\n",
1148  sanitize_line(AH->archdbname, false),
1149  AH->tocCount, AH->compression_spec.level);
1150 
1151  switch (AH->format)
1152  {
1153  case archCustom:
1154  fmtName = "CUSTOM";
1155  break;
1156  case archDirectory:
1157  fmtName = "DIRECTORY";
1158  break;
1159  case archTar:
1160  fmtName = "TAR";
1161  break;
1162  default:
1163  fmtName = "UNKNOWN";
1164  }
1165 
1166  ahprintf(AH, "; Dump Version: %d.%d-%d\n",
1168  ahprintf(AH, "; Format: %s\n", fmtName);
1169  ahprintf(AH, "; Integer: %d bytes\n", (int) AH->intSize);
1170  ahprintf(AH, "; Offset: %d bytes\n", (int) AH->offSize);
1171  if (AH->archiveRemoteVersion)
1172  ahprintf(AH, "; Dumped from database version: %s\n",
1173  AH->archiveRemoteVersion);
1174  if (AH->archiveDumpVersion)
1175  ahprintf(AH, "; Dumped by pg_dump version: %s\n",
1176  AH->archiveDumpVersion);
1177 
1178  ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");
1179 
1180  curSection = SECTION_PRE_DATA;
1181  for (te = AH->toc->next; te != AH->toc; te = te->next)
1182  {
1183  if (te->section != SECTION_NONE)
1184  curSection = te->section;
1185  if (ropt->verbose ||
1186  (_tocEntryRequired(te, curSection, AH) & (REQ_SCHEMA | REQ_DATA)) != 0)
1187  {
1188  char *sanitized_name;
1189  char *sanitized_schema;
1190  char *sanitized_owner;
1191 
1192  /*
1193  */
1194  sanitized_name = sanitize_line(te->tag, false);
1195  sanitized_schema = sanitize_line(te->namespace, true);
1196  sanitized_owner = sanitize_line(te->owner, false);
1197 
1198  ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
1199  te->catalogId.tableoid, te->catalogId.oid,
1200  te->desc, sanitized_schema, sanitized_name,
1201  sanitized_owner);
1202 
1203  free(sanitized_name);
1204  free(sanitized_schema);
1205  free(sanitized_owner);
1206  }
1207  if (ropt->verbose && te->nDeps > 0)
1208  {
1209  int i;
1210 
1211  ahprintf(AH, ";\tdepends on:");
1212  for (i = 0; i < te->nDeps; i++)
1213  ahprintf(AH, " %d", te->dependencies[i]);
1214  ahprintf(AH, "\n");
1215  }
1216  }
1217 
1218  /* Enforce strict names checking */
1219  if (ropt->strict_names)
1220  StrictNamesCheck(ropt);
1221 
1222  if (ropt->filename)
1223  RestoreOutput(AH, sav);
1224 }
@ SECTION_NONE
Definition: pg_backup.h:56
enum _teSection teSection
static void StrictNamesCheck(RestoreOptions *ropt)
static OutputContext SaveOutput(ArchiveHandle *AH)
static void SetOutput(ArchiveHandle *AH, const char *filename, const pg_compress_specification compression_spec)
static void RestoreOutput(ArchiveHandle *AH, OutputContext savedContext)
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:116

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, i, _archiveHandle::intSize, pg_compress_specification::level, _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 305 of file pg_backup_archiver.c.

306 {
307  ArchiveHandle *AH = (ArchiveHandle *) AHX;
308  RestoreOptions *ropt = AH->public.ropt;
309  TocEntry *te;
310  teSection curSection;
311 
312  /* Decide which TOC entries will be dumped/restored, and mark them */
313  curSection = SECTION_PRE_DATA;
314  for (te = AH->toc->next; te != AH->toc; te = te->next)
315  {
316  /*
317  * When writing an archive, we also take this opportunity to check
318  * that we have generated the entries in a sane order that respects
319  * the section divisions. When reading, don't complain, since buggy
320  * old versions of pg_dump might generate out-of-order archives.
321  */
322  if (AH->mode != archModeRead)
323  {
324  switch (te->section)
325  {
326  case SECTION_NONE:
327  /* ok to be anywhere */
328  break;
329  case SECTION_PRE_DATA:
330  if (curSection != SECTION_PRE_DATA)
331  pg_log_warning("archive items not in correct section order");
332  break;
333  case SECTION_DATA:
334  if (curSection == SECTION_POST_DATA)
335  pg_log_warning("archive items not in correct section order");
336  break;
337  case SECTION_POST_DATA:
338  /* ok no matter which section we were in */
339  break;
340  default:
341  pg_fatal("unexpected section code %d",
342  (int) te->section);
343  break;
344  }
345  }
346 
347  if (te->section != SECTION_NONE)
348  curSection = te->section;
349 
350  te->reqs = _tocEntryRequired(te, curSection, AH);
351  }
352 
353  /* Enforce strict names checking */
354  if (ropt->strict_names)
355  StrictNamesCheck(ropt);
356 }
#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 2673 of file pg_backup_archiver.c.

2674 {
2675  /* te->defn should have the form SET client_encoding = 'foo'; */
2676  char *defn = pg_strdup(te->defn);
2677  char *ptr1;
2678  char *ptr2 = NULL;
2679  int encoding;
2680 
2681  ptr1 = strchr(defn, '\'');
2682  if (ptr1)
2683  ptr2 = strchr(++ptr1, '\'');
2684  if (ptr2)
2685  {
2686  *ptr2 = '\0';
2687  encoding = pg_char_to_encoding(ptr1);
2688  if (encoding < 0)
2689  pg_fatal("unrecognized encoding \"%s\"",
2690  ptr1);
2691  AH->public.encoding = encoding;
2692  }
2693  else
2694  pg_fatal("invalid ENCODING item: %s",
2695  te->defn);
2696 
2697  free(defn);
2698 }
int pg_char_to_encoding(const char *name)
Definition: encnames.c:550
int32 encoding
Definition: pg_database.h:41

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

2718 {
2719  /*
2720  * te->defn should contain a command to set search_path. We just copy it
2721  * verbatim for use later.
2722  */
2723  AH->public.searchpath = pg_strdup(te->defn);
2724 }

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

2702 {
2703  /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2704  char *ptr1;
2705 
2706  ptr1 = strchr(te->defn, '\'');
2707  if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2708  AH->public.std_strings = true;
2709  else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2710  AH->public.std_strings = false;
2711  else
2712  pg_fatal("invalid STDSTRINGS item: %s",
2713  te->defn);
2714 }

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

Referenced by ReadToc().

◆ ReadHead()

void ReadHead ( ArchiveHandle AH)

Definition at line 3709 of file pg_backup_archiver.c.

3710 {
3711  char vmaj,
3712  vmin,
3713  vrev;
3714  int fmt;
3715 
3716  /*
3717  * If we haven't already read the header, do so.
3718  *
3719  * NB: this code must agree with _discoverArchiveFormat(). Maybe find a
3720  * way to unify the cases?
3721  */
3722  if (!AH->readHeader)
3723  {
3724  char tmpMag[7];
3725 
3726  AH->ReadBufPtr(AH, tmpMag, 5);
3727 
3728  if (strncmp(tmpMag, "PGDMP", 5) != 0)
3729  pg_fatal("did not find magic string in file header");
3730  }
3731 
3732  vmaj = AH->ReadBytePtr(AH);
3733  vmin = AH->ReadBytePtr(AH);
3734 
3735  if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
3736  vrev = AH->ReadBytePtr(AH);
3737  else
3738  vrev = 0;
3739 
3740  AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev);
3741 
3742  if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
3743  pg_fatal("unsupported version (%d.%d) in file header",
3744  vmaj, vmin);
3745 
3746  AH->intSize = AH->ReadBytePtr(AH);
3747  if (AH->intSize > 32)
3748  pg_fatal("sanity check on integer size (%lu) failed",
3749  (unsigned long) AH->intSize);
3750 
3751  if (AH->intSize > sizeof(int))
3752  pg_log_warning("archive was made on a machine with larger integers, some operations might fail");
3753 
3754  if (AH->version >= K_VERS_1_7)
3755  AH->offSize = AH->ReadBytePtr(AH);
3756  else
3757  AH->offSize = AH->intSize;
3758 
3759  fmt = AH->ReadBytePtr(AH);
3760 
3761  if (AH->format != fmt)
3762  pg_fatal("expected format (%d) differs from format found in file (%d)",
3763  AH->format, fmt);
3764 
3765  /* Guess the compression method based on the level */
3767  if (AH->version >= K_VERS_1_2)
3768  {
3769  if (AH->version < K_VERS_1_4)
3770  AH->compression_spec.level = AH->ReadBytePtr(AH);
3771  else
3772  AH->compression_spec.level = ReadInt(AH);
3773 
3774  if (AH->compression_spec.level != 0)
3776  }
3777  else
3779 
3780 #ifndef HAVE_LIBZ
3782  pg_fatal("archive is compressed, but this installation does not support compression");
3783 #endif
3784 
3785  if (AH->version >= K_VERS_1_4)
3786  {
3787  struct tm crtm;
3788 
3789  crtm.tm_sec = ReadInt(AH);
3790  crtm.tm_min = ReadInt(AH);
3791  crtm.tm_hour = ReadInt(AH);
3792  crtm.tm_mday = ReadInt(AH);
3793  crtm.tm_mon = ReadInt(AH);
3794  crtm.tm_year = ReadInt(AH);
3795  crtm.tm_isdst = ReadInt(AH);
3796 
3797  /*
3798  * Newer versions of glibc have mktime() report failure if tm_isdst is
3799  * inconsistent with the prevailing timezone, e.g. tm_isdst = 1 when
3800  * TZ=UTC. This is problematic when restoring an archive under a
3801  * different timezone setting. If we get a failure, try again with
3802  * tm_isdst set to -1 ("don't know").
3803  *
3804  * XXX with or without this hack, we reconstruct createDate
3805  * incorrectly when the prevailing timezone is different from
3806  * pg_dump's. Next time we bump the archive version, we should flush
3807  * this representation and store a plain seconds-since-the-Epoch
3808  * timestamp instead.
3809  */
3810  AH->createDate = mktime(&crtm);
3811  if (AH->createDate == (time_t) -1)
3812  {
3813  crtm.tm_isdst = -1;
3814  AH->createDate = mktime(&crtm);
3815  if (AH->createDate == (time_t) -1)
3816  pg_log_warning("invalid creation date in header");
3817  }
3818  }
3819 
3820  if (AH->version >= K_VERS_1_4)
3821  {
3822  AH->archdbname = ReadStr(AH);
3823  }
3824 
3825  if (AH->version >= K_VERS_1_10)
3826  {
3827  AH->archiveRemoteVersion = ReadStr(AH);
3828  AH->archiveDumpVersion = ReadStr(AH);
3829  }
3830 }
@ PG_COMPRESSION_GZIP
Definition: compression.h:20
static struct pg_tm tm
Definition: localtime.c:104
char * ReadStr(ArchiveHandle *AH)
int ReadInt(ArchiveHandle *AH)
#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, fmt, _archiveHandle::format, _archiveHandle::intSize, K_VERS_1_0, K_VERS_1_10, 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_COMPRESSION_NONE, pg_fatal, pg_log_warning, _archiveHandle::ReadBufPtr, _archiveHandle::ReadBytePtr, _archiveHandle::readHeader, ReadInt(), ReadStr(), 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 2010 of file pg_backup_archiver.c.

2011 {
2012  int res = 0;
2013  int bv,
2014  b;
2015  int sign = 0; /* Default positive */
2016  int bitShift = 0;
2017 
2018  if (AH->version > K_VERS_1_0)
2019  /* Read a sign byte */
2020  sign = AH->ReadBytePtr(AH);
2021 
2022  for (b = 0; b < AH->intSize; b++)
2023  {
2024  bv = AH->ReadBytePtr(AH) & 0xFF;
2025  if (bv != 0)
2026  res = res + (bv << bitShift);
2027  bitShift += 8;
2028  }
2029 
2030  if (sign)
2031  res = -res;
2032 
2033  return res;
2034 }
char sign
Definition: informix.c:668
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 1915 of file pg_backup_archiver.c.

1916 {
1917  int i;
1918  int off;
1919  int offsetFlg;
1920 
1921  /* Initialize to zero */
1922  *o = 0;
1923 
1924  /* Check for old version */
1925  if (AH->version < K_VERS_1_7)
1926  {
1927  /* Prior versions wrote offsets using WriteInt */
1928  i = ReadInt(AH);
1929  /* -1 means not set */
1930  if (i < 0)
1931  return K_OFFSET_POS_NOT_SET;
1932  else if (i == 0)
1933  return K_OFFSET_NO_DATA;
1934 
1935  /* Cast to pgoff_t because it was written as an int. */
1936  *o = (pgoff_t) i;
1937  return K_OFFSET_POS_SET;
1938  }
1939 
1940  /*
1941  * Read the flag indicating the state of the data pointer. Check if valid
1942  * and die if not.
1943  *
1944  * This used to be handled by a negative or zero pointer, now we use an
1945  * extra byte specifically for the state.
1946  */
1947  offsetFlg = AH->ReadBytePtr(AH) & 0xFF;
1948 
1949  switch (offsetFlg)
1950  {
1951  case K_OFFSET_POS_NOT_SET:
1952  case K_OFFSET_NO_DATA:
1953  case K_OFFSET_POS_SET:
1954 
1955  break;
1956 
1957  default:
1958  pg_fatal("unexpected data offset flag %d", offsetFlg);
1959  }
1960 
1961  /*
1962  * Read the bytes
1963  */
1964  for (off = 0; off < AH->offSize; off++)
1965  {
1966  if (off < sizeof(pgoff_t))
1967  *o |= ((pgoff_t) (AH->ReadBytePtr(AH))) << (off * 8);
1968  else
1969  {
1970  if (AH->ReadBytePtr(AH) != 0)
1971  pg_fatal("file offset in dump file is too large");
1972  }
1973  }
1974 
1975  return offsetFlg;
1976 }
#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 2056 of file pg_backup_archiver.c.

2057 {
2058  char *buf;
2059  int l;
2060 
2061  l = ReadInt(AH);
2062  if (l < 0)
2063  buf = NULL;
2064  else
2065  {
2066  buf = (char *) pg_malloc(l + 1);
2067  AH->ReadBufPtr(AH, (void *) buf, l);
2068 
2069  buf[l] = '\0';
2070  }
2071 
2072  return buf;
2073 }

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

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

◆ ReadToc()

void ReadToc ( ArchiveHandle AH)

Definition at line 2504 of file pg_backup_archiver.c.

2505 {
2506  int i;
2507  char *tmp;
2508  DumpId *deps;
2509  int depIdx;
2510  int depSize;
2511  TocEntry *te;
2512  bool is_supported;
2513 
2514  AH->tocCount = ReadInt(AH);
2515  AH->maxDumpId = 0;
2516 
2517  for (i = 0; i < AH->tocCount; i++)
2518  {
2519  te = (TocEntry *) pg_malloc0(sizeof(TocEntry));
2520  te->dumpId = ReadInt(AH);
2521 
2522  if (te->dumpId > AH->maxDumpId)
2523  AH->maxDumpId = te->dumpId;
2524 
2525  /* Sanity check */
2526  if (te->dumpId <= 0)
2527  pg_fatal("entry ID %d out of range -- perhaps a corrupt TOC",
2528  te->dumpId);
2529 
2530  te->hadDumper = ReadInt(AH);
2531 
2532  if (AH->version >= K_VERS_1_8)
2533  {
2534  tmp = ReadStr(AH);
2535  sscanf(tmp, "%u", &te->catalogId.tableoid);
2536  free(tmp);
2537  }
2538  else
2540  tmp = ReadStr(AH);
2541  sscanf(tmp, "%u", &te->catalogId.oid);
2542  free(tmp);
2543 
2544  te->tag = ReadStr(AH);
2545  te->desc = ReadStr(AH);
2546 
2547  if (AH->version >= K_VERS_1_11)
2548  {
2549  te->section = ReadInt(AH);
2550  }
2551  else
2552  {
2553  /*
2554  * Rules for pre-8.4 archives wherein pg_dump hasn't classified
2555  * the entries into sections. This list need not cover entry
2556  * types added later than 8.4.
2557  */
2558  if (strcmp(te->desc, "COMMENT") == 0 ||
2559  strcmp(te->desc, "ACL") == 0 ||
2560  strcmp(te->desc, "ACL LANGUAGE") == 0)
2561  te->section = SECTION_NONE;
2562  else if (strcmp(te->desc, "TABLE DATA") == 0 ||
2563  strcmp(te->desc, "BLOBS") == 0 ||
2564  strcmp(te->desc, "BLOB COMMENTS") == 0)
2565  te->section = SECTION_DATA;
2566  else if (strcmp(te->desc, "CONSTRAINT") == 0 ||
2567  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2568  strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2569  strcmp(te->desc, "INDEX") == 0 ||
2570  strcmp(te->desc, "RULE") == 0 ||
2571  strcmp(te->desc, "TRIGGER") == 0)
2572  te->section = SECTION_POST_DATA;
2573  else
2574  te->section = SECTION_PRE_DATA;
2575  }
2576 
2577  te->defn = ReadStr(AH);
2578  te->dropStmt = ReadStr(AH);
2579 
2580  if (AH->version >= K_VERS_1_3)
2581  te->copyStmt = ReadStr(AH);
2582 
2583  if (AH->version >= K_VERS_1_6)
2584  te->namespace = ReadStr(AH);
2585 
2586  if (AH->version >= K_VERS_1_10)
2587  te->tablespace = ReadStr(AH);
2588 
2589  if (AH->version >= K_VERS_1_14)
2590  te->tableam = ReadStr(AH);
2591 
2592  te->owner = ReadStr(AH);
2593  is_supported = true;
2594  if (AH->version < K_VERS_1_9)
2595  is_supported = false;
2596  else
2597  {
2598  tmp = ReadStr(AH);
2599 
2600  if (strcmp(tmp, "true") == 0)
2601  is_supported = false;
2602 
2603  free(tmp);
2604  }
2605 
2606  if (!is_supported)
2607  pg_log_warning("restoring tables WITH OIDS is not supported anymore");
2608 
2609  /* Read TOC entry dependencies */
2610  if (AH->version >= K_VERS_1_5)
2611  {
2612  depSize = 100;
2613  deps = (DumpId *) pg_malloc(sizeof(DumpId) * depSize);
2614  depIdx = 0;
2615  for (;;)
2616  {
2617  tmp = ReadStr(AH);
2618  if (!tmp)
2619  break; /* end of list */
2620  if (depIdx >= depSize)
2621  {
2622  depSize *= 2;
2623  deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depSize);
2624  }
2625  sscanf(tmp, "%d", &deps[depIdx]);
2626  free(tmp);
2627  depIdx++;
2628  }
2629 
2630  if (depIdx > 0) /* We have a non-null entry */
2631  {
2632  deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depIdx);
2633  te->dependencies = deps;
2634  te->nDeps = depIdx;
2635  }
2636  else
2637  {
2638  free(deps);
2639  te->dependencies = NULL;
2640  te->nDeps = 0;
2641  }
2642  }
2643  else
2644  {
2645  te->dependencies = NULL;
2646  te->nDeps = 0;
2647  }
2648  te->dataLength = 0;
2649 
2650  if (AH->ReadExtraTocPtr)
2651  AH->ReadExtraTocPtr(AH, te);
2652 
2653  pg_log_debug("read TOC entry %d (ID %d) for %s %s",
2654  i, te->dumpId, te->desc, te->tag);
2655 
2656  /* link completed entry into TOC circular list */
2657  te->prev = AH->toc->prev;
2658  AH->toc->prev->next = te;
2659  AH->toc->prev = te;
2660  te->next = AH->toc;
2661 
2662  /* special processing immediately upon read for some items */
2663  if (strcmp(te->desc, "ENCODING") == 0)
2664  processEncodingEntry(AH, te);
2665  else if (strcmp(te->desc, "STDSTRINGS") == 0)
2666  processStdStringsEntry(AH, te);
2667  else if (strcmp(te->desc, "SEARCHPATH") == 0)
2668  processSearchPathEntry(AH, te);
2669  }
2670 }
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().

◆ ready_list_free()

static void ready_list_free ( ParallelReadyList ready_list)
static

Definition at line 4214 of file pg_backup_archiver.c.

4215 {
4216  pg_free(ready_list->tes);
4217 }
void pg_free(void *ptr)
Definition: fe_memutils.c:105

References pg_free(), and _parallelReadyList::tes.

Referenced by restore_toc_entries_parallel().

◆ ready_list_init()

static void ready_list_init ( ParallelReadyList ready_list,
int  tocCount 
)
static

Definition at line 4201 of file pg_backup_archiver.c.

4202 {
4203  ready_list->tes = (TocEntry **)
4204  pg_malloc(tocCount * sizeof(TocEntry *));
4205  ready_list->first_te = 0;
4206  ready_list->last_te = -1;
4207  ready_list->sorted = false;
4208 }

References _parallelReadyList::first_te, _parallelReadyList::last_te, pg_malloc(), _parallelReadyList::sorted, and _parallelReadyList::tes.

Referenced by restore_toc_entries_parallel().

◆ ready_list_insert()

static void ready_list_insert ( ParallelReadyList ready_list,
TocEntry te 
)
static

Definition at line 4221 of file pg_backup_archiver.c.

4222 {
4223  ready_list->tes[++ready_list->last_te] = te;
4224  /* List is (probably) not sorted anymore. */
4225  ready_list->sorted = false;
4226 }

References _parallelReadyList::last_te, _parallelReadyList::sorted, and _parallelReadyList::tes.

Referenced by move_to_ready_list(), and reduce_dependencies().

◆ ready_list_remove()

static void ready_list_remove ( ParallelReadyList ready_list,
int  i 
)
static

Definition at line 4230 of file pg_backup_archiver.c.

4231 {
4232  int f = ready_list->first_te;
4233 
4234  Assert(i >= f && i <= ready_list->last_te);
4235 
4236  /*
4237  * In the typical case where the item to be removed is the first ready
4238  * entry, we need only increment first_te to remove it. Otherwise, move
4239  * the entries before it to compact the list. (This preserves sortedness,
4240  * if any.) We could alternatively move the entries after i, but there
4241  * are typically many more of those.
4242  */
4243  if (i > f)
4244  {
4245  TocEntry **first_te_ptr = &ready_list->tes[f];
4246 
4247  memmove(first_te_ptr + 1, first_te_ptr, (i - f) * sizeof(TocEntry *));
4248  }
4249  ready_list->first_te++;
4250 }

References Assert(), _parallelReadyList::first_te, i, and _parallelReadyList::tes.

Referenced by pop_next_work_item().

◆ ready_list_sort()

static void ready_list_sort ( ParallelReadyList ready_list)
static

Definition at line 4254 of file pg_backup_archiver.c.

4255 {
4256  if (!ready_list->sorted)
4257  {
4258  int n = ready_list->last_te - ready_list->first_te + 1;
4259 
4260  if (n > 1)
4261  qsort(ready_list->tes + ready_list->first_te, n,
4262  sizeof(TocEntry *),
4264  ready_list->sorted = true;
4265  }
4266 }
static int TocEntrySizeCompare(const void *p1, const void *p2)
#define qsort(a, b, c, d)
Definition: port.h:445

References _parallelReadyList::first_te, _parallelReadyList::last_te, qsort, _parallelReadyList::sorted, _parallelReadyList::tes, and TocEntrySizeCompare().

Referenced by pop_next_work_item().

◆ reduce_dependencies()

static void reduce_dependencies ( ArchiveHandle AH,
TocEntry te,
ParallelReadyList ready_list 
)
static

Definition at line 4683 of file pg_backup_archiver.c.

4685 {
4686  int i;
4687 
4688  pg_log_debug("reducing dependencies for %d", te->dumpId);
4689 
4690  for (i = 0; i < te->nRevDeps; i++)
4691  {
4692  TocEntry *otherte = AH->tocsByDumpId[te->revDeps[i]];
4693 
4694  Assert(otherte->depCount > 0);
4695  otherte->depCount--;
4696 
4697  /*
4698  * It's ready if it has no remaining dependencies, and it belongs in
4699  * the current restore pass, and it is currently a member of the
4700  * pending list (that check is needed to prevent double restore in
4701  * some cases where a list-file forces out-of-order restoring).
4702  * However, if ready_list == NULL then caller doesn't want any list
4703  * memberships changed.
4704  */
4705  if (otherte->depCount == 0 &&
4706  _tocEntryRestorePass(otherte) == AH->restorePass &&
4707  otherte->pending_prev != NULL &&
4708  ready_list != NULL)
4709  {
4710  /* Remove it from pending list ... */
4711  pending_list_remove(otherte);
4712  /* ... and add to ready_list */
4713  ready_list_insert(ready_list, otherte);
4714  }
4715  }
4716 }
RestorePass restorePass

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

4586 {
4587  TocEntry *te;
4588  int i;
4589  DumpId olddep;
4590 
4591  for (te = AH->toc->next; te != AH->toc; te = te->next)
4592  {
4593  if (te->section != SECTION_POST_DATA)
4594  continue;
4595  for (i = 0; i < te->nDeps; i++)
4596  {
4597  olddep = te->dependencies[i];
4598  if (olddep <= AH->maxDumpId &&
4599  AH->tableDataId[olddep] != 0)
4600  {
4601  DumpId tabledataid = AH->tableDataId[olddep];
4602  TocEntry *tabledatate = AH->tocsByDumpId[tabledataid];
4603 
4604  te->dependencies[i] = tabledataid;
4605  te->dataLength = Max(te->dataLength, tabledatate->dataLength);
4606  pg_log_debug("transferring dependency %d -> %d to %d",
4607  te->dumpId, olddep, tabledataid);
4608  }
4609  }
4610  }
4611 }
#define Max(x, y)
Definition: c.h:931

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

3998 {
3999  ParallelReadyList ready_list;
4000  TocEntry *next_work_item;
4001 
4002  pg_log_debug("entering restore_toc_entries_parallel");
4003 
4004  /* Set up ready_list with enough room for all known TocEntrys */
4005  ready_list_init(&ready_list, AH->tocCount);
4006 
4007  /*
4008  * The pending_list contains all items that we need to restore. Move all
4009  * items that are available to process immediately into the ready_list.
4010  * After this setup, the pending list is everything that needs to be done
4011  * but is blocked by one or more dependencies, while the ready list
4012  * contains items that have no remaining dependencies and are OK to
4013  * process in the current restore pass.
4014  */
4016  move_to_ready_list(pending_list, &ready_list, AH->restorePass);
4017 
4018  /*
4019  * main parent loop
4020  *
4021  * Keep going until there is no worker still running AND there is no work
4022  * left to be done. Note invariant: at top of loop, there should always
4023  * be at least one worker available to dispatch a job to.
4024  */
4025  pg_log_info("entering main parallel loop");
4026 
4027  for (;;)
4028  {
4029  /* Look for an item ready to be dispatched to a worker */
4030  next_work_item = pop_next_work_item(&ready_list, pstate);
4031  if (next_work_item != NULL)
4032  {
4033  /* If not to be restored, don't waste time launching a worker */
4034  if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA)) == 0)
4035  {
4036  pg_log_info("skipping item %d %s %s",
4037  next_work_item->dumpId,
4038  next_work_item->desc, next_work_item->tag);
4039  /* Update its dependencies as though we'd completed it */
4040  reduce_dependencies(AH, next_work_item, &ready_list);
4041  /* Loop around to see if anything else can be dispatched */
4042  continue;
4043  }
4044 
4045  pg_log_info("launching item %d %s %s",
4046  next_work_item->dumpId,
4047  next_work_item->desc, next_work_item->tag);
4048 
4049  /* Dispatch to some worker */
4050  DispatchJobForTocEntry(AH, pstate, next_work_item, ACT_RESTORE,
4051  mark_restore_job_done, &ready_list);
4052  }
4053  else if (IsEveryWorkerIdle(pstate))
4054  {
4055  /*
4056  * Nothing is ready and no worker is running, so we're done with
4057  * the current pass or maybe with the whole process.
4058  */
4059  if (AH->restorePass == RESTORE_PASS_LAST)
4060  break; /* No more parallel processing is possible */
4061 
4062  /* Advance to next restore pass */
4063  AH->restorePass++;
4064  /* That probably allows some stuff to be made ready */
4065  move_to_ready_list(pending_list, &ready_list, AH->restorePass);
4066  /* Loop around to see if anything's now ready */
4067  continue;
4068  }
4069  else
4070  {
4071  /*
4072  * We have nothing ready, but at least one child is working, so
4073  * wait for some subjob to finish.
4074  */
4075  }
4076 
4077  /*
4078  * Before dispatching another job, check to see if anything has
4079  * finished. We should check every time through the loop so as to
4080  * reduce dependencies as soon as possible. If we were unable to
4081  * dispatch any job this time through, wait until some worker finishes
4082  * (and, hopefully, unblocks some pending item). If we did dispatch
4083  * something, continue as soon as there's at least one idle worker.
4084  * Note that in either case, there's guaranteed to be at least one
4085  * idle worker when we return to the top of the loop. This ensures we
4086  * won't block inside DispatchJobForTocEntry, which would be
4087  * undesirable: we'd rather postpone dispatching until we see what's
4088  * been unblocked by finished jobs.
4089  */
4090  WaitForWorkers(AH, pstate,
4091  next_work_item ? WFW_ONE_IDLE : WFW_GOT_STATUS);
4092  }
4093 
4094  /* There should now be nothing in ready_list. */
4095  Assert(ready_list.first_te > ready_list.last_te);
4096 
4097  ready_list_free(&ready_list);
4098 
4099  pg_log_info("finished main parallel loop");
4100 }
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
static void ready_list_free(ParallelReadyList *ready_list)
static void mark_restore_job_done(ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
static void ready_list_init(ParallelReadyList *ready_list, int tocCount)
static void move_to_ready_list(TocEntry *pending_list, ParallelReadyList *ready_list, RestorePass pass)
static TocEntry * pop_next_work_item(ParallelReadyList *ready_list, ParallelState *pstate)
#define RESTORE_PASS_LAST
@ ACT_RESTORE

References ACT_RESTORE, Assert(), _tocEntry::desc, DispatchJobForTocEntry(), _tocEntry::dumpId, _parallelReadyList::first_te, IsEveryWorkerIdle(), _parallelReadyList::last_te, mark_restore_job_done(), move_to_ready_list(), pg_log_debug, pg_log_info, pop_next_work_item(), ready_list_free(), ready_list_init(), reduce_dependencies(), REQ_DATA, REQ_SCHEMA, _tocEntry::reqs, RESTORE_PASS_LAST, RESTORE_PASS_MAIN, _archiveHandle::restorePass, _tocEntry::tag, _archiveHandle::tocCount, 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 4112 of file pg_backup_archiver.c.

4113 {
4114  RestoreOptions *ropt = AH->public.ropt;
4115  TocEntry *te;
4116 
4117  pg_log_debug("entering restore_toc_entries_postfork");
4118 
4119  /*
4120  * Now reconnect the single parent connection.
4121  */
4122  ConnectDatabase((Archive *) AH, &ropt->cparams, true);
4123 
4124  /* re-establish fixed state */
4126 
4127  /*
4128  * Make sure there is no work left due to, say, circular dependencies, or
4129  * some other pathological condition. If so, do it in the single parent
4130  * connection. We don't sweat about RestorePass ordering; it's likely we
4131  * already violated that.
4132  */
4133  for (te = pending_list->pending_next; te != pending_list; te = te->pending_next)
4134  {
4135  pg_log_info("processing missed item %d %s %s",
4136  te->dumpId, te->desc, te->tag);
4137  (void) restore_toc_entry(AH, te, false);
4138  }
4139 }

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

3882 {
3883  bool skipped_some;
3884  TocEntry *next_work_item;
3885 
3886  pg_log_debug("entering restore_toc_entries_prefork");
3887 
3888  /* Adjust dependency information */
3889  fix_dependencies(AH);
3890 
3891  /*
3892  * Do all the early stuff in a single connection in the parent. There's no
3893  * great point in running it in parallel, in fact it will actually run
3894  * faster in a single connection because we avoid all the connection and
3895  * setup overhead. Also, pre-9.2 pg_dump versions were not very good
3896  * about showing all the dependencies of SECTION_PRE_DATA items, so we do
3897  * not risk trying to process them out-of-order.
3898  *
3899  * Stuff that we can't do immediately gets added to the pending_list.
3900  * Note: we don't yet filter out entries that aren't going to be restored.
3901  * They might participate in dependency chains connecting entries that
3902  * should be restored, so we treat them as live until we actually process
3903  * them.
3904  *
3905  * Note: as of 9.2, it should be guaranteed that all PRE_DATA items appear
3906  * before DATA items, and all DATA items before POST_DATA items. That is
3907  * not certain to be true in older archives, though, and in any case use
3908  * of a list file would destroy that ordering (cf. SortTocFromFile). So
3909  * this loop cannot assume that it holds.
3910  */
3912  skipped_some = false;
3913  for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
3914  {
3915  bool do_now = true;
3916 
3917  if (next_work_item->section != SECTION_PRE_DATA)
3918  {
3919  /* DATA and POST_DATA items are just ignored for now */
3920  if (next_work_item->section == SECTION_DATA ||
3921  next_work_item->section == SECTION_POST_DATA)
3922  {
3923  do_now = false;
3924  skipped_some = true;
3925  }
3926  else
3927  {
3928  /*
3929  * SECTION_NONE items, such as comments, can be processed now
3930  * if we are still in the PRE_DATA part of the archive. Once
3931  * we've skipped any items, we have to consider whether the
3932  * comment's dependencies are satisfied, so skip it for now.
3933  */
3934  if (skipped_some)
3935  do_now = false;
3936  }
3937  }
3938 
3939  /*
3940  * Also skip items that need to be forced into later passes. We need
3941  * not set skipped_some in this case, since by assumption no main-pass
3942  * items could depend on these.
3943  */
3944  if (_tocEntryRestorePass(next_work_item) != RESTORE_PASS_MAIN)
3945  do_now = false;
3946 
3947  if (do_now)
3948  {
3949  /* OK, restore the item and update its dependencies */
3950  pg_log_info("processing item %d %s %s",
3951  next_work_item->dumpId,
3952  next_work_item->desc, next_work_item->tag);
3953 
3954  (void) restore_toc_entry(AH, next_work_item, false);
3955 
3956  /* Reduce dependencies, but don't move anything to ready_list */
3957  reduce_dependencies(AH, next_work_item, NULL);
3958  }
3959  else
3960  {
3961  /* Nope, so add it to pending_list */
3962  pending_list_append(pending_list, next_work_item);
3963  }
3964  }
3965 
3966  /*
3967  * Now close parent connection in prep for parallel steps. We do this
3968  * mainly to ensure that we don't exceed the specified number of parallel
3969  * connections.
3970  */
3971  DisconnectDatabase(&AH->public);
3972 
3973  /* blow away any transient state from the old connection */
3974  free(AH->currUser);
3975  AH->currUser = NULL;
3976  free(AH->currSchema);
3977  AH->currSchema = NULL;
3978  free(AH->currTablespace);
3979  AH->currTablespace = NULL;
3980  free(AH->currTableAm);
3981  AH->currTableAm = NULL;
3982 }
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(), _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, _tocEntry::section, SECTION_DATA, SECTION_POST_DATA, SECTION_PRE_DATA, _tocEntry::tag, and _archiveHandle::toc.

Referenced by RestoreArchive().

◆ restore_toc_entry()

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

Definition at line 766 of file pg_backup_archiver.c.

767 {
768  RestoreOptions *ropt = AH->public.ropt;
769  int status = WORKER_OK;
770  int reqs;
771  bool defnDumped;
772 
773  AH->currentTE = te;
774 
775  /* Dump any relevant dump warnings to stderr */
776  if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0)
777  {
778  if (!ropt->dataOnly && te->defn != NULL && strlen(te->defn) != 0)
779  pg_log_warning("warning from original dump file: %s", te->defn);
780  else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0)
781  pg_log_warning("warning from original dump file: %s", te->copyStmt);
782  }
783 
784  /* Work out what, if anything, we want from this entry */
785  reqs = te->reqs;
786 
787  defnDumped = false;
788 
789  /*
790  * If it has a schema component that we want, then process that
791  */
792  if ((reqs & REQ_SCHEMA) != 0)
793  {
794  /* Show namespace in log message if available */
795  if (te->namespace)
796  pg_log_info("creating %s \"%s.%s\"",
797  te->desc, te->namespace, te->tag);
798  else
799  pg_log_info("creating %s \"%s\"",
800  te->desc, te->tag);
801 
802  _printTocEntry(AH, te, false);
803  defnDumped = true;
804 
805  if (strcmp(te->desc, "TABLE") == 0)
806  {
807  if (AH->lastErrorTE == te)
808  {
809  /*
810  * We failed to create the table. If
811  * --no-data-for-failed-tables was given, mark the
812  * corresponding TABLE DATA to be ignored.
813  *
814  * In the parallel case this must be done in the parent, so we
815  * just set the return value.
816  */
817  if (ropt->noDataForFailedTables)
818  {
819  if (is_parallel)
821  else
823  }
824  }
825  else
826  {
827  /*
828  * We created the table successfully. Mark the corresponding
829  * TABLE DATA for possible truncation.
830  *
831  * In the parallel case this must be done in the parent, so we
832  * just set the return value.
833  */
834  if (is_parallel)
836  else
837  mark_create_done(AH, te);
838  }
839  }
840 
841  /*
842  * If we created a DB, connect to it. Also, if we changed DB
843  * properties, reconnect to ensure that relevant GUC settings are
844  * applied to our session.
845  */
846  if (strcmp(te->desc, "DATABASE") == 0 ||
847  strcmp(te->desc, "DATABASE PROPERTIES") == 0)
848  {
849  pg_log_info("connecting to new database \"%s\"", te->tag);
850  _reconnectToDB(AH, te->tag);
851  }
852  }
853 
854  /*
855  * If it has a data component that we want, then process that
856  */
857  if ((reqs & REQ_DATA) != 0)
858  {
859  /*
860  * hadDumper will be set if there is genuine data component for this
861  * node. Otherwise, we need to check the defn field for statements
862  * that need to be executed in data-only restores.
863  */
864  if (te->hadDumper)
865  {
866  /*
867  * If we can output the data, then restore it.
868  */
869  if (AH->PrintTocDataPtr != NULL)
870  {
871  _printTocEntry(AH, te, true);
872 
873  if (strcmp(te->desc, "BLOBS") == 0 ||
874  strcmp(te->desc, "BLOB COMMENTS") == 0)
875  {
876  pg_log_info("processing %s", te->desc);
877 
878  _selectOutputSchema(AH, "pg_catalog");
879 
880  /* Send BLOB COMMENTS data to ExecuteSimpleCommands() */
881  if (strcmp(te->desc, "BLOB COMMENTS") == 0)
883 
884  AH->PrintTocDataPtr(AH, te);
885 
887  }
888  else
889  {
891 
892  /* Select owner and schema as necessary */
893  _becomeOwner(AH, te);
894  _selectOutputSchema(AH, te->namespace);
895 
896  pg_log_info("processing data for table \"%s.%s\"",
897  te->namespace, te->tag);
898 
899  /*
900  * In parallel restore, if we created the table earlier in
901  * the run then we wrap the COPY in a transaction and
902  * precede it with a TRUNCATE. If archiving is not on
903  * this prevents WAL-logging the COPY. This obtains a
904  * speedup similar to that from using single_txn mode in
905  * non-parallel restores.
906  */
907  if (is_parallel && te->created)
908  {
909  /*
910  * Parallel restore is always talking directly to a
911  * server, so no need to see if we should issue BEGIN.
912  */
913  StartTransaction(&AH->public);
914 
915  /*
916  * Issue TRUNCATE with ONLY so that child tables are
917  * not wiped.
918  */
919  ahprintf(AH, "TRUNCATE TABLE ONLY %s;\n\n",
920  fmtQualifiedId(te->namespace, te->tag));
921  }
922 
923  /*
924  * If we have a copy statement, use it.
925  */
926  if (te->copyStmt && strlen(te->copyStmt) > 0)
927  {
928  ahprintf(AH, "%s", te->copyStmt);
930  }
931  else
933 
934  AH->PrintTocDataPtr(AH, te);
935 
936  /*
937  * Terminate COPY if needed.
938  */
939  if (AH->outputKind == OUTPUT_COPYDATA &&
940  RestoringToDB(AH))
941  EndDBCopyMode(&AH->public, te->tag);
943 
944  /* close out the transaction started above */
945  if (is_parallel && te->created)
947 
949  }
950  }
951  }
952  else if (!defnDumped)
953  {
954  /* If we haven't already dumped the defn part, do so now */
955  pg_log_info("executing %s %s", te->desc, te->tag);
956  _printTocEntry(AH, te, false);
957  }
958  }
959 
960  if (AH->public.n_errors > 0 && status == WORKER_OK)
962 
963  return status;
964 }
static void _reconnectToDB(ArchiveHandle *AH, const char *dbname)
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:149
int noDataForFailedTables
Definition: pg_backup.h:145
static void StartTransaction(void)
Definition: xact.c:1982

References _becomeOwner(), _disableTriggersIfNecessary(), _enableTriggersIfNecessary(), _printTocEntry(), _reconnectToDB(), _selectOutputSchema(), ahprintf(), CommitTransaction(), _tocEntry::copyStmt, _tocEntry::created, _archiveHandle::currentTE, _restoreOptions::dataOnly, _tocEntry::defn, _tocEntry::desc, EndDBCopyMode(), fmtQualifiedId(), _tocEntry::hadDumper, inhibit_data_for_failed_table(), _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(), status(), _restoreOptions::suppressDumpWarnings, _tocEntry::tag, 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 360 of file pg_backup_archiver.c.

361 {
362  ArchiveHandle *AH = (ArchiveHandle *) AHX;
363  RestoreOptions *ropt = AH->public.ropt;
364  bool parallel_mode;
365  TocEntry *te;
366  OutputContext sav;
367 
369 
370  /*
371  * If we're going to do parallel restore, there are some restrictions.
372  */
373  parallel_mode = (AH->public.numWorkers > 1 && ropt->useDB);
374  if (parallel_mode)
375  {
376  /* We haven't got round to making this work for all archive formats */
377  if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
378  pg_fatal("parallel restore is not supported with this archive file format");
379 
380  /* Doesn't work if the archive represents dependencies as OIDs */
381  if (AH->version < K_VERS_1_8)
382  pg_fatal("parallel restore is not supported with archives made by pre-8.0 pg_dump");
383 
384  /*
385  * It's also not gonna work if we can't reopen the input file, so
386  * let's try that immediately.
387  */
388  AH->ReopenPtr(AH);
389  }
390 
391  /*
392  * Make sure we won't need (de)compression we haven't got
393  */
394 #ifndef HAVE_LIBZ
396  AH->PrintTocDataPtr != NULL)
397  {
398  for (te = AH->toc->next; te != AH->toc; te = te->next)
399  {
400  if (te->hadDumper && (te->reqs & REQ_DATA) != 0)
401  pg_fatal("cannot restore from compressed archive (compression not supported in this installation)");
402  }
403  }
404 #endif
405 
406  /*
407  * Prepare index arrays, so we can assume we have them throughout restore.
408  * It's possible we already did this, though.
409  */
410  if (AH->tocsByDumpId == NULL)
412 
413  /*
414  * If we're using a DB connection, then connect it.
415  */
416  if (ropt->useDB)
417  {
418  pg_log_info("connecting to database for restore");
419  if (AH->version < K_VERS_1_3)
420  pg_fatal("direct database connections are not supported in pre-1.3 archives");
421 
422  /*
423  * We don't want to guess at whether the dump will successfully
424  * restore; allow the attempt regardless of the version of the restore
425  * target.
426  */
427  AHX->minRemoteVersion = 0;
428  AHX->maxRemoteVersion = 9999999;
429 
430  ConnectDatabase(AHX, &ropt->cparams, false);
431 
432  /*
433  * If we're talking to the DB directly, don't send comments since they
434  * obscure SQL when displaying errors
435  */
436  AH->noTocComments = 1;
437  }
438 
439  /*
440  * Work out if we have an implied data-only restore. This can happen if
441  * the dump was data only or if the user has used a toc list to exclude
442  * all of the schema data. All we do is look for schema entries - if none
443  * are found then we set the dataOnly flag.
444  *
445  * We could scan for wanted TABLE entries, but that is not the same as
446  * dataOnly. At this stage, it seems unnecessary (6-Mar-2001).
447  */
448  if (!ropt->dataOnly)
449  {
450  int impliedDataOnly = 1;
451 
452  for (te = AH->toc->next; te != AH->toc; te = te->next)
453  {
454  if ((te->reqs & REQ_SCHEMA) != 0)
455  { /* It's schema, and it's wanted */
456  impliedDataOnly = 0;
457  break;
458  }
459  }
460  if (impliedDataOnly)
461  {
462  ropt->dataOnly = impliedDataOnly;
463  pg_log_info("implied data-only restore");
464  }
465  }
466 
467  /*
468  * Setup the output file if necessary.
469  */
470  sav = SaveOutput(AH);
472  SetOutput(AH, ropt->filename, ropt->compression_spec);
473 
474  ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n");
475 
476  if (AH->archiveRemoteVersion)
477  ahprintf(AH, "-- Dumped from database version %s\n",
479  if (AH->archiveDumpVersion)
480  ahprintf(AH, "-- Dumped by pg_dump version %s\n",
481  AH->archiveDumpVersion);
482 
483  ahprintf(AH, "\n");
484 
485  if (AH->public.verbose)
486  dumpTimestamp(AH, "Started on", AH->createDate);
487 
488  if (ropt->single_txn)
489  {
490  if (AH->connection)
491  StartTransaction(AHX);
492  else
493  ahprintf(AH, "BEGIN;\n\n");
494  }
495 
496  /*
497  * Establish important parameter values right away.
498  */
500 
501  AH->stage = STAGE_PROCESSING;
502 
503  /*
504  * Drop the items at the start, in reverse order
505  */
506  if (ropt->dropSchema)
507  {
508  for (te = AH->toc->prev; te != AH->toc; te = te->prev)
509  {
510  AH->currentTE = te;
511 
512  /*
513  * In createDB mode, issue a DROP *only* for the database as a
514  * whole. Issuing drops against anything else would be wrong,
515  * because at this point we're connected to the wrong database.
516  * (The DATABASE PROPERTIES entry, if any, should be treated like
517  * the DATABASE entry.)
518  */
519  if (ropt->createDB)
520  {
521  if (strcmp(te->desc, "DATABASE") != 0 &&
522  strcmp(te->desc, "DATABASE PROPERTIES") != 0)
523  continue;
524  }
525 
526  /* Otherwise, drop anything that's selected and has a dropStmt */
527  if (((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0) && te->dropStmt)
528  {
529  pg_log_info("dropping %s %s", te->desc, te->tag);
530  /* Select owner and schema as necessary */
531  _becomeOwner(AH, te);
532  _selectOutputSchema(AH, te->namespace);
533 
534  /*
535  * Now emit the DROP command, if the object has one. Note we
536  * don't necessarily emit it verbatim; at this point we add an
537  * appropriate IF EXISTS clause, if the user requested it.
538  */
539  if (*te->dropStmt != '\0')
540  {
541  if (!ropt->if_exists)
542  {
543  /* No --if-exists? Then just use the original */
544  ahprintf(AH, "%s", te->dropStmt);
545  }
546  else
547  {
548  /*
549  * Inject an appropriate spelling of "if exists". For
550  * large objects, we have a separate routine that
551  * knows how to do it, without depending on
552  * te->dropStmt; use that. For other objects we need
553  * to parse the command.
554  */
555  if (strncmp(te->desc, "BLOB", 4) == 0)
556  {
557  DropLOIfExists(AH, te->catalogId.oid);
558  }
559  else
560  {
561  char *dropStmt = pg_strdup(te->dropStmt);
562  char *dropStmtOrig = dropStmt;
563  PQExpBuffer ftStmt = createPQExpBuffer();
564 
565  /*
566  * Need to inject IF EXISTS clause after ALTER
567  * TABLE part in ALTER TABLE .. DROP statement
568  */
569  if (strncmp(dropStmt, "ALTER TABLE", 11) == 0)
570  {
571  appendPQExpBufferStr(ftStmt,
572  "ALTER TABLE IF EXISTS");
573  dropStmt = dropStmt + 11;
574  }
575 
576  /*
577  * ALTER TABLE..ALTER COLUMN..DROP DEFAULT does
578  * not support the IF EXISTS clause, and therefore
579  * we simply emit the original command for DEFAULT
580  * objects (modulo the adjustment made above).
581  *
582  * Likewise, don't mess with DATABASE PROPERTIES.
583  *
584  * If we used CREATE OR REPLACE VIEW as a means of
585  * quasi-dropping an ON SELECT rule, that should
586  * be emitted unchanged as well.
587  *
588  * For other object types, we need to extract the
589  * first part of the DROP which includes the
590  * object type. Most of the time this matches
591  * te->desc, so search for that; however for the
592  * different kinds of CONSTRAINTs, we know to
593  * search for hardcoded "DROP CONSTRAINT" instead.
594  */
595  if (strcmp(te->desc, "DEFAULT") == 0 ||
596  strcmp(te->desc, "DATABASE PROPERTIES") == 0 ||
597  strncmp(dropStmt, "CREATE OR REPLACE VIEW", 22) == 0)
598  appendPQExpBufferStr(ftStmt, dropStmt);
599  else
600  {
601  char buffer[40];
602  char *mark;
603 
604  if (strcmp(te->desc, "CONSTRAINT") == 0 ||
605  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
606  strcmp(te->desc, "FK CONSTRAINT") == 0)
607  strcpy(buffer, "DROP CONSTRAINT");
608  else
609  snprintf(buffer, sizeof(buffer), "DROP %s",
610  te->desc);
611 
612  mark = strstr(dropStmt, buffer);
613 
614  if (mark)
615  {
616  *mark = '\0';
617  appendPQExpBuffer(ftStmt, "%s%s IF EXISTS%s",
618  dropStmt, buffer,
619  mark + strlen(buffer));
620  }
621  else
622  {
623  /* complain and emit unmodified command */
624  pg_log_warning("could not find where to insert IF EXISTS in statement \"%s\"",
625  dropStmtOrig);
626  appendPQExpBufferStr(ftStmt, dropStmt);
627  }
628  }
629 
630