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 int compression, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupWorkerPtr)
 
static void _getObjectDescription (PQExpBuffer buf, 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, int compression)
 
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 int compression, 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 StartBlob (Archive *AHX, Oid oid)
 
int EndBlob (Archive *AHX, Oid oid)
 
void StartRestoreBlobs (ArchiveHandle *AH)
 
void EndRestoreBlobs (ArchiveHandle *AH)
 
void StartRestoreBlob (ArchiveHandle *AH, Oid oid, bool drop)
 
void EndRestoreBlob (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 int  compression,
bool  dosync,
ArchiveMode  mode,
SetupWorkerPtrType  setupWorkerPtr 
)
static

Definition at line 2202 of file pg_backup_archiver.c.

2205 {
2206  ArchiveHandle *AH;
2207 
2208  pg_log_debug("allocating AH for %s, format %d",
2209  FileSpec ? FileSpec : "(stdio)", fmt);
2210 
2211  AH = (ArchiveHandle *) pg_malloc0(sizeof(ArchiveHandle));
2212 
2213  AH->version = K_VERS_SELF;
2214 
2215  /* initialize for backwards compatible string processing */
2216  AH->public.encoding = 0; /* PG_SQL_ASCII */
2217  AH->public.std_strings = false;
2218 
2219  /* sql error handling */
2220  AH->public.exit_on_error = true;
2221  AH->public.n_errors = 0;
2222 
2223  AH->archiveDumpVersion = PG_VERSION;
2224 
2225  AH->createDate = time(NULL);
2226 
2227  AH->intSize = sizeof(int);
2228  AH->offSize = sizeof(pgoff_t);
2229  if (FileSpec)
2230  {
2231  AH->fSpec = pg_strdup(FileSpec);
2232 
2233  /*
2234  * Not used; maybe later....
2235  *
2236  * AH->workDir = pg_strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
2237  * i--) if (AH->workDir[i-1] == '/')
2238  */
2239  }
2240  else
2241  AH->fSpec = NULL;
2242 
2243  AH->currUser = NULL; /* unknown */
2244  AH->currSchema = NULL; /* ditto */
2245  AH->currTablespace = NULL; /* ditto */
2246  AH->currTableAm = NULL; /* ditto */
2247 
2248  AH->toc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
2249 
2250  AH->toc->next = AH->toc;
2251  AH->toc->prev = AH->toc;
2252 
2253  AH->mode = mode;
2254  AH->compression = compression;
2255  AH->dosync = dosync;
2256 
2257  memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse));
2258 
2259  /* Open stdout with no compression for AH output handle */
2260  AH->gzOut = 0;
2261  AH->OF = stdout;
2262 
2263  /*
2264  * On Windows, we need to use binary mode to read/write non-text files,
2265  * which include all archive formats as well as compressed plain text.
2266  * Force stdin/stdout into binary mode if that is what we are using.
2267  */
2268 #ifdef WIN32
2269  if ((fmt != archNull || compression != 0) &&
2270  (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
2271  {
2272  if (mode == archModeWrite)
2273  _setmode(fileno(stdout), O_BINARY);
2274  else
2275  _setmode(fileno(stdin), O_BINARY);
2276  }
2277 #endif
2278 
2279  AH->SetupWorkerPtr = setupWorkerPtr;
2280 
2281  if (fmt == archUnknown)
2282  AH->format = _discoverArchiveFormat(AH);
2283  else
2284  AH->format = fmt;
2285 
2286  switch (AH->format)
2287  {
2288  case archCustom:
2290  break;
2291 
2292  case archNull:
2293  InitArchiveFmt_Null(AH);
2294  break;
2295 
2296  case archDirectory:
2298  break;
2299 
2300  case archTar:
2301  InitArchiveFmt_Tar(AH);
2302  break;
2303 
2304  default:
2305  pg_fatal("unrecognized file format \"%d\"", fmt);
2306  }
2307 
2308  return AH;
2309 }
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:49
@ archUnknown
Definition: pg_backup.h:39
@ archTar
Definition: pg_backup.h:41
@ archCustom
Definition: pg_backup.h:40
@ archDirectory
Definition: pg_backup.h:43
@ archNull
Definition: pg_backup.h:42
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:100
bool exit_on_error
Definition: pg_backup.h:232
int n_errors
Definition: pg_backup.h:233
bool std_strings
Definition: pg_backup.h:225
int encoding
Definition: pg_backup.h:224
ArchiveFormat format
struct _tocEntry * toc
sqlparseInfo sqlparse
SetupWorkerPtrType SetupWorkerPtr
struct _tocEntry * prev
struct _tocEntry * next
#define pgoff_t
Definition: win32_port.h:208

References _discoverArchiveFormat(), archCustom, archDirectory, _archiveHandle::archiveDumpVersion, archModeWrite, archNull, archTar, archUnknown, _archiveHandle::compression, _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_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 3232 of file pg_backup_archiver.c.

3233 {
3234  RestoreOptions *ropt = AH->public.ropt;
3235 
3236  if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
3237  return;
3238 
3239  _becomeUser(AH, te->owner);
3240 }
static void _becomeUser(ArchiveHandle *AH, const char *user)
RestoreOptions * ropt
Definition: pg_backup.h:210

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

3209 {
3210  if (!user)
3211  user = ""; /* avoid null pointers */
3212 
3213  if (AH->currUser && strcmp(AH->currUser, user) == 0)
3214  return; /* no need to do anything */
3215 
3216  _doSetSessionAuth(AH, user);
3217 
3218  /*
3219  * NOTE: currUser keeps track of what the imaginary session user in our
3220  * script is
3221  */
3222  if (AH->currUser)
3223  free(AH->currUser);
3224  AH->currUser = pg_strdup(user);
3225 }
#define free(a)
Definition: header.h:65
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user)
static char * user
Definition: pg_regress.c:95

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

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

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

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

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

3068 {
3069  RestoreOptions *ropt = AH->public.ropt;
3070 
3071  /*
3072  * Disable timeouts to allow for slow commands, idle parallel workers, etc
3073  */
3074  ahprintf(AH, "SET statement_timeout = 0;\n");
3075  ahprintf(AH, "SET lock_timeout = 0;\n");
3076  ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
3077 
3078  /* Select the correct character set encoding */
3079  ahprintf(AH, "SET client_encoding = '%s';\n",
3081 
3082  /* Select the correct string literal syntax */
3083  ahprintf(AH, "SET standard_conforming_strings = %s;\n",
3084  AH->public.std_strings ? "on" : "off");
3085 
3086  /* Select the role to be used during restore */
3087  if (ropt && ropt->use_role)
3088  ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));
3089 
3090  /* Select the dump-time search_path */
3091  if (AH->public.searchpath)
3092  ahprintf(AH, "%s", AH->public.searchpath);
3093 
3094  /* Make sure function checking is disabled */
3095  ahprintf(AH, "SET check_function_bodies = false;\n");
3096 
3097  /* Ensure that all valid XML data will be accepted */
3098  ahprintf(AH, "SET xmloption = content;\n");
3099 
3100  /* Avoid annoying notices etc */
3101  ahprintf(AH, "SET client_min_messages = warning;\n");
3102  if (!AH->public.std_strings)
3103  ahprintf(AH, "SET escape_string_warning = off;\n");
3104 
3105  /* Adjust row-security state */
3106  if (ropt && ropt->enable_row_security)
3107  ahprintf(AH, "SET row_security = on;\n");
3108  else
3109  ahprintf(AH, "SET row_security = off;\n");
3110 
3111  ahprintf(AH, "\n");
3112 }
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:228
char * use_role
Definition: pg_backup.h:103
int enable_row_security
Definition: pg_backup.h:152

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

