/src/bin/pg_dump/pg_dump.c
C | 15699 lines | 11346 code | 1874 blank | 2479 comment | 1611 complexity | bb079b515b6be228674b0fcc00c8e61b MD5 | raw file
Possible License(s): AGPL-3.0
Large files files are truncated, but you can click here to view the full file
- /*-------------------------------------------------------------------------
- *
- * pg_dump.c
- * pg_dump is a utility for dumping out a postgres database
- * into a script file.
- *
- * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * pg_dump will read the system catalogs in a database and dump out a
- * script that reproduces the schema in terms of SQL that is understood
- * by PostgreSQL
- *
- * Note that pg_dump runs in a transaction-snapshot mode transaction,
- * so it sees a consistent snapshot of the database including system
- * catalogs. However, it relies in part on various specialized backend
- * functions like pg_get_indexdef(), and those things tend to look at
- * the currently committed state. So it is possible to get 'cache
- * lookup failed' error if someone performs DDL changes while a dump is
- * happening. The window for this sort of thing is from the acquisition
- * of the transaction snapshot to getSchemaData() (when pg_dump acquires
- * AccessShareLock on every table it intends to dump). It isn't very large,
- * but it can happen.
- *
- * http://archives.postgresql.org/pgsql-bugs/2010-02/msg00187.php
- *
- * IDENTIFICATION
- * src/bin/pg_dump/pg_dump.c
- *
- *-------------------------------------------------------------------------
- */
- #include "postgres_fe.h"
- #include <unistd.h>
- #include <ctype.h>
- #ifdef ENABLE_NLS
- #include <locale.h>
- #endif
- #ifdef HAVE_TERMIOS_H
- #include <termios.h>
- #endif
- #include "getopt_long.h"
- #include "access/attnum.h"
- #include "access/sysattr.h"
- #include "access/transam.h"
- #include "catalog/pg_cast.h"
- #include "catalog/pg_class.h"
- #include "catalog/pg_default_acl.h"
- #include "catalog/pg_event_trigger.h"
- #include "catalog/pg_largeobject.h"
- #include "catalog/pg_largeobject_metadata.h"
- #include "catalog/pg_proc.h"
- #include "catalog/pg_trigger.h"
- #include "catalog/pg_type.h"
- #include "libpq/libpq-fs.h"
- #include "pg_backup_archiver.h"
- #include "pg_backup_db.h"
- #include "pg_backup_utils.h"
- #include "dumputils.h"
- #include "parallel.h"
- typedef struct
- {
- const char *descr; /* comment for an object */
- Oid classoid; /* object class (catalog OID) */
- Oid objoid; /* object OID */
- int objsubid; /* subobject (table column #) */
- } CommentItem;
- typedef struct
- {
- const char *provider; /* label provider of this security label */
- const char *label; /* security label for an object */
- Oid classoid; /* object class (catalog OID) */
- Oid objoid; /* object OID */
- int objsubid; /* subobject (table column #) */
- } SecLabelItem;
- /* global decls */
- bool g_verbose; /* User wants verbose narration of our
- * activities. */
- /* various user-settable parameters */
- static bool schemaOnly;
- static bool dataOnly;
- static int dumpSections; /* bitmask of chosen sections */
- static bool aclsSkip;
- static const char *lockWaitTimeout;
- /* subquery used to convert user ID (eg, datdba) to user name */
- static const char *username_subquery;
- /* obsolete as of 7.3: */
- static Oid g_last_builtin_oid; /* value of the last builtin oid */
- /*
- * Object inclusion/exclusion lists
- *
- * The string lists record the patterns given by command-line switches,
- * which we then convert to lists of OIDs of matching objects.
- */
- static SimpleStringList schema_include_patterns = {NULL, NULL};
- static SimpleOidList schema_include_oids = {NULL, NULL};
- static SimpleStringList schema_exclude_patterns = {NULL, NULL};
- static SimpleOidList schema_exclude_oids = {NULL, NULL};
- static SimpleStringList table_include_patterns = {NULL, NULL};
- static SimpleOidList table_include_oids = {NULL, NULL};
- static SimpleStringList table_exclude_patterns = {NULL, NULL};
- static SimpleOidList table_exclude_oids = {NULL, NULL};
- static SimpleStringList tabledata_exclude_patterns = {NULL, NULL};
- static SimpleOidList tabledata_exclude_oids = {NULL, NULL};
- /* default, if no "inclusion" switches appear, is to dump everything */
- static bool include_everything = true;
- char g_opaque_type[10]; /* name for the opaque type */
- /* placeholders for the delimiters for comments */
- char g_comment_start[10];
- char g_comment_end[10];
- static const CatalogId nilCatalogId = {0, 0};
- /* flags for various command-line long options */
- static int binary_upgrade = 0;
- static int disable_dollar_quoting = 0;
- static int dump_inserts = 0;
- static int column_inserts = 0;
- static int if_exists = 0;
- static int no_security_labels = 0;
- static int no_synchronized_snapshots = 0;
- static int no_unlogged_table_data = 0;
- static int serializable_deferrable = 0;
- static void help(const char *progname);
- static void setup_connection(Archive *AH, const char *dumpencoding,
- char *use_role);
- static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
- static void expand_schema_name_patterns(Archive *fout,
- SimpleStringList *patterns,
- SimpleOidList *oids);
- static void expand_table_name_patterns(Archive *fout,
- SimpleStringList *patterns,
- SimpleOidList *oids);
- static NamespaceInfo *findNamespace(Archive *fout, Oid nsoid, Oid objoid);
- static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
- static void refreshMatViewData(Archive *fout, TableDataInfo *tdinfo);
- static void guessConstraintInheritance(TableInfo *tblinfo, int numTables);
- static void dumpComment(Archive *fout, const char *target,
- const char *namespace, const char *owner,
- CatalogId catalogId, int subid, DumpId dumpId);
- static int findComments(Archive *fout, Oid classoid, Oid objoid,
- CommentItem **items);
- static int collectComments(Archive *fout, CommentItem **items);
- static void dumpSecLabel(Archive *fout, const char *target,
- const char *namespace, const char *owner,
- CatalogId catalogId, int subid, DumpId dumpId);
- static int findSecLabels(Archive *fout, Oid classoid, Oid objoid,
- SecLabelItem **items);
- static int collectSecLabels(Archive *fout, SecLabelItem **items);
- static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
- static void dumpNamespace(Archive *fout, NamespaceInfo *nspinfo);
- static void dumpExtension(Archive *fout, ExtensionInfo *extinfo);
- static void dumpType(Archive *fout, TypeInfo *tyinfo);
- static void dumpBaseType(Archive *fout, TypeInfo *tyinfo);
- static void dumpEnumType(Archive *fout, TypeInfo *tyinfo);
- static void dumpRangeType(Archive *fout, TypeInfo *tyinfo);
- static void dumpDomain(Archive *fout, TypeInfo *tyinfo);
- static void dumpCompositeType(Archive *fout, TypeInfo *tyinfo);
- static void dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo);
- static void dumpShellType(Archive *fout, ShellTypeInfo *stinfo);
- static void dumpProcLang(Archive *fout, ProcLangInfo *plang);
- static void dumpFunc(Archive *fout, FuncInfo *finfo);
- static void dumpCast(Archive *fout, CastInfo *cast);
- static void dumpOpr(Archive *fout, OprInfo *oprinfo);
- static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo);
- static void dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo);
- static void dumpCollation(Archive *fout, CollInfo *convinfo);
- static void dumpConversion(Archive *fout, ConvInfo *convinfo);
- static void dumpRule(Archive *fout, RuleInfo *rinfo);
- static void dumpAgg(Archive *fout, AggInfo *agginfo);
- static void dumpTrigger(Archive *fout, TriggerInfo *tginfo);
- static void dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo);
- static void dumpTable(Archive *fout, TableInfo *tbinfo);
- static void dumpTableSchema(Archive *fout, TableInfo *tbinfo);
- static void dumpAttrDef(Archive *fout, AttrDefInfo *adinfo);
- static void dumpSequence(Archive *fout, TableInfo *tbinfo);
- static void dumpSequenceData(Archive *fout, TableDataInfo *tdinfo);
- static void dumpIndex(Archive *fout, IndxInfo *indxinfo);
- static void dumpConstraint(Archive *fout, ConstraintInfo *coninfo);
- static void dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo);
- static void dumpTSParser(Archive *fout, TSParserInfo *prsinfo);
- static void dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo);
- static void dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo);
- static void dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo);
- static void dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo);
- static void dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo);
- static void dumpUserMappings(Archive *fout,
- const char *servername, const char *namespace,
- const char *owner, CatalogId catalogId, DumpId dumpId);
- static void dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo);
- static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
- const char *type, const char *name, const char *subname,
- const char *tag, const char *nspname, const char *owner,
- const char *acls);
- static void getDependencies(Archive *fout);
- static void BuildArchiveDependencies(Archive *fout);
- static void findDumpableDependencies(ArchiveHandle *AH, DumpableObject *dobj,
- DumpId **dependencies, int *nDeps, int *allocDeps);
- static DumpableObject *createBoundaryObjects(void);
- static void addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
- DumpableObject *boundaryObjs);
- static void getDomainConstraints(Archive *fout, TypeInfo *tyinfo);
- static void getTableData(TableInfo *tblinfo, int numTables, bool oids);
- static void makeTableDataInfo(TableInfo *tbinfo, bool oids);
- static void buildMatViewRefreshDependencies(Archive *fout);
- static void getTableDataFKConstraints(void);
- static char *format_function_arguments(FuncInfo *finfo, char *funcargs,
- bool is_agg);
- static char *format_function_arguments_old(Archive *fout,
- FuncInfo *finfo, int nallargs,
- char **allargtypes,
- char **argmodes,
- char **argnames);
- static char *format_function_signature(Archive *fout,
- FuncInfo *finfo, bool honor_quotes);
- static char *convertRegProcReference(Archive *fout,
- const char *proc);
- static char *convertOperatorReference(Archive *fout, const char *opr);
- static const char *convertTSFunction(Archive *fout, Oid funcOid);
- static Oid findLastBuiltinOid_V71(Archive *fout, const char *);
- static Oid findLastBuiltinOid_V70(Archive *fout);
- static void selectSourceSchema(Archive *fout, const char *schemaName);
- static char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts);
- static char *myFormatType(const char *typname, int32 typmod);
- static void getBlobs(Archive *fout);
- static void dumpBlob(Archive *fout, BlobInfo *binfo);
- static int dumpBlobs(Archive *fout, void *arg);
- static void dumpDatabase(Archive *AH);
- static void dumpEncoding(Archive *AH);
- static void dumpStdStrings(Archive *AH);
- static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
- PQExpBuffer upgrade_buffer, Oid pg_type_oid);
- static bool binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
- PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
- static void binary_upgrade_set_pg_class_oids(Archive *fout,
- PQExpBuffer upgrade_buffer,
- Oid pg_class_oid, bool is_index);
- static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
- DumpableObject *dobj,
- const char *objlabel);
- static const char *getAttrName(int attrnum, TableInfo *tblInfo);
- static const char *fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer);
- static char *get_synchronized_snapshot(Archive *fout);
- static PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
- static void setupDumpWorker(Archive *AHX, RestoreOptions *ropt);
- int
- main(int argc, char **argv)
- {
- int c;
- const char *filename = NULL;
- const char *format = "p";
- const char *dbname = NULL;
- const char *pghost = NULL;
- const char *pgport = NULL;
- const char *username = NULL;
- const char *dumpencoding = NULL;
- bool oids = false;
- TableInfo *tblinfo;
- int numTables;
- DumpableObject **dobjs;
- int numObjs;
- DumpableObject *boundaryObjs;
- int i;
- int numWorkers = 1;
- enum trivalue prompt_password = TRI_DEFAULT;
- int compressLevel = -1;
- int plainText = 0;
- int outputClean = 0;
- int outputCreateDB = 0;
- bool outputBlobs = false;
- int outputNoOwner = 0;
- char *outputSuperuser = NULL;
- char *use_role = NULL;
- int optindex;
- RestoreOptions *ropt;
- ArchiveFormat archiveFormat = archUnknown;
- ArchiveMode archiveMode;
- Archive *fout; /* the script file */
- static int disable_triggers = 0;
- static int outputNoTablespaces = 0;
- static int use_setsessauth = 0;
- static struct option long_options[] = {
- {"data-only", no_argument, NULL, 'a'},
- {"blobs", no_argument, NULL, 'b'},
- {"clean", no_argument, NULL, 'c'},
- {"create", no_argument, NULL, 'C'},
- {"dbname", required_argument, NULL, 'd'},
- {"file", required_argument, NULL, 'f'},
- {"format", required_argument, NULL, 'F'},
- {"host", required_argument, NULL, 'h'},
- {"ignore-version", no_argument, NULL, 'i'},
- {"jobs", 1, NULL, 'j'},
- {"no-reconnect", no_argument, NULL, 'R'},
- {"oids", no_argument, NULL, 'o'},
- {"no-owner", no_argument, NULL, 'O'},
- {"port", required_argument, NULL, 'p'},
- {"schema", required_argument, NULL, 'n'},
- {"exclude-schema", required_argument, NULL, 'N'},
- {"schema-only", no_argument, NULL, 's'},
- {"superuser", required_argument, NULL, 'S'},
- {"table", required_argument, NULL, 't'},
- {"exclude-table", required_argument, NULL, 'T'},
- {"no-password", no_argument, NULL, 'w'},
- {"password", no_argument, NULL, 'W'},
- {"username", required_argument, NULL, 'U'},
- {"verbose", no_argument, NULL, 'v'},
- {"no-privileges", no_argument, NULL, 'x'},
- {"no-acl", no_argument, NULL, 'x'},
- {"compress", required_argument, NULL, 'Z'},
- {"encoding", required_argument, NULL, 'E'},
- {"help", no_argument, NULL, '?'},
- {"version", no_argument, NULL, 'V'},
- /*
- * the following options don't have an equivalent short option letter
- */
- {"attribute-inserts", no_argument, &column_inserts, 1},
- {"binary-upgrade", no_argument, &binary_upgrade, 1},
- {"column-inserts", no_argument, &column_inserts, 1},
- {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
- {"disable-triggers", no_argument, &disable_triggers, 1},
- {"exclude-table-data", required_argument, NULL, 4},
- {"if-exists", no_argument, &if_exists, 1},
- {"inserts", no_argument, &dump_inserts, 1},
- {"lock-wait-timeout", required_argument, NULL, 2},
- {"no-tablespaces", no_argument, &outputNoTablespaces, 1},
- {"quote-all-identifiers", no_argument, "e_all_identifiers, 1},
- {"role", required_argument, NULL, 3},
- {"section", required_argument, NULL, 5},
- {"serializable-deferrable", no_argument, &serializable_deferrable, 1},
- {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
- {"no-security-labels", no_argument, &no_security_labels, 1},
- {"no-synchronized-snapshots", no_argument, &no_synchronized_snapshots, 1},
- {"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
- {NULL, 0, NULL, 0}
- };
- set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
- /*
- * Initialize what we need for parallel execution, especially for thread
- * support on Windows.
- */
- init_parallel_dump_utils();
- g_verbose = false;
- strcpy(g_comment_start, "-- ");
- g_comment_end[0] = '\0';
- strcpy(g_opaque_type, "opaque");
- dataOnly = schemaOnly = false;
- dumpSections = DUMP_UNSECTIONED;
- lockWaitTimeout = NULL;
- progname = get_progname(argv[0]);
- /* Set default options based on progname */
- if (strcmp(progname, "pg_backup") == 0)
- format = "c";
- if (argc > 1)
- {
- if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
- {
- help(progname);
- exit_nicely(0);
- }
- if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
- {
- puts("pg_dump (PostgreSQL) " PG_VERSION);
- exit_nicely(0);
- }
- }
- while ((c = getopt_long(argc, argv, "abcCd:E:f:F:h:ij:n:N:oOp:RsS:t:T:U:vwWxZ:",
- long_options, &optindex)) != -1)
- {
- switch (c)
- {
- case 'a': /* Dump data only */
- dataOnly = true;
- break;
- case 'b': /* Dump blobs */
- outputBlobs = true;
- break;
- case 'c': /* clean (i.e., drop) schema prior to create */
- outputClean = 1;
- break;
- case 'C': /* Create DB */
- outputCreateDB = 1;
- break;
- case 'd': /* database name */
- dbname = pg_strdup(optarg);
- break;
- case 'E': /* Dump encoding */
- dumpencoding = pg_strdup(optarg);
- break;
- case 'f':
- filename = pg_strdup(optarg);
- break;
- case 'F':
- format = pg_strdup(optarg);
- break;
- case 'h': /* server host */
- pghost = pg_strdup(optarg);
- break;
- case 'i':
- /* ignored, deprecated option */
- break;
- case 'j': /* number of dump jobs */
- numWorkers = atoi(optarg);
- break;
- case 'n': /* include schema(s) */
- simple_string_list_append(&schema_include_patterns, optarg);
- include_everything = false;
- break;
- case 'N': /* exclude schema(s) */
- simple_string_list_append(&schema_exclude_patterns, optarg);
- break;
- case 'o': /* Dump oids */
- oids = true;
- break;
- case 'O': /* Don't reconnect to match owner */
- outputNoOwner = 1;
- break;
- case 'p': /* server port */
- pgport = pg_strdup(optarg);
- break;
- case 'R':
- /* no-op, still accepted for backwards compatibility */
- break;
- case 's': /* dump schema only */
- schemaOnly = true;
- break;
- case 'S': /* Username for superuser in plain text output */
- outputSuperuser = pg_strdup(optarg);
- break;
- case 't': /* include table(s) */
- simple_string_list_append(&table_include_patterns, optarg);
- include_everything = false;
- break;
- case 'T': /* exclude table(s) */
- simple_string_list_append(&table_exclude_patterns, optarg);
- break;
- case 'U':
- username = pg_strdup(optarg);
- break;
- case 'v': /* verbose */
- g_verbose = true;
- break;
- case 'w':
- prompt_password = TRI_NO;
- break;
- case 'W':
- prompt_password = TRI_YES;
- break;
- case 'x': /* skip ACL dump */
- aclsSkip = true;
- break;
- case 'Z': /* Compression Level */
- compressLevel = atoi(optarg);
- break;
- case 0:
- /* This covers the long options. */
- break;
- case 2: /* lock-wait-timeout */
- lockWaitTimeout = pg_strdup(optarg);
- break;
- case 3: /* SET ROLE */
- use_role = pg_strdup(optarg);
- break;
- case 4: /* exclude table(s) data */
- simple_string_list_append(&tabledata_exclude_patterns, optarg);
- break;
- case 5: /* section */
- set_dump_section(optarg, &dumpSections);
- break;
- default:
- fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
- exit_nicely(1);
- }
- }
- /*
- * Non-option argument specifies database name as long as it wasn't
- * already specified with -d / --dbname
- */
- if (optind < argc && dbname == NULL)
- dbname = argv[optind++];
- /* Complain if any arguments remain */
- if (optind < argc)
- {
- fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
- progname, argv[optind]);
- fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
- progname);
- exit_nicely(1);
- }
- /* --column-inserts implies --inserts */
- if (column_inserts)
- dump_inserts = 1;
- if (dataOnly && schemaOnly)
- {
- write_msg(NULL, "options -s/--schema-only and -a/--data-only cannot be used together\n");
- exit_nicely(1);
- }
- if (dataOnly && outputClean)
- {
- write_msg(NULL, "options -c/--clean and -a/--data-only cannot be used together\n");
- exit_nicely(1);
- }
- if (dump_inserts && oids)
- {
- write_msg(NULL, "options --inserts/--column-inserts and -o/--oids cannot be used together\n");
- write_msg(NULL, "(The INSERT command cannot set OIDs.)\n");
- exit_nicely(1);
- }
- if (if_exists && !outputClean)
- exit_horribly(NULL, "option --if-exists requires option -c/--clean\n");
- /* Identify archive format to emit */
- archiveFormat = parseArchiveFormat(format, &archiveMode);
- /* archiveFormat specific setup */
- if (archiveFormat == archNull)
- plainText = 1;
- /* Custom and directory formats are compressed by default, others not */
- if (compressLevel == -1)
- {
- if (archiveFormat == archCustom || archiveFormat == archDirectory)
- compressLevel = Z_DEFAULT_COMPRESSION;
- else
- compressLevel = 0;
- }
- /*
- * On Windows we can only have at most MAXIMUM_WAIT_OBJECTS (= 64 usually)
- * parallel jobs because that's the maximum limit for the
- * WaitForMultipleObjects() call.
- */
- if (numWorkers <= 0
- #ifdef WIN32
- || numWorkers > MAXIMUM_WAIT_OBJECTS
- #endif
- )
- exit_horribly(NULL, "%s: invalid number of parallel jobs\n", progname);
- /* Parallel backup only in the directory archive format so far */
- if (archiveFormat != archDirectory && numWorkers > 1)
- exit_horribly(NULL, "parallel backup only supported by the directory format\n");
- /* Open the output file */
- fout = CreateArchive(filename, archiveFormat, compressLevel, archiveMode,
- setupDumpWorker);
- /* Register the cleanup hook */
- on_exit_close_archive(fout);
- if (fout == NULL)
- exit_horribly(NULL, "could not open output file \"%s\" for writing\n", filename);
- /* Let the archiver know how noisy to be */
- fout->verbose = g_verbose;
- /*
- * We allow the server to be back to 7.0, and up to any minor release of
- * our own major version. (See also version check in pg_dumpall.c.)
- */
- fout->minRemoteVersion = 70000;
- fout->maxRemoteVersion = (PG_VERSION_NUM / 100) * 100 + 99;
- fout->numWorkers = numWorkers;
- /*
- * Open the database using the Archiver, so it knows about it. Errors mean
- * death.
- */
- ConnectDatabase(fout, dbname, pghost, pgport, username, prompt_password);
- setup_connection(fout, dumpencoding, use_role);
- /*
- * Disable security label support if server version < v9.1.x (prevents
- * access to nonexistent pg_seclabel catalog)
- */
- if (fout->remoteVersion < 90100)
- no_security_labels = 1;
- /*
- * When running against 9.0 or later, check if we are in recovery mode,
- * which means we are on a hot standby.
- */
- if (fout->remoteVersion >= 90000)
- {
- PGresult *res = ExecuteSqlQueryForSingleRow(fout, "SELECT pg_catalog.pg_is_in_recovery()");
- if (strcmp(PQgetvalue(res, 0, 0), "t") == 0)
- {
- /*
- * On hot standby slaves, never try to dump unlogged table data,
- * since it will just throw an error.
- */
- no_unlogged_table_data = true;
- }
- PQclear(res);
- }
- /* Select the appropriate subquery to convert user IDs to names */
- if (fout->remoteVersion >= 80100)
- username_subquery = "SELECT rolname FROM pg_catalog.pg_roles WHERE oid =";
- else if (fout->remoteVersion >= 70300)
- username_subquery = "SELECT usename FROM pg_catalog.pg_user WHERE usesysid =";
- else
- username_subquery = "SELECT usename FROM pg_user WHERE usesysid =";
- /* check the version for the synchronized snapshots feature */
- if (numWorkers > 1 && fout->remoteVersion < 90200
- && !no_synchronized_snapshots)
- exit_horribly(NULL,
- "Synchronized snapshots are not supported by this server version.\n"
- "Run with --no-synchronized-snapshots instead if you do not need\n"
- "synchronized snapshots.\n");
- /* Find the last built-in OID, if needed */
- if (fout->remoteVersion < 70300)
- {
- if (fout->remoteVersion >= 70100)
- g_last_builtin_oid = findLastBuiltinOid_V71(fout,
- PQdb(GetConnection(fout)));
- else
- g_last_builtin_oid = findLastBuiltinOid_V70(fout);
- if (g_verbose)
- write_msg(NULL, "last built-in OID is %u\n", g_last_builtin_oid);
- }
- /* Expand schema selection patterns into OID lists */
- if (schema_include_patterns.head != NULL)
- {
- expand_schema_name_patterns(fout, &schema_include_patterns,
- &schema_include_oids);
- if (schema_include_oids.head == NULL)
- exit_horribly(NULL, "No matching schemas were found\n");
- }
- expand_schema_name_patterns(fout, &schema_exclude_patterns,
- &schema_exclude_oids);
- /* non-matching exclusion patterns aren't an error */
- /* Expand table selection patterns into OID lists */
- if (table_include_patterns.head != NULL)
- {
- expand_table_name_patterns(fout, &table_include_patterns,
- &table_include_oids);
- if (table_include_oids.head == NULL)
- exit_horribly(NULL, "No matching tables were found\n");
- }
- expand_table_name_patterns(fout, &table_exclude_patterns,
- &table_exclude_oids);
- expand_table_name_patterns(fout, &tabledata_exclude_patterns,
- &tabledata_exclude_oids);
- /* non-matching exclusion patterns aren't an error */
- /*
- * Dumping blobs is now default unless we saw an inclusion switch or -s
- * ... but even if we did see one of these, -b turns it back on.
- */
- if (include_everything && !schemaOnly)
- outputBlobs = true;
- /*
- * Now scan the database and create DumpableObject structs for all the
- * objects we intend to dump.
- */
- tblinfo = getSchemaData(fout, &numTables);
- if (fout->remoteVersion < 80400)
- guessConstraintInheritance(tblinfo, numTables);
- if (!schemaOnly)
- {
- getTableData(tblinfo, numTables, oids);
- buildMatViewRefreshDependencies(fout);
- if (dataOnly)
- getTableDataFKConstraints();
- }
- if (outputBlobs)
- getBlobs(fout);
- /*
- * Collect dependency data to assist in ordering the objects.
- */
- getDependencies(fout);
- /* Lastly, create dummy objects to represent the section boundaries */
- boundaryObjs = createBoundaryObjects();
- /* Get pointers to all the known DumpableObjects */
- getDumpableObjects(&dobjs, &numObjs);
- /*
- * Add dummy dependencies to enforce the dump section ordering.
- */
- addBoundaryDependencies(dobjs, numObjs, boundaryObjs);
- /*
- * Sort the objects into a safe dump order (no forward references).
- *
- * In 7.3 or later, we can rely on dependency information to help us
- * determine a safe order, so the initial sort is mostly for cosmetic
- * purposes: we sort by name to ensure that logically identical schemas
- * will dump identically. Before 7.3 we don't have dependencies and we
- * use OID ordering as an (unreliable) guide to creation order.
- */
- if (fout->remoteVersion >= 70300)
- sortDumpableObjectsByTypeName(dobjs, numObjs);
- else
- sortDumpableObjectsByTypeOid(dobjs, numObjs);
- /* If we do a parallel dump, we want the largest tables to go first */
- if (archiveFormat == archDirectory && numWorkers > 1)
- sortDataAndIndexObjectsBySize(dobjs, numObjs);
- sortDumpableObjects(dobjs, numObjs,
- boundaryObjs[0].dumpId, boundaryObjs[1].dumpId);
- /*
- * Create archive TOC entries for all the objects to be dumped, in a safe
- * order.
- */
- /* First the special ENCODING and STDSTRINGS entries. */
- dumpEncoding(fout);
- dumpStdStrings(fout);
- /* The database item is always next, unless we don't want it at all */
- if (include_everything && !dataOnly)
- dumpDatabase(fout);
- /* Now the rearrangeable objects. */
- for (i = 0; i < numObjs; i++)
- dumpDumpableObject(fout, dobjs[i]);
- /*
- * Set up options info to ensure we dump what we want.
- */
- ropt = NewRestoreOptions();
- ropt->filename = filename;
- ropt->dropSchema = outputClean;
- ropt->dataOnly = dataOnly;
- ropt->schemaOnly = schemaOnly;
- ropt->if_exists = if_exists;
- ropt->dumpSections = dumpSections;
- ropt->aclsSkip = aclsSkip;
- ropt->superuser = outputSuperuser;
- ropt->createDB = outputCreateDB;
- ropt->noOwner = outputNoOwner;
- ropt->noTablespace = outputNoTablespaces;
- ropt->disable_triggers = disable_triggers;
- ropt->use_setsessauth = use_setsessauth;
- if (compressLevel == -1)
- ropt->compression = 0;
- else
- ropt->compression = compressLevel;
- ropt->suppressDumpWarnings = true; /* We've already shown them */
- SetArchiveRestoreOptions(fout, ropt);
- /*
- * The archive's TOC entries are now marked as to which ones will actually
- * be output, so we can set up their dependency lists properly. This isn't
- * necessary for plain-text output, though.
- */
- if (!plainText)
- BuildArchiveDependencies(fout);
- /*
- * And finally we can do the actual output.
- *
- * Note: for non-plain-text output formats, the output file is written
- * inside CloseArchive(). This is, um, bizarre; but not worth changing
- * right now.
- */
- if (plainText)
- RestoreArchive(fout);
- CloseArchive(fout);
- exit_nicely(0);
- }
- static void
- help(const char *progname)
- {
- printf(_("%s dumps a database as a text file or to other formats.\n\n"), progname);
- printf(_("Usage:\n"));
- printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
- printf(_("\nGeneral options:\n"));
- printf(_(" -f, --file=FILENAME output file or directory name\n"));
- printf(_(" -F, --format=c|d|t|p output file format (custom, directory, tar,\n"
- " plain text (default))\n"));
- printf(_(" -j, --jobs=NUM use this many parallel jobs to dump\n"));
- printf(_(" -v, --verbose verbose mode\n"));
- printf(_(" -V, --version output version information, then exit\n"));
- printf(_(" -Z, --compress=0-9 compression level for compressed formats\n"));
- printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
- printf(_(" -?, --help show this help, then exit\n"));
- printf(_("\nOptions controlling the output content:\n"));
- printf(_(" -a, --data-only dump only the data, not the schema\n"));
- printf(_(" -b, --blobs include large objects in dump\n"));
- printf(_(" -c, --clean clean (drop) database objects before recreating\n"));
- printf(_(" -C, --create include commands to create database in dump\n"));
- printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
- printf(_(" -n, --schema=SCHEMA dump the named schema(s) only\n"));
- printf(_(" -N, --exclude-schema=SCHEMA do NOT dump the named schema(s)\n"));
- printf(_(" -o, --oids include OIDs in dump\n"));
- printf(_(" -O, --no-owner skip restoration of object ownership in\n"
- " plain-text format\n"));
- printf(_(" -s, --schema-only dump only the schema, no data\n"));
- printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n"));
- printf(_(" -t, --table=TABLE dump the named table(s) only\n"));
- printf(_(" -T, --exclude-table=TABLE do NOT dump the named table(s)\n"));
- printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
- printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
- printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
- printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
- printf(_(" --disable-triggers disable triggers during data-only restore\n"));
- printf(_(" --exclude-table-data=TABLE do NOT dump data for the named table(s)\n"));
- printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
- printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
- printf(_(" --no-security-labels do not dump security label assignments\n"));
- printf(_(" --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n"));
- printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
- printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
- printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
- printf(_(" --section=SECTION dump named section (pre-data, data, or post-data)\n"));
- printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n"));
- printf(_(" --use-set-session-authorization\n"
- " use SET SESSION AUTHORIZATION commands instead of\n"
- " ALTER OWNER commands to set ownership\n"));
- printf(_("\nConnection options:\n"));
- printf(_(" -d, --dbname=DBNAME database to dump\n"));
- printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
- printf(_(" -p, --port=PORT database server port number\n"));
- printf(_(" -U, --username=NAME connect as specified database user\n"));
- printf(_(" -w, --no-password never prompt for password\n"));
- printf(_(" -W, --password force password prompt (should happen automatically)\n"));
- printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
- printf(_("\nIf no database name is supplied, then the PGDATABASE environment\n"
- "variable value is used.\n\n"));
- printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
- }
- static void
- setup_connection(Archive *AH, const char *dumpencoding, char *use_role)
- {
- PGconn *conn = GetConnection(AH);
- const char *std_strings;
- /*
- * Set the client encoding if requested. If dumpencoding == NULL then
- * either it hasn't been requested or we're a cloned connection and then
- * this has already been set in CloneArchive according to the original
- * connection encoding.
- */
- if (dumpencoding)
- {
- if (PQsetClientEncoding(conn, dumpencoding) < 0)
- exit_horribly(NULL, "invalid client encoding \"%s\" specified\n",
- dumpencoding);
- }
- /*
- * Get the active encoding and the standard_conforming_strings setting, so
- * we know how to escape strings.
- */
- AH->encoding = PQclientEncoding(conn);
- std_strings = PQparameterStatus(conn, "standard_conforming_strings");
- AH->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
- /* Set the role if requested */
- if (!use_role && AH->use_role)
- use_role = AH->use_role;
- /* Set the role if requested */
- if (use_role && AH->remoteVersion >= 80100)
- {
- PQExpBuffer query = createPQExpBuffer();
- appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
- ExecuteSqlStatement(AH, query->data);
- destroyPQExpBuffer(query);
- /* save this for later use on parallel connections */
- if (!AH->use_role)
- AH->use_role = strdup(use_role);
- }
- /* Set the datestyle to ISO to ensure the dump's portability */
- ExecuteSqlStatement(AH, "SET DATESTYLE = ISO");
- /* Likewise, avoid using sql_standard intervalstyle */
- if (AH->remoteVersion >= 80400)
- ExecuteSqlStatement(AH, "SET INTERVALSTYLE = POSTGRES");
- /*
- * If supported, set extra_float_digits so that we can dump float data
- * exactly (given correctly implemented float I/O code, anyway)
- */
- if (AH->remoteVersion >= 90000)
- ExecuteSqlStatement(AH, "SET extra_float_digits TO 3");
- else if (AH->remoteVersion >= 70400)
- ExecuteSqlStatement(AH, "SET extra_float_digits TO 2");
- /*
- * If synchronized scanning is supported, disable it, to prevent
- * unpredictable changes in row ordering across a dump and reload.
- */
- if (AH->remoteVersion >= 80300)
- ExecuteSqlStatement(AH, "SET synchronize_seqscans TO off");
- /*
- * Disable timeouts if supported.
- */
- if (AH->remoteVersion >= 70300)
- ExecuteSqlStatement(AH, "SET statement_timeout = 0");
- if (AH->remoteVersion >= 90300)
- ExecuteSqlStatement(AH, "SET lock_timeout = 0");
- /*
- * Quote all identifiers, if requested.
- */
- if (quote_all_identifiers && AH->remoteVersion >= 90100)
- ExecuteSqlStatement(AH, "SET quote_all_identifiers = true");
- /*
- * Start transaction-snapshot mode transaction to dump consistent data.
- */
- ExecuteSqlStatement(AH, "BEGIN");
- if (AH->remoteVersion >= 90100)
- {
- if (serializable_deferrable)
- ExecuteSqlStatement(AH,
- "SET TRANSACTION ISOLATION LEVEL "
- "SERIALIZABLE, READ ONLY, DEFERRABLE");
- else
- ExecuteSqlStatement(AH,
- "SET TRANSACTION ISOLATION LEVEL "
- "REPEATABLE READ, READ ONLY");
- }
- else if (AH->remoteVersion >= 70400)
- {
- /* note: comma was not accepted in SET TRANSACTION before 8.0 */
- ExecuteSqlStatement(AH,
- "SET TRANSACTION ISOLATION LEVEL "
- "SERIALIZABLE READ ONLY");
- }
- else
- ExecuteSqlStatement(AH,
- "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
- if (AH->numWorkers > 1 && AH->remoteVersion >= 90200 && !no_synchronized_snapshots)
- {
- if (AH->sync_snapshot_id)
- {
- PQExpBuffer query = createPQExpBuffer();
- appendPQExpBufferStr(query, "SET TRANSACTION SNAPSHOT ");
- appendStringLiteralConn(query, AH->sync_snapshot_id, conn);
- ExecuteSqlStatement(AH, query->data);
- destroyPQExpBuffer(query);
- }
- else
- AH->sync_snapshot_id = get_synchronized_snapshot(AH);
- }
- }
- static void
- setupDumpWorker(Archive *AHX, RestoreOptions *ropt)
- {
- setup_connection(AHX, NULL, NULL);
- }
- static char *
- get_synchronized_snapshot(Archive *fout)
- {
- char *query = "SELECT pg_export_snapshot()";
- char *result;
- PGresult *res;
- res = ExecuteSqlQueryForSingleRow(fout, query);
- result = strdup(PQgetvalue(res, 0, 0));
- PQclear(res);
- return result;
- }
- static ArchiveFormat
- parseArchiveFormat(const char *format, ArchiveMode *mode)
- {
- ArchiveFormat archiveFormat;
- *mode = archModeWrite;
- if (pg_strcasecmp(format, "a") == 0 || pg_strcasecmp(format, "append") == 0)
- {
- /* This is used by pg_dumpall, and is not documented */
- archiveFormat = archNull;
- *mode = archModeAppend;
- }
- else if (pg_strcasecmp(format, "c") == 0)
- archiveFormat = archCustom;
- else if (pg_strcasecmp(format, "custom") == 0)
- archiveFormat = archCustom;
- else if (pg_strcasecmp(format, "d") == 0)
- archiveFormat = archDirectory;
- else if (pg_strcasecmp(format, "directory") == 0)
- archiveFormat = archDirectory;
- else if (pg_strcasecmp(format, "p") == 0)
- archiveFormat = archNull;
- else if (pg_strcasecmp(format, "plain") == 0)
- archiveFormat = archNull;
- else if (pg_strcasecmp(format, "t") == 0)
- archiveFormat = archTar;
- else if (pg_strcasecmp(format, "tar") == 0)
- archiveFormat = archTar;
- else
- exit_horribly(NULL, "invalid output format \"%s\" specified\n", format);
- return archiveFormat;
- }
- /*
- * Find the OIDs of all schemas matching the given list of patterns,
- * and append them to the given OID list.
- */
- static void
- expand_schema_name_patterns(Archive *fout,
- SimpleStringList *patterns,
- SimpleOidList *oids)
- {
- PQExpBuffer query;
- PGresult *res;
- SimpleStringListCell *cell;
- int i;
- if (patterns->head == NULL)
- return; /* nothing to do */
- if (fout->remoteVersion < 70300)
- exit_horribly(NULL, "server version must be at least 7.3 to use schema selection switches\n");
- query = createPQExpBuffer();
- /*
- * We use UNION ALL rather than UNION; this might sometimes result in
- * duplicate entries in the OID list, but we don't care.
- */
- for (cell = patterns->head; cell; cell = cell->next)
- {
- if (cell != patterns->head)
- appendPQExpBufferStr(query, "UNION ALL\n");
- appendPQExpBuffer(query,
- "SELECT oid FROM pg_catalog.pg_namespace n\n");
- processSQLNamePattern(GetConnection(fout), query, cell->val, false,
- false, NULL, "n.nspname", NULL, NULL);
- }
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
- for (i = 0; i < PQntuples(res); i++)
- {
- simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
- }
- PQclear(res);
- destroyPQExpBuffer(query);
- }
- /*
- * Find the OIDs of all tables matching the given list of patterns,
- * and append them to the given OID list.
- */
- static void
- expand_table_name_patterns(Archive *fout,
- SimpleStringList *patterns, SimpleOidList *oids)
- {
- PQExpBuffer query;
- PGresult *res;
- SimpleStringListCell *cell;
- int i;
- if (patterns->head == NULL)
- return; /* nothing to do */
- query = createPQExpBuffer();
- /*
- * We use UNION ALL rather than UNION; this might sometimes result in
- * duplicate entries in the OID list, but we don't care.
- */
- for (cell = patterns->head; cell; cell = cell->next)
- {
- if (cell != patterns->head)
- appendPQExpBufferStr(query, "UNION ALL\n");
- appendPQExpBuffer(query,
- "SELECT c.oid"
- "\nFROM pg_catalog.pg_class c"
- "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
- "\nWHERE c.relkind in ('%c', '%c', '%c', '%c', '%c')\n",
- RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
- RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
- processSQLNamePattern(GetConnection(fout), query, cell->val, true,
- false, "n.nspname", "c.relname", NULL,
- "pg_catalog.pg_table_is_visible(c.oid)");
- }
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
- for (i = 0; i < PQntuples(res); i++)
- {
- simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
- }
- PQclear(res);
- destroyPQExpBuffer(query);
- }
- /*
- * selectDumpableNamespace: policy-setting subroutine
- * Mark a namespace as to be dumped or not
- */
- static void
- selectDumpableNamespace(NamespaceInfo *nsinfo)
- {
- /*
- * If specific tables are being dumped, do not dump any complete
- * namespaces. If specific namespaces are being dumped, dump just those
- * namespaces. Otherwise, dump all non-system namespaces.
- */
- if (table_include_oids.head != NULL)
- nsinfo->dobj.dump = false;
- else if (schema_include_oids.head != NULL)
- nsinfo->dobj.dump = simple_oid_list_member(&schema_include_oids,
- nsinfo->dobj.catId.oid);
- else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 ||
- strcmp(nsinfo->dobj.name, "information_schema") == 0)
- nsinfo->dobj.dump = false;
- else
- nsinfo->dobj.dump = true;
- /*
- * In any case, a namespace can be excluded by an exclusion switch
- */
- if (nsinfo->dobj.dump &&
- simple_oid_list_member(&schema_exclude_oids,
- nsinfo->dobj.catId.oid))
- nsinfo->dobj.dump = false;
- }
- /*
- * selectDumpableTable: policy-setting subroutine
- * Mark a table as to be dumped or not
- */
- static void
- selectDumpableTable(TableInfo *tbinfo)
- {
- /*
- * If specific tables are being dumped, dump just those tables; else, dump
- * according to the parent namespace's dump flag.
- */
- if (table_include_oids.head != NULL)
- tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids,
- tbinfo->dobj.catId.oid);
- else
- tbinfo->dobj.dump = tbinfo->dobj.namespace->dobj.dump;
- /*
- * In any case, a table can be excluded by an exclusion switch
- */
- if (tbinfo->dobj.dump &&
- simple_oid_list_member(&table_exclude_oids,
- tbinfo->dobj.catId.oid))
- tbinfo->dobj.dump = false;
- }
- /*
- * selectDumpableType: policy-setting subroutine
- * Mark a type as to be dumped or not
- *
- * If it's a table's rowtype or an autogenerated array type, we also apply a
- * special type code to facilitate sorting into the desired order. (We don't
- * want to consider those to be ordinary types because that would bring tables
- * up into the datatype part of the dump order.) We still set the object's
- * dump flag; that's not going to cause the dummy type to be dumped, but we
- * need it so that casts involving such types will be dumped correctly -- see
- * dumpCast. This means the flag should be set the same as for the underlying
- * object (the table or base type).
- */
- static void
- selectDumpableType(TypeInfo *tyinfo)
- {
- /* skip complex types, except for standalone composite types */
- if (OidIsValid(tyinfo->typrelid) &&
- tyinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
- {
- TableInfo *tytable = findTableByOid(tyinfo->typrelid);
- tyinfo->dobj.objType = DO_DUMMY_TYPE;
- if (tytable != NULL)
- tyinfo->dobj.dump = tytable->dobj.dump;
- else
- tyinfo->dobj.dump = false;
- return;
- }
- /* skip auto-generated array types */
- if (tyinfo->isArray)
- {
- tyinfo->dobj.objType = DO_DUMMY_TYPE;
- /*
- * Fall through to set the dump flag; we assume that the subsequent
- * rules will do the same thing as they would for the array's base
- * type. (We cannot reliably look up the base type here, since
- * getTypes may not have processed it yet.)
- */
- }
- /* dump only types in dumpable namespaces */
- if (!tyinfo->dobj.namespace->dobj.dump)
- tyinfo->dobj.dump = false;
- /* skip undefined placeholder types */
- else if (!tyinfo->isDefined)
- tyinfo->dobj.dump = false;
- else
- tyinfo->dobj.dump = true;
- }
- /*
- * selectDumpableDefaultACL: policy-setting subroutine
- * Mark a default ACL as to be dumped or not
- *
- * For per-schema default ACLs, dump if the schema is to be dumped.
- * Otherwise dump if we are dumping "everything". Note that dataOnly
- * and aclsSkip are checked separately.
- */
- static void
- selectDumpableDefaultACL(DefaultACLInfo *dinfo)
- {
- if (dinfo->dobj.namespace)
- dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump;
- else
- dinfo->dobj.dump = include_everything;
- }
- /*
- * selectDumpableExtension: policy-setting subroutine
- * Mark an extension as to be dumped or not
- *
- * Normally, we dump all extensions, or none of them if include_everything
- * is false (i.e., a --schema or --table switch was given). However, in
- * binary-upgrade mode it's necessary to skip built-in extensions, since we
- * assume those will already be installed in the target database. We identify
- * such extensions by their having OIDs in the range reserved for initdb.
- */
- static void
- selectDumpableExtension(ExtensionInfo *extinfo)
- {
- if (binary_upgrade && extinfo->dobj.catId.oid < (Oid) FirstNormalObjectId)
- extinfo->dobj.dump = false;
- else
- extinfo->dobj.dump = include_everything;
- }
- /*
- * selectDumpableObject: policy-setting subroutine
- * Mark a generic dumpable object as to be dumped or not
- *
- * Use this only for object types without a special-case routine above.
- */
- static void
- selectDumpableObject(DumpableObject *dobj)
- {
- /*
- * Default policy is to dump if parent namespace is dumpable, or always
- * for non-namespace-associated items.
- */
- if (dobj->namespace)
- dobj->dump = dobj->namespace->dobj.dump;
- else
- dobj->dump = true;
- }
- /*
- * Dump a table's contents for loading using the COPY command
- * - this routine is called by the Archiver when it wants the table
- * to be dumped.
- */
- static int
- dumpTableData_copy(Archive *fout, void *dcontext)
- {
- TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
- TableInfo *tbinfo = tdinfo->tdtable;
- const char *classname = tbinfo->dobj.name;
- const bool hasoids = tbinfo->hasoids;
- const bool oids = tdinfo->oids;
- PQExpBuffer q = createPQExpBuffer();
- /*
- * Note: can't use getThreadLocalPQExpBuffer() here, we're calling fmtId
- * which uses it already.
- */
- PQExpBuffer clistBuf = createPQExpBuffer();
- PGconn *conn = GetConnection(fout);
- PGresult *res;
- int ret;
- char *copybuf;
- const char *column_list;
- if (g_verbose)
- write_msg(NULL, "dumping contents of table %s\n", classname);
- /*
- * Make sure we are in proper schema. We will qualify the table name
- * below anyway (in case its name conflicts with a pg_catalog table); but
- * this ensures reproducible results in case the table contains regproc,
- * regclass, etc columns.
- */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
- /*
- * If possible, specify the column list explicitly so that we have no
- * possibility of retrieving data in the wrong column order. (The default
- * column ordering of COPY will not be what we want in certain corner
- * cases involving ADD COLUMN and inheritance.)
- */
- if (fout->remoteVersion >= 70300)
- column_list = fmtCopyColumnList(tbinfo, clistBuf);
- else
- column_list = ""; /* can't select columns in COPY */
- if (oids && hasoids)
- {
- appendPQExpBuffer(q, "COPY %s %s WITH OIDS TO stdout;",
- fmtQualifiedId(fout->remoteVersion,
- tbinfo->dobj.namespace->dobj.name,
- classname),
- column_list);
- }
- else if (tdinfo->filtercond)
- {
- /* Note: this syntax is only supported in 8.2 and up */
- appendPQExpBufferStr(q, "COPY (SELECT ");
- /* klugery to get rid of parens in column list */
- if (strlen(column_list) > 2)
- {
- appendPQExpBufferStr(q, column_list + 1);
- q->data[q->len - 1] = ' ';
- }
- else
- appendPQExpBufferStr(q, "* ");
- appendPQExpBuffer(q, "FROM %s %s) TO stdout;",
- fmtQualifiedId(fout->remoteVersion,
- tbinfo->dobj.namespace->dobj.name,
- classname),
- tdinfo->filtercond);
- }
- else
- {
- appendPQExpBuffer(q, "COPY %s %s TO stdout;",
- fmtQualifiedId(fout->remoteVersion,
- tbinfo->dobj.namespace->dobj.name,
- classname),
- column_list);
- }
- res = ExecuteSqlQuery(fout, q->data, PGRES_COPY_OUT);
- PQclear(res);
- destroyPQExpBuffer(clistBuf);
- for (;;)
- {
- ret = PQgetCopyData(conn, ©buf, 0);
- if (ret < 0)
- break; /* done or error */
- if (copybuf)
- {
- WriteData(fout, copybuf, ret);
- PQfreemem(copybuf);
- }
- /* ----------
- * THROTTLE:
- *
- * There was considerable discussion in late July, 2000 regarding
- * slowing down pg_dump when backing up large tables. Users with both
- * slow & fast (multi-processor) machines experienced performance
- * degradation when doing a backup.
- *
- * Initial attempts based on sleeping for a number of ms for each ms
- * of work were deemed too complex, then a simple 'sleep in each loop'
- * implementation was suggested. The latter failed because the loop
- * was too tight. Finally, the following was implemented:
- *
- * If throttle is non-zero, then
- * See how long since the last sleep.
- * Work out how long to sleep (based on ratio).
- * If sleep is more than 100ms, then
- * sleep
- * reset timer
- * EndIf
- * EndIf
- *
- * where the throttle value was the number of ms to sleep per ms of
- * work. The calculation was done in each loop.
- *
- * Most of the hard work is done in the backend, and this solution
- * still did not work particularly well: on slow machines, the ratio
- * was 50:1, and on medium paced machines, 1:1, and on fast
- * multi-processor machines, it had little or no effect, for reasons
- * that were unclear.
- *
- * Further discussion ensued, and the proposal was dropped.
- *
- * For those people who want this feature, it can be implemented using
- * gettimeofday in each loop, calculating the time since last sleep,
- * multiplying that by the sleep ratio, then if the result is more
- * than a preset 'minimum sleep time' (say 100ms), call the 'select'
- * function to sleep for a subsecond period ie.
- *
- * select(0, NULL, NULL, NULL, &tvi);
- *
- * This will return after the interval specified in the structure tvi.
- * Finally, call gettimeofday again to save the 'last sleep time'.
- * ----------
- */
- }
- archprintf(fout, "\\.\n\n\n");
- …
Large files files are truncated, but you can click here to view the full file