3121 {
3123 
3124  appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3125 
3126  /*
3127  * SQL requires a string literal here. Might as well be correct.
3128  */
3129  if (user && *user)
3130  appendStringLiteralAHX(cmd, user, AH);
3131  else
3132  appendPQExpBufferStr(cmd, "DEFAULT");
3133  appendPQExpBufferChar(cmd, ';');
3134 
3135  if (RestoringToDB(AH))
3136  {
3137  PGresult *res;
3138 
3139  res = PQexec(AH->connection, cmd->data);
3140 
3141  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3142  /* NOT warn_or_exit_horribly... use -O instead to skip this. */
3143  pg_fatal("could not set session user to \"%s\": %s",
3145 
3146  PQclear(res);
3147  }
3148  else
3149  ahprintf(AH, "%s\n\n", cmd->data);
3150 
3151  destroyPQExpBuffer(cmd);
3152 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6908
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3270
void PQclear(PGresult *res)
Definition: fe-exec.c:718
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2273
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:97
static int RestoringToDB(ArchiveHandle *AH)
#define appendStringLiteralAHX(buf, str, AH)
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:74
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:116
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369

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

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

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,
TocEntry te 
)
static

Definition at line 3413 of file pg_backup_archiver.c.

3414 {
3415  const char *type = te->desc;
3416 
3417  /* Use ALTER TABLE for views and sequences */
3418  if (strcmp(type, "VIEW") == 0 || strcmp(type, "SEQUENCE") == 0 ||
3419  strcmp(type, "MATERIALIZED VIEW") == 0)
3420  type = "TABLE";
3421 
3422  /* objects that don't require special decoration */
3423  if (strcmp(type, "COLLATION") == 0 ||
3424  strcmp(type, "CONVERSION") == 0 ||
3425  strcmp(type, "DOMAIN") == 0 ||
3426  strcmp(type, "TABLE") == 0 ||
3427  strcmp(type, "TYPE") == 0 ||
3428  strcmp(type, "FOREIGN TABLE") == 0 ||
3429  strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
3430  strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 ||
3431  strcmp(type, "STATISTICS") == 0 ||
3432  /* non-schema-specified objects */
3433  strcmp(type, "DATABASE") == 0 ||
3434  strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
3435  strcmp(type, "SCHEMA") == 0 ||
3436  strcmp(type, "EVENT TRIGGER") == 0 ||
3437  strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
3438  strcmp(type, "SERVER") == 0 ||
3439  strcmp(type, "PUBLICATION") == 0 ||
3440  strcmp(type, "SUBSCRIPTION") == 0 ||
3441  strcmp(type, "USER MAPPING") == 0)
3442  {
3443  appendPQExpBuffer(buf, "%s ", type);
3444  if (te->namespace && *te->namespace)
3445  appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
3447  return;
3448  }
3449 
3450  /* BLOBs just have a name, but it's numeric so must not use fmtId */
3451  if (strcmp(type, "BLOB") == 0)
3452  {
3453  appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag);
3454  return;
3455  }
3456 
3457  /*
3458  * These object types require additional decoration. Fortunately, the
3459  * information needed is exactly what's in the DROP command.
3460  */
3461  if (strcmp(type, "AGGREGATE") == 0 ||
3462  strcmp(type, "FUNCTION") == 0 ||
3463  strcmp(type, "OPERATOR") == 0 ||
3464  strcmp(type, "OPERATOR CLASS") == 0 ||
3465  strcmp(type, "OPERATOR FAMILY") == 0 ||
3466  strcmp(type, "PROCEDURE") == 0)
3467  {
3468  /* Chop "DROP " off the front and make a modifiable copy */
3469  char *first = pg_strdup(te->dropStmt + 5);
3470  char *last;
3471 
3472  /* point to last character in string */
3473  last = first + strlen(first) - 1;
3474 
3475  /* Strip off any ';' or '\n' at the end */
3476  while (last >= first && (*last == '\n' || *last == ';'))
3477  last--;
3478  *(last + 1) = '\0';
3479 
3480  appendPQExpBufferStr(buf, first);
3481 
3482  free(first);
3483  return;
3484  }
3485 
3486  pg_log_warning("don't know how to set owner for object type \"%s\"",
3487  type);
3488 }
#define pg_log_warning(...)
Definition: pgfnames.c:24
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267

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

Referenced by _printTocEntry().

◆ _moveBefore()

static void _moveBefore ( TocEntry pos,
TocEntry te 
)
static

Definition at line 1793 of file pg_backup_archiver.c.

1794 {
1795  /* Unlink te from list */
1796  te->prev->next = te->next;
1797  te->next->prev = te->prev;
1798 
1799  /* and insert it before "pos" */
1800  te->prev = pos->prev;
1801  te->next = pos;
1802  pos->prev->next = te;
1803  pos->prev = te;
1804 }

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

Referenced by SortTocFromFile().

◆ _printTocEntry()

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

Definition at line 3498 of file pg_backup_archiver.c.

3499 {
3500  RestoreOptions *ropt = AH->public.ropt;
3501 
3502  /* Select owner, schema, tablespace and default AM as necessary */
3503  _becomeOwner(AH, te);
3504  _selectOutputSchema(AH, te->namespace);
3505  _selectTablespace(AH, te->tablespace);
3507 
3508  /* Emit header comment for item */
3509  if (!AH->noTocComments)
3510  {
3511  const char *pfx;
3512  char *sanitized_name;
3513  char *sanitized_schema;
3514  char *sanitized_owner;
3515 
3516  if (isData)
3517  pfx = "Data for ";
3518  else
3519  pfx = "";
3520 
3521  ahprintf(AH, "--\n");
3522  if (AH->public.verbose)
3523  {
3524  ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
3525  te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
3526  if (te->nDeps > 0)
3527  {
3528  int i;
3529 
3530  ahprintf(AH, "-- Dependencies:");
3531  for (i = 0; i < te->nDeps; i++)
3532  ahprintf(AH, " %d", te->dependencies[i]);
3533  ahprintf(AH, "\n");
3534  }
3535  }
3536 
3537  sanitized_name = sanitize_line(te->tag, false);
3538  sanitized_schema = sanitize_line(te->namespace, true);
3539  sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
3540 
3541  ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
3542  pfx, sanitized_name, te->desc, sanitized_schema,
3543  sanitized_owner);
3544 
3545  free(sanitized_name);
3546  free(sanitized_schema);
3547  free(sanitized_owner);
3548 
3549  if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace)
3550  {
3551  char *sanitized_tablespace;
3552 
3553  sanitized_tablespace = sanitize_line(te->tablespace, false);
3554  ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
3555  free(sanitized_tablespace);
3556  }
3557  ahprintf(AH, "\n");
3558 
3559  if (AH->PrintExtraTocPtr != NULL)
3560  AH->PrintExtraTocPtr(AH, te);
3561  ahprintf(AH, "--\n\n");
3562  }
3563 
3564  /*
3565  * Actually print the definition.
3566  *
3567  * Really crude hack for suppressing AUTHORIZATION clause that old pg_dump
3568  * versions put into CREATE SCHEMA. Don't mutate the variant for schema
3569  * "public" that is a comment. We have to do this when --no-owner mode is
3570  * selected. This is ugly, but I see no other good way ...
3571  */
3572  if (ropt->noOwner &&
3573  strcmp(te->desc, "SCHEMA") == 0 && strncmp(te->defn, "--", 2) != 0)
3574  {
3575  ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
3576  }
3577  else
3578  {
3579  if (te->defn && strlen(te->defn) > 0)
3580  ahprintf(AH, "%s\n\n", te->defn);
3581  }
3582 
3583  /*
3584  * If we aren't using SET SESSION AUTH to determine ownership, we must
3585  * instead issue an ALTER OWNER command. Schema "public" is special; when
3586  * a dump emits a comment in lieu of creating it, we use ALTER OWNER even
3587  * when using SET SESSION for all other objects. We assume that anything
3588  * without a DROP command is not a separately ownable object. All the
3589  * categories with DROP commands must appear in one list or the other.
3590  */
3591  if (!ropt->noOwner &&
3592  (!ropt->use_setsessauth ||
3593  (strcmp(te->desc, "SCHEMA") == 0 &&
3594  strncmp(te->defn, "--", 2) == 0)) &&
3595  te->owner && strlen(te->owner) > 0 &&
3596  te->dropStmt && strlen(te->dropStmt) > 0)
3597  {
3598  if (strcmp(te->desc, "AGGREGATE") == 0 ||
3599  strcmp(te->desc, "BLOB") == 0 ||
3600  strcmp(te->desc, "COLLATION") == 0 ||
3601  strcmp(te->desc, "CONVERSION") == 0 ||
3602  strcmp(te->desc, "DATABASE") == 0 ||
3603  strcmp(te->desc, "DOMAIN") == 0 ||
3604  strcmp(te->desc, "FUNCTION") == 0 ||
3605  strcmp(te->desc, "OPERATOR") == 0 ||
3606  strcmp(te->desc, "OPERATOR CLASS") == 0 ||
3607  strcmp(te->desc, "OPERATOR FAMILY") == 0 ||
3608  strcmp(te->desc, "PROCEDURE") == 0 ||
3609  strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 ||
3610  strcmp(te->desc, "SCHEMA") == 0 ||
3611  strcmp(te->desc, "EVENT TRIGGER") == 0 ||
3612  strcmp(te->desc, "TABLE") == 0 ||
3613  strcmp(te->desc, "TYPE") == 0 ||
3614  strcmp(te->desc, "VIEW") == 0 ||
3615  strcmp(te->desc, "MATERIALIZED VIEW") == 0 ||
3616  strcmp(te->desc, "SEQUENCE") == 0 ||
3617  strcmp(te->desc, "FOREIGN TABLE") == 0 ||
3618  strcmp(te->desc, "TEXT SEARCH DICTIONARY") == 0 ||
3619  strcmp(te->desc, "TEXT SEARCH CONFIGURATION") == 0 ||
3620  strcmp(te->desc, "FOREIGN DATA WRAPPER") == 0 ||
3621  strcmp(te->desc, "SERVER") == 0 ||
3622  strcmp(te->desc, "STATISTICS") == 0 ||
3623  strcmp(te->desc, "PUBLICATION") == 0 ||
3624  strcmp(te->desc, "SUBSCRIPTION") == 0)
3625  {
3626  PQExpBuffer temp = createPQExpBuffer();
3627 
3628  appendPQExpBufferStr(temp, "ALTER ");
3629  _getObjectDescription(temp, te);
3630  appendPQExpBuffer(temp, " OWNER TO %s;", fmtId(te->owner));
3631  ahprintf(AH, "%s\n\n", temp->data);
3632  destroyPQExpBuffer(temp);
3633  }
3634  else if (strcmp(te->desc, "CAST") == 0 ||
3635  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
3636  strcmp(te->desc, "CONSTRAINT") == 0 ||
3637  strcmp(te->desc, "DATABASE PROPERTIES") == 0 ||
3638  strcmp(te->desc, "DEFAULT") == 0 ||
3639  strcmp(te->desc, "FK CONSTRAINT") == 0 ||
3640  strcmp(te->desc, "INDEX") == 0 ||
3641  strcmp(te->desc, "RULE") == 0 ||
3642  strcmp(te->desc, "TRIGGER") == 0 ||
3643  strcmp(te->desc, "ROW SECURITY") == 0 ||
3644  strcmp(te->desc, "POLICY") == 0 ||
3645  strcmp(te->desc, "USER MAPPING") == 0)
3646  {
3647  /* these object types don't have separate owners */
3648  }
3649  else
3650  {
3651  pg_log_warning("don't know how to set owner for object type \"%s\"",
3652  te->desc);
3653  }
3654  }
3655 
3656  /*
3657  * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
3658  * commands, so we can no longer assume we know the current auth setting.
3659  */
3660  if (_tocEntryIsACL(te))
3661  {
3662  if (AH->currUser)
3663  free(AH->currUser);
3664  AH->currUser = NULL;
3665  }
3666 }
int i
Definition: isn.c:73
static void _becomeOwner(ArchiveHandle *AH, TocEntry *te)
static bool _tocEntryIsACL(TocEntry *te)
static void _selectTableAccessMethod(ArchiveHandle *AH, const char *tableam)
static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
static void _getObjectDescription(PQExpBuffer buf, TocEntry *te)
static char * sanitize_line(const char *str, bool want_hyphen)
static void _selectTablespace(ArchiveHandle *AH, const char *tablespace)
int verbose
Definition: pg_backup.h:212
Oid tableoid
Definition: pg_backup.h:261
PrintExtraTocPtrType PrintExtraTocPtr
CatalogId catalogId
DumpId * dependencies

References _becomeOwner(), _getObjectDescription(), _selectOutputSchema(), _selectTableAccessMethod(), _selectTablespace(), _tocEntryIsACL(), ahprintf(), appendPQExpBuffer(), appendPQExpBufferStr(), _tocEntry::catalogId, createPQExpBuffer(), _archiveHandle::currUser, PQExpBufferData::data, _tocEntry::defn, _tocEntry::dependencies, _tocEntry::desc, destroyPQExpBuffer(), _tocEntry::dropStmt, _tocEntry::dumpId, fmtId(), free, i, _tocEntry::nDeps, _restoreOptions::noOwner, _restoreOptions::noTablespace, _archiveHandle::noTocComments, CatalogId::oid, _tocEntry::owner, pg_log_warning, _archiveHandle::PrintExtraTocPtr, _archiveHandle::public, Archive::ropt, sanitize_line(), _tocEntry::tableam, CatalogId::tableoid, _tocEntry::tablespace, _tocEntry::tag, _restoreOptions::use_setsessauth, and Archive::verbose.

Referenced by restore_toc_entry().

◆ _reconnectToDB()

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

Definition at line 3163 of file pg_backup_archiver.c.

3164 {
3165  if (RestoringToDB(AH))
3167  else
3168  {
3169  PQExpBufferData connectbuf;
3170 
3171  initPQExpBuffer(&connectbuf);
3172  appendPsqlMetaConnect(&connectbuf, dbname);
3173  ahprintf(AH, "%s\n", connectbuf.data);
3174  termPQExpBuffer(&connectbuf);
3175  }
3176 
3177  /*
3178  * NOTE: currUser keeps track of what the imaginary session user in our
3179  * script is. It's now effectively reset to the original userID.
3180  */
3181  if (AH->currUser)
3182  free(AH->currUser);
3183  AH->currUser = NULL;
3184 
3185  /* don't assume we still know the output schema, tablespace, etc either */
3186  if (AH->currSchema)
3187  free(AH->currSchema);
3188  AH->currSchema = NULL;
3189 
3190  if (AH->currTableAm)
3191  free(AH->currTableAm);
3192  AH->currTableAm = NULL;
3193 
3194  if (AH->currTablespace)
3195  free(AH->currTablespace);
3196  AH->currTablespace = NULL;
3197 
3198  /* re-establish fixed state */
3200 }
static void _doSetFixedOutputState(ArchiveHandle *AH)
void ReconnectToServer(ArchiveHandle *AH, const char *dbname)
Definition: pg_backup_db.c:74
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
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 3248 of file pg_backup_archiver.c.

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

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

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

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

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

3053 {
3054  /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3055  if (strcmp(te->desc, "ACL") == 0 ||
3056  strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3057  strcmp(te->desc, "DEFAULT ACL") == 0)
3058  return true;
3059  return false;
3060 }

References _tocEntry::desc.

Referenced by _printTocEntry(), and _tocEntryRequired().

◆ _tocEntryRequired()

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

Definition at line 2762 of file pg_backup_archiver.c.

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

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

3020 {
3021  /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3022  if (strcmp(te->desc, "ACL") == 0 ||
3023  strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3024  strcmp(te->desc, "DEFAULT ACL") == 0)
3025  return RESTORE_PASS_ACL;
3026  if (strcmp(te->desc, "EVENT TRIGGER") == 0 ||
3027  strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0)
3028  return RESTORE_PASS_POST_ACL;
3029 
3030  /*
3031  * Comments need to be emitted in the same pass as their parent objects.
3032  * ACLs haven't got comments, and neither do matview data objects, but
3033  * event triggers do. (Fortunately, event triggers haven't got ACLs, or
3034  * we'd need yet another weird special case.)
3035  */
3036  if (strcmp(te->desc, "COMMENT") == 0 &&
3037  strncmp(te->tag, "EVENT TRIGGER ", 14) == 0)
3038  return RESTORE_PASS_POST_ACL;
3039 
3040  /* All else can be handled in the main pass. */
3041  return RESTORE_PASS_MAIN;
3042 }
@ 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 1588 of file pg_backup_archiver.c.

1589 {
1590  int save_errno = errno;
1591  char *p;
1592  size_t len = 128; /* initial assumption about buffer size */
1593  size_t cnt;
1594 
1595  for (;;)
1596  {
1597  va_list args;
1598 
1599  /* Allocate work buffer. */
1600  p = (char *) pg_malloc(len);
1601 
1602  /* Try to format the data. */
1603  errno = save_errno;
1604  va_start(args, fmt);
1605  cnt = pvsnprintf(p, len, fmt, args);
1606  va_end(args);
1607 
1608  if (cnt < len)
1609  break; /* success */
1610 
1611  /* Release buffer and loop around to try again with larger len. */
1612  free(p);
1613  len = cnt;
1614  }
1615 
1616  ahwrite(p, 1, cnt, AH);
1617  free(p);
1618  return (int) cnt;
1619 }
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(), _EndBlob(), _EndBlobs(), _EndData(), _PrintExtraToc(), _PrintTocData(), _printTocEntry(), _reconnectToDB(), _selectOutputSchema(), _selectTableAccessMethod(), _selectTablespace(), _StartBlob(), _StartBlobs(), _WriteBlobData(), DropBlobIfExists(), dump_lo_buf(), dumpTimestamp(), EndRestoreBlob(), EndRestoreBlobs(), PrintTOCSummary(), restore_toc_entry(), RestoreArchive(), StartRestoreBlob(), and StartRestoreBlobs().

◆ ahwrite()

void ahwrite ( const void *  ptr,
size_t  size,
size_t  nmemb,
ArchiveHandle AH 
)

Definition at line 1679 of file pg_backup_archiver.c.

1680 {
1681  int bytes_written = 0;
1682 
1683  if (AH->writingBlob)
1684  {
1685  size_t remaining = size * nmemb;
1686 
1687  while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1688  {
1689  size_t avail = AH->lo_buf_size - AH->lo_buf_used;
1690 
1691  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1692  ptr = (const void *) ((const char *) ptr + avail);
1693  remaining -= avail;
1694  AH->lo_buf_used += avail;
1695  dump_lo_buf(AH);
1696  }
1697 
1698  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1699  AH->lo_buf_used += remaining;
1700 
1701  bytes_written = size * nmemb;
1702  }
1703  else if (AH->gzOut)
1704  bytes_written = GZWRITE(ptr, size, nmemb, AH->OF);
1705  else if (AH->CustomOutPtr)
1706  bytes_written = AH->CustomOutPtr(AH, ptr, size * nmemb);
1707 
1708  else
1709  {
1710  /*
1711  * If we're doing a restore, and it's direct to DB, and we're
1712  * connected then send it to the DB.
1713  */
1714  if (RestoringToDB(AH))
1715  bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb);
1716  else
1717  bytes_written = fwrite(ptr, size, nmemb, AH->OF) * size;
1718  }
1719 
1720  if (bytes_written != size * nmemb)
1722 }
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:446
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::writingBlob.

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

◆ ArchiveEntry()

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

Definition at line 1056 of file pg_backup_archiver.c.

1058 {
1059  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1060  TocEntry *newToc;
1061 
1062  newToc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
1063 
1064  AH->tocCount++;
1065  if (dumpId > AH->maxDumpId)
1066  AH->maxDumpId = dumpId;
1067 
1068  newToc->prev = AH->toc->prev;
1069  newToc->next = AH->toc;
1070  AH->toc->prev->next = newToc;
1071  AH->toc->prev = newToc;
1072 
1073  newToc->catalogId = catalogId;
1074  newToc->dumpId = dumpId;
1075  newToc->section = opts->section;
1076 
1077  newToc->tag = pg_strdup(opts->tag);
1078  newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
1079  newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
1080  newToc->tableam = opts->tableam ? pg_strdup(opts->tableam) : NULL;
1081  newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
1082  newToc->desc = pg_strdup(opts->description);
1083  newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
1084  newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
1085  newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
1086 
1087  if (opts->nDeps > 0)
1088  {
1089  newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId));
1090  memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
1091  newToc->nDeps = opts->nDeps;
1092  }
1093  else
1094  {
1095  newToc->dependencies = NULL;
1096  newToc->nDeps = 0;
1097  }
1098 
1099  newToc->dataDumper = opts->dumpFn;
1100  newToc->dataDumperArg = opts->dumpArg;
1101  newToc->hadDumper = opts->dumpFn ? true : false;
1102 
1103  newToc->formatData = NULL;
1104  newToc->dataLength = 0;
1105 
1106  if (AH->ArchiveEntryPtr != NULL)
1107  AH->ArchiveEntryPtr(AH, newToc);
1108 
1109  return newToc;
1110 }
return true
Definition: isn.c:126
static AmcheckOptions opts
Definition: pg_amcheck.c:110
int DumpId
Definition: pg_backup.h:265
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(), dumpBlob(), dumpCast(), dumpCollation(), dumpCommentExtended(), dumpCompositeType(), dumpCompositeTypeColComments(), dumpConstraint(), dumpConversion(), dumpDatabase(), dumpDefaultACL(), dumpDomain(), dumpDumpableObject(), dumpEncoding(), dumpEnumType(), dumpEventTrigger(), dumpExtension(), dumpForeignDataWrapper(), dumpForeignServer(), dumpFunc(), dumpIndex(), dumpIndexAttach(), 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 1450 of file pg_backup_archiver.c.

1451 {
1452  int save_errno = errno;
1453  char *p;
1454  size_t len = 128; /* initial assumption about buffer size */
1455  size_t cnt;
1456 
1457  for (;;)
1458  {
1459  va_list args;
1460 
1461  /* Allocate work buffer. */
1462  p = (char *) pg_malloc(len);
1463 
1464  /* Try to format the data. */
1465  errno = save_errno;
1466  va_start(args, fmt);
1467  cnt = pvsnprintf(p, len, fmt, args);
1468  va_end(args);
1469 
1470  if (cnt < len)
1471  break; /* success */
1472 
1473  /* Release buffer and loop around to try again with larger len. */
1474  free(p);
1475  len = cnt;
1476  }
1477 
1478  WriteData(AH, p, cnt);
1479  free(p);
1480  return (int) cnt;
1481 }
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 1443 of file pg_backup_archiver.c.

1444 {
1445  WriteData(AH, s, strlen(s));
1446 }

References WriteData().

Referenced by dumpTableData_insert().

◆ buildTocEntryArrays()

static void buildTocEntryArrays ( ArchiveHandle AH)
static

Definition at line 1818 of file pg_backup_archiver.c.

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

3859 {
3860  pgoff_t tpos;
3861 
3862  /* Check that ftello works on this file */
3863  tpos = ftello(fp);
3864  if (tpos < 0)
3865  return false;
3866 
3867  /*
3868  * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
3869  * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
3870  * successful no-op even on files that are otherwise unseekable.
3871  */
3872  if (fseeko(fp, tpos, SEEK_SET) != 0)
3873  return false;
3874 
3875  return true;
3876 }
#define ftello(stream)
Definition: win32_port.h:218
#define fseeko(stream, offset, origin)
Definition: win32_port.h:215

References fseeko, ftello, and pgoff_t.

Referenced by InitArchiveFmt_Custom(), and InitArchiveFmt_Tar().

◆ CloneArchive()

ArchiveHandle* CloneArchive ( ArchiveHandle AH)

Definition at line 4782 of file pg_backup_archiver.c.

4783 {
4784  ArchiveHandle *clone;
4785 
4786  /* Make a "flat" copy */
4787  clone = (ArchiveHandle *) pg_malloc(sizeof(ArchiveHandle));
4788  memcpy(clone, AH, sizeof(ArchiveHandle));
4789 
4790  /* Handle format-independent fields */
4791  memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse));
4792 
4793  /* The clone will have its own connection, so disregard connection state */
4794  clone->connection = NULL;
4795  clone->connCancel = NULL;
4796  clone->currUser = NULL;
4797  clone->currSchema = NULL;
4798  clone->currTableAm = NULL;
4799  clone->currTablespace = NULL;
4800 
4801  /* savedPassword must be local in case we change it while connecting */
4802  if (clone->savedPassword)
4803  clone->savedPassword = pg_strdup(clone->savedPassword);
4804 
4805  /* clone has its own error count, too */
4806  clone->public.n_errors = 0;
4807 
4808  /*
4809  * Connect our new clone object to the database, using the same connection
4810  * parameters used for the original connection.
4811  */
4812  ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true);
4813 
4814  /* re-establish fixed state */
4815  if (AH->mode == archModeRead)
4816  _doSetFixedOutputState(clone);
4817  /* in write case, setupDumpWorker will fix up connection state */
4818 
4819  /* Let the format-specific code have a chance too */
4820  clone->ClonePtr(clone);
4821 
4822  Assert(clone->connection != NULL);
4823  return clone;
4824 }
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:50
PGcancel *volatile connCancel
ClonePtrType ClonePtr
ConnParams cparams
Definition: pg_backup.h:142

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

265 {
266  int res = 0;
267  ArchiveHandle *AH = (ArchiveHandle *) AHX;
268 
269  AH->ClosePtr(AH);
270 
271  /* Close the output */
272  errno = 0; /* in case gzclose() doesn't set it */
273  if (AH->gzOut)
274  res = GZCLOSE(AH->OF);
275  else if (AH->OF != stdout)
276  res = fclose(AH->OF);
277 
278  if (res != 0)
279  pg_fatal("could not close output file: %m");
280 }
#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 int  compression,
bool  dosync,
ArchiveMode  mode,
SetupWorkerPtrType  setupDumpWorker 
)

Definition at line 241 of file pg_backup_archiver.c.

245 {
246  ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, dosync,
248 
249  return (Archive *) AH;
250 }
static ArchiveHandle * _allocAH(const char *FileSpec, const ArchiveFormat fmt, const int compression, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupWorkerPtr)
static void setupDumpWorker(Archive *AHX)
Definition: pg_dump.c:1232

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

Referenced by main().

◆ DeCloneArchive()

void DeCloneArchive ( ArchiveHandle AH)

Definition at line 4832 of file pg_backup_archiver.c.

4833 {
4834  /* Should not have an open database connection */
4835  Assert(AH->connection == NULL);
4836 
4837  /* Clear format-specific state */
4838  AH->DeClonePtr(AH);
4839 
4840  /* Clear state allocated by CloneArchive */
4841  if (AH->sqlparse.curCmd)
4843 
4844  /* Clear any connection-local state */
4845  if (AH->currUser)
4846  free(AH->currUser);
4847  if (AH->currSchema)
4848  free(AH->currSchema);
4849  if (AH->currTablespace)
4850  free(AH->currTablespace);
4851  if (AH->currTableAm)
4852  free(AH->currTableAm);
4853  if (AH->savedPassword)
4854  free(AH->savedPassword);
4855 
4856  free(AH);
4857 }
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 1636 of file pg_backup_archiver.c.

1637 {
1638  if (AH->connection)
1639  {
1640  int res;
1641 
1642  res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1643  pg_log_debug(ngettext("wrote %zu byte of large object data (result = %d)",
1644  "wrote %zu bytes of large object data (result = %d)",
1645  AH->lo_buf_used),
1646  AH->lo_buf_used, res);
1647  /* We assume there are no short writes, only errors */
1648  if (res != AH->lo_buf_used)
1649  warn_or_exit_horribly(AH, "could not write to large object: %s",
1650  PQerrorMessage(AH->connection));
1651  }
1652  else
1653  {
1655 
1657  (const unsigned char *) AH->lo_buf,
1658  AH->lo_buf_used,
1659  AH);
1660 
1661  /* Hack: turn off writingBlob so ahwrite doesn't recurse to here */
1662  AH->writingBlob = 0;
1663  ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
1664  AH->writingBlob = 1;
1665 
1667  }
1668  AH->lo_buf_used = 0;
1669 }
int lo_write(int fd, const char *buf, int len)
Definition: be-fsstubs.c:177
#define ngettext(s, p, n)
Definition: c.h:1179
#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::writingBlob.

Referenced by ahwrite(), and EndRestoreBlob().

◆ dumpOptionsFromRestoreOptions()

DumpOptions* dumpOptionsFromRestoreOptions ( RestoreOptions ropt)

Definition at line 177 of file pg_backup_archiver.c.

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

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

3884 {
3885  char buf[64];
3886 
3887  if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
3888  ahprintf(AH, "-- %s %s\n\n", msg, buf);
3889 }
#define PGDUMP_STRFTIME_FMT
Definition: dumputils.h:33

References ahprintf(), buf, and PGDUMP_STRFTIME_FMT.

Referenced by RestoreArchive().

◆ EndBlob()

int EndBlob ( Archive AHX,
Oid  oid 
)

Definition at line 1232 of file pg_backup_archiver.c.

1233 {
1234  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1235 
1236  if (AH->EndBlobPtr)
1237  AH->EndBlobPtr(AH, AH->currToc, oid);
1238 
1239  return 1;
1240 }
EndBlobPtrType EndBlobPtr
struct _tocEntry * currToc

References _archiveHandle::currToc, and _archiveHandle::EndBlobPtr.

Referenced by dumpBlobs().

◆ EndRestoreBlob()

void EndRestoreBlob ( ArchiveHandle AH,
Oid  oid 
)

Definition at line 1336 of file pg_backup_archiver.c.

1337 {
1338  if (AH->lo_buf_used > 0)
1339  {
1340  /* Write remaining bytes from the LO buffer */
1341  dump_lo_buf(AH);
1342  }
1343 
1344  AH->writingBlob = 0;
1345 
1346  if (AH->connection)
1347  {
1348  lo_close(AH->connection, AH->loFd);
1349  AH->loFd = -1;
1350  }
1351  else
1352  {
1353  ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
1354  }
1355 }
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::writingBlob.

Referenced by _LoadBlobs().

◆ EndRestoreBlobs()

void EndRestoreBlobs ( ArchiveHandle AH)

Definition at line 1269 of file pg_backup_archiver.c.

1270 {
1271  RestoreOptions *ropt = AH->public.ropt;
1272 
1273  if (!ropt->single_txn)
1274  {
1275  if (AH->connection)
1276  CommitTransaction(&AH->public);
1277  else
1278  ahprintf(AH, "COMMIT;\n\n");
1279  }
1280 
1281  pg_log_info(ngettext("restored %d large object",
1282  "restored %d large objects",
1283  AH->blobCount),
1284  AH->blobCount);
1285 }
static void CommitTransaction(void)
Definition: xact.c:2141

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

Referenced by _LoadBlobs().

◆ fix_dependencies()

static void fix_dependencies ( ArchiveHandle AH)
static

Definition at line 4479 of file pg_backup_archiver.c.

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

1860 {
1861  /* build index arrays if we didn't already */
1862  if (AH->tocsByDumpId == NULL)
1863  buildTocEntryArrays(AH);
1864 
1865  if (id > 0 && id <= AH->maxDumpId)
1866  return AH->tocsByDumpId[id];
1867 
1868  return NULL;
1869 }
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 4170 of file pg_backup_archiver.c.

4171 {
4172  int j,
4173  k;
4174 
4175  for (j = 0; j < te1->nLockDeps; j++)
4176  {
4177  for (k = 0; k < te2->nDeps; k++)
4178  {
4179  if (te1->lockDeps[j] == te2->dependencies[k])
4180  return true;
4181  }
4182  }
4183  return false;
4184 }
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 4643 of file pg_backup_archiver.c.

4644 {
4645  DumpId *lockids;
4646  int nlockids;
4647  int i;
4648 
4649  /*
4650  * We only care about this for POST_DATA items. PRE_DATA items are not
4651  * run in parallel, and DATA items are all independent by assumption.
4652  */
4653  if (te->section != SECTION_POST_DATA)
4654  return;
4655 
4656  /* Quick exit if no dependencies at all */
4657  if (te->nDeps == 0)
4658  return;
4659 
4660  /*
4661  * Most POST_DATA items are ALTER TABLEs or some moral equivalent of that,
4662  * and hence require exclusive lock. However, we know that CREATE INDEX
4663  * does not. (Maybe someday index-creating CONSTRAINTs will fall in that
4664  * category too ... but today is not that day.)
4665  */
4666  if (strcmp(te->desc, "INDEX") == 0)
4667  return;
4668 
4669  /*
4670  * We assume the entry requires exclusive lock on each TABLE or TABLE DATA
4671  * item listed among its dependencies. Originally all of these would have
4672  * been TABLE items, but repoint_table_dependencies would have repointed
4673  * them to the TABLE DATA items if those are present (which they might not
4674  * be, eg in a schema-only dump). Note that all of the entries we are
4675  * processing here are POST_DATA; otherwise there might be a significant
4676  * difference between a dependency on a table and a dependency on its
4677  * data, so that closer analysis would be needed here.
4678  */
4679  lockids = (DumpId *) pg_malloc(te->nDeps * sizeof(DumpId));
4680  nlockids = 0;
4681  for (i = 0; i < te->nDeps; i++)
4682  {
4683  DumpId depid = te->dependencies[i];
4684 
4685  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL &&
4686  ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) ||
4687  strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0))
4688  lockids[nlockids++] = depid;
4689  }
4690 
4691  if (nlockids == 0)
4692  {
4693  free(lockids);
4694  return;
4695  }
4696 
4697  te->lockDeps = pg_realloc(lockids, nlockids * sizeof(DumpId));
4698  te->nLockDeps = nlockids;
4699 }
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 4762 of file pg_backup_archiver.c.

4763 {
4764  pg_log_info("table \"%s\" could not be created, will not restore its data",
4765  te->tag);
4766 
4767  if (AH->tableDataId[te->dumpId] != 0)
4768  {
4769  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4770 
4771  ted->reqs = 0;
4772  }
4773 }

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

164 {
165  memset(opts, 0, sizeof(DumpOptions));
166  /* set any fields that shouldn't default to zeroes */
167  opts->include_everything = true;
168  opts->cparams.promptPassword = TRI_DEFAULT;
169  opts->dumpSections = DUMP_UNSECTIONED;
170 }
#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 4747 of file pg_backup_archiver.c.

4748 {
4749  if (AH->tableDataId[te->dumpId] != 0)
4750  {
4751  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4752 
4753  ted->created = true;
4754  }
4755 }

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

2386 {
2387  pg_log_info("finished item %d %s %s",
2388  te->dumpId, te->desc, te->tag);
2389 
2390  if (status != 0)
2391  pg_fatal("worker process failed: exit code %d",
2392  status);
2393 }
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229

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

4442 {
4443  ParallelReadyList *ready_list = (ParallelReadyList *) callback_data;
4444 
4445  pg_log_info("finished item %d %s %s",
4446  te->dumpId, te->desc, te->tag);
4447 
4448  if (status == WORKER_CREATE_DONE)
4449  mark_create_done(AH, te);
4450  else if (status == WORKER_INHIBIT_DATA)
4451  {
4453  AH->public.n_errors++;
4454  }
4455  else if (status == WORKER_IGNORED_ERRORS)
4456  AH->public.n_errors++;
4457  else if (status != 0)
4458  pg_fatal("worker process failed: exit code %d",
4459  status);
4460 
4461  reduce_dependencies(AH, te, ready_list);
4462 }
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 4323 of file pg_backup_archiver.c.

4326 {
4327  TocEntry *te;
4328  TocEntry *next_te;
4329 
4330  for (te = pending_list->pending_next; te != pending_list; te = next_te)
4331  {
4332  /* must save list link before possibly removing te from list */
4333  next_te = te->pending_next;
4334 
4335  if (te->depCount == 0 &&
4336  _tocEntryRestorePass(te) == pass)
4337  {
4338  /* Remove it from pending_list ... */
4339  pending_list_remove(te);
4340  /* ... and add to ready_list */
4341  ready_list_insert(ready_list, te);
4342  }
4343  }
4344 }
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 151 of file pg_backup_archiver.c.

152 {
154 
156  return opts;
157 }
void InitDumpOptions(DumpOptions *opts)

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

Referenced by dumpOptionsFromRestoreOptions().

◆ NewRestoreOptions()

RestoreOptions* NewRestoreOptions ( void  )

Definition at line 963 of file pg_backup_archiver.c.

964 {
966 
968 
969  /* set any fields that shouldn't default to zeroes */
970  opts->format = archUnknown;
971  opts->cparams.promptPassword = TRI_DEFAULT;
972  opts->dumpSections = DUMP_UNSECTIONED;
973 
974  return opts;
975 }

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

Referenced by _CloseArchive(), and main().

◆ OpenArchive()

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

Definition at line 255 of file pg_backup_archiver.c.

256 {
257  ArchiveHandle *AH = _allocAH(FileSpec, fmt, 0, true, archModeRead, setupRestoreWorker);
258 
259  return (Archive *) AH;
260 }
static void setupRestoreWorker(Archive *AHX)

References _allocAH(), archModeRead, fmt, and setupRestoreWorker().

Referenced by main().

◆ parallel_restore()

int parallel_restore ( ArchiveHandle AH,
TocEntry te 
)

Definition at line 4415 of file pg_backup_archiver.c.

4416 {
4417  int status;
4418 
4419  Assert(AH->connection != NULL);
4420 
4421  /* Count only errors associated with this TOC entry */
4422  AH->public.n_errors = 0;
4423 
4424  /* Restore the TOC item */
4425  status = restore_toc_entry(AH, te, true);
4426 
4427  return status;
4428 }
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 4202 of file pg_backup_archiver.c.

4203 {
4204  te->pending_prev = l->pending_prev;
4205  l->pending_prev->pending_next = te;
4206  l->pending_prev = te;
4207  te->pending_next = l;
4208 }

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

4196 {
4197  l->pending_prev = l->pending_next = l;
4198 }

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

4213 {
4216  te->pending_prev = NULL;
4217  te->pending_next = NULL;
4218 }

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

4360 {
4361  /*
4362  * Sort the ready_list so that we'll tackle larger jobs first.
4363  */
4364  ready_list_sort(ready_list);
4365 
4366  /*
4367  * Search the ready_list until we find a suitable item.
4368  */
4369  for (int i = ready_list->first_te; i <= ready_list->last_te; i++)
4370  {
4371  TocEntry *te = ready_list->tes[i];
4372  bool conflicts = false;
4373 
4374  /*
4375  * Check to see if the item would need exclusive lock on something
4376  * that a currently running item also needs lock on, or vice versa. If
4377  * so, we don't want to schedule them together.
4378  */
4379  for (int k = 0; k < pstate->numWorkers; k++)
4380  {
4381  TocEntry *running_te = pstate->te[k];
4382 
4383  if (running_te == NULL)
4384  continue;
4385  if (has_lock_conflicts(te, running_te) ||
4386  has_lock_conflicts(running_te, te))
4387  {
4388  conflicts = true;
4389  break;
4390  }
4391  }
4392 
4393  if (conflicts)
4394  continue;
4395 
4396  /* passed all tests, so this item can run */
4397  ready_list_remove(ready_list, i);
4398  return te;
4399  }
4400 
4401  pg_log_debug("no item ready");
4402  return NULL;
4403 }
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 1114 of file pg_backup_archiver.c.

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

References _tocEntryRequired(), ahprintf(), archCustom, _archiveHandle::archdbname, archDirectory, ARCHIVE_MAJOR, ARCHIVE_MINOR, ARCHIVE_REV, _archiveHandle::archiveDumpVersion, _archiveHandle::archiveRemoteVersion, archTar, _tocEntry::catalogId, _archiveHandle::compression, _archiveHandle::createDate, _tocEntry::dependencies, _tocEntry::desc, _tocEntry::dumpId, _restoreOptions::filename, _archiveHandle::format, free, i, _archiveHandle::intSize, _tocEntry::nDeps, _tocEntry::next, _archiveHandle::offSize, CatalogId::oid, _tocEntry::owner, 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 297 of file pg_backup_archiver.c.

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

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

2659 {
2660  /* te->defn should have the form SET client_encoding = 'foo'; */
2661  char *defn = pg_strdup(te->defn);
2662  char *ptr1;
2663  char *ptr2 = NULL;
2664  int encoding;
2665 
2666  ptr1 = strchr(defn, '\'');
2667  if (ptr1)
2668  ptr2 = strchr(++ptr1, '\'');
2669  if (ptr2)
2670  {
2671  *ptr2 = '\0';
2672  encoding = pg_char_to_encoding(ptr1);
2673  if (encoding < 0)
2674  pg_fatal("unrecognized encoding \"%s\"",
2675  ptr1);
2676  AH->public.encoding = encoding;
2677  }
2678  else
2679  pg_fatal("invalid ENCODING item: %s",
2680  te->defn);
2681 
2682  free(defn);
2683 }
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 2702 of file pg_backup_archiver.c.

2703 {
2704  /*
2705  * te->defn should contain a command to set search_path. We just copy it
2706  * verbatim for use later.
2707  */
2708  AH->public.searchpath = pg_strdup(te->defn);
2709 }

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

2687 {
2688  /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2689  char *ptr1;
2690 
2691  ptr1 = strchr(te->defn, '\'');
2692  if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2693  AH->public.std_strings = true;
2694  else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2695  AH->public.std_strings = false;
2696  else
2697  pg_fatal("invalid STDSTRINGS item: %s",
2698  te->defn);
2699 }

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

Referenced by ReadToc().

◆ ReadHead()

void ReadHead ( ArchiveHandle AH)

Definition at line 3734 of file pg_backup_archiver.c.

3735 {
3736  char vmaj,
3737  vmin,
3738  vrev;
3739  int fmt;
3740 
3741  /*
3742  * If we haven't already read the header, do so.
3743  *
3744  * NB: this code must agree with _discoverArchiveFormat(). Maybe find a
3745  * way to unify the cases?
3746  */
3747  if (!AH->readHeader)
3748  {
3749  char tmpMag[7];
3750 
3751  AH->ReadBufPtr(AH, tmpMag, 5);
3752 
3753  if (strncmp(tmpMag, "PGDMP", 5) != 0)
3754  pg_fatal("did not find magic string in file header");
3755  }
3756 
3757  vmaj = AH->ReadBytePtr(AH);
3758  vmin = AH->ReadBytePtr(AH);
3759 
3760  if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
3761  vrev = AH->ReadBytePtr(AH);
3762  else
3763  vrev = 0;
3764 
3765  AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev);
3766 
3767  if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
3768  pg_fatal("unsupported version (%d.%d) in file header",
3769  vmaj, vmin);
3770 
3771  AH->intSize = AH->ReadBytePtr(AH);
3772  if (AH->intSize > 32)
3773  pg_fatal("sanity check on integer size (%lu) failed",
3774  (unsigned long) AH->intSize);
3775 
3776  if (AH->intSize > sizeof(int))
3777  pg_log_warning("archive was made on a machine with larger integers, some operations might fail");
3778 
3779  if (AH->version >= K_VERS_1_7)
3780  AH->offSize = AH->ReadBytePtr(AH);
3781  else
3782  AH->offSize = AH->intSize;
3783 
3784  fmt = AH->ReadBytePtr(AH);
3785 
3786  if (AH->format != fmt)
3787  pg_fatal("expected format (%d) differs from format found in file (%d)",
3788  AH->format, fmt);
3789 
3790  if (AH->version >= K_VERS_1_2)
3791  {
3792  if (AH->version < K_VERS_1_4)
3793  AH->compression = AH->ReadBytePtr(AH);
3794  else
3795  AH->compression = ReadInt(AH);
3796  }
3797  else
3799 
3800 #ifndef HAVE_LIBZ
3801  if (AH->compression != 0)
3802  pg_log_warning("archive is compressed, but this installation does not support compression -- no data will be available");
3803 #endif
3804 
3805  if (AH->version >= K_VERS_1_4)
3806  {
3807  struct tm crtm;
3808 
3809  crtm.tm_sec = ReadInt(AH);
3810  crtm.tm_min = ReadInt(AH);
3811  crtm.tm_hour = ReadInt(AH);
3812  crtm.tm_mday = ReadInt(AH);
3813  crtm.tm_mon = ReadInt(AH);
3814  crtm.tm_year = ReadInt(AH);
3815  crtm.tm_isdst = ReadInt(AH);
3816 
3817  /*
3818  * Newer versions of glibc have mktime() report failure if tm_isdst is
3819  * inconsistent with the prevailing timezone, e.g. tm_isdst = 1 when
3820  * TZ=UTC. This is problematic when restoring an archive under a
3821  * different timezone setting. If we get a failure, try again with
3822  * tm_isdst set to -1 ("don't know").
3823  *
3824  * XXX with or without this hack, we reconstruct createDate
3825  * incorrectly when the prevailing timezone is different from
3826  * pg_dump's. Next time we bump the archive version, we should flush
3827  * this representation and store a plain seconds-since-the-Epoch
3828  * timestamp instead.
3829  */
3830  AH->createDate = mktime(&crtm);
3831  if (AH->createDate == (time_t) -1)
3832  {
3833  crtm.tm_isdst = -1;
3834  AH->createDate = mktime(&crtm);
3835  if (AH->createDate == (time_t) -1)
3836  pg_log_warning("invalid creation date in header");
3837  }
3838  }
3839 
3840  if (AH->version >= K_VERS_1_4)
3841  {
3842  AH->archdbname = ReadStr(AH);
3843  }
3844 
3845  if (AH->version >= K_VERS_1_10)
3846  {
3847  AH->archiveRemoteVersion = ReadStr(AH);
3848  AH->archiveDumpVersion = ReadStr(AH);
3849  }
3850 }
static struct pg_tm tm
Definition: localtime.c:102
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 Z_DEFAULT_COMPRESSION
#define K_VERS_1_7
ReadBytePtrType ReadBytePtr
ReadBufPtrType ReadBufPtr
int tm_sec
Definition: pgtime.h:36

References _archiveHandle::archdbname, _archiveHandle::archiveDumpVersion, _archiveHandle::archiveRemoteVersion, _archiveHandle::compression, _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, MAKE_ARCHIVE_VERSION, _archiveHandle::offSize, pg_fatal, pg_log_warning, _archiveHandle::ReadBufPtr, _archiveHandle::ReadBytePtr, _archiveHandle::readHeader, ReadInt(), ReadStr(), tm, pg_tm::tm_sec, _archiveHandle::version, and Z_DEFAULT_COMPRESSION.

Referenced by InitArchiveFmt_Custom(), InitArchiveFmt_Directory(), and InitArchiveFmt_Tar().

◆ ReadInt()

int ReadInt ( ArchiveHandle AH)

Definition at line 1995 of file pg_backup_archiver.c.

1996 {
1997  int res = 0;
1998  int bv,
1999  b;
2000  int sign = 0; /* Default positive */
2001  int bitShift = 0;
2002 
2003  if (AH->version > K_VERS_1_0)
2004  /* Read a sign byte */
2005  sign = AH->ReadBytePtr(AH);
2006 
2007  for (b = 0; b < AH->intSize; b++)
2008  {
2009  bv = AH->ReadBytePtr(AH) & 0xFF;
2010  if (bv != 0)
2011  res = res + (bv << bitShift);
2012  bitShift += 8;
2013  }
2014 
2015  if (sign)
2016  res = -res;
2017 
2018  return res;
2019 }
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(), _LoadBlobs(), _readBlockHeader(), _ReadExtraToc(), _skipBlobs(), _skipData(), ReadHead(), ReadOffset(), ReadStr(), and ReadToc().

◆ ReadOffset()

int ReadOffset ( ArchiveHandle AH,
pgoff_t o 
)

Definition at line 1900 of file pg_backup_archiver.c.

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

2042 {
2043  char *buf;
2044  int l;
2045 
2046  l = ReadInt(AH);
2047  if (l < 0)
2048  buf = NULL;
2049  else
2050  {
2051  buf = (char *) pg_malloc(l + 1);
2052  AH->ReadBufPtr(AH, (void *) buf, l);
2053 
2054  buf[l] = '\0';
2055  }
2056 
2057  return buf;
2058 }

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

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

◆ ReadToc()

void ReadToc ( ArchiveHandle AH)

Definition at line 2489 of file pg_backup_archiver.c.

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

4239 {
4240  pg_free(ready_list->tes);
4241 }
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 4225 of file pg_backup_archiver.c.

4226 {
4227  ready_list->tes = (TocEntry **)
4228  pg_malloc(tocCount * sizeof(TocEntry *));
4229  ready_list->first_te = 0;
4230  ready_list->last_te = -1;
4231  ready_list->sorted = false;
4232 }

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

4246 {
4247  ready_list->tes[++ready_list->last_te] = te;
4248  /* List is (probably) not sorted anymore. */
4249  ready_list->sorted = false;
4250 }

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

4255 {
4256  int f = ready_list->first_te;
4257 
4258  Assert(i >= f && i <= ready_list->last_te);
4259 
4260  /*
4261  * In the typical case where the item to be removed is the first ready
4262  * entry, we need only increment first_te to remove it. Otherwise, move
4263  * the entries before it to compact the list. (This preserves sortedness,
4264  * if any.) We could alternatively move the entries after i, but there
4265  * are typically many more of those.
4266  */
4267  if (i > f)
4268  {
4269  TocEntry **first_te_ptr = &ready_list->tes[f];
4270 
4271  memmove(first_te_ptr + 1, first_te_ptr, (i - f) * sizeof(TocEntry *));
4272  }
4273  ready_list->first_te++;
4274 }

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

4279 {
4280  if (!ready_list->sorted)
4281  {
4282  int n = ready_list->last_te - ready_list->first_te + 1;
4283 
4284  if (n > 1)
4285  qsort(ready_list->tes + ready_list->first_te, n,
4286  sizeof(TocEntry *),
4288  ready_list->sorted = true;
4289  }
4290 }
static int TocEntrySizeCompare(const void *p1, const void *p2)
#define qsort(a, b, c, d)
Definition: port.h:495

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

4709 {
4710  int i;
4711 
4712  pg_log_debug("reducing dependencies for %d", te->dumpId);
4713 
4714  for (i = 0; i < te->nRevDeps; i++)
4715  {
4716  TocEntry *otherte = AH->tocsByDumpId[te->revDeps[i]];
4717 
4718  Assert(otherte->depCount > 0);
4719  otherte->depCount--;
4720 
4721  /*
4722  * It's ready if it has no remaining dependencies, and it belongs in
4723  * the current restore pass, and it is currently a member of the
4724  * pending list (that check is needed to prevent double restore in
4725  * some cases where a list-file forces out-of-order restoring).
4726  * However, if ready_list == NULL then caller doesn't want any list
4727  * memberships changed.
4728  */
4729  if (otherte->depCount == 0 &&
4730  _tocEntryRestorePass(otherte) == AH->restorePass &&
4731  otherte->pending_prev != NULL &&
4732  ready_list != NULL)
4733  {
4734  /* Remove it from pending list ... */
4735  pending_list_remove(otherte);
4736  /* ... and add to ready_list */
4737  ready_list_insert(ready_list, otherte);
4738  }
4739  }
4740 }
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 4609 of file pg_backup_archiver.c.

4610 {
4611  TocEntry *te;
4612  int i;
4613  DumpId olddep;
4614 
4615  for (te = AH->toc->next; te != AH->toc; te = te->next)
4616  {
4617  if (te->section != SECTION_POST_DATA)
4618  continue;
4619  for (i = 0; i < te->nDeps; i++)
4620  {
4621  olddep = te->dependencies[i];
4622  if (olddep <= AH->maxDumpId &&
4623  AH->tableDataId[olddep] != 0)
4624  {
4625  DumpId tabledataid = AH->tableDataId[olddep];
4626  TocEntry *tabledatate = AH->tocsByDumpId[tabledataid];
4627 
4628  te->dependencies[i] = tabledataid;
4629  te->dataLength = Max(te->dataLength, tabledatate->dataLength);
4630  pg_log_debug("transferring dependency %d -> %d to %d",
4631  te->dumpId, olddep, tabledataid);
4632  }
4633  }
4634  }
4635 }
#define Max(x, y)
Definition: c.h:980

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

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

4137 {
4138  RestoreOptions *ropt = AH->public.ropt;
4139  TocEntry *te;
4140 
4141  pg_log_debug("entering restore_toc_entries_postfork");
4142 
4143  /*
4144  * Now reconnect the single parent connection.
4145  */
4146  ConnectDatabase((Archive *) AH, &ropt->cparams, true);
4147 
4148  /* re-establish fixed state */
4150 
4151  /*
4152  * Make sure there is no work left due to, say, circular dependencies, or
4153  * some other pathological condition. If so, do it in the single parent
4154  * connection. We don't sweat about RestorePass ordering; it's likely we
4155  * already violated that.
4156  */
4157  for (te = pending_list->pending_next; te != pending_list; te = te->pending_next)
4158  {
4159  pg_log_info("processing missed item %d %s %s",
4160  te->dumpId, te->desc, te->tag);
4161  (void) restore_toc_entry(AH, te, false);
4162  }
4163 }

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

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

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

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