* pg_dump is a utility for dumping out a postgres database
* into a script file.
*
- * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2019, 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
#include <unistd.h>
#include <ctype.h>
+#include <limits.h>
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
#include "access/attnum.h"
#include "access/sysattr.h"
#include "access/transam.h"
-#include "catalog/pg_am.h"
-#include "catalog/pg_attribute.h"
-#include "catalog/pg_cast.h"
-#include "catalog/pg_class.h"
-#include "catalog/pg_default_acl.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 "catalog/pg_aggregate_d.h"
+#include "catalog/pg_am_d.h"
+#include "catalog/pg_attribute_d.h"
+#include "catalog/pg_cast_d.h"
+#include "catalog/pg_class_d.h"
+#include "catalog/pg_default_acl_d.h"
+#include "catalog/pg_largeobject_d.h"
+#include "catalog/pg_largeobject_metadata_d.h"
+#include "catalog/pg_proc_d.h"
+#include "catalog/pg_trigger_d.h"
+#include "catalog/pg_type_d.h"
#include "libpq/libpq-fs.h"
+#include "storage/block.h"
#include "dumputils.h"
#include "parallel.h"
#include "pg_backup_db.h"
#include "pg_backup_utils.h"
#include "pg_dump.h"
+#include "fe_utils/connect.h"
#include "fe_utils/string_utils.h"
} OidOptions;
/* global decls */
-bool g_verbose; /* User wants verbose narration of our
- * activities. */
static bool dosync = true; /* Issue fsync() to make dump durable on disk. */
/* subquery used to convert user ID (eg, datdba) to user name */
static const CatalogId nilCatalogId = {0, 0};
+/* override for standard extra_float_digits setting */
+static bool have_extra_float_digits = false;
+static int extra_float_digits;
+
+/*
+ * The default number of rows per INSERT when
+ * --inserts is specified without --rows-per-insert
+ */
+#define DUMP_DEFAULT_ROWS_PER_INSERT 1
+
+/*
+ * Macro for producing quoted, schema-qualified name of a dumpable object.
+ */
+#define fmtQualifiedDumpable(obj) \
+ fmtQualifiedId((obj)->dobj.namespace->dobj.name, \
+ (obj)->dobj.name)
+
static void help(const char *progname);
static void setup_connection(Archive *AH,
- const char *dumpencoding, const char *dumpsnapshot,
- char *use_role);
+ const char *dumpencoding, const char *dumpsnapshot,
+ char *use_role);
static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
static void expand_schema_name_patterns(Archive *fout,
- SimpleStringList *patterns,
- SimpleOidList *oids,
- bool strict_names);
+ SimpleStringList *patterns,
+ SimpleOidList *oids,
+ bool strict_names);
static void expand_table_name_patterns(Archive *fout,
- SimpleStringList *patterns,
- SimpleOidList *oids,
- bool strict_names);
+ SimpleStringList *patterns,
+ SimpleOidList *oids,
+ bool strict_names);
static NamespaceInfo *findNamespace(Archive *fout, Oid nsoid);
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 void dumpComment(Archive *fout, const char *type, const char *name,
+ 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 void dumpSecLabel(Archive *fout, const char *type, const char *name,
+ 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 dumpSequence(Archive *fout, TableInfo *tbinfo);
static void dumpSequenceData(Archive *fout, TableDataInfo *tdinfo);
static void dumpIndex(Archive *fout, IndxInfo *indxinfo);
+static void dumpIndexAttach(Archive *fout, IndexAttachInfo *attachinfo);
static void dumpStatisticsExt(Archive *fout, StatsExtInfo *statsextinfo);
static void dumpConstraint(Archive *fout, ConstraintInfo *coninfo);
static void dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo);
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);
+ 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, const char *racls,
- const char *initacls, const char *initracls);
+ const char *type, const char *name, const char *subname,
+ const char *nspname, const char *owner,
+ const char *acls, const char *racls,
+ const char *initacls, const char *initracls);
static void getDependencies(Archive *fout);
static void BuildArchiveDependencies(Archive *fout);
static void findDumpableDependencies(ArchiveHandle *AH, DumpableObject *dobj,
- DumpId **dependencies, int *nDeps, int *allocDeps);
+ DumpId **dependencies, int *nDeps, int *allocDeps);
static DumpableObject *createBoundaryObjects(void);
static void addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
- DumpableObject *boundaryObjs);
+ DumpableObject *boundaryObjs);
static void getDomainConstraints(Archive *fout, TypeInfo *tyinfo);
-static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, bool oids, char relkind);
-static void makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo, bool oids);
+static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind);
+static void makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo);
static void buildMatViewRefreshDependencies(Archive *fout);
static void getTableDataFKConstraints(void);
static char *format_function_arguments(FuncInfo *finfo, char *funcargs,
- bool is_agg);
+ bool is_agg);
static char *format_function_arguments_old(Archive *fout,
- FuncInfo *finfo, int nallargs,
- char **allargtypes,
- char **argmodes,
- char **argnames);
+ FuncInfo *finfo, int nallargs,
+ char **allargtypes,
+ char **argmodes,
+ char **argnames);
static char *format_function_signature(Archive *fout,
- FuncInfo *finfo, bool honor_quotes);
+ FuncInfo *finfo, bool honor_quotes);
static char *convertRegProcReference(Archive *fout,
- const char *proc);
-static char *convertOperatorReference(Archive *fout, const char *opr);
+ const char *proc);
+static char *getFormattedOperatorName(Archive *fout, const char *oproid);
static char *convertTSFunction(Archive *fout, Oid funcOid);
-static Oid findLastBuiltinOid_V71(Archive *fout, const char *);
-static void selectSourceSchema(Archive *fout, const char *schemaName);
+static Oid findLastBuiltinOid_V71(Archive *fout);
static char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts);
static void getBlobs(Archive *fout);
static void dumpBlob(Archive *fout, BlobInfo *binfo);
static void dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo);
static void dumpSubscription(Archive *fout, SubscriptionInfo *subinfo);
static void dumpDatabase(Archive *AH);
+static void dumpDatabaseConfig(Archive *AH, PQExpBuffer outbuf,
+ const char *dbname, Oid dboid);
static void dumpEncoding(Archive *AH);
static void dumpStdStrings(Archive *AH);
+static void dumpSearchPath(Archive *AH);
static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
- PQExpBuffer upgrade_buffer,
- Oid pg_type_oid,
- bool force_array_type);
+ PQExpBuffer upgrade_buffer,
+ Oid pg_type_oid,
+ bool force_array_type);
static bool binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
- PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
+ 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);
+ PQExpBuffer upgrade_buffer,
+ Oid pg_class_oid, bool is_index);
static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
- DumpableObject *dobj,
- const char *objlabel);
+ DumpableObject *dobj,
+ const char *objtype,
+ const char *objname,
+ const char *objnamespace);
static const char *getAttrName(int attrnum, TableInfo *tblInfo);
static const char *fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer);
static bool nonemptyReloptions(const char *reloptions);
static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
- const char *prefix, Archive *fout);
+ const char *prefix, Archive *fout);
static char *get_synchronized_snapshot(Archive *fout);
static void setupDumpWorker(Archive *AHX);
static TableInfo *getRootTableInfo(TableInfo *tbinfo);
DumpableObject *boundaryObjs;
int i;
int optindex;
+ char *endptr;
RestoreOptions *ropt;
Archive *fout; /* the script file */
+ bool g_verbose = false;
const char *dumpencoding = NULL;
const char *dumpsnapshot = NULL;
char *use_role = NULL;
+ long rowsPerInsert;
int numWorkers = 1;
trivalue prompt_password = TRI_DEFAULT;
int compressLevel = -1;
{"host", required_argument, NULL, 'h'},
{"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'},
{"disable-triggers", no_argument, &dopt.disable_triggers, 1},
{"enable-row-security", no_argument, &dopt.enable_row_security, 1},
{"exclude-table-data", required_argument, NULL, 4},
+ {"extra-float-digits", required_argument, NULL, 8},
{"if-exists", no_argument, &dopt.if_exists, 1},
- {"inserts", no_argument, &dopt.dump_inserts, 1},
+ {"inserts", no_argument, NULL, 9},
{"lock-wait-timeout", required_argument, NULL, 2},
{"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1},
{"quote-all-identifiers", no_argument, "e_all_identifiers, 1},
{"snapshot", required_argument, NULL, 6},
{"strict-names", no_argument, &strict_names, 1},
{"use-set-session-authorization", no_argument, &dopt.use_setsessauth, 1},
+ {"no-comments", no_argument, &dopt.no_comments, 1},
{"no-publications", no_argument, &dopt.no_publications, 1},
{"no-security-labels", no_argument, &dopt.no_security_labels, 1},
{"no-synchronized-snapshots", no_argument, &dopt.no_synchronized_snapshots, 1},
{"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1},
{"no-subscriptions", no_argument, &dopt.no_subscriptions, 1},
{"no-sync", no_argument, NULL, 7},
+ {"on-conflict-do-nothing", no_argument, &dopt.do_nothing, 1},
+ {"rows-per-insert", required_argument, NULL, 10},
{NULL, 0, NULL, 0}
};
+ pg_logging_init(argv[0]);
+ pg_logging_set_level(PG_LOG_WARNING);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
/*
*/
init_parallel_dump_utils();
- g_verbose = false;
-
strcpy(g_comment_start, "-- ");
g_comment_end[0] = '\0';
strcpy(g_opaque_type, "opaque");
InitDumpOptions(&dopt);
- while ((c = getopt_long(argc, argv, "abBcCd:E:f:F:h:j:n:N:oOp:RsS:t:T:U:vwWxZ:",
+ while ((c = getopt_long(argc, argv, "abBcCd:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxZ:",
long_options, &optindex)) != -1)
{
switch (c)
simple_string_list_append(&schema_exclude_patterns, optarg);
break;
- case 'o': /* Dump oids */
- dopt.oids = true;
- break;
-
case 'O': /* Don't reconnect to match owner */
dopt.outputNoOwner = 1;
break;
case 'v': /* verbose */
g_verbose = true;
+ pg_logging_set_level(PG_LOG_INFO);
break;
case 'w':
compressLevel = atoi(optarg);
if (compressLevel < 0 || compressLevel > 9)
{
- write_msg(NULL, "compression level must be in range 0..9\n");
+ pg_log_error("compression level must be in range 0..9");
exit_nicely(1);
}
break;
dosync = false;
break;
+ case 8:
+ have_extra_float_digits = true;
+ extra_float_digits = atoi(optarg);
+ if (extra_float_digits < -15 || extra_float_digits > 3)
+ {
+ pg_log_error("extra_float_digits must be in range -15..3");
+ exit_nicely(1);
+ }
+ break;
+
+ case 9: /* inserts */
+
+ /*
+ * dump_inserts also stores --rows-per-insert, careful not to
+ * overwrite that.
+ */
+ if (dopt.dump_inserts == 0)
+ dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT;
+ break;
+
+ case 10: /* rows per insert */
+ errno = 0;
+ rowsPerInsert = strtol(optarg, &endptr, 10);
+
+ if (endptr == optarg || *endptr != '\0' ||
+ rowsPerInsert <= 0 || rowsPerInsert > INT_MAX ||
+ errno == ERANGE)
+ {
+ pg_log_error("rows-per-insert must be in range %d..%d",
+ 1, INT_MAX);
+ exit_nicely(1);
+ }
+ dopt.dump_inserts = (int) rowsPerInsert;
+ break;
+
default:
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit_nicely(1);
/* Complain if any arguments remain */
if (optind < argc)
{
- fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
- progname, argv[optind]);
+ pg_log_error("too many command-line arguments (first is \"%s\")",
+ argv[optind]);
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
progname);
exit_nicely(1);
}
/* --column-inserts implies --inserts */
- if (dopt.column_inserts)
- dopt.dump_inserts = 1;
+ if (dopt.column_inserts && dopt.dump_inserts == 0)
+ dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT;
/*
* Binary upgrade mode implies dumping sequence data even in schema-only
if (dopt.dataOnly && dopt.schemaOnly)
{
- write_msg(NULL, "options -s/--schema-only and -a/--data-only cannot be used together\n");
+ pg_log_error("options -s/--schema-only and -a/--data-only cannot be used together");
exit_nicely(1);
}
if (dopt.dataOnly && dopt.outputClean)
{
- write_msg(NULL, "options -c/--clean and -a/--data-only cannot be used together\n");
- exit_nicely(1);
- }
-
- if (dopt.dump_inserts && dopt.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");
+ pg_log_error("options -c/--clean and -a/--data-only cannot be used together");
exit_nicely(1);
}
if (dopt.if_exists && !dopt.outputClean)
- exit_horribly(NULL, "option --if-exists requires option -c/--clean\n");
+ fatal("option --if-exists requires option -c/--clean");
+
+ /*
+ * --inserts are already implied above if --column-inserts or
+ * --rows-per-insert were specified.
+ */
+ if (dopt.do_nothing && dopt.dump_inserts == 0)
+ fatal("option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts");
/* Identify archive format to emit */
archiveFormat = parseArchiveFormat(format, &archiveMode);
#ifndef HAVE_LIBZ
if (compressLevel != 0)
- write_msg(NULL, "WARNING: requested compression not available in this "
- "installation -- archive will be uncompressed\n");
+ pg_log_warning("requested compression not available in this installation -- archive will be uncompressed");
compressLevel = 0;
#endif
+ /*
+ * If emitting an archive format, we always want to emit a DATABASE item,
+ * in case --create is specified at pg_restore time.
+ */
+ if (!plainText)
+ dopt.outputCreateDB = 1;
+
/*
* On Windows we can only have at most MAXIMUM_WAIT_OBJECTS (= 64 usually)
* parallel jobs because that's the maximum limit for the
|| numWorkers > MAXIMUM_WAIT_OBJECTS
#endif
)
- exit_horribly(NULL, "invalid number of parallel jobs\n");
+ fatal("invalid number of parallel jobs");
/* 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");
+ fatal("parallel backup only supported by the directory format");
/* Open the output file */
fout = CreateArchive(filename, archiveFormat, compressLevel, dosync,
/* Let the archiver know how noisy to be */
fout->verbose = g_verbose;
+
/*
* We allow the server to be back to 8.0, and up to any minor release of
* our own major version. (See also version check in pg_dumpall.c.)
/* check the version for the synchronized snapshots feature */
if (numWorkers > 1 && fout->remoteVersion < 90200
&& !dopt.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");
+ fatal("Synchronized snapshots are not supported by this server version.\n"
+ "Run with --no-synchronized-snapshots instead if you do not need\n"
+ "synchronized snapshots.");
/* check the version when a snapshot is explicitly specified by user */
if (dumpsnapshot && fout->remoteVersion < 90200)
- exit_horribly(NULL,
- "Exported snapshots are not supported by this server version.\n");
+ fatal("Exported snapshots are not supported by this server version.");
/*
* Find the last built-in OID, if needed (prior to 8.1)
* With 8.1 and above, we can just use FirstNormalObjectId - 1.
*/
if (fout->remoteVersion < 80100)
- g_last_builtin_oid = findLastBuiltinOid_V71(fout,
- PQdb(GetConnection(fout)));
+ g_last_builtin_oid = findLastBuiltinOid_V71(fout);
else
g_last_builtin_oid = FirstNormalObjectId - 1;
- if (g_verbose)
- write_msg(NULL, "last built-in OID is %u\n", g_last_builtin_oid);
+ pg_log_info("last built-in OID is %u", g_last_builtin_oid);
/* Expand schema selection patterns into OID lists */
if (schema_include_patterns.head != NULL)
&schema_include_oids,
strict_names);
if (schema_include_oids.head == NULL)
- exit_horribly(NULL, "no matching schemas were found\n");
+ fatal("no matching schemas were found");
}
expand_schema_name_patterns(fout, &schema_exclude_patterns,
&schema_exclude_oids,
&table_include_oids,
strict_names);
if (table_include_oids.head == NULL)
- exit_horribly(NULL, "no matching tables were found\n");
+ fatal("no matching tables were found");
}
expand_table_name_patterns(fout, &table_exclude_patterns,
&table_exclude_oids,
if (!dopt.schemaOnly)
{
- getTableData(&dopt, tblinfo, numTables, dopt.oids, 0);
+ getTableData(&dopt, tblinfo, numTables, 0);
buildMatViewRefreshDependencies(fout);
if (dopt.dataOnly)
getTableDataFKConstraints();
}
if (dopt.schemaOnly && dopt.sequence_data)
- getTableData(&dopt, tblinfo, numTables, dopt.oids, RELKIND_SEQUENCE);
+ getTableData(&dopt, tblinfo, numTables, RELKIND_SEQUENCE);
/*
* In binary-upgrade mode, we do not have to worry about the actual blob
* data or the associated metadata that resides in the pg_largeobject and
- * pg_largeobject_metadata tables, respectivly.
+ * pg_largeobject_metadata tables, respectively.
*
* However, we do need to collect blob information as there may be
* comments or other information on blobs that we do need to dump out.
*/
sortDumpableObjectsByTypeName(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);
* order.
*/
- /* First the special ENCODING and STDSTRINGS entries. */
+ /* First the special ENCODING, STDSTRINGS, and SEARCHPATH entries. */
dumpEncoding(fout);
dumpStdStrings(fout);
+ dumpSearchPath(fout);
- /* The database item is always next, unless we don't want it at all */
- if (dopt.include_everything && !dopt.dataOnly)
+ /* The database items are always next, unless we don't want them at all */
+ if (dopt.outputCreateDB)
dumpDatabase(fout);
/* Now the rearrangeable objects. */
ropt->use_setsessauth = dopt.use_setsessauth;
ropt->disable_dollar_quoting = dopt.disable_dollar_quoting;
ropt->dump_inserts = dopt.dump_inserts;
+ ropt->no_comments = dopt.no_comments;
ropt->no_publications = dopt.no_publications;
ropt->no_security_labels = dopt.no_security_labels;
ropt->no_subscriptions = dopt.no_subscriptions;
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(_(" --enable-row-security enable row security (dump only content user has\n"
" access to)\n"));
printf(_(" --exclude-table-data=TABLE do NOT dump data for the named table(s)\n"));
+ printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n"));
printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
+ printf(_(" --load-via-partition-root load partitions via the root table\n"));
+ printf(_(" --no-comments do not dump comments\n"));
printf(_(" --no-publications do not dump publications\n"));
printf(_(" --no-security-labels do not dump security label assignments\n"));
printf(_(" --no-subscriptions do not dump subscriptions\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(_(" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n"));
printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
- printf(_(" --load-via-partition-root load partitions via the root table\n"));
+ printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\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(_(" --snapshot=SNAPSHOT use given snapshot for the 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"));
+ printf(_("Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"));
}
static void
PGconn *conn = GetConnection(AH);
const char *std_strings;
+ PQclear(ExecuteSqlQueryForSingleRow(AH, ALWAYS_SECURE_SEARCH_PATH_SQL));
+
/*
* Set the client encoding if requested.
*/
if (dumpencoding)
{
if (PQsetClientEncoding(conn, dumpencoding) < 0)
- exit_horribly(NULL, "invalid client encoding \"%s\" specified\n",
- dumpencoding);
+ fatal("invalid client encoding \"%s\" specified",
+ dumpencoding);
}
/*
ExecuteSqlStatement(AH, "SET INTERVALSTYLE = POSTGRES");
/*
- * Set extra_float_digits so that we can dump float data exactly (given
- * correctly implemented float I/O code, anyway)
+ * Use an explicitly specified extra_float_digits if it has been provided.
+ * Otherwise, set extra_float_digits so that we can dump float data
+ * exactly (given correctly implemented float I/O code, anyway).
*/
- if (AH->remoteVersion >= 90000)
+ if (have_extra_float_digits)
+ {
+ PQExpBuffer q = createPQExpBuffer();
+
+ appendPQExpBuffer(q, "SET extra_float_digits TO %d",
+ extra_float_digits);
+ ExecuteSqlStatement(AH, q->data);
+ destroyPQExpBuffer(q);
+ }
+ else if (AH->remoteVersion >= 90000)
ExecuteSqlStatement(AH, "SET extra_float_digits TO 3");
else
ExecuteSqlStatement(AH, "SET extra_float_digits TO 2");
{
PQExpBuffer query = createPQExpBuffer();
- appendPQExpBuffer(query, "SET TRANSACTION SNAPSHOT ");
+ appendPQExpBufferStr(query, "SET TRANSACTION SNAPSHOT ");
appendStringLiteralConn(query, AH->sync_snapshot_id, conn);
ExecuteSqlStatement(AH, query->data);
destroyPQExpBuffer(query);
!dopt->no_synchronized_snapshots)
{
if (AH->isStandby && AH->remoteVersion < 100000)
- exit_horribly(NULL,
- "Synchronized snapshots on standby servers are not supported by this server version.\n"
- "Run with --no-synchronized-snapshots instead if you do not need\n"
- "synchronized snapshots.\n");
+ fatal("Synchronized snapshots on standby servers are not supported by this server version.\n"
+ "Run with --no-synchronized-snapshots instead if you do not need\n"
+ "synchronized snapshots.");
AH->sync_snapshot_id = get_synchronized_snapshot(AH);
else if (pg_strcasecmp(format, "tar") == 0)
archiveFormat = archTar;
else
- exit_horribly(NULL, "invalid output format \"%s\" specified\n", format);
+ fatal("invalid output format \"%s\" specified", format);
return archiveFormat;
}
for (cell = patterns->head; cell; cell = cell->next)
{
- appendPQExpBuffer(query,
- "SELECT oid FROM pg_catalog.pg_namespace n\n");
+ appendPQExpBufferStr(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);
if (strict_names && PQntuples(res) == 0)
- exit_horribly(NULL, "no matching schemas were found for pattern \"%s\"\n", cell->val);
+ fatal("no matching schemas were found for pattern \"%s\"", cell->val);
for (i = 0; i < PQntuples(res); i++)
{
/*
* Find the OIDs of all tables matching the given list of patterns,
- * and append them to the given OID list.
+ * and append them to the given OID list. See also expand_dbname_patterns()
+ * in pg_dumpall.c
*/
static void
expand_table_name_patterns(Archive *fout,
for (cell = patterns->head; cell; cell = cell->next)
{
+ /*
+ * Query must remain ABSOLUTELY devoid of unqualified names. This
+ * would be unnecessary given a pg_table_is_visible() variant taking a
+ * search_path argument.
+ */
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', '%c')\n",
+ "\n LEFT JOIN pg_catalog.pg_namespace n"
+ "\n ON n.oid OPERATOR(pg_catalog.=) c.relnamespace"
+ "\nWHERE c.relkind OPERATOR(pg_catalog.=) ANY"
+ "\n (array['%c', '%c', '%c', '%c', '%c', '%c'])\n",
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
RELKIND_PARTITIONED_TABLE);
false, "n.nspname", "c.relname", NULL,
"pg_catalog.pg_table_is_visible(c.oid)");
+ ExecuteSqlStatement(fout, "RESET search_path");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+ PQclear(ExecuteSqlQueryForSingleRow(fout,
+ ALWAYS_SECURE_SEARCH_PATH_SQL));
if (strict_names && PQntuples(res) == 0)
- exit_horribly(NULL, "no matching tables were found for pattern \"%s\"\n", cell->val);
+ fatal("no matching tables were found for pattern \"%s\"", cell->val);
for (i = 0; i < PQntuples(res); i++)
{
/* Other system schemas don't get dumped */
nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_NONE;
}
+ else if (strcmp(nsinfo->dobj.name, "public") == 0)
+ {
+ /*
+ * The public schema is a strange beast that sits in a sort of
+ * no-mans-land between being a system object and a user object. We
+ * don't want to dump creation or comment commands for it, because
+ * that complicates matters for non-superuser use of pg_dump. But we
+ * should dump any ACL changes that have occurred for it, and of
+ * course we should dump contained objects.
+ */
+ nsinfo->dobj.dump = DUMP_COMPONENT_ACL;
+ nsinfo->dobj.dump_contains = DUMP_COMPONENT_ALL;
+ }
else
nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_ALL;
* 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
+ * Built-in extensions should be skipped except for checking ACLs, 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.
+ * We dump all user-added extensions by default, or none of them if
+ * include_everything is false (i.e., a --schema or --table switch was given).
*/
static void
selectDumpableExtension(ExtensionInfo *extinfo, DumpOptions *dopt)
{
/*
- * Use DUMP_COMPONENT_ACL for from-initdb extensions, to allow users to
- * change permissions on those objects, if they wish to, and have those
- * changes preserved.
+ * Use DUMP_COMPONENT_ACL for built-in extensions, to allow users to
+ * change permissions on their member objects, if they wish to, and have
+ * those changes preserved.
*/
- if (dopt->binary_upgrade && extinfo->dobj.catId.oid <= (Oid) g_last_builtin_oid)
+ if (extinfo->dobj.catId.oid <= (Oid) g_last_builtin_oid)
extinfo->dobj.dump = extinfo->dobj.dump_contains = DUMP_COMPONENT_ACL;
else
extinfo->dobj.dump = extinfo->dobj.dump_contains =
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();
/*
char *copybuf;
const char *column_list;
- if (g_verbose)
- write_msg(NULL, "dumping contents of table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name, 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);
+ pg_log_info("dumping contents of table \"%s.%s\"",
+ tbinfo->dobj.namespace->dobj.name, classname);
/*
* Specify the column list explicitly so that we have no possibility of
*/
column_list = fmtCopyColumnList(tbinfo, clistBuf);
- 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)
+ if (tdinfo->filtercond)
{
/* Note: this syntax is only supported in 8.2 and up */
appendPQExpBufferStr(q, "COPY (SELECT ");
else
appendPQExpBufferStr(q, "* ");
appendPQExpBuffer(q, "FROM %s %s) TO stdout;",
- fmtQualifiedId(fout->remoteVersion,
- tbinfo->dobj.namespace->dobj.name,
- classname),
+ fmtQualifiedDumpable(tbinfo),
tdinfo->filtercond);
}
else
{
appendPQExpBuffer(q, "COPY %s %s TO stdout;",
- fmtQualifiedId(fout->remoteVersion,
- tbinfo->dobj.namespace->dobj.name,
- classname),
+ fmtQualifiedDumpable(tbinfo),
column_list);
}
res = ExecuteSqlQuery(fout, q->data, PGRES_COPY_OUT);
if (ret == -2)
{
/* copy data transfer failed */
- write_msg(NULL, "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed.\n", classname);
- write_msg(NULL, "Error message from server: %s", PQerrorMessage(conn));
- write_msg(NULL, "The command was: %s\n", q->data);
+ pg_log_error("Dumping the contents of table \"%s\" failed: PQgetCopyData() failed.", classname);
+ pg_log_error("Error message from server: %s", PQerrorMessage(conn));
+ pg_log_error("The command was: %s", q->data);
exit_nicely(1);
}
res = PQgetResult(conn);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
- write_msg(NULL, "Dumping the contents of table \"%s\" failed: PQgetResult() failed.\n", classname);
- write_msg(NULL, "Error message from server: %s", PQerrorMessage(conn));
- write_msg(NULL, "The command was: %s\n", q->data);
+ pg_log_error("Dumping the contents of table \"%s\" failed: PQgetResult() failed.", classname);
+ pg_log_error("Error message from server: %s", PQerrorMessage(conn));
+ pg_log_error("The command was: %s", q->data);
exit_nicely(1);
}
PQclear(res);
/* Do this to ensure we've pumped libpq back to idle state */
if (PQgetResult(conn) != NULL)
- write_msg(NULL, "WARNING: unexpected extra results during COPY of table \"%s\"\n",
- classname);
+ pg_log_warning("unexpected extra results during COPY of table \"%s\"",
+ classname);
destroyPQExpBuffer(q);
return 1;
{
TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
TableInfo *tbinfo = tdinfo->tdtable;
- const char *classname = tbinfo->dobj.name;
DumpOptions *dopt = fout->dopt;
PQExpBuffer q = createPQExpBuffer();
PQExpBuffer insertStmt = NULL;
PGresult *res;
- int tuple;
int nfields;
- int field;
-
- /*
- * 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);
+ int rows_per_statement = dopt->dump_inserts;
+ int rows_this_statement = 0;
appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
"SELECT * FROM ONLY %s",
- fmtQualifiedId(fout->remoteVersion,
- tbinfo->dobj.namespace->dobj.name,
- classname));
+ fmtQualifiedDumpable(tbinfo));
if (tdinfo->filtercond)
appendPQExpBuffer(q, " %s", tdinfo->filtercond);
res = ExecuteSqlQuery(fout, "FETCH 100 FROM _pg_dump_cursor",
PGRES_TUPLES_OK);
nfields = PQnfields(res);
- for (tuple = 0; tuple < PQntuples(res); tuple++)
- {
- /*
- * First time through, we build as much of the INSERT statement as
- * possible in "insertStmt", which we can then just print for each
- * line. If the table happens to have zero columns then this will
- * be a complete statement, otherwise it will end in "VALUES(" and
- * be ready to have the row's column values appended.
- */
- if (insertStmt == NULL)
- {
- insertStmt = createPQExpBuffer();
- /*
- * When load-via-partition-root is set, get the root table
- * name for the partition table, so that we can reload data
- * through the root table.
- */
- if (dopt->load_via_partition_root && tbinfo->ispartition)
- {
- TableInfo *parentTbinfo;
+ /*
+ * First time through, we build as much of the INSERT statement as
+ * possible in "insertStmt", which we can then just print for each
+ * statement. If the table happens to have zero columns then this will
+ * be a complete statement, otherwise it will end in "VALUES" and be
+ * ready to have the row's column values printed.
+ */
+ if (insertStmt == NULL)
+ {
+ TableInfo *targettab;
- parentTbinfo = getRootTableInfo(tbinfo);
+ insertStmt = createPQExpBuffer();
- /*
- * When we loading data through the root, we will qualify
- * the table name. This is needed because earlier
- * search_path will be set for the partition table.
- */
- classname = (char *) fmtQualifiedId(fout->remoteVersion,
- parentTbinfo->dobj.namespace->dobj.name,
- parentTbinfo->dobj.name);
- }
- else
- classname = fmtId(tbinfo->dobj.name);
+ /*
+ * When load-via-partition-root is set, get the root table name
+ * for the partition table, so that we can reload data through the
+ * root table.
+ */
+ if (dopt->load_via_partition_root && tbinfo->ispartition)
+ targettab = getRootTableInfo(tbinfo);
+ else
+ targettab = tbinfo;
- appendPQExpBuffer(insertStmt, "INSERT INTO %s ",
- classname);
+ appendPQExpBuffer(insertStmt, "INSERT INTO %s ",
+ fmtQualifiedDumpable(targettab));
- /* corner case for zero-column table */
- if (nfields == 0)
- {
- appendPQExpBufferStr(insertStmt, "DEFAULT VALUES;\n");
- }
- else
+ /* corner case for zero-column table */
+ if (nfields == 0)
+ {
+ appendPQExpBufferStr(insertStmt, "DEFAULT VALUES;\n");
+ }
+ else
+ {
+ /* append the list of column names if required */
+ if (dopt->column_inserts)
{
- /* append the list of column names if required */
- if (dopt->column_inserts)
+ appendPQExpBufferChar(insertStmt, '(');
+ for (int field = 0; field < nfields; field++)
{
- appendPQExpBufferChar(insertStmt, '(');
- for (field = 0; field < nfields; field++)
- {
- if (field > 0)
- appendPQExpBufferStr(insertStmt, ", ");
- appendPQExpBufferStr(insertStmt,
- fmtId(PQfname(res, field)));
- }
- appendPQExpBufferStr(insertStmt, ") ");
+ if (field > 0)
+ appendPQExpBufferStr(insertStmt, ", ");
+ appendPQExpBufferStr(insertStmt,
+ fmtId(PQfname(res, field)));
}
+ appendPQExpBufferStr(insertStmt, ") ");
+ }
- if (tbinfo->needs_override)
- appendPQExpBufferStr(insertStmt, "OVERRIDING SYSTEM VALUE ");
+ if (tbinfo->needs_override)
+ appendPQExpBufferStr(insertStmt, "OVERRIDING SYSTEM VALUE ");
- appendPQExpBufferStr(insertStmt, "VALUES (");
- }
+ appendPQExpBufferStr(insertStmt, "VALUES");
}
+ }
- archputs(insertStmt->data, fout);
+ for (int tuple = 0; tuple < PQntuples(res); tuple++)
+ {
+ /* Write the INSERT if not in the middle of a multi-row INSERT. */
+ if (rows_this_statement == 0)
+ archputs(insertStmt->data, fout);
- /* if it is zero-column table then we're done */
+ /*
+ * If it is zero-column table then we've already written the
+ * complete statement, which will mean we've disobeyed
+ * --rows-per-insert when it's set greater than 1. We do support
+ * a way to make this multi-row with: SELECT UNION ALL SELECT
+ * UNION ALL ... but that's non-standard so we should avoid it
+ * given that using INSERTs is mostly only ever needed for
+ * cross-database exports.
+ */
if (nfields == 0)
continue;
- for (field = 0; field < nfields; field++)
+ /* Emit a row heading */
+ if (rows_per_statement == 1)
+ archputs(" (", fout);
+ else if (rows_this_statement > 0)
+ archputs(",\n\t(", fout);
+ else
+ archputs("\n\t(", fout);
+
+ for (int field = 0; field < nfields; field++)
{
if (field > 0)
archputs(", ", fout);
+ if (tbinfo->attgenerated[field])
+ {
+ archputs("DEFAULT", fout);
+ continue;
+ }
if (PQgetisnull(res, tuple, field))
{
archputs("NULL", fout);
break;
}
}
- archputs(");\n", fout);
+
+ /* Terminate the row ... */
+ archputs(")", fout);
+
+ /* ... and the statement, if the target no. of rows is reached */
+ if (++rows_this_statement >= rows_per_statement)
+ {
+ if (dopt->do_nothing)
+ archputs(" ON CONFLICT DO NOTHING;\n", fout);
+ else
+ archputs(";\n", fout);
+ /* Reset the row counter */
+ rows_this_statement = 0;
+ }
}
if (PQntuples(res) <= 0)
PQclear(res);
}
+ /* Terminate any statements that didn't make the row count. */
+ if (rows_this_statement > 0)
+ {
+ if (dopt->do_nothing)
+ archputs(" ON CONFLICT DO NOTHING;\n", fout);
+ else
+ archputs(";\n", fout);
+ }
+
archputs("\n\n", fout);
ExecuteSqlStatement(fout, "CLOSE _pg_dump_cursor");
TableInfo *parentTbinfo;
parentTbinfo = getRootTableInfo(tbinfo);
-
- /*
- * When we load data through the root, we will qualify the table
- * name, because search_path is set for the partition.
- */
- copyFrom = fmtQualifiedId(fout->remoteVersion,
- parentTbinfo->dobj.namespace->dobj.name,
- parentTbinfo->dobj.name);
+ copyFrom = fmtQualifiedDumpable(parentTbinfo);
}
else
- copyFrom = fmtId(tbinfo->dobj.name);
+ copyFrom = fmtQualifiedDumpable(tbinfo);
/* must use 2 steps here 'cause fmtId is nonreentrant */
appendPQExpBuffer(copyBuf, "COPY %s ",
copyFrom);
- appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n",
- fmtCopyColumnList(tbinfo, clistBuf),
- (tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "");
+ appendPQExpBuffer(copyBuf, "%s FROM stdin;\n",
+ fmtCopyColumnList(tbinfo, clistBuf));
copyStmt = copyBuf->data;
}
else
* See comments for BuildArchiveDependencies.
*/
if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
- ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
- tbinfo->dobj.name, tbinfo->dobj.namespace->dobj.name,
- NULL, tbinfo->rolname,
- false, "TABLE DATA", SECTION_DATA,
- "", "", copyStmt,
- &(tbinfo->dobj.dumpId), 1,
- dumpFn, tdinfo);
+ {
+ TocEntry *te;
+
+ te = ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
+ ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "TABLE DATA",
+ .section = SECTION_DATA,
+ .copyStmt = copyStmt,
+ .deps = &(tbinfo->dobj.dumpId),
+ .nDeps = 1,
+ .dumpFn = dumpFn,
+ .dumpArg = tdinfo));
+
+ /*
+ * Set the TocEntry's dataLength in case we are doing a parallel dump
+ * and want to order dump jobs by table size. We choose to measure
+ * dataLength in table pages during dump, so no scaling is needed.
+ * However, relpages is declared as "integer" in pg_class, and hence
+ * also in TableInfo, but it's really BlockNumber a/k/a unsigned int.
+ * Cast so that we get the right interpretation of table sizes
+ * exceeding INT_MAX pages.
+ */
+ te->dataLength = (BlockNumber) tbinfo->relpages;
+ }
destroyPQExpBuffer(copyBuf);
destroyPQExpBuffer(clistBuf);
q = createPQExpBuffer();
appendPQExpBuffer(q, "REFRESH MATERIALIZED VIEW %s;\n",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
ArchiveEntry(fout,
tdinfo->dobj.catId, /* catalog ID */
tdinfo->dobj.dumpId, /* dump ID */
- tbinfo->dobj.name, /* Name */
- tbinfo->dobj.namespace->dobj.name, /* Namespace */
- NULL, /* Tablespace */
- tbinfo->rolname, /* Owner */
- false, /* with oids */
- "MATERIALIZED VIEW DATA", /* Desc */
- SECTION_POST_DATA, /* Section */
- q->data, /* Create */
- "", /* Del */
- NULL, /* Copy */
- tdinfo->dobj.dependencies, /* Deps */
- tdinfo->dobj.nDeps, /* # Deps */
- NULL, /* Dumper */
- NULL); /* Dumper Arg */
+ ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "MATERIALIZED VIEW DATA",
+ .section = SECTION_POST_DATA,
+ .createStmt = q->data,
+ .deps = tdinfo->dobj.dependencies,
+ .nDeps = tdinfo->dobj.nDeps));
destroyPQExpBuffer(q);
}
* set up dumpable objects representing the contents of tables
*/
static void
-getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, bool oids, char relkind)
+getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind)
{
int i;
{
if (tblinfo[i].dobj.dump & DUMP_COMPONENT_DATA &&
(!relkind || tblinfo[i].relkind == relkind))
- makeTableDataInfo(dopt, &(tblinfo[i]), oids);
+ makeTableDataInfo(dopt, &(tblinfo[i]));
}
}
* table data; the "dump" flag in such objects isn't used.
*/
static void
-makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo, bool oids)
+makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo)
{
TableDataInfo *tdinfo;
tdinfo->dobj.name = tbinfo->dobj.name;
tdinfo->dobj.namespace = tbinfo->dobj.namespace;
tdinfo->tdtable = tbinfo;
- tdinfo->oids = oids;
tdinfo->filtercond = NULL; /* might get set later */
addObjectDependency(&tdinfo->dobj, tbinfo->dobj.dumpId);
if (fout->remoteVersion < 90300)
return;
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
query = createPQExpBuffer();
appendPQExpBufferStr(query, "WITH RECURSIVE w AS "
* In 8.4 and up we can rely on the conislocal field to decide which
* constraints must be dumped; much safer.
*
- * This function assumes all conislocal flags were initialized to TRUE.
+ * This function assumes all conislocal flags were initialized to true.
* It clears the flag on anything that seems to be inherited.
*/
static void
PQExpBuffer dbQry = createPQExpBuffer();
PQExpBuffer delQry = createPQExpBuffer();
PQExpBuffer creaQry = createPQExpBuffer();
+ PQExpBuffer labelq = createPQExpBuffer();
PGconn *conn = GetConnection(fout);
PGresult *res;
int i_tableoid,
i_oid,
+ i_datname,
i_dba,
i_encoding,
i_collate,
i_ctype,
i_frozenxid,
i_minmxid,
+ i_datacl,
+ i_rdatacl,
+ i_datistemplate,
+ i_datconnlimit,
i_tablespace;
CatalogId dbCatId;
DumpId dbDumpId;
*encoding,
*collate,
*ctype,
+ *datacl,
+ *rdatacl,
+ *datistemplate,
+ *datconnlimit,
*tablespace;
uint32 frozenxid,
minmxid;
+ char *qdatname;
- datname = PQdb(conn);
-
- if (g_verbose)
- write_msg(NULL, "saving database definition\n");
+ pg_log_info("saving database definition");
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
+ /*
+ * Fetch the database-level properties for this database.
+ *
+ * The order in which privileges are in the ACL string (the order they
+ * have been GRANT'd in, which the backend maintains) must be preserved to
+ * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on
+ * those are dumped in the correct order. Note that initial privileges
+ * (pg_init_privs) are not supported on databases, so this logic cannot
+ * make use of buildACLQueries().
+ */
+ if (fout->remoteVersion >= 90600)
+ {
+ appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
+ "(%s datdba) AS dba, "
+ "pg_encoding_to_char(encoding) AS encoding, "
+ "datcollate, datctype, datfrozenxid, datminmxid, "
+ "(SELECT array_agg(acl ORDER BY row_n) FROM "
+ " (SELECT acl, row_n FROM "
+ " unnest(coalesce(datacl,acldefault('d',datdba))) "
+ " WITH ORDINALITY AS perm(acl,row_n) "
+ " WHERE NOT EXISTS ( "
+ " SELECT 1 "
+ " FROM unnest(acldefault('d',datdba)) "
+ " AS init(init_acl) "
+ " WHERE acl = init_acl)) AS datacls) "
+ " AS datacl, "
+ "(SELECT array_agg(acl ORDER BY row_n) FROM "
+ " (SELECT acl, row_n FROM "
+ " unnest(acldefault('d',datdba)) "
+ " WITH ORDINALITY AS initp(acl,row_n) "
+ " WHERE NOT EXISTS ( "
+ " SELECT 1 "
+ " FROM unnest(coalesce(datacl,acldefault('d',datdba))) "
+ " AS permp(orig_acl) "
+ " WHERE acl = orig_acl)) AS rdatacls) "
+ " AS rdatacl, "
+ "datistemplate, datconnlimit, "
+ "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
+ "shobj_description(oid, 'pg_database') AS description "
- /* Get the database owner and parameters from pg_database */
- if (fout->remoteVersion >= 90300)
+ "FROM pg_database "
+ "WHERE datname = current_database()",
+ username_subquery);
+ }
+ else if (fout->remoteVersion >= 90300)
{
- appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+ appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
"(%s datdba) AS dba, "
"pg_encoding_to_char(encoding) AS encoding, "
"datcollate, datctype, datfrozenxid, datminmxid, "
+ "datacl, '' as rdatacl, datistemplate, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
"shobj_description(oid, 'pg_database') AS description "
"FROM pg_database "
- "WHERE datname = ",
+ "WHERE datname = current_database()",
username_subquery);
- appendStringLiteralAH(dbQry, datname, fout);
}
else if (fout->remoteVersion >= 80400)
{
- appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+ appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
"(%s datdba) AS dba, "
"pg_encoding_to_char(encoding) AS encoding, "
"datcollate, datctype, datfrozenxid, 0 AS datminmxid, "
+ "datacl, '' as rdatacl, datistemplate, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
"shobj_description(oid, 'pg_database') AS description "
"FROM pg_database "
- "WHERE datname = ",
+ "WHERE datname = current_database()",
username_subquery);
- appendStringLiteralAH(dbQry, datname, fout);
}
else if (fout->remoteVersion >= 80200)
{
- appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+ appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
"(%s datdba) AS dba, "
"pg_encoding_to_char(encoding) AS encoding, "
"NULL AS datcollate, NULL AS datctype, datfrozenxid, 0 AS datminmxid, "
+ "datacl, '' as rdatacl, datistemplate, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
"shobj_description(oid, 'pg_database') AS description "
"FROM pg_database "
- "WHERE datname = ",
+ "WHERE datname = current_database()",
username_subquery);
- appendStringLiteralAH(dbQry, datname, fout);
}
else
{
- appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+ appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
"(%s datdba) AS dba, "
"pg_encoding_to_char(encoding) AS encoding, "
"NULL AS datcollate, NULL AS datctype, datfrozenxid, 0 AS datminmxid, "
+ "datacl, '' as rdatacl, datistemplate, "
+ "-1 as datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace "
"FROM pg_database "
- "WHERE datname = ",
+ "WHERE datname = current_database()",
username_subquery);
- appendStringLiteralAH(dbQry, datname, fout);
}
res = ExecuteSqlQueryForSingleRow(fout, dbQry->data);
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
+ i_datname = PQfnumber(res, "datname");
i_dba = PQfnumber(res, "dba");
i_encoding = PQfnumber(res, "encoding");
i_collate = PQfnumber(res, "datcollate");
i_ctype = PQfnumber(res, "datctype");
i_frozenxid = PQfnumber(res, "datfrozenxid");
i_minmxid = PQfnumber(res, "datminmxid");
+ i_datacl = PQfnumber(res, "datacl");
+ i_rdatacl = PQfnumber(res, "rdatacl");
+ i_datistemplate = PQfnumber(res, "datistemplate");
+ i_datconnlimit = PQfnumber(res, "datconnlimit");
i_tablespace = PQfnumber(res, "tablespace");
dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid));
dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid));
+ datname = PQgetvalue(res, 0, i_datname);
dba = PQgetvalue(res, 0, i_dba);
encoding = PQgetvalue(res, 0, i_encoding);
collate = PQgetvalue(res, 0, i_collate);
ctype = PQgetvalue(res, 0, i_ctype);
frozenxid = atooid(PQgetvalue(res, 0, i_frozenxid));
minmxid = atooid(PQgetvalue(res, 0, i_minmxid));
+ datacl = PQgetvalue(res, 0, i_datacl);
+ rdatacl = PQgetvalue(res, 0, i_rdatacl);
+ datistemplate = PQgetvalue(res, 0, i_datistemplate);
+ datconnlimit = PQgetvalue(res, 0, i_datconnlimit);
tablespace = PQgetvalue(res, 0, i_tablespace);
+ qdatname = pg_strdup(fmtId(datname));
+
+ /*
+ * Prepare the CREATE DATABASE command. We must specify encoding, locale,
+ * and tablespace since those can't be altered later. Other DB properties
+ * are left to the DATABASE PROPERTIES entry, so that they can be applied
+ * after reconnecting to the target DB.
+ */
appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0",
- fmtId(datname));
+ qdatname);
if (strlen(encoding) > 0)
{
appendPQExpBufferStr(creaQry, " ENCODING = ");
appendStringLiteralAH(creaQry, encoding, fout);
}
- if (strlen(collate) > 0)
+ if (strlen(collate) > 0 && strcmp(collate, ctype) == 0)
{
- appendPQExpBufferStr(creaQry, " LC_COLLATE = ");
+ appendPQExpBufferStr(creaQry, " LOCALE = ");
appendStringLiteralAH(creaQry, collate, fout);
}
- if (strlen(ctype) > 0)
+ else
{
- appendPQExpBufferStr(creaQry, " LC_CTYPE = ");
- appendStringLiteralAH(creaQry, ctype, fout);
+ if (strlen(collate) > 0)
+ {
+ appendPQExpBufferStr(creaQry, " LC_COLLATE = ");
+ appendStringLiteralAH(creaQry, collate, fout);
+ }
+ if (strlen(ctype) > 0)
+ {
+ appendPQExpBufferStr(creaQry, " LC_CTYPE = ");
+ appendStringLiteralAH(creaQry, ctype, fout);
+ }
}
+
+ /*
+ * Note: looking at dopt->outputNoTablespaces here is completely the wrong
+ * thing; the decision whether to specify a tablespace should be left till
+ * pg_restore, so that pg_restore --no-tablespaces applies. Ideally we'd
+ * label the DATABASE entry with the tablespace and let the normal
+ * tablespace selection logic work ... but CREATE DATABASE doesn't pay
+ * attention to default_tablespace, so that won't work.
+ */
if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0 &&
!dopt->outputNoTablespaces)
appendPQExpBuffer(creaQry, " TABLESPACE = %s",
fmtId(tablespace));
appendPQExpBufferStr(creaQry, ";\n");
+ appendPQExpBuffer(delQry, "DROP DATABASE %s;\n",
+ qdatname);
+
+ dbDumpId = createDumpId();
+
+ ArchiveEntry(fout,
+ dbCatId, /* catalog ID */
+ dbDumpId, /* dump ID */
+ ARCHIVE_OPTS(.tag = datname,
+ .owner = dba,
+ .description = "DATABASE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = creaQry->data,
+ .dropStmt = delQry->data));
+
+ /* Compute correct tag for archive entry */
+ appendPQExpBuffer(labelq, "DATABASE %s", qdatname);
+
+ /* Dump DB comment if any */
+ if (fout->remoteVersion >= 80200)
+ {
+ /*
+ * 8.2 and up keep comments on shared objects in a shared table, so we
+ * cannot use the dumpComment() code used for other database objects.
+ * Be careful that the ArchiveEntry parameters match that function.
+ */
+ char *comment = PQgetvalue(res, 0, PQfnumber(res, "description"));
+
+ if (comment && *comment && !dopt->no_comments)
+ {
+ resetPQExpBuffer(dbQry);
+
+ /*
+ * Generates warning when loaded into a differently-named
+ * database.
+ */
+ appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", qdatname);
+ appendStringLiteralAH(dbQry, comment, fout);
+ appendPQExpBufferStr(dbQry, ";\n");
+
+ ArchiveEntry(fout, nilCatalogId, createDumpId(),
+ ARCHIVE_OPTS(.tag = labelq->data,
+ .owner = dba,
+ .description = "COMMENT",
+ .section = SECTION_NONE,
+ .createStmt = dbQry->data,
+ .deps = &dbDumpId,
+ .nDeps = 1));
+ }
+ }
+ else
+ {
+ dumpComment(fout, "DATABASE", qdatname, NULL, dba,
+ dbCatId, 0, dbDumpId);
+ }
+
+ /* Dump DB security label, if enabled */
+ if (!dopt->no_security_labels && fout->remoteVersion >= 90200)
+ {
+ PGresult *shres;
+ PQExpBuffer seclabelQry;
+
+ seclabelQry = createPQExpBuffer();
+
+ buildShSecLabelQuery(conn, "pg_database", dbCatId.oid, seclabelQry);
+ shres = ExecuteSqlQuery(fout, seclabelQry->data, PGRES_TUPLES_OK);
+ resetPQExpBuffer(seclabelQry);
+ emitShSecLabels(conn, shres, seclabelQry, "DATABASE", datname);
+ if (seclabelQry->len > 0)
+ ArchiveEntry(fout, nilCatalogId, createDumpId(),
+ ARCHIVE_OPTS(.tag = labelq->data,
+ .owner = dba,
+ .description = "SECURITY LABEL",
+ .section = SECTION_NONE,
+ .createStmt = seclabelQry->data,
+ .deps = &dbDumpId,
+ .nDeps = 1));
+ destroyPQExpBuffer(seclabelQry);
+ PQclear(shres);
+ }
+
+ /*
+ * Dump ACL if any. Note that we do not support initial privileges
+ * (pg_init_privs) on databases.
+ */
+ dumpACL(fout, dbCatId, dbDumpId, "DATABASE",
+ qdatname, NULL, NULL,
+ dba, datacl, rdatacl, "", "");
+
+ /*
+ * Now construct a DATABASE PROPERTIES archive entry to restore any
+ * non-default database-level properties. (The reason this must be
+ * separate is that we cannot put any additional commands into the TOC
+ * entry that has CREATE DATABASE. pg_restore would execute such a group
+ * in an implicit transaction block, and the backend won't allow CREATE
+ * DATABASE in that context.)
+ */
+ resetPQExpBuffer(creaQry);
+ resetPQExpBuffer(delQry);
+
+ if (strlen(datconnlimit) > 0 && strcmp(datconnlimit, "-1") != 0)
+ appendPQExpBuffer(creaQry, "ALTER DATABASE %s CONNECTION LIMIT = %s;\n",
+ qdatname, datconnlimit);
+
+ if (strcmp(datistemplate, "t") == 0)
+ {
+ appendPQExpBuffer(creaQry, "ALTER DATABASE %s IS_TEMPLATE = true;\n",
+ qdatname);
+
+ /*
+ * The backend won't accept DROP DATABASE on a template database. We
+ * can deal with that by removing the template marking before the DROP
+ * gets issued. We'd prefer to use ALTER DATABASE IF EXISTS here, but
+ * since no such command is currently supported, fake it with a direct
+ * UPDATE on pg_database.
+ */
+ appendPQExpBufferStr(delQry, "UPDATE pg_catalog.pg_database "
+ "SET datistemplate = false WHERE datname = ");
+ appendStringLiteralAH(delQry, datname, fout);
+ appendPQExpBufferStr(delQry, ";\n");
+ }
+
+ /* Add database-specific SET options */
+ dumpDatabaseConfig(fout, creaQry, datname, dbCatId.oid);
+
+ /*
+ * We stick this binary-upgrade query into the DATABASE PROPERTIES archive
+ * entry, too, for lack of a better place.
+ */
if (dopt->binary_upgrade)
{
appendPQExpBufferStr(creaQry, "\n-- For binary upgrade, set datfrozenxid and datminmxid.\n");
frozenxid, minmxid);
appendStringLiteralAH(creaQry, datname, fout);
appendPQExpBufferStr(creaQry, ";\n");
-
}
- appendPQExpBuffer(delQry, "DROP DATABASE %s;\n",
- fmtId(datname));
-
- dbDumpId = createDumpId();
-
- ArchiveEntry(fout,
- dbCatId, /* catalog ID */
- dbDumpId, /* dump ID */
- datname, /* Name */
- NULL, /* Namespace */
- NULL, /* Tablespace */
- dba, /* Owner */
- false, /* with oids */
- "DATABASE", /* Desc */
- SECTION_PRE_DATA, /* Section */
- creaQry->data, /* Create */
- delQry->data, /* Del */
- NULL, /* Copy */
- NULL, /* Deps */
- 0, /* # Deps */
- NULL, /* Dumper */
- NULL); /* Dumper Arg */
+ if (creaQry->len > 0)
+ ArchiveEntry(fout, nilCatalogId, createDumpId(),
+ ARCHIVE_OPTS(.tag = datname,
+ .owner = dba,
+ .description = "DATABASE PROPERTIES",
+ .section = SECTION_PRE_DATA,
+ .createStmt = creaQry->data,
+ .dropStmt = delQry->data,
+ .deps = &dbDumpId));
/*
- * pg_largeobject and pg_largeobject_metadata come from the old system
- * intact, so set their relfrozenxids and relminmxids.
+ * pg_largeobject comes from the old system intact, so set its
+ * relfrozenxids and relminmxids.
*/
if (dopt->binary_upgrade)
{
appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n"
"SET relfrozenxid = '%u', relminmxid = '%u'\n"
"WHERE oid = %u;\n",
- atoi(PQgetvalue(lo_res, 0, i_relfrozenxid)),
- atoi(PQgetvalue(lo_res, 0, i_relminmxid)),
+ atooid(PQgetvalue(lo_res, 0, i_relfrozenxid)),
+ atooid(PQgetvalue(lo_res, 0, i_relminmxid)),
LargeObjectRelationId);
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- "pg_largeobject", NULL, NULL, "",
- false, "pg_largeobject", SECTION_PRE_DATA,
- loOutQry->data, "", NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = "pg_largeobject",
+ .description = "pg_largeobject",
+ .section = SECTION_PRE_DATA,
+ .createStmt = loOutQry->data));
PQclear(lo_res);
- /*
- * pg_largeobject_metadata
- */
- if (fout->remoteVersion >= 90000)
- {
- resetPQExpBuffer(loFrozenQry);
- resetPQExpBuffer(loOutQry);
-
- if (fout->remoteVersion >= 90300)
- appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, relminmxid\n"
- "FROM pg_catalog.pg_class\n"
- "WHERE oid = %u;\n",
- LargeObjectMetadataRelationId);
- else
- appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, 0 AS relminmxid\n"
- "FROM pg_catalog.pg_class\n"
- "WHERE oid = %u;\n",
- LargeObjectMetadataRelationId);
-
- lo_res = ExecuteSqlQueryForSingleRow(fout, loFrozenQry->data);
-
- i_relfrozenxid = PQfnumber(lo_res, "relfrozenxid");
- i_relminmxid = PQfnumber(lo_res, "relminmxid");
-
- appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, set pg_largeobject_metadata relfrozenxid and relminmxid\n");
- appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n"
- "SET relfrozenxid = '%u', relminmxid = '%u'\n"
- "WHERE oid = %u;\n",
- atoi(PQgetvalue(lo_res, 0, i_relfrozenxid)),
- atoi(PQgetvalue(lo_res, 0, i_relminmxid)),
- LargeObjectMetadataRelationId);
- ArchiveEntry(fout, nilCatalogId, createDumpId(),
- "pg_largeobject_metadata", NULL, NULL, "",
- false, "pg_largeobject_metadata", SECTION_PRE_DATA,
- loOutQry->data, "", NULL,
- NULL, 0,
- NULL, NULL);
-
- PQclear(lo_res);
- }
-
destroyPQExpBuffer(loFrozenQry);
destroyPQExpBuffer(loOutQry);
}
- /* Dump DB comment if any */
- if (fout->remoteVersion >= 80200)
- {
- /*
- * 8.2 keeps comments on shared objects in a shared table, so we
- * cannot use the dumpComment used for other database objects.
- */
- char *comment = PQgetvalue(res, 0, PQfnumber(res, "description"));
+ PQclear(res);
- if (comment && strlen(comment))
- {
- resetPQExpBuffer(dbQry);
+ free(qdatname);
+ destroyPQExpBuffer(dbQry);
+ destroyPQExpBuffer(delQry);
+ destroyPQExpBuffer(creaQry);
+ destroyPQExpBuffer(labelq);
+}
- /*
- * Generates warning when loaded into a differently-named
- * database.
- */
- appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
- appendStringLiteralAH(dbQry, comment, fout);
- appendPQExpBufferStr(dbQry, ";\n");
+/*
+ * Collect any database-specific or role-and-database-specific SET options
+ * for this database, and append them to outbuf.
+ */
+static void
+dumpDatabaseConfig(Archive *AH, PQExpBuffer outbuf,
+ const char *dbname, Oid dboid)
+{
+ PGconn *conn = GetConnection(AH);
+ PQExpBuffer buf = createPQExpBuffer();
+ PGresult *res;
+ int count = 1;
- ArchiveEntry(fout, dbCatId, createDumpId(), datname, NULL, NULL,
- dba, false, "COMMENT", SECTION_NONE,
- dbQry->data, "", NULL,
- &dbDumpId, 1, NULL, NULL);
- }
- }
- else
+ /*
+ * First collect database-specific options. Pre-8.4 server versions lack
+ * unnest(), so we do this the hard way by querying once per subscript.
+ */
+ for (;;)
{
- resetPQExpBuffer(dbQry);
- appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
- dumpComment(fout, dbQry->data, NULL, "",
- dbCatId, 0, dbDumpId);
+ if (AH->remoteVersion >= 90000)
+ printfPQExpBuffer(buf, "SELECT setconfig[%d] FROM pg_db_role_setting "
+ "WHERE setrole = 0 AND setdatabase = '%u'::oid",
+ count, dboid);
+ else
+ printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE oid = '%u'::oid", count, dboid);
+
+ res = ExecuteSqlQuery(AH, buf->data, PGRES_TUPLES_OK);
+
+ if (PQntuples(res) == 1 &&
+ !PQgetisnull(res, 0, 0))
+ {
+ makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
+ "DATABASE", dbname, NULL, NULL,
+ outbuf);
+ PQclear(res);
+ count++;
+ }
+ else
+ {
+ PQclear(res);
+ break;
+ }
}
- /* Dump shared security label. */
- if (!dopt->no_security_labels && fout->remoteVersion >= 90200)
+ /* Now look for role-and-database-specific options */
+ if (AH->remoteVersion >= 90000)
{
- PGresult *shres;
- PQExpBuffer seclabelQry;
+ /* Here we can assume we have unnest() */
+ printfPQExpBuffer(buf, "SELECT rolname, unnest(setconfig) "
+ "FROM pg_db_role_setting s, pg_roles r "
+ "WHERE setrole = r.oid AND setdatabase = '%u'::oid",
+ dboid);
- seclabelQry = createPQExpBuffer();
+ res = ExecuteSqlQuery(AH, buf->data, PGRES_TUPLES_OK);
- buildShSecLabelQuery(conn, "pg_database", dbCatId.oid, seclabelQry);
- shres = ExecuteSqlQuery(fout, seclabelQry->data, PGRES_TUPLES_OK);
- resetPQExpBuffer(seclabelQry);
- emitShSecLabels(conn, shres, seclabelQry, "DATABASE", datname);
- if (strlen(seclabelQry->data))
- ArchiveEntry(fout, dbCatId, createDumpId(), datname, NULL, NULL,
- dba, false, "SECURITY LABEL", SECTION_NONE,
- seclabelQry->data, "", NULL,
- &dbDumpId, 1, NULL, NULL);
- destroyPQExpBuffer(seclabelQry);
- PQclear(shres);
- }
+ if (PQntuples(res) > 0)
+ {
+ int i;
- PQclear(res);
+ for (i = 0; i < PQntuples(res); i++)
+ makeAlterConfigCommand(conn, PQgetvalue(res, i, 1),
+ "ROLE", PQgetvalue(res, i, 0),
+ "DATABASE", dbname,
+ outbuf);
+ }
- destroyPQExpBuffer(dbQry);
- destroyPQExpBuffer(delQry);
- destroyPQExpBuffer(creaQry);
+ PQclear(res);
+ }
+
+ destroyPQExpBuffer(buf);
}
/*
const char *encname = pg_encoding_to_char(AH->encoding);
PQExpBuffer qry = createPQExpBuffer();
- if (g_verbose)
- write_msg(NULL, "saving encoding = %s\n", encname);
+ pg_log_info("saving encoding = %s", encname);
appendPQExpBufferStr(qry, "SET client_encoding = ");
appendStringLiteralAH(qry, encname, AH);
appendPQExpBufferStr(qry, ";\n");
ArchiveEntry(AH, nilCatalogId, createDumpId(),
- "ENCODING", NULL, NULL, "",
- false, "ENCODING", SECTION_PRE_DATA,
- qry->data, "", NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = "ENCODING",
+ .description = "ENCODING",
+ .section = SECTION_PRE_DATA,
+ .createStmt = qry->data));
destroyPQExpBuffer(qry);
}
const char *stdstrings = AH->std_strings ? "on" : "off";
PQExpBuffer qry = createPQExpBuffer();
- if (g_verbose)
- write_msg(NULL, "saving standard_conforming_strings = %s\n",
- stdstrings);
+ pg_log_info("saving standard_conforming_strings = %s",
+ stdstrings);
appendPQExpBuffer(qry, "SET standard_conforming_strings = '%s';\n",
stdstrings);
ArchiveEntry(AH, nilCatalogId, createDumpId(),
- "STDSTRINGS", NULL, NULL, "",
- false, "STDSTRINGS", SECTION_PRE_DATA,
- qry->data, "", NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = "STDSTRINGS",
+ .description = "STDSTRINGS",
+ .section = SECTION_PRE_DATA,
+ .createStmt = qry->data));
+
+ destroyPQExpBuffer(qry);
+}
+
+/*
+ * dumpSearchPath: record the active search_path in the archive
+ */
+static void
+dumpSearchPath(Archive *AH)
+{
+ PQExpBuffer qry = createPQExpBuffer();
+ PQExpBuffer path = createPQExpBuffer();
+ PGresult *res;
+ char **schemanames = NULL;
+ int nschemanames = 0;
+ int i;
+
+ /*
+ * We use the result of current_schemas(), not the search_path GUC,
+ * because that might contain wildcards such as "$user", which won't
+ * necessarily have the same value during restore. Also, this way avoids
+ * listing schemas that may appear in search_path but not actually exist,
+ * which seems like a prudent exclusion.
+ */
+ res = ExecuteSqlQueryForSingleRow(AH,
+ "SELECT pg_catalog.current_schemas(false)");
+
+ if (!parsePGArray(PQgetvalue(res, 0, 0), &schemanames, &nschemanames))
+ fatal("could not parse result of current_schemas()");
+
+ /*
+ * We use set_config(), not a simple "SET search_path" command, because
+ * the latter has less-clean behavior if the search path is empty. While
+ * that's likely to get fixed at some point, it seems like a good idea to
+ * be as backwards-compatible as possible in what we put into archives.
+ */
+ for (i = 0; i < nschemanames; i++)
+ {
+ if (i > 0)
+ appendPQExpBufferStr(path, ", ");
+ appendPQExpBufferStr(path, fmtId(schemanames[i]));
+ }
+
+ appendPQExpBufferStr(qry, "SELECT pg_catalog.set_config('search_path', ");
+ appendStringLiteralAH(qry, path->data, AH);
+ appendPQExpBufferStr(qry, ", false);\n");
+
+ pg_log_info("saving search_path = %s", path->data);
+
+ ArchiveEntry(AH, nilCatalogId, createDumpId(),
+ ARCHIVE_OPTS(.tag = "SEARCHPATH",
+ .description = "SEARCHPATH",
+ .section = SECTION_PRE_DATA,
+ .createStmt = qry->data));
+ /* Also save it in AH->searchpath, in case we're doing plain text dump */
+ AH->searchpath = pg_strdup(qry->data);
+
+ if (schemanames)
+ free(schemanames);
+ PQclear(res);
destroyPQExpBuffer(qry);
+ destroyPQExpBuffer(path);
}
int i_initlomacl;
int i_initrlomacl;
- /* Verbose message */
- if (g_verbose)
- write_msg(NULL, "reading large objects\n");
-
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
+ pg_log_info("reading large objects");
/* Fetch BLOB OIDs, and owner/ACL data if >= 9.0 */
if (fout->remoteVersion >= 90600)
binfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
/*
- * In binary-upgrade mode for blobs, we do *not* dump out the data or
- * the ACLs, should any exist. The data and ACL (if any) will be
- * copied by pg_upgrade, which simply copies the pg_largeobject and
- * pg_largeobject_metadata tables.
- *
- * We *do* dump out the definition of the blob because we need that to
- * make the restoration of the comments, and anything else, work since
- * pg_upgrade copies the files behind pg_largeobject and
- * pg_largeobject_metadata after the dump is restored.
+ * In binary-upgrade mode for blobs, we do *not* dump out the blob
+ * data, as it will be copied by pg_upgrade, which simply copies the
+ * pg_largeobject table. We *do* however dump out anything but the
+ * data, as pg_upgrade copies just pg_largeobject, but not
+ * pg_largeobject_metadata, after the dump is restored.
*/
if (dopt->binary_upgrade)
- binfo[i].dobj.dump &= ~(DUMP_COMPONENT_DATA | DUMP_COMPONENT_ACL);
+ binfo[i].dobj.dump &= ~DUMP_COMPONENT_DATA;
}
/*
if (binfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, binfo->dobj.catId, binfo->dobj.dumpId,
- binfo->dobj.name,
- NULL, NULL,
- binfo->rolname, false,
- "BLOB", SECTION_PRE_DATA,
- cquery->data, dquery->data, NULL,
- NULL, 0,
- NULL, NULL);
-
- /* set up tag for comment and/or ACL */
- resetPQExpBuffer(cquery);
- appendPQExpBuffer(cquery, "LARGE OBJECT %s", binfo->dobj.name);
+ ARCHIVE_OPTS(.tag = binfo->dobj.name,
+ .owner = binfo->rolname,
+ .description = "BLOB",
+ .section = SECTION_PRE_DATA,
+ .createStmt = cquery->data,
+ .dropStmt = dquery->data));
/* Dump comment if any */
if (binfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, cquery->data,
+ dumpComment(fout, "LARGE OBJECT", binfo->dobj.name,
NULL, binfo->rolname,
binfo->dobj.catId, 0, binfo->dobj.dumpId);
/* Dump security label if any */
if (binfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, cquery->data,
+ dumpSecLabel(fout, "LARGE OBJECT", binfo->dobj.name,
NULL, binfo->rolname,
binfo->dobj.catId, 0, binfo->dobj.dumpId);
/* Dump ACL if any */
if (binfo->blobacl && (binfo->dobj.dump & DUMP_COMPONENT_ACL))
dumpACL(fout, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
- binfo->dobj.name, NULL, cquery->data,
+ binfo->dobj.name, NULL,
NULL, binfo->rolname, binfo->blobacl, binfo->rblobacl,
binfo->initblobacl, binfo->initrblobacl);
int i;
int cnt;
- if (g_verbose)
- write_msg(NULL, "saving large objects\n");
-
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
+ pg_log_info("saving large objects");
/*
* Currently, we re-fetch all BLOB OIDs using a cursor. Consider scanning
* the already-in-memory dumpable objects instead...
*/
if (fout->remoteVersion >= 90000)
- blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_largeobject_metadata";
+ blobQry =
+ "DECLARE bloboid CURSOR FOR "
+ "SELECT oid FROM pg_largeobject_metadata ORDER BY 1";
else
- blobQry = "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
+ blobQry =
+ "DECLARE bloboid CURSOR FOR "
+ "SELECT DISTINCT loid FROM pg_largeobject ORDER BY 1";
ExecuteSqlStatement(fout, blobQry);
/* Open the BLOB */
loFd = lo_open(conn, blobOid, INV_READ);
if (loFd == -1)
- exit_horribly(NULL, "could not open large object %u: %s",
- blobOid, PQerrorMessage(conn));
+ fatal("could not open large object %u: %s",
+ blobOid, PQerrorMessage(conn));
StartBlob(fout, blobOid);
{
cnt = lo_read(conn, loFd, buf, LOBBUFSIZE);
if (cnt < 0)
- exit_horribly(NULL, "error reading large object %u: %s",
- blobOid, PQerrorMessage(conn));
+ fatal("error reading large object %u: %s",
+ blobOid, PQerrorMessage(conn));
WriteData(fout, buf, cnt);
} while (cnt > 0);
if (!(tbinfo->dobj.dump & DUMP_COMPONENT_POLICY))
continue;
- if (g_verbose)
- write_msg(NULL, "reading row security enabled for table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
+ pg_log_info("reading row security enabled for table \"%s.%s\"",
+ tbinfo->dobj.namespace->dobj.name,
+ tbinfo->dobj.name);
/*
* Get row security enabled information for the table. We represent
- * RLS enabled on a table by creating PolicyInfo object with an empty
- * policy.
+ * RLS being enabled on a table by creating a PolicyInfo object with
+ * null polname.
*/
if (tbinfo->rowsec)
{
polinfo->polwithcheck = NULL;
}
- if (g_verbose)
- write_msg(NULL, "reading policies for table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
-
- /*
- * select table schema to ensure regproc name is qualified if needed
- */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+ pg_log_info("reading policies for table \"%s.%s\"",
+ tbinfo->dobj.namespace->dobj.name,
+ tbinfo->dobj.name);
resetPQExpBuffer(query);
query = createPQExpBuffer();
appendPQExpBuffer(query, "ALTER TABLE %s ENABLE ROW LEVEL SECURITY;",
- fmtId(polinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
+ /*
+ * We must emit the ROW SECURITY object's dependency on its table
+ * explicitly, because it will not match anything in pg_depend (unlike
+ * the case for other PolicyInfo objects).
+ */
if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
- polinfo->dobj.name,
- polinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname, false,
- "ROW SECURITY", SECTION_POST_DATA,
- query->data, "", NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = polinfo->dobj.name,
+ .namespace = polinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "ROW SECURITY",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .deps = &(tbinfo->dobj.dumpId),
+ .nDeps = 1));
destroyPQExpBuffer(query);
return;
cmd = " FOR DELETE";
else
{
- write_msg(NULL, "unexpected policy command type: %c\n",
- polinfo->polcmd);
+ pg_log_error("unexpected policy command type: %c",
+ polinfo->polcmd);
exit_nicely(1);
}
appendPQExpBuffer(query, "CREATE POLICY %s", fmtId(polinfo->polname));
- appendPQExpBuffer(query, " ON %s%s%s", fmtId(tbinfo->dobj.name),
+ appendPQExpBuffer(query, " ON %s%s%s", fmtQualifiedDumpable(tbinfo),
!polinfo->polpermissive ? " AS RESTRICTIVE" : "", cmd);
if (polinfo->polroles != NULL)
if (polinfo->polwithcheck != NULL)
appendPQExpBuffer(query, " WITH CHECK (%s)", polinfo->polwithcheck);
- appendPQExpBuffer(query, ";\n");
+ appendPQExpBufferStr(query, ";\n");
appendPQExpBuffer(delqry, "DROP POLICY %s", fmtId(polinfo->polname));
- appendPQExpBuffer(delqry, " ON %s;\n", fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delqry, " ON %s;\n", fmtQualifiedDumpable(tbinfo));
tag = psprintf("%s %s", tbinfo->dobj.name, polinfo->dobj.name);
if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
- tag,
- polinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname, false,
- "POLICY", SECTION_POST_DATA,
- query->data, delqry->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = polinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "POLICY",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .dropStmt = delqry->data));
free(tag);
destroyPQExpBuffer(query);
int i_pubinsert;
int i_pubupdate;
int i_pubdelete;
+ int i_pubtruncate;
int i,
ntups;
resetPQExpBuffer(query);
/* Get the publications. */
- appendPQExpBuffer(query,
- "SELECT p.tableoid, p.oid, p.pubname, "
- "(%s p.pubowner) AS rolname, "
- "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete "
- "FROM pg_catalog.pg_publication p",
- username_subquery);
+ if (fout->remoteVersion >= 110000)
+ appendPQExpBuffer(query,
+ "SELECT p.tableoid, p.oid, p.pubname, "
+ "(%s p.pubowner) AS rolname, "
+ "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate "
+ "FROM pg_publication p",
+ username_subquery);
+ else
+ appendPQExpBuffer(query,
+ "SELECT p.tableoid, p.oid, p.pubname, "
+ "(%s p.pubowner) AS rolname, "
+ "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate "
+ "FROM pg_publication p",
+ username_subquery);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
i_pubinsert = PQfnumber(res, "pubinsert");
i_pubupdate = PQfnumber(res, "pubupdate");
i_pubdelete = PQfnumber(res, "pubdelete");
+ i_pubtruncate = PQfnumber(res, "pubtruncate");
pubinfo = pg_malloc(ntups * sizeof(PublicationInfo));
(strcmp(PQgetvalue(res, i, i_pubupdate), "t") == 0);
pubinfo[i].pubdelete =
(strcmp(PQgetvalue(res, i, i_pubdelete), "t") == 0);
+ pubinfo[i].pubtruncate =
+ (strcmp(PQgetvalue(res, i, i_pubtruncate), "t") == 0);
if (strlen(pubinfo[i].rolname) == 0)
- write_msg(NULL, "WARNING: owner of publication \"%s\" appears to be invalid\n",
- pubinfo[i].dobj.name);
+ pg_log_warning("owner of publication \"%s\" appears to be invalid",
+ pubinfo[i].dobj.name);
/* Decide whether we want to dump it */
selectDumpableObject(&(pubinfo[i].dobj), fout);
{
PQExpBuffer delq;
PQExpBuffer query;
- PQExpBuffer labelq;
+ char *qpubname;
bool first = true;
if (!(pubinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
delq = createPQExpBuffer();
query = createPQExpBuffer();
- labelq = createPQExpBuffer();
+
+ qpubname = pg_strdup(fmtId(pubinfo->dobj.name));
appendPQExpBuffer(delq, "DROP PUBLICATION %s;\n",
- fmtId(pubinfo->dobj.name));
+ qpubname);
appendPQExpBuffer(query, "CREATE PUBLICATION %s",
- fmtId(pubinfo->dobj.name));
-
- appendPQExpBuffer(labelq, "PUBLICATION %s", fmtId(pubinfo->dobj.name));
+ qpubname);
if (pubinfo->puballtables)
appendPQExpBufferStr(query, " FOR ALL TABLES");
first = false;
}
+ if (pubinfo->pubtruncate)
+ {
+ if (!first)
+ appendPQExpBufferStr(query, ", ");
+
+ appendPQExpBufferStr(query, "truncate");
+ first = false;
+ }
+
appendPQExpBufferStr(query, "');\n");
ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
- pubinfo->dobj.name,
- NULL,
- NULL,
- pubinfo->rolname, false,
- "PUBLICATION", SECTION_POST_DATA,
- query->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = pubinfo->dobj.name,
+ .owner = pubinfo->rolname,
+ .description = "PUBLICATION",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .dropStmt = delq->data));
if (pubinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "PUBLICATION", qpubname,
NULL, pubinfo->rolname,
pubinfo->dobj.catId, 0, pubinfo->dobj.dumpId);
if (pubinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "PUBLICATION", qpubname,
NULL, pubinfo->rolname,
pubinfo->dobj.catId, 0, pubinfo->dobj.dumpId);
destroyPQExpBuffer(delq);
destroyPQExpBuffer(query);
+ free(qpubname);
}
/*
PQExpBuffer query;
PGresult *res;
PublicationRelInfo *pubrinfo;
+ DumpOptions *dopt = fout->dopt;
int i_tableoid;
int i_oid;
int i_pubname;
j,
ntups;
- if (fout->remoteVersion < 100000)
+ if (dopt->no_publications || fout->remoteVersion < 100000)
return;
query = createPQExpBuffer();
if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
continue;
- if (g_verbose)
- write_msg(NULL, "reading publication membership for table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
+ pg_log_info("reading publication membership for table \"%s.%s\"",
+ tbinfo->dobj.namespace->dobj.name,
+ tbinfo->dobj.name);
resetPQExpBuffer(query);
/* Get the publication membership for the table. */
appendPQExpBuffer(query,
"SELECT pr.tableoid, pr.oid, p.pubname "
- "FROM pg_catalog.pg_publication_rel pr,"
- " pg_catalog.pg_publication p "
+ "FROM pg_publication_rel pr, pg_publication p "
"WHERE pr.prrelid = '%u'"
" AND p.oid = pr.prpubid",
tbinfo->dobj.catId.oid);
appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
fmtId(pubrinfo->pubname));
- appendPQExpBuffer(query, " %s;",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(query, " %s;\n",
+ fmtQualifiedDumpable(tbinfo));
/*
- * There is no point in creating drop query as drop query as the drop is
- * done by table drop.
+ * There is no point in creating drop query as the drop is done by table
+ * drop.
*/
ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
- tag,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- "", false,
- "PUBLICATION TABLE", SECTION_POST_DATA,
- query->data, "", NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .description = "PUBLICATION TABLE",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data));
free(tag);
destroyPQExpBuffer(query);
res = ExecuteSqlQuery(fout,
"SELECT count(*) FROM pg_subscription "
- "WHERE subdbid = (SELECT oid FROM pg_catalog.pg_database"
+ "WHERE subdbid = (SELECT oid FROM pg_database"
" WHERE datname = current_database())",
PGRES_TUPLES_OK);
n = atoi(PQgetvalue(res, 0, 0));
if (n > 0)
- write_msg(NULL, "WARNING: subscriptions not dumped because current user is not a superuser\n");
+ pg_log_warning("subscriptions not dumped because current user is not a superuser");
PQclear(res);
return;
}
"(%s s.subowner) AS rolname, "
" s.subconninfo, s.subslotname, s.subsynccommit, "
" s.subpublications "
- "FROM pg_catalog.pg_subscription s "
- "WHERE s.subdbid = (SELECT oid FROM pg_catalog.pg_database"
+ "FROM pg_subscription s "
+ "WHERE s.subdbid = (SELECT oid FROM pg_database"
" WHERE datname = current_database())",
username_subquery);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
pg_strdup(PQgetvalue(res, i, i_subpublications));
if (strlen(subinfo[i].rolname) == 0)
- write_msg(NULL, "WARNING: owner of subscription \"%s\" appears to be invalid\n",
- subinfo[i].dobj.name);
+ pg_log_warning("owner of subscription \"%s\" appears to be invalid",
+ subinfo[i].dobj.name);
/* Decide whether we want to dump it */
selectDumpableObject(&(subinfo[i].dobj), fout);
{
PQExpBuffer delq;
PQExpBuffer query;
- PQExpBuffer labelq;
PQExpBuffer publications;
+ char *qsubname;
char **pubnames = NULL;
int npubnames = 0;
int i;
delq = createPQExpBuffer();
query = createPQExpBuffer();
- labelq = createPQExpBuffer();
+
+ qsubname = pg_strdup(fmtId(subinfo->dobj.name));
appendPQExpBuffer(delq, "DROP SUBSCRIPTION %s;\n",
- fmtId(subinfo->dobj.name));
+ qsubname);
appendPQExpBuffer(query, "CREATE SUBSCRIPTION %s CONNECTION ",
- fmtId(subinfo->dobj.name));
+ qsubname);
appendStringLiteralAH(query, subinfo->subconninfo, fout);
/* Build list of quoted publications and append them to query. */
if (!parsePGArray(subinfo->subpublications, &pubnames, &npubnames))
{
- write_msg(NULL,
- "WARNING: could not parse subpublications array\n");
+ pg_log_warning("could not parse subpublications array");
if (pubnames)
free(pubnames);
pubnames = NULL;
appendPQExpBufferStr(query, ");\n");
- appendPQExpBuffer(labelq, "SUBSCRIPTION %s", fmtId(subinfo->dobj.name));
-
ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId,
- subinfo->dobj.name,
- NULL,
- NULL,
- subinfo->rolname, false,
- "SUBSCRIPTION", SECTION_POST_DATA,
- query->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = subinfo->dobj.name,
+ .owner = subinfo->rolname,
+ .description = "SUBSCRIPTION",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .dropStmt = delq->data));
if (subinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "SUBSCRIPTION", qsubname,
NULL, subinfo->rolname,
subinfo->dobj.catId, 0, subinfo->dobj.dumpId);
if (subinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "SUBSCRIPTION", qsubname,
NULL, subinfo->rolname,
subinfo->dobj.catId, 0, subinfo->dobj.dumpId);
destroyPQExpBuffer(delq);
destroyPQExpBuffer(query);
+ free(qsubname);
}
static void
Oid pg_type_oid;
bool toast_set = false;
- /* we only support old >= 8.3 for binary upgrades */
+ /*
+ * We only support old >= 8.3 for binary upgrades.
+ *
+ * We purposefully ignore toast OIDs for partitioned tables; the reason is
+ * that versions 10 and 11 have them, but 12 does not, so emitting them
+ * causes the upgrade to fail.
+ */
appendPQExpBuffer(upgrade_query,
"SELECT c.reltype AS crel, t.reltype AS trel "
"FROM pg_catalog.pg_class c "
"LEFT JOIN pg_catalog.pg_class t ON "
- " (c.reltoastrelid = t.oid) "
+ " (c.reltoastrelid = t.oid AND c.relkind <> '%c') "
"WHERE c.oid = '%u'::pg_catalog.oid;",
- pg_rel_oid);
+ RELKIND_PARTITIONED_TABLE, pg_rel_oid);
upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
/*
* If the DumpableObject is a member of an extension, add a suitable
* ALTER EXTENSION ADD command to the creation commands in upgrade_buffer.
+ *
+ * For somewhat historical reasons, objname should already be quoted,
+ * but not objnamespace (if any).
*/
static void
binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
DumpableObject *dobj,
- const char *objlabel)
+ const char *objtype,
+ const char *objname,
+ const char *objnamespace)
{
DumpableObject *extobj = NULL;
int i;
extobj = NULL;
}
if (extobj == NULL)
- exit_horribly(NULL, "could not find parent extension for %s\n", objlabel);
+ fatal("could not find parent extension for %s %s",
+ objtype, objname);
appendPQExpBufferStr(upgrade_buffer,
"\n-- For binary upgrade, handle extension membership the hard way\n");
- appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s;\n",
+ appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s ",
fmtId(extobj->name),
- objlabel);
+ objtype);
+ if (objnamespace && *objnamespace)
+ appendPQExpBuffer(upgrade_buffer, "%s.", fmtId(objnamespace));
+ appendPQExpBuffer(upgrade_buffer, "%s;\n", objname);
}
/*
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
/*
* we fetch all namespaces including system ones, so that every object we
* read in can be linked to a containing namespace.
init_acl_subquery->data,
init_racl_subquery->data);
- /*
- * When we are doing a 'clean' run, we will be dropping and recreating
- * the 'public' schema (the only object which has that kind of
- * treatment in the backend and which has an entry in pg_init_privs)
- * and therefore we should not consider any initial privileges in
- * pg_init_privs in that case.
- *
- * See pg_backup_archiver.c:_printTocEntry() for the details on why
- * the public schema is special in this regard.
- *
- * Note that if the public schema is dropped and re-created, this is
- * essentially a no-op because the new public schema won't have an
- * entry in pg_init_privs anyway, as the entry will be removed when
- * the public schema is dropped.
- *
- * Further, we have to handle the case where the public schema does
- * not exist at all.
- */
- if (dopt->outputClean)
- appendPQExpBuffer(query, " AND pip.objoid <> "
- "coalesce((select oid from pg_namespace "
- "where nspname = 'public'),0)");
-
- appendPQExpBuffer(query, ") ");
+ appendPQExpBufferStr(query, ") ");
destroyPQExpBuffer(acl_subquery);
destroyPQExpBuffer(racl_subquery);
nsinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
if (strlen(nsinfo[i].rolname) == 0)
- write_msg(NULL, "WARNING: owner of schema \"%s\" appears to be invalid\n",
- nsinfo[i].dobj.name);
+ pg_log_warning("owner of schema \"%s\" appears to be invalid",
+ nsinfo[i].dobj.name);
}
PQclear(res);
nsinfo = findNamespaceByOid(nsoid);
if (nsinfo == NULL)
- exit_horribly(NULL, "schema with OID %u does not exist\n", nsoid);
+ fatal("schema with OID %u does not exist", nsoid);
return nsinfo;
}
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBufferStr(query, "SELECT x.tableoid, x.oid, "
"x.extname, n.nspname, x.extrelocatable, x.extversion, x.extconfig, x.extcondition "
"FROM pg_extension x "
* be revisited if the backend ever allows renaming of array types.
*/
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
if (fout->remoteVersion >= 90600)
{
PQExpBuffer acl_subquery = createPQExpBuffer();
}
if (strlen(tyinfo[i].rolname) == 0)
- write_msg(NULL, "WARNING: owner of data type \"%s\" appears to be invalid\n",
- tyinfo[i].dobj.name);
+ pg_log_warning("owner of data type \"%s\" appears to be invalid",
+ tyinfo[i].dobj.name);
}
*numTypes = ntups;
* system-defined operators at dump-out time.
*/
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
"oprnamespace, "
"(%s oprowner) AS rolname, "
oprinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
if (strlen(oprinfo[i].rolname) == 0)
- write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
- oprinfo[i].dobj.name);
+ pg_log_warning("owner of operator \"%s\" appears to be invalid",
+ oprinfo[i].dobj.name);
}
PQclear(res);
* system-defined collations at dump-out time.
*/
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBuffer(query, "SELECT tableoid, oid, collname, "
"collnamespace, "
"(%s collowner) AS rolname "
* system-defined conversions at dump-out time.
*/
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
"connamespace, "
"(%s conowner) AS rolname "
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
/* Select all access methods from pg_am table */
- appendPQExpBuffer(query, "SELECT tableoid, oid, amname, amtype, "
- "amhandler::pg_catalog.regproc AS amhandler "
- "FROM pg_am");
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, amname, amtype, "
+ "amhandler::pg_catalog.regproc AS amhandler "
+ "FROM pg_am");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
* system-defined opclasses at dump-out time.
*/
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
"opcnamespace, "
"(%s opcowner) AS rolname "
opcinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
if (strlen(opcinfo[i].rolname) == 0)
- write_msg(NULL, "WARNING: owner of operator class \"%s\" appears to be invalid\n",
- opcinfo[i].dobj.name);
+ pg_log_warning("owner of operator class \"%s\" appears to be invalid",
+ opcinfo[i].dobj.name);
}
PQclear(res);
* system-defined opfamilies at dump-out time.
*/
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, "
"opfnamespace, "
"(%s opfowner) AS rolname "
opfinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
if (strlen(opfinfo[i].rolname) == 0)
- write_msg(NULL, "WARNING: owner of operator family \"%s\" appears to be invalid\n",
- opfinfo[i].dobj.name);
+ pg_log_warning("owner of operator family \"%s\" appears to be invalid",
+ opfinfo[i].dobj.name);
}
PQclear(res);
int i_initaggacl;
int i_initraggacl;
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
/*
* Find all interesting aggregates. See comment in getFuncs() for the
* rationale behind the filtering logic.
PQExpBuffer racl_subquery = createPQExpBuffer();
PQExpBuffer initacl_subquery = createPQExpBuffer();
PQExpBuffer initracl_subquery = createPQExpBuffer();
+ const char *agg_check;
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
initracl_subquery, "p.proacl", "p.proowner", "'f'",
dopt->binary_upgrade);
+ agg_check = (fout->remoteVersion >= 110000 ? "p.prokind = 'a'"
+ : "p.proisagg");
+
appendPQExpBuffer(query, "SELECT p.tableoid, p.oid, "
"p.proname AS aggname, "
"p.pronamespace AS aggnamespace, "
"(p.oid = pip.objoid "
"AND pip.classoid = 'pg_proc'::regclass "
"AND pip.objsubid = 0) "
- "WHERE p.proisagg AND ("
+ "WHERE %s AND ("
"p.pronamespace != "
"(SELECT oid FROM pg_namespace "
"WHERE nspname = 'pg_catalog') OR "
acl_subquery->data,
racl_subquery->data,
initacl_subquery->data,
- initracl_subquery->data);
+ initracl_subquery->data,
+ agg_check);
if (dopt->binary_upgrade)
appendPQExpBufferStr(query,
" OR EXISTS(SELECT 1 FROM pg_depend WHERE "
atooid(PQgetvalue(res, i, i_aggnamespace)));
agginfo[i].aggfn.rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
if (strlen(agginfo[i].aggfn.rolname) == 0)
- write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
- agginfo[i].aggfn.dobj.name);
+ pg_log_warning("owner of aggregate function \"%s\" appears to be invalid",
+ agginfo[i].aggfn.dobj.name);
agginfo[i].aggfn.lang = InvalidOid; /* not currently interesting */
agginfo[i].aggfn.prorettype = InvalidOid; /* not saved */
agginfo[i].aggfn.proacl = pg_strdup(PQgetvalue(res, i, i_aggacl));
int i_initproacl;
int i_initrproacl;
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
/*
* Find all interesting functions. This is a bit complicated:
*
PQExpBuffer racl_subquery = createPQExpBuffer();
PQExpBuffer initacl_subquery = createPQExpBuffer();
PQExpBuffer initracl_subquery = createPQExpBuffer();
+ const char *not_agg_check;
buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
initracl_subquery, "p.proacl", "p.proowner", "'f'",
dopt->binary_upgrade);
+ not_agg_check = (fout->remoteVersion >= 110000 ? "p.prokind <> 'a'"
+ : "NOT p.proisagg");
+
appendPQExpBuffer(query,
"SELECT p.tableoid, p.oid, p.proname, p.prolang, "
"p.pronargs, p.proargtypes, p.prorettype, "
"(p.oid = pip.objoid "
"AND pip.classoid = 'pg_proc'::regclass "
"AND pip.objsubid = 0) "
- "WHERE NOT proisagg"
+ "WHERE %s"
"\n AND NOT EXISTS (SELECT 1 FROM pg_depend "
"WHERE classid = 'pg_proc'::regclass AND "
"objid = p.oid AND deptype = 'i')"
initacl_subquery->data,
initracl_subquery->data,
username_subquery,
+ not_agg_check,
g_last_builtin_oid,
g_last_builtin_oid);
if (dopt->binary_upgrade)
finfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
if (strlen(finfo[i].rolname) == 0)
- write_msg(NULL,
- "WARNING: owner of function \"%s\" appears to be invalid\n",
- finfo[i].dobj.name);
+ pg_log_warning("owner of function \"%s\" appears to be invalid",
+ finfo[i].dobj.name);
}
PQclear(res);
int i_partkeydef;
int i_ispartition;
int i_partbound;
-
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
+ int i_amname;
/*
* Find all the tables and table-like objects.
* information about each table, basically just enough to decide if it is
* interesting. We must fetch all tables in this phase because otherwise
* we cannot correctly identify inherited columns, owned sequences, etc.
+ *
+ * We purposefully ignore toast OIDs for partitioned tables; the reason is
+ * that versions 10 and 11 have them, but 12 does not, so emitting them
+ * causes the upgrade to fail.
*/
if (fout->remoteVersion >= 90600)
char *partkeydef = "NULL";
char *ispartition = "false";
char *partbound = "NULL";
+ char *relhasoids = "c.relhasoids";
PQExpBuffer acl_subquery = createPQExpBuffer();
PQExpBuffer racl_subquery = createPQExpBuffer();
partbound = "pg_get_expr(c.relpartbound, c.oid)";
}
+ /* In PG12 upwards WITH OIDS does not exist anymore. */
+ if (fout->remoteVersion >= 120000)
+ relhasoids = "'f'::bool";
+
/*
* Left join to pick up dependency info linking sequences to their
* owning column, if any (note this dependency is AUTO as of 8.2)
"c.relkind, c.relnamespace, "
"(%s c.relowner) AS rolname, "
"c.relchecks, c.relhastriggers, "
- "c.relhasindex, c.relhasrules, c.relhasoids, "
+ "c.relhasindex, c.relhasrules, %s AS relhasoids, "
"c.relrowsecurity, c.relforcerowsecurity, "
"c.relfrozenxid, c.relminmxid, tc.oid AS toid, "
"tc.relfrozenxid AS tfrozenxid, "
"tc.relminmxid AS tminmxid, "
"c.relpersistence, c.relispopulated, "
- "c.relreplident, c.relpages, "
+ "c.relreplident, c.relpages, am.amname, "
"CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
"d.classid = c.tableoid AND d.objid = c.oid AND "
"d.objsubid = 0 AND "
"d.refclassid = c.tableoid AND d.deptype IN ('a', 'i')) "
- "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
+ "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid AND c.relkind <> '%c') "
+ "LEFT JOIN pg_am am ON (c.relam = am.oid) "
"LEFT JOIN pg_init_privs pip ON "
"(c.oid = pip.objoid "
"AND pip.classoid = 'pg_class'::regclass "
initacl_subquery->data,
initracl_subquery->data,
username_subquery,
+ relhasoids,
RELKIND_SEQUENCE,
attacl_subquery->data,
attracl_subquery->data,
ispartition,
partbound,
RELKIND_SEQUENCE,
+ RELKIND_PARTITIONED_TABLE,
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
"tc.relminmxid AS tminmxid, "
"c.relpersistence, c.relispopulated, "
"c.relreplident, c.relpages, "
+ "NULL AS amname, "
"CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
"tc.relminmxid AS tminmxid, "
"c.relpersistence, c.relispopulated, "
"c.relreplident, c.relpages, "
+ "NULL AS amname, "
"CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
"tc.relminmxid AS tminmxid, "
"c.relpersistence, c.relispopulated, "
"'d' AS relreplident, c.relpages, "
+ "NULL AS amname, "
"CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
"0 AS tminmxid, "
"c.relpersistence, 't' as relispopulated, "
"'d' AS relreplident, c.relpages, "
+ "NULL AS amname, "
"CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
"0 AS tminmxid, "
"'p' AS relpersistence, 't' as relispopulated, "
"'d' AS relreplident, c.relpages, "
+ "NULL AS amname, "
"CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
"0 AS tminmxid, "
"'p' AS relpersistence, 't' as relispopulated, "
"'d' AS relreplident, c.relpages, "
+ "NULL AS amname, "
"NULL AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
"0 AS tminmxid, "
"'p' AS relpersistence, 't' as relispopulated, "
"'d' AS relreplident, c.relpages, "
+ "NULL AS amname, "
"NULL AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
"0 AS tfrozenxid, 0 AS tminmxid,"
"'p' AS relpersistence, 't' as relispopulated, "
"'d' AS relreplident, relpages, "
+ "NULL AS amname, "
"NULL AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
i_partkeydef = PQfnumber(res, "partkeydef");
i_ispartition = PQfnumber(res, "ispartition");
i_partbound = PQfnumber(res, "partbound");
+ i_amname = PQfnumber(res, "amname");
if (dopt->lockWaitTimeout)
{
else
tblinfo[i].checkoption = pg_strdup(PQgetvalue(res, i, i_checkoption));
tblinfo[i].toast_reloptions = pg_strdup(PQgetvalue(res, i, i_toastreloptions));
+ if (PQgetisnull(res, i, i_amname))
+ tblinfo[i].amname = NULL;
+ else
+ tblinfo[i].amname = pg_strdup(PQgetvalue(res, i, i_amname));
/* other fields were zeroed above */
* alterations to parent tables.
*
* NOTE: it'd be kinda nice to lock other relations too, not only
- * plain tables, but the backend doesn't presently allow that.
+ * plain or partitioned tables, but the backend doesn't presently
+ * allow that.
*
* We only need to lock the table for certain components; see
* pg_dump.h
resetPQExpBuffer(query);
appendPQExpBuffer(query,
"LOCK TABLE %s IN ACCESS SHARE MODE",
- fmtQualifiedId(fout->remoteVersion,
- tblinfo[i].dobj.namespace->dobj.name,
- tblinfo[i].dobj.name));
+ fmtQualifiedDumpable(&tblinfo[i]));
ExecuteSqlStatement(fout, query->data);
}
/* Emit notice if join for owner failed */
if (strlen(tblinfo[i].rolname) == 0)
- write_msg(NULL, "WARNING: owner of table \"%s\" appears to be invalid\n",
- tblinfo[i].dobj.name);
+ pg_log_warning("owner of table \"%s\" appears to be invalid",
+ tblinfo[i].dobj.name);
}
if (dopt->lockWaitTimeout)
owning_tab = findTableByOid(seqinfo->owning_tab);
if (owning_tab == NULL)
- exit_horribly(NULL, "failed sanity check, parent table with OID %u of sequence with OID %u not found\n",
- seqinfo->owning_tab, seqinfo->dobj.catId.oid);
+ fatal("failed sanity check, parent table with OID %u of sequence with OID %u not found",
+ seqinfo->owning_tab, seqinfo->dobj.catId.oid);
+
+ /*
+ * Only dump identity sequences if we're going to dump the table that
+ * it belongs to.
+ */
+ if (owning_tab->dobj.dump == DUMP_COMPONENT_NONE &&
+ seqinfo->is_identity_sequence)
+ {
+ seqinfo->dobj.dump = DUMP_COMPONENT_NONE;
+ continue;
+ }
/*
- * We need to dump the components that are being dumped for the table
- * and any components which the sequence is explicitly marked with.
+ * Otherwise we need to dump the components that are being dumped for
+ * the table and any components which the sequence is explicitly
+ * marked with.
*
* We can't simply use the set of components which are being dumped
* for the table as the table might be in an extension (and only the
int i_inhrelid;
int i_inhparent;
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
/*
* Find all the inheritance information, excluding implicit inheritance
- * via partitioning. We handle that case using getPartitions(), because
- * we want more information about partitions than just the parent-child
- * relationship.
+ * via partitioning.
*/
appendPQExpBufferStr(query, "SELECT inhrelid, inhparent FROM pg_inherits");
int i_tableoid,
i_oid,
i_indexname,
+ i_parentidx,
i_indexdef,
- i_indnkeys,
+ i_indnkeyatts,
+ i_indnatts,
i_indkey,
i_indisclustered,
i_indisreplident,
i_condef,
i_tablespace,
i_indreloptions,
- i_relpages;
+ i_indstatcols,
+ i_indstatvals;
int ntups;
for (i = 0; i < numTables; i++)
{
TableInfo *tbinfo = &tblinfo[i];
- /* Only plain tables and materialized views have indexes. */
- if (tbinfo->relkind != RELKIND_RELATION &&
- tbinfo->relkind != RELKIND_MATVIEW)
- continue;
if (!tbinfo->hasindex)
continue;
- /* Ignore indexes of tables whose definitions are not to be dumped */
- if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
+ /*
+ * Ignore indexes of tables whose definitions are not to be dumped.
+ *
+ * We also need indexes on partitioned tables which have partitions to
+ * be dumped, in order to dump the indexes on the partitions.
+ */
+ if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) &&
+ !tbinfo->interesting)
continue;
- if (g_verbose)
- write_msg(NULL, "reading indexes for table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
-
- /* Make sure we are in proper schema so indexdef is right */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+ pg_log_info("reading indexes for table \"%s.%s\"",
+ tbinfo->dobj.namespace->dobj.name,
+ tbinfo->dobj.name);
/*
* The point of the messy-looking outer join is to find a constraint
* is not.
*/
resetPQExpBuffer(query);
- if (fout->remoteVersion >= 90400)
+ if (fout->remoteVersion >= 110000)
+ {
+ appendPQExpBuffer(query,
+ "SELECT t.tableoid, t.oid, "
+ "t.relname AS indexname, "
+ "inh.inhparent AS parentidx, "
+ "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
+ "i.indnkeyatts AS indnkeyatts, "
+ "i.indnatts AS indnatts, "
+ "i.indkey, i.indisclustered, "
+ "i.indisreplident, "
+ "c.contype, c.conname, "
+ "c.condeferrable, c.condeferred, "
+ "c.tableoid AS contableoid, "
+ "c.oid AS conoid, "
+ "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
+ "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
+ "t.reloptions AS indreloptions, "
+ "(SELECT pg_catalog.array_agg(attnum ORDER BY attnum) "
+ " FROM pg_catalog.pg_attribute "
+ " WHERE attrelid = i.indexrelid AND "
+ " attstattarget >= 0) AS indstatcols,"
+ "(SELECT pg_catalog.array_agg(attstattarget ORDER BY attnum) "
+ " FROM pg_catalog.pg_attribute "
+ " WHERE attrelid = i.indexrelid AND "
+ " attstattarget >= 0) AS indstatvals "
+ "FROM pg_catalog.pg_index i "
+ "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
+ "JOIN pg_catalog.pg_class t2 ON (t2.oid = i.indrelid) "
+ "LEFT JOIN pg_catalog.pg_constraint c "
+ "ON (i.indrelid = c.conrelid AND "
+ "i.indexrelid = c.conindid AND "
+ "c.contype IN ('p','u','x')) "
+ "LEFT JOIN pg_catalog.pg_inherits inh "
+ "ON (inh.inhrelid = indexrelid) "
+ "WHERE i.indrelid = '%u'::pg_catalog.oid "
+ "AND (i.indisvalid OR t2.relkind = 'p') "
+ "AND i.indisready "
+ "ORDER BY indexname",
+ tbinfo->dobj.catId.oid);
+ }
+ else if (fout->remoteVersion >= 90400)
{
/*
* the test on indisready is necessary in 9.2, and harmless in
appendPQExpBuffer(query,
"SELECT t.tableoid, t.oid, "
"t.relname AS indexname, "
+ "0 AS parentidx, "
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
- "t.relnatts AS indnkeys, "
+ "i.indnatts AS indnkeyatts, "
+ "i.indnatts AS indnatts, "
"i.indkey, i.indisclustered, "
- "i.indisreplident, t.relpages, "
+ "i.indisreplident, "
"c.contype, c.conname, "
"c.condeferrable, c.condeferred, "
"c.tableoid AS contableoid, "
"c.oid AS conoid, "
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
- "t.reloptions AS indreloptions "
+ "t.reloptions AS indreloptions, "
+ "'' AS indstatcols, "
+ "'' AS indstatvals "
"FROM pg_catalog.pg_index i "
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
"LEFT JOIN pg_catalog.pg_constraint c "
appendPQExpBuffer(query,
"SELECT t.tableoid, t.oid, "
"t.relname AS indexname, "
+ "0 AS parentidx, "
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
- "t.relnatts AS indnkeys, "
+ "i.indnatts AS indnkeyatts, "
+ "i.indnatts AS indnatts, "
"i.indkey, i.indisclustered, "
- "false AS indisreplident, t.relpages, "
+ "false AS indisreplident, "
"c.contype, c.conname, "
"c.condeferrable, c.condeferred, "
"c.tableoid AS contableoid, "
"c.oid AS conoid, "
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
- "t.reloptions AS indreloptions "
+ "t.reloptions AS indreloptions, "
+ "'' AS indstatcols, "
+ "'' AS indstatvals "
"FROM pg_catalog.pg_index i "
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
"LEFT JOIN pg_catalog.pg_constraint c "
appendPQExpBuffer(query,
"SELECT t.tableoid, t.oid, "
"t.relname AS indexname, "
+ "0 AS parentidx, "
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
- "t.relnatts AS indnkeys, "
+ "i.indnatts AS indnkeyatts, "
+ "i.indnatts AS indnatts, "
"i.indkey, i.indisclustered, "
- "false AS indisreplident, t.relpages, "
+ "false AS indisreplident, "
"c.contype, c.conname, "
"c.condeferrable, c.condeferred, "
"c.tableoid AS contableoid, "
"c.oid AS conoid, "
"null AS condef, "
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
- "t.reloptions AS indreloptions "
+ "t.reloptions AS indreloptions, "
+ "'' AS indstatcols, "
+ "'' AS indstatvals "
"FROM pg_catalog.pg_index i "
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
"LEFT JOIN pg_catalog.pg_depend d "
appendPQExpBuffer(query,
"SELECT t.tableoid, t.oid, "
"t.relname AS indexname, "
+ "0 AS parentidx, "
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
- "t.relnatts AS indnkeys, "
+ "t.relnatts AS indnkeyatts, "
+ "t.relnatts AS indnatts, "
"i.indkey, i.indisclustered, "
- "false AS indisreplident, t.relpages, "
+ "false AS indisreplident, "
"c.contype, c.conname, "
"c.condeferrable, c.condeferred, "
"c.tableoid AS contableoid, "
"c.oid AS conoid, "
"null AS condef, "
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
- "null AS indreloptions "
+ "null AS indreloptions, "
+ "'' AS indstatcols, "
+ "'' AS indstatvals "
"FROM pg_catalog.pg_index i "
"JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
"LEFT JOIN pg_catalog.pg_depend d "
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
i_indexname = PQfnumber(res, "indexname");
+ i_parentidx = PQfnumber(res, "parentidx");
i_indexdef = PQfnumber(res, "indexdef");
- i_indnkeys = PQfnumber(res, "indnkeys");
+ i_indnkeyatts = PQfnumber(res, "indnkeyatts");
+ i_indnatts = PQfnumber(res, "indnatts");
i_indkey = PQfnumber(res, "indkey");
i_indisclustered = PQfnumber(res, "indisclustered");
i_indisreplident = PQfnumber(res, "indisreplident");
- i_relpages = PQfnumber(res, "relpages");
i_contype = PQfnumber(res, "contype");
i_conname = PQfnumber(res, "conname");
i_condeferrable = PQfnumber(res, "condeferrable");
i_condef = PQfnumber(res, "condef");
i_tablespace = PQfnumber(res, "tablespace");
i_indreloptions = PQfnumber(res, "indreloptions");
+ i_indstatcols = PQfnumber(res, "indstatcols");
+ i_indstatvals = PQfnumber(res, "indstatvals");
- indxinfo = (IndxInfo *) pg_malloc(ntups * sizeof(IndxInfo));
+ tbinfo->indexes = indxinfo =
+ (IndxInfo *) pg_malloc(ntups * sizeof(IndxInfo));
constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo));
+ tbinfo->numIndexes = ntups;
for (j = 0; j < ntups; j++)
{
indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
indxinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
AssignDumpId(&indxinfo[j].dobj);
+ indxinfo[j].dobj.dump = tbinfo->dobj.dump;
indxinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_indexname));
indxinfo[j].dobj.namespace = tbinfo->dobj.namespace;
indxinfo[j].indextable = tbinfo;
indxinfo[j].indexdef = pg_strdup(PQgetvalue(res, j, i_indexdef));
- indxinfo[j].indnkeys = atoi(PQgetvalue(res, j, i_indnkeys));
+ indxinfo[j].indnkeyattrs = atoi(PQgetvalue(res, j, i_indnkeyatts));
+ indxinfo[j].indnattrs = atoi(PQgetvalue(res, j, i_indnatts));
indxinfo[j].tablespace = pg_strdup(PQgetvalue(res, j, i_tablespace));
indxinfo[j].indreloptions = pg_strdup(PQgetvalue(res, j, i_indreloptions));
- indxinfo[j].indkeys = (Oid *) pg_malloc(indxinfo[j].indnkeys * sizeof(Oid));
+ indxinfo[j].indstatcols = pg_strdup(PQgetvalue(res, j, i_indstatcols));
+ indxinfo[j].indstatvals = pg_strdup(PQgetvalue(res, j, i_indstatvals));
+ indxinfo[j].indkeys = (Oid *) pg_malloc(indxinfo[j].indnattrs * sizeof(Oid));
parseOidArray(PQgetvalue(res, j, i_indkey),
- indxinfo[j].indkeys, indxinfo[j].indnkeys);
+ indxinfo[j].indkeys, indxinfo[j].indnattrs);
indxinfo[j].indisclustered = (PQgetvalue(res, j, i_indisclustered)[0] == 't');
indxinfo[j].indisreplident = (PQgetvalue(res, j, i_indisreplident)[0] == 't');
- indxinfo[j].relpages = atoi(PQgetvalue(res, j, i_relpages));
+ indxinfo[j].parentidx = atooid(PQgetvalue(res, j, i_parentidx));
contype = *(PQgetvalue(res, j, i_contype));
if (contype == 'p' || contype == 'u' || contype == 'x')
constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
AssignDumpId(&constrinfo[j].dobj);
+ constrinfo[j].dobj.dump = tbinfo->dobj.dump;
constrinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
constrinfo[j].contable = tbinfo;
/*
* getExtendedStatistics
- * get information about extended statistics on a dumpable table
- * or materialized view.
+ * get information about extended-statistics objects.
*
* Note: extended statistics data is not returned directly to the caller, but
* it does get entered into the DumpableObject tables.
*/
void
-getExtendedStatistics(Archive *fout, TableInfo tblinfo[], int numTables)
+getExtendedStatistics(Archive *fout)
{
- int i,
- j;
PQExpBuffer query;
PGresult *res;
StatsExtInfo *statsextinfo;
int i_tableoid;
int i_oid;
int i_stxname;
- int i_stxdef;
+ int i_stxnamespace;
+ int i_rolname;
+ int i;
/* Extended statistics were new in v10 */
if (fout->remoteVersion < 100000)
query = createPQExpBuffer();
- for (i = 0; i < numTables; i++)
- {
- TableInfo *tbinfo = &tblinfo[i];
-
- /*
- * Only plain tables, materialized views, foreign tables and
- * partitioned tables can have extended statistics.
- */
- if (tbinfo->relkind != RELKIND_RELATION &&
- tbinfo->relkind != RELKIND_MATVIEW &&
- tbinfo->relkind != RELKIND_FOREIGN_TABLE &&
- tbinfo->relkind != RELKIND_PARTITIONED_TABLE)
- continue;
-
- /*
- * Ignore extended statistics of tables whose definitions are not to
- * be dumped.
- */
- if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
- continue;
-
- if (g_verbose)
- write_msg(NULL, "reading extended statistics for table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
-
- /* Make sure we are in proper schema so stadef is right */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
- resetPQExpBuffer(query);
+ appendPQExpBuffer(query, "SELECT tableoid, oid, stxname, "
+ "stxnamespace, (%s stxowner) AS rolname "
+ "FROM pg_catalog.pg_statistic_ext",
+ username_subquery);
- appendPQExpBuffer(query,
- "SELECT "
- "tableoid, "
- "oid, "
- "stxname, "
- "pg_catalog.pg_get_statisticsobjdef(oid) AS stxdef "
- "FROM pg_statistic_ext "
- "WHERE stxrelid = '%u' "
- "ORDER BY stxname", tbinfo->dobj.catId.oid);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+ ntups = PQntuples(res);
- ntups = PQntuples(res);
+ i_tableoid = PQfnumber(res, "tableoid");
+ i_oid = PQfnumber(res, "oid");
+ i_stxname = PQfnumber(res, "stxname");
+ i_stxnamespace = PQfnumber(res, "stxnamespace");
+ i_rolname = PQfnumber(res, "rolname");
- i_tableoid = PQfnumber(res, "tableoid");
- i_oid = PQfnumber(res, "oid");
- i_stxname = PQfnumber(res, "stxname");
- i_stxdef = PQfnumber(res, "stxdef");
+ statsextinfo = (StatsExtInfo *) pg_malloc(ntups * sizeof(StatsExtInfo));
- statsextinfo = (StatsExtInfo *) pg_malloc(ntups * sizeof(StatsExtInfo));
+ for (i = 0; i < ntups; i++)
+ {
+ statsextinfo[i].dobj.objType = DO_STATSEXT;
+ statsextinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+ statsextinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+ AssignDumpId(&statsextinfo[i].dobj);
+ statsextinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_stxname));
+ statsextinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_stxnamespace)));
+ statsextinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
- for (j = 0; j < ntups; j++)
- {
- statsextinfo[j].dobj.objType = DO_STATSEXT;
- statsextinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
- statsextinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
- AssignDumpId(&statsextinfo[j].dobj);
- statsextinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_stxname));
- statsextinfo[j].dobj.namespace = tbinfo->dobj.namespace;
- statsextinfo[j].statsexttable = tbinfo;
- statsextinfo[j].statsextdef = pg_strdup(PQgetvalue(res, j, i_stxdef));
- }
+ /* Decide whether we want to dump it */
+ selectDumpableObject(&(statsextinfo[i].dobj), fout);
- PQclear(res);
+ /* Stats objects do not currently have ACLs. */
+ statsextinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
}
+ PQclear(res);
destroyPQExpBuffer(query);
}
{
TableInfo *tbinfo = &tblinfo[i];
- if (!tbinfo->hastriggers ||
+ /*
+ * For partitioned tables, foreign keys have no triggers so they must
+ * be included anyway in case some foreign keys are defined.
+ */
+ if ((!tbinfo->hastriggers &&
+ tbinfo->relkind != RELKIND_PARTITIONED_TABLE) ||
!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
continue;
- if (g_verbose)
- write_msg(NULL, "reading foreign key constraints for table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
-
- /*
- * select table schema to ensure constraint expr is qualified if
- * needed
- */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+ pg_log_info("reading foreign key constraints for table \"%s.%s\"",
+ tbinfo->dobj.namespace->dobj.name,
+ tbinfo->dobj.name);
resetPQExpBuffer(query);
- appendPQExpBuffer(query,
- "SELECT tableoid, oid, conname, confrelid, "
- "pg_catalog.pg_get_constraintdef(oid) AS condef "
- "FROM pg_catalog.pg_constraint "
- "WHERE conrelid = '%u'::pg_catalog.oid "
- "AND contype = 'f'",
- tbinfo->dobj.catId.oid);
+ if (fout->remoteVersion >= 110000)
+ appendPQExpBuffer(query,
+ "SELECT tableoid, oid, conname, confrelid, "
+ "pg_catalog.pg_get_constraintdef(oid) AS condef "
+ "FROM pg_catalog.pg_constraint "
+ "WHERE conrelid = '%u'::pg_catalog.oid "
+ "AND conparentid = 0 "
+ "AND contype = 'f'",
+ tbinfo->dobj.catId.oid);
+ else
+ appendPQExpBuffer(query,
+ "SELECT tableoid, oid, conname, confrelid, "
+ "pg_catalog.pg_get_constraintdef(oid) AS condef "
+ "FROM pg_catalog.pg_constraint "
+ "WHERE conrelid = '%u'::pg_catalog.oid "
+ "AND contype = 'f'",
+ tbinfo->dobj.catId.oid);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
i_consrc;
int ntups;
- /*
- * select appropriate schema to ensure names in constraint are properly
- * qualified
- */
- selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
-
query = createPQExpBuffer();
if (fout->remoteVersion >= 90100)
int i_is_instead;
int i_ev_enabled;
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
if (fout->remoteVersion >= 80300)
{
appendPQExpBufferStr(query, "SELECT "
ruletableoid = atooid(PQgetvalue(res, i, i_ruletable));
ruleinfo[i].ruletable = findTableByOid(ruletableoid);
if (ruleinfo[i].ruletable == NULL)
- exit_horribly(NULL, "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found\n",
- ruletableoid, ruleinfo[i].dobj.catId.oid);
+ fatal("failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found",
+ ruletableoid, ruleinfo[i].dobj.catId.oid);
ruleinfo[i].dobj.namespace = ruleinfo[i].ruletable->dobj.namespace;
ruleinfo[i].dobj.dump = ruleinfo[i].ruletable->dobj.dump;
ruleinfo[i].ev_type = *(PQgetvalue(res, i, i_ev_type));
!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
continue;
- if (g_verbose)
- write_msg(NULL, "reading triggers for table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
-
- /*
- * select table schema to ensure regproc name is qualified if needed
- */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+ pg_log_info("reading triggers for table \"%s.%s\"",
+ tbinfo->dobj.namespace->dobj.name,
+ tbinfo->dobj.name);
resetPQExpBuffer(query);
if (fout->remoteVersion >= 90000)
if (OidIsValid(tginfo[j].tgconstrrelid))
{
if (PQgetisnull(res, j, i_tgconstrrelname))
- exit_horribly(NULL, "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)\n",
- tginfo[j].dobj.name,
- tbinfo->dobj.name,
- tginfo[j].tgconstrrelid);
+ fatal("query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)",
+ tginfo[j].dobj.name,
+ tbinfo->dobj.name,
+ tginfo[j].tgconstrrelid);
tginfo[j].tgconstrrelname = pg_strdup(PQgetvalue(res, j, i_tgconstrrelname));
}
else
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBuffer(query,
"SELECT e.tableoid, e.oid, evtname, evtenabled, "
"evtevent, (%s evtowner) AS evtowner, "
int i_initrlanacl;
int i_lanowner;
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
if (fout->remoteVersion >= 90600)
{
PQExpBuffer acl_subquery = createPQExpBuffer();
int i_castcontext;
int i_castmethod;
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
if (fout->remoteVersion >= 80400)
{
appendPQExpBufferStr(query, "SELECT tableoid, oid, "
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
- appendPQExpBuffer(query, "SELECT tableoid, oid, "
- "trftype, trflang, trffromsql::oid, trftosql::oid "
- "FROM pg_transform "
- "ORDER BY 3,4");
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, "
+ "trftype, trflang, trffromsql::oid, trftosql::oid "
+ "FROM pg_transform "
+ "ORDER BY 3,4");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
int i_attnotnull;
int i_atthasdef;
int i_attidentity;
+ int i_attgenerated;
int i_attisdropped;
int i_attlen;
int i_attalign;
int i_attoptions;
int i_attcollation;
int i_attfdwoptions;
+ int i_attmissingval;
PGresult *res;
int ntups;
bool hasdefaults;
if (!tbinfo->interesting)
continue;
- /*
- * Make sure we are in proper schema for this table; this allows
- * correct retrieval of formatted type names and default exprs
- */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
/* find all the user attributes and their types */
/*
* we must read the attribute names in attribute number order! because
* we will use the attnum to index into the attnames array later.
*/
- if (g_verbose)
- write_msg(NULL, "finding the columns and types of table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
+ pg_log_info("finding the columns and types of table \"%s.%s\"",
+ tbinfo->dobj.namespace->dobj.name,
+ tbinfo->dobj.name);
resetPQExpBuffer(q);
+ appendPQExpBufferStr(q,
+ "SELECT\n"
+ "a.attnum,\n"
+ "a.attname,\n"
+ "a.atttypmod,\n"
+ "a.attstattarget,\n"
+ "a.attstorage,\n"
+ "t.typstorage,\n"
+ "a.attnotnull,\n"
+ "a.atthasdef,\n"
+ "a.attisdropped,\n"
+ "a.attlen,\n"
+ "a.attalign,\n"
+ "a.attislocal,\n"
+ "pg_catalog.format_type(t.oid, a.atttypmod) AS atttypname,\n");
+
+ if (fout->remoteVersion >= 120000)
+ appendPQExpBufferStr(q,
+ "a.attgenerated,\n");
+ else
+ appendPQExpBufferStr(q,
+ "'' AS attgenerated,\n");
+
+ if (fout->remoteVersion >= 110000)
+ appendPQExpBufferStr(q,
+ "CASE WHEN a.atthasmissing AND NOT a.attisdropped "
+ "THEN a.attmissingval ELSE null END AS attmissingval,\n");
+ else
+ appendPQExpBufferStr(q,
+ "NULL AS attmissingval,\n");
+
if (fout->remoteVersion >= 100000)
+ appendPQExpBufferStr(q,
+ "a.attidentity,\n");
+ else
+ appendPQExpBufferStr(q,
+ "'' AS attidentity,\n");
+
+ if (fout->remoteVersion >= 90200)
+ appendPQExpBufferStr(q,
+ "pg_catalog.array_to_string(ARRAY("
+ "SELECT pg_catalog.quote_ident(option_name) || "
+ "' ' || pg_catalog.quote_literal(option_value) "
+ "FROM pg_catalog.pg_options_to_table(attfdwoptions) "
+ "ORDER BY option_name"
+ "), E',\n ') AS attfdwoptions,\n");
+ else
+ appendPQExpBufferStr(q,
+ "'' AS attfdwoptions,\n");
+
+ if (fout->remoteVersion >= 90100)
{
/*
- * attidentity is new in version 10.
- */
- appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
- "a.attstattarget, a.attstorage, t.typstorage, "
- "a.attnotnull, a.atthasdef, a.attisdropped, "
- "a.attlen, a.attalign, a.attislocal, "
- "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
- "array_to_string(a.attoptions, ', ') AS attoptions, "
- "CASE WHEN a.attcollation <> t.typcollation "
- "THEN a.attcollation ELSE 0 END AS attcollation, "
- "a.attidentity, "
- "pg_catalog.array_to_string(ARRAY("
- "SELECT pg_catalog.quote_ident(option_name) || "
- "' ' || pg_catalog.quote_literal(option_value) "
- "FROM pg_catalog.pg_options_to_table(attfdwoptions) "
- "ORDER BY option_name"
- "), E',\n ') AS attfdwoptions "
- "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
- "ON a.atttypid = t.oid "
- "WHERE a.attrelid = '%u'::pg_catalog.oid "
- "AND a.attnum > 0::pg_catalog.int2 "
- "ORDER BY a.attnum",
- tbinfo->dobj.catId.oid);
- }
- else if (fout->remoteVersion >= 90200)
- {
- /*
- * attfdwoptions is new in 9.2.
- */
- appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
- "a.attstattarget, a.attstorage, t.typstorage, "
- "a.attnotnull, a.atthasdef, a.attisdropped, "
- "a.attlen, a.attalign, a.attislocal, "
- "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
- "array_to_string(a.attoptions, ', ') AS attoptions, "
- "CASE WHEN a.attcollation <> t.typcollation "
- "THEN a.attcollation ELSE 0 END AS attcollation, "
- "pg_catalog.array_to_string(ARRAY("
- "SELECT pg_catalog.quote_ident(option_name) || "
- "' ' || pg_catalog.quote_literal(option_value) "
- "FROM pg_catalog.pg_options_to_table(attfdwoptions) "
- "ORDER BY option_name"
- "), E',\n ') AS attfdwoptions "
- "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
- "ON a.atttypid = t.oid "
- "WHERE a.attrelid = '%u'::pg_catalog.oid "
- "AND a.attnum > 0::pg_catalog.int2 "
- "ORDER BY a.attnum",
- tbinfo->dobj.catId.oid);
- }
- else if (fout->remoteVersion >= 90100)
- {
- /*
- * attcollation is new in 9.1. Since we only want to dump COLLATE
- * clauses for attributes whose collation is different from their
- * type's default, we use a CASE here to suppress uninteresting
- * attcollations cheaply.
+ * Since we only want to dump COLLATE clauses for attributes whose
+ * collation is different from their type's default, we use a CASE
+ * here to suppress uninteresting attcollations cheaply.
*/
- appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
- "a.attstattarget, a.attstorage, t.typstorage, "
- "a.attnotnull, a.atthasdef, a.attisdropped, "
- "a.attlen, a.attalign, a.attislocal, "
- "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
- "array_to_string(a.attoptions, ', ') AS attoptions, "
- "CASE WHEN a.attcollation <> t.typcollation "
- "THEN a.attcollation ELSE 0 END AS attcollation, "
- "NULL AS attfdwoptions "
- "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
- "ON a.atttypid = t.oid "
- "WHERE a.attrelid = '%u'::pg_catalog.oid "
- "AND a.attnum > 0::pg_catalog.int2 "
- "ORDER BY a.attnum",
- tbinfo->dobj.catId.oid);
- }
- else if (fout->remoteVersion >= 90000)
- {
- /* attoptions is new in 9.0 */
- appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
- "a.attstattarget, a.attstorage, t.typstorage, "
- "a.attnotnull, a.atthasdef, a.attisdropped, "
- "a.attlen, a.attalign, a.attislocal, "
- "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
- "array_to_string(a.attoptions, ', ') AS attoptions, "
- "0 AS attcollation, "
- "NULL AS attfdwoptions "
- "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
- "ON a.atttypid = t.oid "
- "WHERE a.attrelid = '%u'::pg_catalog.oid "
- "AND a.attnum > 0::pg_catalog.int2 "
- "ORDER BY a.attnum",
- tbinfo->dobj.catId.oid);
+ appendPQExpBufferStr(q,
+ "CASE WHEN a.attcollation <> t.typcollation "
+ "THEN a.attcollation ELSE 0 END AS attcollation,\n");
}
else
- {
- /* need left join here to not fail on dropped columns ... */
- appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
- "a.attstattarget, a.attstorage, t.typstorage, "
- "a.attnotnull, a.atthasdef, a.attisdropped, "
- "a.attlen, a.attalign, a.attislocal, "
- "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
- "'' AS attoptions, 0 AS attcollation, "
- "NULL AS attfdwoptions "
- "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
- "ON a.atttypid = t.oid "
- "WHERE a.attrelid = '%u'::pg_catalog.oid "
- "AND a.attnum > 0::pg_catalog.int2 "
- "ORDER BY a.attnum",
- tbinfo->dobj.catId.oid);
- }
+ appendPQExpBufferStr(q,
+ "0 AS attcollation,\n");
+
+ if (fout->remoteVersion >= 90000)
+ appendPQExpBufferStr(q,
+ "array_to_string(a.attoptions, ', ') AS attoptions\n");
+ else
+ appendPQExpBufferStr(q,
+ "'' AS attoptions\n");
+
+ /* need left join here to not fail on dropped columns ... */
+ appendPQExpBuffer(q,
+ "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
+ "ON a.atttypid = t.oid\n"
+ "WHERE a.attrelid = '%u'::pg_catalog.oid "
+ "AND a.attnum > 0::pg_catalog.int2\n"
+ "ORDER BY a.attnum",
+ tbinfo->dobj.catId.oid);
res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
i_attnotnull = PQfnumber(res, "attnotnull");
i_atthasdef = PQfnumber(res, "atthasdef");
i_attidentity = PQfnumber(res, "attidentity");
+ i_attgenerated = PQfnumber(res, "attgenerated");
i_attisdropped = PQfnumber(res, "attisdropped");
i_attlen = PQfnumber(res, "attlen");
i_attalign = PQfnumber(res, "attalign");
i_attoptions = PQfnumber(res, "attoptions");
i_attcollation = PQfnumber(res, "attcollation");
i_attfdwoptions = PQfnumber(res, "attfdwoptions");
+ i_attmissingval = PQfnumber(res, "attmissingval");
tbinfo->numatts = ntups;
tbinfo->attnames = (char **) pg_malloc(ntups * sizeof(char *));
tbinfo->attstorage = (char *) pg_malloc(ntups * sizeof(char));
tbinfo->typstorage = (char *) pg_malloc(ntups * sizeof(char));
tbinfo->attidentity = (char *) pg_malloc(ntups * sizeof(char));
+ tbinfo->attgenerated = (char *) pg_malloc(ntups * sizeof(char));
tbinfo->attisdropped = (bool *) pg_malloc(ntups * sizeof(bool));
tbinfo->attlen = (int *) pg_malloc(ntups * sizeof(int));
tbinfo->attalign = (char *) pg_malloc(ntups * sizeof(char));
tbinfo->attoptions = (char **) pg_malloc(ntups * sizeof(char *));
tbinfo->attcollation = (Oid *) pg_malloc(ntups * sizeof(Oid));
tbinfo->attfdwoptions = (char **) pg_malloc(ntups * sizeof(char *));
+ tbinfo->attmissingval = (char **) pg_malloc(ntups * sizeof(char *));
tbinfo->notnull = (bool *) pg_malloc(ntups * sizeof(bool));
tbinfo->inhNotNull = (bool *) pg_malloc(ntups * sizeof(bool));
tbinfo->attrdefs = (AttrDefInfo **) pg_malloc(ntups * sizeof(AttrDefInfo *));
for (j = 0; j < ntups; j++)
{
if (j + 1 != atoi(PQgetvalue(res, j, i_attnum)))
- exit_horribly(NULL,
- "invalid column numbering in table \"%s\"\n",
- tbinfo->dobj.name);
+ fatal("invalid column numbering in table \"%s\"",
+ tbinfo->dobj.name);
tbinfo->attnames[j] = pg_strdup(PQgetvalue(res, j, i_attname));
tbinfo->atttypnames[j] = pg_strdup(PQgetvalue(res, j, i_atttypname));
tbinfo->atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod));
tbinfo->attstattarget[j] = atoi(PQgetvalue(res, j, i_attstattarget));
tbinfo->attstorage[j] = *(PQgetvalue(res, j, i_attstorage));
tbinfo->typstorage[j] = *(PQgetvalue(res, j, i_typstorage));
- tbinfo->attidentity[j] = (i_attidentity >= 0 ? *(PQgetvalue(res, j, i_attidentity)) : '\0');
+ tbinfo->attidentity[j] = *(PQgetvalue(res, j, i_attidentity));
+ tbinfo->attgenerated[j] = *(PQgetvalue(res, j, i_attgenerated));
tbinfo->needs_override = tbinfo->needs_override || (tbinfo->attidentity[j] == ATTRIBUTE_IDENTITY_ALWAYS);
tbinfo->attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't');
tbinfo->attlen[j] = atoi(PQgetvalue(res, j, i_attlen));
tbinfo->attoptions[j] = pg_strdup(PQgetvalue(res, j, i_attoptions));
tbinfo->attcollation[j] = atooid(PQgetvalue(res, j, i_attcollation));
tbinfo->attfdwoptions[j] = pg_strdup(PQgetvalue(res, j, i_attfdwoptions));
+ tbinfo->attmissingval[j] = pg_strdup(PQgetvalue(res, j, i_attmissingval));
tbinfo->attrdefs[j] = NULL; /* fix below */
if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
hasdefaults = true;
AttrDefInfo *attrdefs;
int numDefaults;
- if (g_verbose)
- write_msg(NULL, "finding default expressions of table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
+ pg_log_info("finding default expressions of table \"%s.%s\"",
+ tbinfo->dobj.namespace->dobj.name,
+ tbinfo->dobj.name);
printfPQExpBuffer(q, "SELECT tableoid, oid, adnum, "
"pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
adnum = atoi(PQgetvalue(res, j, 2));
if (adnum <= 0 || adnum > ntups)
- exit_horribly(NULL,
- "invalid adnum value %d for table \"%s\"\n",
- adnum, tbinfo->dobj.name);
+ fatal("invalid adnum value %d for table \"%s\"",
+ adnum, tbinfo->dobj.name);
/*
* dropped columns shouldn't have defaults, but just in case,
ConstraintInfo *constrs;
int numConstrs;
- if (g_verbose)
- write_msg(NULL, "finding check constraints for table \"%s.%s\"\n",
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->dobj.name);
+ pg_log_info("finding check constraints for table \"%s.%s\"",
+ tbinfo->dobj.namespace->dobj.name,
+ tbinfo->dobj.name);
resetPQExpBuffer(q);
if (fout->remoteVersion >= 90200)
numConstrs = PQntuples(res);
if (numConstrs != tbinfo->ncheck)
{
- write_msg(NULL, ngettext("expected %d check constraint on table \"%s\" but found %d\n",
- "expected %d check constraints on table \"%s\" but found %d\n",
- tbinfo->ncheck),
- tbinfo->ncheck, tbinfo->dobj.name, numConstrs);
- write_msg(NULL, "(The system catalogs might be corrupted.)\n");
+ pg_log_error(ngettext("expected %d check constraint on table \"%s\" but found %d",
+ "expected %d check constraints on table \"%s\" but found %d",
+ tbinfo->ncheck),
+ tbinfo->ncheck, tbinfo->dobj.name, numConstrs);
+ pg_log_error("(The system catalogs might be corrupted.)");
exit_nicely(1);
}
* Normally this is always true, but it's false for dropped columns, as well
* as those that were inherited without any local definition. (If we print
* such a column it will mistakenly get pg_attribute.attislocal set to true.)
- * However, in binary_upgrade mode, we must print all such columns anyway and
- * fix the attislocal/attisdropped state later, so as to keep control of the
- * physical column order.
+ * For partitions, it's always true, because we want the partitions to be
+ * created independently and ATTACH PARTITION used afterwards.
+ *
+ * In binary_upgrade mode, we must print all columns and fix the attislocal/
+ * attisdropped state later, so as to keep control of the physical column
+ * order.
*
* This function exists because there are scattered nonobvious places that
* must be kept in sync with this decision.
{
if (dopt->binary_upgrade)
return true;
- return (tbinfo->attislocal[colno] && !tbinfo->attisdropped[colno]);
+ if (tbinfo->attisdropped[colno])
+ return false;
+ return (tbinfo->attislocal[colno] || tbinfo->ispartition);
}
* system-defined objects at dump-out time.
*/
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBufferStr(query, "SELECT tableoid, oid, prsname, prsnamespace, "
"prsstart::oid, prstoken::oid, "
"prsend::oid, prsheadline::oid, prslextype::oid "
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBuffer(query, "SELECT tableoid, oid, dictname, "
"dictnamespace, (%s dictowner) AS rolname, "
"dicttemplate, dictinitoption "
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBufferStr(query, "SELECT tableoid, oid, tmplname, "
"tmplnamespace, tmplinit::oid, tmpllexize::oid "
"FROM pg_ts_template");
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBuffer(query, "SELECT tableoid, oid, cfgname, "
"cfgnamespace, (%s cfgowner) AS rolname, cfgparser "
"FROM pg_ts_config",
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
if (fout->remoteVersion >= 90600)
{
PQExpBuffer acl_subquery = createPQExpBuffer();
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
if (fout->remoteVersion >= 90600)
{
PQExpBuffer acl_subquery = createPQExpBuffer();
query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
if (fout->remoteVersion >= 90600)
{
PQExpBuffer acl_subquery = createPQExpBuffer();
* dumpComment --
*
* This routine is used to dump any comments associated with the
- * object handed to this routine. The routine takes a constant character
- * string for the target part of the comment-creation command, plus
+ * object handed to this routine. The routine takes the object type
+ * and object name (ready to print, except for schema decoration), plus
* the namespace and owner of the object (for labeling the ArchiveEntry),
* plus catalog ID and subid which are the lookup key for pg_description,
* plus the dump ID for the object (for setting a dependency).
* If a matching pg_description entry is found, it is dumped.
*
+ * Note: in some cases, such as comments for triggers and rules, the "type"
+ * string really looks like, e.g., "TRIGGER name ON". This is a bit of a hack
+ * but it doesn't seem worth complicating the API for all callers to make
+ * it cleaner.
+ *
* Note: although this routine takes a dumpId for dependency purposes,
* that purpose is just to mark the dependency in the emitted dump file
* for possible future use by pg_restore. We do NOT use it for determining
* calling ArchiveEntry() for the specified object.
*/
static void
-dumpComment(Archive *fout, const char *target,
+dumpComment(Archive *fout, const char *type, const char *name,
const char *namespace, const char *owner,
CatalogId catalogId, int subid, DumpId dumpId)
{
CommentItem *comments;
int ncomments;
+ /* do nothing, if --no-comments is supplied */
+ if (dopt->no_comments)
+ return;
+
/* Comments are schema not data ... except blob comments are data */
- if (strncmp(target, "LARGE OBJECT ", 13) != 0)
+ if (strcmp(type, "LARGE OBJECT") != 0)
{
if (dopt->dataOnly)
return;
if (ncomments > 0)
{
PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer tag = createPQExpBuffer();
- appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
+ appendPQExpBuffer(query, "COMMENT ON %s ", type);
+ if (namespace && *namespace)
+ appendPQExpBuffer(query, "%s.", fmtId(namespace));
+ appendPQExpBuffer(query, "%s IS ", name);
appendStringLiteralAH(query, comments->descr, fout);
appendPQExpBufferStr(query, ";\n");
+ appendPQExpBuffer(tag, "%s %s", type, name);
+
/*
* We mark comments as SECTION_NONE because they really belong in the
* same section as their parent, whether that is pre-data or
* post-data.
*/
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- target, namespace, NULL, owner,
- false, "COMMENT", SECTION_NONE,
- query->data, "", NULL,
- &(dumpId), 1,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag->data,
+ .namespace = namespace,
+ .owner = owner,
+ .description = "COMMENT",
+ .section = SECTION_NONE,
+ .createStmt = query->data,
+ .deps = &dumpId,
+ .nDeps = 1));
destroyPQExpBuffer(query);
+ destroyPQExpBuffer(tag);
}
}
CommentItem *comments;
int ncomments;
PQExpBuffer query;
- PQExpBuffer target;
+ PQExpBuffer tag;
+
+ /* do nothing, if --no-comments is supplied */
+ if (dopt->no_comments)
+ return;
/* Comments are SCHEMA not data */
if (dopt->dataOnly)
return;
query = createPQExpBuffer();
- target = createPQExpBuffer();
+ tag = createPQExpBuffer();
while (ncomments > 0)
{
if (objsubid == 0)
{
- resetPQExpBuffer(target);
- appendPQExpBuffer(target, "%s %s", reltypename,
+ resetPQExpBuffer(tag);
+ appendPQExpBuffer(tag, "%s %s", reltypename,
fmtId(tbinfo->dobj.name));
resetPQExpBuffer(query);
- appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
+ appendPQExpBuffer(query, "COMMENT ON %s %s IS ", reltypename,
+ fmtQualifiedDumpable(tbinfo));
appendStringLiteralAH(query, descr, fout);
appendPQExpBufferStr(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- target->data,
- tbinfo->dobj.namespace->dobj.name,
- NULL, tbinfo->rolname,
- false, "COMMENT", SECTION_NONE,
- query->data, "", NULL,
- &(tbinfo->dobj.dumpId), 1,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag->data,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "COMMENT",
+ .section = SECTION_NONE,
+ .createStmt = query->data,
+ .deps = &(tbinfo->dobj.dumpId),
+ .nDeps = 1));
}
else if (objsubid > 0 && objsubid <= tbinfo->numatts)
{
- resetPQExpBuffer(target);
- appendPQExpBuffer(target, "COLUMN %s.",
+ resetPQExpBuffer(tag);
+ appendPQExpBuffer(tag, "COLUMN %s.",
fmtId(tbinfo->dobj.name));
- appendPQExpBufferStr(target, fmtId(tbinfo->attnames[objsubid - 1]));
+ appendPQExpBufferStr(tag, fmtId(tbinfo->attnames[objsubid - 1]));
resetPQExpBuffer(query);
- appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
+ appendPQExpBuffer(query, "COMMENT ON COLUMN %s.",
+ fmtQualifiedDumpable(tbinfo));
+ appendPQExpBuffer(query, "%s IS ",
+ fmtId(tbinfo->attnames[objsubid - 1]));
appendStringLiteralAH(query, descr, fout);
appendPQExpBufferStr(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- target->data,
- tbinfo->dobj.namespace->dobj.name,
- NULL, tbinfo->rolname,
- false, "COMMENT", SECTION_NONE,
- query->data, "", NULL,
- &(tbinfo->dobj.dumpId), 1,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag->data,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "COMMENT",
+ .section = SECTION_NONE,
+ .createStmt = query->data,
+ .deps = &(tbinfo->dobj.dumpId),
+ .nDeps = 1));
}
comments++;
}
destroyPQExpBuffer(query);
- destroyPQExpBuffer(target);
+ destroyPQExpBuffer(tag);
}
/*
int i;
CommentItem *comments;
- /*
- * Note we do NOT change source schema here; preserve the caller's
- * setting, instead.
- */
-
query = createPQExpBuffer();
appendPQExpBufferStr(query, "SELECT description, classoid, objoid, objsubid "
case DO_INDEX:
dumpIndex(fout, (IndxInfo *) dobj);
break;
+ case DO_INDEX_ATTACH:
+ dumpIndexAttach(fout, (IndexAttachInfo *) dobj);
+ break;
case DO_STATSEXT:
dumpStatisticsExt(fout, (StatsExtInfo *) dobj);
break;
break;
case DO_BLOB_DATA:
if (dobj->dump & DUMP_COMPONENT_DATA)
- ArchiveEntry(fout, dobj->catId, dobj->dumpId,
- dobj->name, NULL, NULL, "",
- false, "BLOBS", SECTION_DATA,
- "", "", NULL,
- NULL, 0,
- dumpBlobs, NULL);
+ {
+ TocEntry *te;
+
+ te = ArchiveEntry(fout, dobj->catId, dobj->dumpId,
+ ARCHIVE_OPTS(.tag = dobj->name,
+ .description = "BLOBS",
+ .section = SECTION_DATA,
+ .dumpFn = dumpBlobs));
+
+ /*
+ * Set the TocEntry's dataLength in case we are doing a
+ * parallel dump and want to order dump jobs by table size.
+ * (We need some size estimate for every TocEntry with a
+ * DataDumper function.) We don't currently have any cheap
+ * way to estimate the size of blobs, but it doesn't matter;
+ * let's just set the size to a large value so parallel dumps
+ * will launch this job first. If there's lots of blobs, we
+ * win, and if there aren't, we don't lose much. (If you want
+ * to improve on this, really what you should be thinking
+ * about is allowing blob dumping to be parallelized, not just
+ * getting a smarter estimate for the single TOC entry.)
+ */
+ te->dataLength = MaxBlockNumber;
+ }
break;
case DO_POLICY:
dumpPolicy(fout, (PolicyInfo *) dobj);
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
char *qnspname;
/* Skip if not to be dumped */
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
qnspname = pg_strdup(fmtId(nspinfo->dobj.name));
appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
- appendPQExpBuffer(labelq, "SCHEMA %s", qnspname);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &nspinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &nspinfo->dobj,
+ "SCHEMA", qnspname, NULL);
if (nspinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
- nspinfo->dobj.name,
- NULL, NULL,
- nspinfo->rolname,
- false, "SCHEMA", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = nspinfo->dobj.name,
+ .owner = nspinfo->rolname,
+ .description = "SCHEMA",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Schema Comments and Security Labels */
if (nspinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "SCHEMA", qnspname,
NULL, nspinfo->rolname,
nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
if (nspinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "SCHEMA", qnspname,
NULL, nspinfo->rolname,
nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
if (nspinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
- qnspname, NULL, nspinfo->dobj.name, NULL,
+ qnspname, NULL, NULL,
nspinfo->rolname, nspinfo->nspacl, nspinfo->rnspacl,
nspinfo->initnspacl, nspinfo->initrnspacl);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
char *qextname;
/* Skip if not to be dumped */
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
qextname = pg_strdup(fmtId(extinfo->dobj.name));
if (!dopt->binary_upgrade)
{
/*
- * In a regular dump, we use IF NOT EXISTS so that there isn't a
- * problem if the extension already exists in the target database;
- * this is essential for installed-by-default extensions such as
- * plpgsql.
+ * In a regular dump, we simply create the extension, intentionally
+ * not specifying a version, so that the destination installation's
+ * default version is used.
*
- * In binary-upgrade mode, that doesn't work well, so instead we skip
- * built-in extensions based on their OIDs; see
- * selectDumpableExtension.
+ * Use of IF NOT EXISTS here is unlike our behavior for other object
+ * types; but there are various scenarios in which it's convenient to
+ * manually create the desired extension before restoring, so we
+ * prefer to allow it to exist already.
*/
appendPQExpBuffer(q, "CREATE EXTENSION IF NOT EXISTS %s WITH SCHEMA %s;\n",
qextname, fmtId(extinfo->namespace));
}
else
{
+ /*
+ * In binary-upgrade mode, it's critical to reproduce the state of the
+ * database exactly, so our procedure is to create an empty extension,
+ * restore all the contained objects normally, and add them to the
+ * extension one by one. This function performs just the first of
+ * those steps. binary_upgrade_extension_member() takes care of
+ * adding member objects as they're created.
+ */
int i;
int n;
* We unconditionally create the extension, so we must drop it if it
* exists. This could happen if the user deleted 'plpgsql' and then
* readded it, causing its oid to be greater than g_last_builtin_oid.
- * The g_last_builtin_oid test was kept to avoid repeatedly dropping
- * and recreating extensions like 'plpgsql'.
*/
appendPQExpBuffer(q, "DROP EXTENSION IF EXISTS %s;\n", qextname);
appendPQExpBufferStr(q, ");\n");
}
- appendPQExpBuffer(labelq, "EXTENSION %s", qextname);
-
if (extinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId,
- extinfo->dobj.name,
- NULL, NULL,
- "",
- false, "EXTENSION", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = extinfo->dobj.name,
+ .description = "EXTENSION",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Extension Comments and Security Labels */
if (extinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "EXTENSION", qextname,
NULL, "",
extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
if (extinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "EXTENSION", qextname,
NULL, "",
extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
}
/*
else if (tyinfo->typtype == TYPTYPE_PSEUDO && !tyinfo->isDefined)
dumpUndefinedType(fout, tyinfo);
else
- write_msg(NULL, "WARNING: typtype of data type \"%s\" appears to be invalid\n",
- tyinfo->dobj.name);
+ pg_log_warning("typtype of data type \"%s\" appears to be invalid",
+ tyinfo->dobj.name);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q = createPQExpBuffer();
PQExpBuffer delq = createPQExpBuffer();
- PQExpBuffer labelq = createPQExpBuffer();
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
int num,
i;
Oid enum_oid;
char *qtypname;
+ char *qualtypname;
char *label;
- /* Set proper schema search path */
- selectSourceSchema(fout, "pg_catalog");
-
if (fout->remoteVersion >= 90100)
appendPQExpBuffer(query, "SELECT oid, enumlabel "
"FROM pg_catalog.pg_enum "
num = PQntuples(res);
qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+ qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
/*
- * DROP must be fully qualified in case same name appears in pg_catalog.
* CASCADE shouldn't be required here as for normal types since the I/O
* functions are generic and do not get dropped.
*/
- appendPQExpBuffer(delq, "DROP TYPE %s.",
- fmtId(tyinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s;\n",
- qtypname);
+ appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
if (dopt->binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(fout, q,
false);
appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (",
- qtypname);
+ qualtypname);
if (!dopt->binary_upgrade)
{
appendPQExpBuffer(q,
"SELECT pg_catalog.binary_upgrade_set_next_pg_enum_oid('%u'::pg_catalog.oid);\n",
enum_oid);
- appendPQExpBuffer(q, "ALTER TYPE %s.",
- fmtId(tyinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(q, "%s ADD VALUE ",
- qtypname);
+ appendPQExpBuffer(q, "ALTER TYPE %s ADD VALUE ", qualtypname);
appendStringLiteralAH(q, label, fout);
appendPQExpBufferStr(q, ";\n\n");
}
}
- appendPQExpBuffer(labelq, "TYPE %s", qtypname);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &tyinfo->dobj,
+ "TYPE", qtypname,
+ tyinfo->dobj.namespace->dobj.name);
if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
- tyinfo->dobj.name,
- tyinfo->dobj.namespace->dobj.name,
- NULL,
- tyinfo->rolname, false,
- "TYPE", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+ .namespace = tyinfo->dobj.namespace->dobj.name,
+ .owner = tyinfo->rolname,
+ .description = "TYPE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Type Comments and Security Labels */
if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "TYPE", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "TYPE", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
- qtypname, NULL, tyinfo->dobj.name,
+ qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
tyinfo->inittypacl, tyinfo->initrtypacl);
PQclear(res);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(query);
+ free(qtypname);
+ free(qualtypname);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q = createPQExpBuffer();
PQExpBuffer delq = createPQExpBuffer();
- PQExpBuffer labelq = createPQExpBuffer();
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
Oid collationOid;
char *qtypname;
+ char *qualtypname;
char *procname;
- /*
- * select appropriate schema to ensure names in CREATE are properly
- * qualified
- */
- selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
-
appendPQExpBuffer(query,
"SELECT pg_catalog.format_type(rngsubtype, NULL) AS rngsubtype, "
"opc.opcname AS opcname, "
res = ExecuteSqlQueryForSingleRow(fout, query->data);
qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+ qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
/*
- * DROP must be fully qualified in case same name appears in pg_catalog.
* CASCADE shouldn't be required here as for normal types since the I/O
* functions are generic and do not get dropped.
*/
- appendPQExpBuffer(delq, "DROP TYPE %s.",
- fmtId(tyinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s;\n",
- qtypname);
+ appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
if (dopt->binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(fout, q,
false);
appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (",
- qtypname);
+ qualtypname);
appendPQExpBuffer(q, "\n subtype = %s",
PQgetvalue(res, 0, PQfnumber(res, "rngsubtype")));
char *opcname = PQgetvalue(res, 0, PQfnumber(res, "opcname"));
char *nspname = PQgetvalue(res, 0, PQfnumber(res, "opcnsp"));
- /* always schema-qualify, don't try to be smart */
appendPQExpBuffer(q, ",\n subtype_opclass = %s.",
fmtId(nspname));
appendPQExpBufferStr(q, fmtId(opcname));
CollInfo *coll = findCollationByOid(collationOid);
if (coll)
- {
- /* always schema-qualify, don't try to be smart */
- appendPQExpBuffer(q, ",\n collation = %s.",
- fmtId(coll->dobj.namespace->dobj.name));
- appendPQExpBufferStr(q, fmtId(coll->dobj.name));
- }
+ appendPQExpBuffer(q, ",\n collation = %s",
+ fmtQualifiedDumpable(coll));
}
procname = PQgetvalue(res, 0, PQfnumber(res, "rngcanonical"));
appendPQExpBufferStr(q, "\n);\n");
- appendPQExpBuffer(labelq, "TYPE %s", qtypname);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &tyinfo->dobj,
+ "TYPE", qtypname,
+ tyinfo->dobj.namespace->dobj.name);
if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
- tyinfo->dobj.name,
- tyinfo->dobj.namespace->dobj.name,
- NULL,
- tyinfo->rolname, false,
- "TYPE", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+ .namespace = tyinfo->dobj.namespace->dobj.name,
+ .owner = tyinfo->rolname,
+ .description = "TYPE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Type Comments and Security Labels */
if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "TYPE", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "TYPE", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
- qtypname, NULL, tyinfo->dobj.name,
+ qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
tyinfo->inittypacl, tyinfo->initrtypacl);
PQclear(res);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(query);
+ free(qtypname);
+ free(qualtypname);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q = createPQExpBuffer();
PQExpBuffer delq = createPQExpBuffer();
- PQExpBuffer labelq = createPQExpBuffer();
char *qtypname;
+ char *qualtypname;
qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+ qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog.
- */
- appendPQExpBuffer(delq, "DROP TYPE %s.",
- fmtId(tyinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s;\n",
- qtypname);
+ appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
if (dopt->binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(fout, q,
false);
appendPQExpBuffer(q, "CREATE TYPE %s;\n",
- qtypname);
-
- appendPQExpBuffer(labelq, "TYPE %s", qtypname);
+ qualtypname);
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &tyinfo->dobj,
+ "TYPE", qtypname,
+ tyinfo->dobj.namespace->dobj.name);
if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
- tyinfo->dobj.name,
- tyinfo->dobj.namespace->dobj.name,
- NULL,
- tyinfo->rolname, false,
- "TYPE", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+ .namespace = tyinfo->dobj.namespace->dobj.name,
+ .owner = tyinfo->rolname,
+ .description = "TYPE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Type Comments and Security Labels */
if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "TYPE", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "TYPE", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
- qtypname, NULL, tyinfo->dobj.name,
+ qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
tyinfo->inittypacl, tyinfo->initrtypacl);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ free(qtypname);
+ free(qualtypname);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q = createPQExpBuffer();
PQExpBuffer delq = createPQExpBuffer();
- PQExpBuffer labelq = createPQExpBuffer();
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
char *qtypname;
+ char *qualtypname;
char *typlen;
char *typinput;
char *typoutput;
char *typdefault;
bool typdefault_is_literal = false;
- /* Set proper schema search path so regproc references list correctly */
- selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
-
/* Fetch type-specific details */
if (fout->remoteVersion >= 90100)
{
typdefault = NULL;
qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+ qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
/*
- * DROP must be fully qualified in case same name appears in pg_catalog.
* The reason we include CASCADE is that the circular dependency between
* the type and its I/O functions makes it impossible to drop the type any
* other way.
*/
- appendPQExpBuffer(delq, "DROP TYPE %s.",
- fmtId(tyinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s CASCADE;\n",
- qtypname);
+ appendPQExpBuffer(delq, "DROP TYPE %s CASCADE;\n", qualtypname);
/*
* We might already have a shell type, but setting pg_type_oid is
appendPQExpBuffer(q,
"CREATE TYPE %s (\n"
" INTERNALLENGTH = %s",
- qtypname,
+ qualtypname,
(strcmp(typlen, "-1") == 0) ? "variable" : typlen);
/* regproc result is sufficiently quoted already */
{
char *elemType;
- /* reselect schema in case changed by function dump */
- selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
elemType = getFormattedTypeName(fout, tyinfo->typelem, zeroAsOpaque);
appendPQExpBuffer(q, ",\n ELEMENT = %s", elemType);
free(elemType);
appendPQExpBufferStr(q, "\n);\n");
- appendPQExpBuffer(labelq, "TYPE %s", qtypname);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &tyinfo->dobj,
+ "TYPE", qtypname,
+ tyinfo->dobj.namespace->dobj.name);
if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
- tyinfo->dobj.name,
- tyinfo->dobj.namespace->dobj.name,
- NULL,
- tyinfo->rolname, false,
- "TYPE", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+ .namespace = tyinfo->dobj.namespace->dobj.name,
+ .owner = tyinfo->rolname,
+ .description = "TYPE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Type Comments and Security Labels */
if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "TYPE", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "TYPE", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
- qtypname, NULL, tyinfo->dobj.name,
+ qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
tyinfo->inittypacl, tyinfo->initrtypacl);
PQclear(res);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(query);
+ free(qtypname);
+ free(qualtypname);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q = createPQExpBuffer();
PQExpBuffer delq = createPQExpBuffer();
- PQExpBuffer labelq = createPQExpBuffer();
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
int i;
char *qtypname;
+ char *qualtypname;
char *typnotnull;
char *typdefn;
char *typdefault;
Oid typcollation;
bool typdefault_is_literal = false;
- /* Set proper schema search path so type references list correctly */
- selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
-
/* Fetch domain specific details */
if (fout->remoteVersion >= 90100)
{
true); /* force array type */
qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+ qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
appendPQExpBuffer(q,
"CREATE DOMAIN %s AS %s",
- qtypname,
+ qualtypname,
typdefn);
/* Print collation only if different from base type's collation */
coll = findCollationByOid(typcollation);
if (coll)
- {
- /* always schema-qualify, don't try to be smart */
- appendPQExpBuffer(q, " COLLATE %s.",
- fmtId(coll->dobj.namespace->dobj.name));
- appendPQExpBufferStr(q, fmtId(coll->dobj.name));
- }
+ appendPQExpBuffer(q, " COLLATE %s", fmtQualifiedDumpable(coll));
}
if (typnotnull[0] == 't')
appendPQExpBufferStr(q, ";\n");
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
- appendPQExpBuffer(delq, "DROP DOMAIN %s.",
- fmtId(tyinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s;\n",
- qtypname);
-
- appendPQExpBuffer(labelq, "DOMAIN %s", qtypname);
+ appendPQExpBuffer(delq, "DROP DOMAIN %s;\n", qualtypname);
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &tyinfo->dobj,
+ "DOMAIN", qtypname,
+ tyinfo->dobj.namespace->dobj.name);
if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
- tyinfo->dobj.name,
- tyinfo->dobj.namespace->dobj.name,
- NULL,
- tyinfo->rolname, false,
- "DOMAIN", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+ .namespace = tyinfo->dobj.namespace->dobj.name,
+ .owner = tyinfo->rolname,
+ .description = "DOMAIN",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Domain Comments and Security Labels */
if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "DOMAIN", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "DOMAIN", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
- qtypname, NULL, tyinfo->dobj.name,
+ qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
tyinfo->inittypacl, tyinfo->initrtypacl);
for (i = 0; i < tyinfo->nDomChecks; i++)
{
ConstraintInfo *domcheck = &(tyinfo->domChecks[i]);
- PQExpBuffer labelq = createPQExpBuffer();
+ PQExpBuffer conprefix = createPQExpBuffer();
- appendPQExpBuffer(labelq, "CONSTRAINT %s ",
+ appendPQExpBuffer(conprefix, "CONSTRAINT %s ON DOMAIN",
fmtId(domcheck->dobj.name));
- appendPQExpBuffer(labelq, "ON DOMAIN %s",
- qtypname);
if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, conprefix->data, qtypname,
tyinfo->dobj.namespace->dobj.name,
tyinfo->rolname,
domcheck->dobj.catId, 0, tyinfo->dobj.dumpId);
- destroyPQExpBuffer(labelq);
+ destroyPQExpBuffer(conprefix);
}
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(query);
+ free(qtypname);
+ free(qualtypname);
}
/*
PQExpBuffer q = createPQExpBuffer();
PQExpBuffer dropped = createPQExpBuffer();
PQExpBuffer delq = createPQExpBuffer();
- PQExpBuffer labelq = createPQExpBuffer();
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
char *qtypname;
+ char *qualtypname;
int ntups;
int i_attname;
int i_atttypdefn;
int i;
int actual_atts;
- /* Set proper schema search path so type references list correctly */
- selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
-
/* Fetch type specific details */
if (fout->remoteVersion >= 90100)
{
}
qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+ qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
appendPQExpBuffer(q, "CREATE TYPE %s AS (",
- qtypname);
+ qualtypname);
actual_atts = 0;
for (i = 0; i < ntups; i++)
coll = findCollationByOid(attcollation);
if (coll)
- {
- /* always schema-qualify, don't try to be smart */
- appendPQExpBuffer(q, " COLLATE %s.",
- fmtId(coll->dobj.namespace->dobj.name));
- appendPQExpBufferStr(q, fmtId(coll->dobj.name));
- }
+ appendPQExpBuffer(q, " COLLATE %s",
+ fmtQualifiedDumpable(coll));
}
}
else
"WHERE attname = ", attlen, attalign);
appendStringLiteralAH(dropped, attname, fout);
appendPQExpBufferStr(dropped, "\n AND attrelid = ");
- appendStringLiteralAH(dropped, qtypname, fout);
+ appendStringLiteralAH(dropped, qualtypname, fout);
appendPQExpBufferStr(dropped, "::pg_catalog.regclass;\n");
appendPQExpBuffer(dropped, "ALTER TYPE %s ",
- qtypname);
+ qualtypname);
appendPQExpBuffer(dropped, "DROP ATTRIBUTE %s;\n",
fmtId(attname));
}
appendPQExpBufferStr(q, "\n);\n");
appendPQExpBufferStr(q, dropped->data);
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
- appendPQExpBuffer(delq, "DROP TYPE %s.",
- fmtId(tyinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s;\n",
- qtypname);
-
- appendPQExpBuffer(labelq, "TYPE %s", qtypname);
+ appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &tyinfo->dobj,
+ "TYPE", qtypname,
+ tyinfo->dobj.namespace->dobj.name);
if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
- tyinfo->dobj.name,
- tyinfo->dobj.namespace->dobj.name,
- NULL,
- tyinfo->rolname, false,
- "TYPE", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+ .namespace = tyinfo->dobj.namespace->dobj.name,
+ .owner = tyinfo->rolname,
+ .description = "TYPE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Type Comments and Security Labels */
if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "TYPE", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "TYPE", qtypname,
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
- qtypname, NULL, tyinfo->dobj.name,
+ qtypname, NULL,
tyinfo->dobj.namespace->dobj.name,
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
tyinfo->inittypacl, tyinfo->initrtypacl);
destroyPQExpBuffer(q);
destroyPQExpBuffer(dropped);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(query);
+ free(qtypname);
+ free(qualtypname);
/* Dump any per-column comments */
if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
int i_attname;
int i_attnum;
+ /* do nothing, if --no-comments is supplied */
+ if (fout->dopt->no_comments)
+ return;
+
query = createPQExpBuffer();
appendPQExpBuffer(query,
appendPQExpBufferStr(target, fmtId(attname));
resetPQExpBuffer(query);
- appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
+ appendPQExpBuffer(query, "COMMENT ON COLUMN %s.",
+ fmtQualifiedDumpable(tyinfo));
+ appendPQExpBuffer(query, "%s IS ", fmtId(attname));
appendStringLiteralAH(query, descr, fout);
appendPQExpBufferStr(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- target->data,
- tyinfo->dobj.namespace->dobj.name,
- NULL, tyinfo->rolname,
- false, "COMMENT", SECTION_NONE,
- query->data, "", NULL,
- &(tyinfo->dobj.dumpId), 1,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = target->data,
+ .namespace = tyinfo->dobj.namespace->dobj.name,
+ .owner = tyinfo->rolname,
+ .description = "COMMENT",
+ .section = SECTION_NONE,
+ .createStmt = query->data,
+ .deps = &(tyinfo->dobj.dumpId),
+ .nDeps = 1));
}
comments++;
false);
appendPQExpBuffer(q, "CREATE TYPE %s;\n",
- fmtId(stinfo->dobj.name));
+ fmtQualifiedDumpable(stinfo));
if (stinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
- stinfo->dobj.name,
- stinfo->dobj.namespace->dobj.name,
- NULL,
- stinfo->baseType->rolname, false,
- "SHELL TYPE", SECTION_PRE_DATA,
- q->data, "", NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = stinfo->dobj.name,
+ .namespace = stinfo->dobj.namespace->dobj.name,
+ .owner = stinfo->baseType->rolname,
+ .description = "SHELL TYPE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data));
destroyPQExpBuffer(q);
}
DumpOptions *dopt = fout->dopt;
PQExpBuffer defqry;
PQExpBuffer delqry;
- PQExpBuffer labelq;
bool useParams;
char *qlanname;
- char *lanschema;
FuncInfo *funcInfo;
FuncInfo *inlineInfo = NULL;
FuncInfo *validatorInfo = NULL;
defqry = createPQExpBuffer();
delqry = createPQExpBuffer();
- labelq = createPQExpBuffer();
qlanname = pg_strdup(fmtId(plang->dobj.name));
- /*
- * If dumping a HANDLER clause, treat the language as being in the handler
- * function's schema; this avoids cluttering the HANDLER clause. Otherwise
- * it doesn't really have a schema.
- */
- if (useParams)
- lanschema = funcInfo->dobj.namespace->dobj.name;
- else
- lanschema = NULL;
-
appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n",
qlanname);
plang->lanpltrusted ? "TRUSTED " : "",
qlanname);
appendPQExpBuffer(defqry, " HANDLER %s",
- fmtId(funcInfo->dobj.name));
+ fmtQualifiedDumpable(funcInfo));
if (OidIsValid(plang->laninline))
- {
- appendPQExpBufferStr(defqry, " INLINE ");
- /* Cope with possibility that inline is in different schema */
- if (inlineInfo->dobj.namespace != funcInfo->dobj.namespace)
- appendPQExpBuffer(defqry, "%s.",
- fmtId(inlineInfo->dobj.namespace->dobj.name));
- appendPQExpBufferStr(defqry, fmtId(inlineInfo->dobj.name));
- }
+ appendPQExpBuffer(defqry, " INLINE %s",
+ fmtQualifiedDumpable(inlineInfo));
if (OidIsValid(plang->lanvalidator))
- {
- appendPQExpBufferStr(defqry, " VALIDATOR ");
- /* Cope with possibility that validator is in different schema */
- if (validatorInfo->dobj.namespace != funcInfo->dobj.namespace)
- appendPQExpBuffer(defqry, "%s.",
- fmtId(validatorInfo->dobj.namespace->dobj.name));
- appendPQExpBufferStr(defqry, fmtId(validatorInfo->dobj.name));
- }
+ appendPQExpBuffer(defqry, " VALIDATOR %s",
+ fmtQualifiedDumpable(validatorInfo));
}
else
{
}
appendPQExpBufferStr(defqry, ";\n");
- appendPQExpBuffer(labelq, "LANGUAGE %s", qlanname);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(defqry, &plang->dobj, labelq->data);
+ binary_upgrade_extension_member(defqry, &plang->dobj,
+ "LANGUAGE", qlanname, NULL);
if (plang->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
- plang->dobj.name,
- lanschema, NULL, plang->lanowner,
- false, "PROCEDURAL LANGUAGE", SECTION_PRE_DATA,
- defqry->data, delqry->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = plang->dobj.name,
+ .owner = plang->lanowner,
+ .description = "PROCEDURAL LANGUAGE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = defqry->data,
+ .dropStmt = delqry->data,
+ ));
/* Dump Proc Lang Comments and Security Labels */
if (plang->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
- lanschema, plang->lanowner,
+ dumpComment(fout, "LANGUAGE", qlanname,
+ NULL, plang->lanowner,
plang->dobj.catId, 0, plang->dobj.dumpId);
if (plang->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
- lanschema, plang->lanowner,
+ dumpSecLabel(fout, "LANGUAGE", qlanname,
+ NULL, plang->lanowner,
plang->dobj.catId, 0, plang->dobj.dumpId);
if (plang->lanpltrusted && plang->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
- qlanname, NULL, plang->dobj.name,
- lanschema,
+ qlanname, NULL, NULL,
plang->lanowner, plang->lanacl, plang->rlanacl,
plang->initlanacl, plang->initrlanacl);
destroyPQExpBuffer(defqry);
destroyPQExpBuffer(delqry);
- destroyPQExpBuffer(labelq);
}
/*
argmode = "INOUT ";
break;
default:
- write_msg(NULL, "WARNING: bogus value in proargmodes array\n");
+ pg_log_warning("bogus value in proargmodes array");
argmode = "";
break;
}
PQExpBuffer query;
PQExpBuffer q;
PQExpBuffer delqry;
- PQExpBuffer labelq;
PQExpBuffer asPart;
PGresult *res;
char *funcsig; /* identity signature */
char *proargmodes;
char *proargnames;
char *protrftypes;
- char *proiswindow;
+ char *prokind;
char *provolatile;
char *proisstrict;
char *prosecdef;
char *proconfig;
char *procost;
char *prorows;
+ char *prosupport;
char *proparallel;
char *lanname;
char *rettypename;
char **argnames = NULL;
char **configitems = NULL;
int nconfigitems = 0;
+ const char *keyword;
int i;
/* Skip if not to be dumped */
query = createPQExpBuffer();
q = createPQExpBuffer();
delqry = createPQExpBuffer();
- labelq = createPQExpBuffer();
asPart = createPQExpBuffer();
- /* Set proper schema search path so type references list correctly */
- selectSourceSchema(fout, finfo->dobj.namespace->dobj.name);
-
/* Fetch function-specific details */
- if (fout->remoteVersion >= 90600)
+ if (fout->remoteVersion >= 120000)
+ {
+ /*
+ * prosupport was added in 12
+ */
+ appendPQExpBuffer(query,
+ "SELECT proretset, prosrc, probin, "
+ "pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
+ "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
+ "pg_catalog.pg_get_function_result(oid) AS funcresult, "
+ "array_to_string(protrftypes, ' ') AS protrftypes, "
+ "prokind, provolatile, proisstrict, prosecdef, "
+ "proleakproof, proconfig, procost, prorows, "
+ "prosupport, proparallel, "
+ "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
+ "FROM pg_catalog.pg_proc "
+ "WHERE oid = '%u'::pg_catalog.oid",
+ finfo->dobj.catId.oid);
+ }
+ else if (fout->remoteVersion >= 110000)
+ {
+ /*
+ * prokind was added in 11
+ */
+ appendPQExpBuffer(query,
+ "SELECT proretset, prosrc, probin, "
+ "pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
+ "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
+ "pg_catalog.pg_get_function_result(oid) AS funcresult, "
+ "array_to_string(protrftypes, ' ') AS protrftypes, "
+ "prokind, provolatile, proisstrict, prosecdef, "
+ "proleakproof, proconfig, procost, prorows, "
+ "'-' AS prosupport, proparallel, "
+ "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
+ "FROM pg_catalog.pg_proc "
+ "WHERE oid = '%u'::pg_catalog.oid",
+ finfo->dobj.catId.oid);
+ }
+ else if (fout->remoteVersion >= 90600)
{
/*
* proparallel was added in 9.6
"pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
"pg_catalog.pg_get_function_result(oid) AS funcresult, "
"array_to_string(protrftypes, ' ') AS protrftypes, "
- "proiswindow, provolatile, proisstrict, prosecdef, "
+ "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind, "
+ "provolatile, proisstrict, prosecdef, "
"proleakproof, proconfig, procost, prorows, "
- "proparallel, "
+ "'-' AS prosupport, proparallel, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
"FROM pg_catalog.pg_proc "
"WHERE oid = '%u'::pg_catalog.oid",
"pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
"pg_catalog.pg_get_function_result(oid) AS funcresult, "
"array_to_string(protrftypes, ' ') AS protrftypes, "
- "proiswindow, provolatile, proisstrict, prosecdef, "
+ "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind, "
+ "provolatile, proisstrict, prosecdef, "
"proleakproof, proconfig, procost, prorows, "
+ "'-' AS prosupport, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
"FROM pg_catalog.pg_proc "
"WHERE oid = '%u'::pg_catalog.oid",
"pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
"pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
"pg_catalog.pg_get_function_result(oid) AS funcresult, "
- "proiswindow, provolatile, proisstrict, prosecdef, "
+ "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind, "
+ "provolatile, proisstrict, prosecdef, "
"proleakproof, proconfig, procost, prorows, "
+ "'-' AS prosupport, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
"FROM pg_catalog.pg_proc "
"WHERE oid = '%u'::pg_catalog.oid",
"pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
"pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
"pg_catalog.pg_get_function_result(oid) AS funcresult, "
- "proiswindow, provolatile, proisstrict, prosecdef, "
+ "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind, "
+ "provolatile, proisstrict, prosecdef, "
"false AS proleakproof, "
" proconfig, procost, prorows, "
+ "'-' AS prosupport, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
"FROM pg_catalog.pg_proc "
"WHERE oid = '%u'::pg_catalog.oid",
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
"proallargtypes, proargmodes, proargnames, "
- "false AS proiswindow, "
+ "'f' AS prokind, "
"provolatile, proisstrict, prosecdef, "
"false AS proleakproof, "
"proconfig, procost, prorows, "
+ "'-' AS prosupport, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
"FROM pg_catalog.pg_proc "
"WHERE oid = '%u'::pg_catalog.oid",
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
"proallargtypes, proargmodes, proargnames, "
- "false AS proiswindow, "
+ "'f' AS prokind, "
"provolatile, proisstrict, prosecdef, "
"false AS proleakproof, "
"null AS proconfig, 0 AS procost, 0 AS prorows, "
+ "'-' AS prosupport, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
"FROM pg_catalog.pg_proc "
"WHERE oid = '%u'::pg_catalog.oid",
"null AS proallargtypes, "
"null AS proargmodes, "
"proargnames, "
- "false AS proiswindow, "
+ "'f' AS prokind, "
"provolatile, proisstrict, prosecdef, "
"false AS proleakproof, "
"null AS proconfig, 0 AS procost, 0 AS prorows, "
+ "'-' AS prosupport, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
"FROM pg_catalog.pg_proc "
"WHERE oid = '%u'::pg_catalog.oid",
protrftypes = PQgetvalue(res, 0, PQfnumber(res, "protrftypes"));
else
protrftypes = NULL;
- proiswindow = PQgetvalue(res, 0, PQfnumber(res, "proiswindow"));
+ prokind = PQgetvalue(res, 0, PQfnumber(res, "prokind"));
provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
proconfig = PQgetvalue(res, 0, PQfnumber(res, "proconfig"));
procost = PQgetvalue(res, 0, PQfnumber(res, "procost"));
prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
+ prosupport = PQgetvalue(res, 0, PQfnumber(res, "prosupport"));
if (PQfnumber(res, "proparallel") != -1)
proparallel = PQgetvalue(res, 0, PQfnumber(res, "proparallel"));
if (!parsePGArray(proallargtypes, &allargtypes, &nitems) ||
nitems < finfo->nargs)
{
- write_msg(NULL, "WARNING: could not parse proallargtypes array\n");
+ pg_log_warning("could not parse proallargtypes array");
if (allargtypes)
free(allargtypes);
allargtypes = NULL;
if (!parsePGArray(proargmodes, &argmodes, &nitems) ||
nitems != nallargs)
{
- write_msg(NULL, "WARNING: could not parse proargmodes array\n");
+ pg_log_warning("could not parse proargmodes array");
if (argmodes)
free(argmodes);
argmodes = NULL;
if (!parsePGArray(proargnames, &argnames, &nitems) ||
nitems != nallargs)
{
- write_msg(NULL, "WARNING: could not parse proargnames array\n");
+ pg_log_warning("could not parse proargnames array");
if (argnames)
free(argnames);
argnames = NULL;
{
if (!parsePGArray(proconfig, &configitems, &nconfigitems))
{
- write_msg(NULL, "WARNING: could not parse proconfig array\n");
+ pg_log_warning("could not parse proconfig array");
if (configitems)
free(configitems);
configitems = NULL;
funcsig_tag = format_function_signature(fout, finfo, false);
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
- appendPQExpBuffer(delqry, "DROP FUNCTION %s.%s;\n",
+ if (prokind[0] == PROKIND_PROCEDURE)
+ keyword = "PROCEDURE";
+ else
+ keyword = "FUNCTION"; /* works for window functions too */
+
+ appendPQExpBuffer(delqry, "DROP %s %s.%s;\n",
+ keyword,
fmtId(finfo->dobj.namespace->dobj.name),
funcsig);
- appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcfullsig ? funcfullsig :
+ appendPQExpBuffer(q, "CREATE %s %s.%s",
+ keyword,
+ fmtId(finfo->dobj.namespace->dobj.name),
+ funcfullsig ? funcfullsig :
funcsig);
- if (funcresult)
- appendPQExpBuffer(q, "RETURNS %s", funcresult);
+
+ if (prokind[0] == PROKIND_PROCEDURE)
+ /* no result type to output */ ;
+ else if (funcresult)
+ appendPQExpBuffer(q, " RETURNS %s", funcresult);
else
{
rettypename = getFormattedTypeName(fout, finfo->prorettype,
zeroAsOpaque);
- appendPQExpBuffer(q, "RETURNS %s%s",
+ appendPQExpBuffer(q, " RETURNS %s%s",
(proretset[0] == 't') ? "SETOF " : "",
rettypename);
free(rettypename);
}
}
- if (proiswindow[0] == 't')
+ if (prokind[0] == PROKIND_WINDOW)
appendPQExpBufferStr(q, " WINDOW");
if (provolatile[0] != PROVOLATILE_VOLATILE)
else if (provolatile[0] == PROVOLATILE_STABLE)
appendPQExpBufferStr(q, " STABLE");
else if (provolatile[0] != PROVOLATILE_VOLATILE)
- exit_horribly(NULL, "unrecognized provolatile value for function \"%s\"\n",
- finfo->dobj.name);
+ fatal("unrecognized provolatile value for function \"%s\"",
+ finfo->dobj.name);
}
if (proisstrict[0] == 't')
strcmp(prorows, "0") != 0 && strcmp(prorows, "1000") != 0)
appendPQExpBuffer(q, " ROWS %s", prorows);
+ if (strcmp(prosupport, "-") != 0)
+ {
+ /* We rely on regprocout to provide quoting and qualification */
+ appendPQExpBuffer(q, " SUPPORT %s", prosupport);
+ }
+
if (proparallel != NULL && proparallel[0] != PROPARALLEL_UNSAFE)
{
if (proparallel[0] == PROPARALLEL_SAFE)
else if (proparallel[0] == PROPARALLEL_RESTRICTED)
appendPQExpBufferStr(q, " PARALLEL RESTRICTED");
else if (proparallel[0] != PROPARALLEL_UNSAFE)
- exit_horribly(NULL, "unrecognized proparallel value for function \"%s\"\n",
- finfo->dobj.name);
+ fatal("unrecognized proparallel value for function \"%s\"",
+ finfo->dobj.name);
}
for (i = 0; i < nconfigitems; i++)
appendPQExpBuffer(q, "\n SET %s TO ", fmtId(configitem));
/*
- * Some GUC variable names are 'LIST' type and hence must not be
- * quoted.
+ * Variables that are marked GUC_LIST_QUOTE were already fully quoted
+ * by flatten_set_variable_args() before they were put into the
+ * proconfig array. However, because the quoting rules used there
+ * aren't exactly like SQL's, we have to break the list value apart
+ * and then quote the elements as string literals. (The elements may
+ * be double-quoted as-is, but we can't just feed them to the SQL
+ * parser; it would do the wrong thing with elements that are
+ * zero-length or longer than NAMEDATALEN.)
+ *
+ * Variables that are not so marked should just be emitted as simple
+ * string literals. If the variable is not known to
+ * variable_is_guc_list_quote(), we'll do that; this makes it unsafe
+ * to use GUC_LIST_QUOTE for extension variables.
*/
- if (pg_strcasecmp(configitem, "DateStyle") == 0
- || pg_strcasecmp(configitem, "search_path") == 0)
- appendPQExpBufferStr(q, pos);
+ if (variable_is_guc_list_quote(configitem))
+ {
+ char **namelist;
+ char **nameptr;
+
+ /* Parse string into list of identifiers */
+ /* this shouldn't fail really */
+ if (SplitGUCList(pos, ',', &namelist))
+ {
+ for (nameptr = namelist; *nameptr; nameptr++)
+ {
+ if (nameptr != namelist)
+ appendPQExpBufferStr(q, ", ");
+ appendStringLiteralAH(q, *nameptr, fout);
+ }
+ }
+ pg_free(namelist);
+ }
else
appendStringLiteralAH(q, pos, fout);
}
appendPQExpBuffer(q, "\n %s;\n", asPart->data);
- appendPQExpBuffer(labelq, "FUNCTION %s", funcsig);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &finfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &finfo->dobj,
+ keyword, funcsig,
+ finfo->dobj.namespace->dobj.name);
if (finfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
- funcsig_tag,
- finfo->dobj.namespace->dobj.name,
- NULL,
- finfo->rolname, false,
- "FUNCTION", SECTION_PRE_DATA,
- q->data, delqry->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = funcsig_tag,
+ .namespace = finfo->dobj.namespace->dobj.name,
+ .owner = finfo->rolname,
+ .description = keyword,
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delqry->data));
/* Dump Function Comments and Security Labels */
if (finfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, keyword, funcsig,
finfo->dobj.namespace->dobj.name, finfo->rolname,
finfo->dobj.catId, 0, finfo->dobj.dumpId);
if (finfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, keyword, funcsig,
finfo->dobj.namespace->dobj.name, finfo->rolname,
finfo->dobj.catId, 0, finfo->dobj.dumpId);
if (finfo->dobj.dump & DUMP_COMPONENT_ACL)
- dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, "FUNCTION",
- funcsig, NULL, funcsig_tag,
+ dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, keyword,
+ funcsig, NULL,
finfo->dobj.namespace->dobj.name,
finfo->rolname, finfo->proacl, finfo->rproacl,
finfo->initproacl, finfo->initrproacl);
destroyPQExpBuffer(query);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delqry);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(asPart);
free(funcsig);
if (funcfullsig)
PQExpBuffer defqry;
PQExpBuffer delqry;
PQExpBuffer labelq;
+ PQExpBuffer castargs;
FuncInfo *funcInfo = NULL;
char *sourceType;
char *targetType;
{
funcInfo = findFuncByOid(cast->castfunc);
if (funcInfo == NULL)
- exit_horribly(NULL, "could not find function definition for function with OID %u\n",
- cast->castfunc);
+ fatal("could not find function definition for function with OID %u",
+ cast->castfunc);
}
- /*
- * Make sure we are in proper schema (needed for getFormattedTypeName).
- * Casts don't have a schema of their own, so use pg_catalog.
- */
- selectSourceSchema(fout, "pg_catalog");
-
defqry = createPQExpBuffer();
delqry = createPQExpBuffer();
labelq = createPQExpBuffer();
+ castargs = createPQExpBuffer();
sourceType = getFormattedTypeName(fout, cast->castsource, zeroAsNone);
targetType = getFormattedTypeName(fout, cast->casttarget, zeroAsNone);
char *fsig = format_function_signature(fout, funcInfo, true);
/*
- * Always qualify the function name, in case it is not in
- * pg_catalog schema (format_function_signature won't qualify
- * it).
+ * Always qualify the function name (format_function_signature
+ * won't qualify it).
*/
appendPQExpBuffer(defqry, "WITH FUNCTION %s.%s",
fmtId(funcInfo->dobj.namespace->dobj.name), fsig);
free(fsig);
}
else
- write_msg(NULL, "WARNING: bogus value in pg_cast.castfunc or pg_cast.castmethod field\n");
+ pg_log_warning("bogus value in pg_cast.castfunc or pg_cast.castmethod field");
break;
default:
- write_msg(NULL, "WARNING: bogus value in pg_cast.castmethod field\n");
+ pg_log_warning("bogus value in pg_cast.castmethod field");
}
if (cast->castcontext == 'a')
appendPQExpBuffer(labelq, "CAST (%s AS %s)",
sourceType, targetType);
+ appendPQExpBuffer(castargs, "(%s AS %s)",
+ sourceType, targetType);
+
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(defqry, &cast->dobj, labelq->data);
+ binary_upgrade_extension_member(defqry, &cast->dobj,
+ "CAST", castargs->data, NULL);
if (cast->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
- labelq->data,
- "pg_catalog", NULL, "",
- false, "CAST", SECTION_PRE_DATA,
- defqry->data, delqry->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = labelq->data,
+ .description = "CAST",
+ .section = SECTION_PRE_DATA,
+ .createStmt = defqry->data,
+ .dropStmt = delqry->data));
/* Dump Cast Comments */
if (cast->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
- "pg_catalog", "",
+ dumpComment(fout, "CAST", castargs->data,
+ NULL, "",
cast->dobj.catId, 0, cast->dobj.dumpId);
free(sourceType);
destroyPQExpBuffer(defqry);
destroyPQExpBuffer(delqry);
destroyPQExpBuffer(labelq);
+ destroyPQExpBuffer(castargs);
}
/*
PQExpBuffer defqry;
PQExpBuffer delqry;
PQExpBuffer labelq;
+ PQExpBuffer transformargs;
FuncInfo *fromsqlFuncInfo = NULL;
FuncInfo *tosqlFuncInfo = NULL;
char *lanname;
{
fromsqlFuncInfo = findFuncByOid(transform->trffromsql);
if (fromsqlFuncInfo == NULL)
- exit_horribly(NULL, "could not find function definition for function with OID %u\n",
- transform->trffromsql);
+ fatal("could not find function definition for function with OID %u",
+ transform->trffromsql);
}
if (OidIsValid(transform->trftosql))
{
tosqlFuncInfo = findFuncByOid(transform->trftosql);
if (tosqlFuncInfo == NULL)
- exit_horribly(NULL, "could not find function definition for function with OID %u\n",
- transform->trftosql);
+ fatal("could not find function definition for function with OID %u",
+ transform->trftosql);
}
- /* Make sure we are in proper schema (needed for getFormattedTypeName) */
- selectSourceSchema(fout, "pg_catalog");
-
defqry = createPQExpBuffer();
delqry = createPQExpBuffer();
labelq = createPQExpBuffer();
+ transformargs = createPQExpBuffer();
lanname = get_language_name(fout, transform->trflang);
transformType = getFormattedTypeName(fout, transform->trftype, zeroAsNone);
transformType, lanname);
if (!transform->trffromsql && !transform->trftosql)
- write_msg(NULL, "WARNING: bogus transform definition, at least one of trffromsql and trftosql should be nonzero\n");
+ pg_log_warning("bogus transform definition, at least one of trffromsql and trftosql should be nonzero");
if (transform->trffromsql)
{
char *fsig = format_function_signature(fout, fromsqlFuncInfo, true);
/*
- * Always qualify the function name, in case it is not in
- * pg_catalog schema (format_function_signature won't qualify it).
+ * Always qualify the function name (format_function_signature
+ * won't qualify it).
*/
appendPQExpBuffer(defqry, "FROM SQL WITH FUNCTION %s.%s",
fmtId(fromsqlFuncInfo->dobj.namespace->dobj.name), fsig);
free(fsig);
}
else
- write_msg(NULL, "WARNING: bogus value in pg_transform.trffromsql field\n");
+ pg_log_warning("bogus value in pg_transform.trffromsql field");
}
if (transform->trftosql)
{
if (transform->trffromsql)
- appendPQExpBuffer(defqry, ", ");
+ appendPQExpBufferStr(defqry, ", ");
if (tosqlFuncInfo)
{
char *fsig = format_function_signature(fout, tosqlFuncInfo, true);
/*
- * Always qualify the function name, in case it is not in
- * pg_catalog schema (format_function_signature won't qualify it).
+ * Always qualify the function name (format_function_signature
+ * won't qualify it).
*/
appendPQExpBuffer(defqry, "TO SQL WITH FUNCTION %s.%s",
fmtId(tosqlFuncInfo->dobj.namespace->dobj.name), fsig);
free(fsig);
}
else
- write_msg(NULL, "WARNING: bogus value in pg_transform.trftosql field\n");
+ pg_log_warning("bogus value in pg_transform.trftosql field");
}
- appendPQExpBuffer(defqry, ");\n");
+ appendPQExpBufferStr(defqry, ");\n");
appendPQExpBuffer(labelq, "TRANSFORM FOR %s LANGUAGE %s",
transformType, lanname);
+ appendPQExpBuffer(transformargs, "FOR %s LANGUAGE %s",
+ transformType, lanname);
+
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(defqry, &transform->dobj, labelq->data);
+ binary_upgrade_extension_member(defqry, &transform->dobj,
+ "TRANSFORM", transformargs->data, NULL);
if (transform->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, transform->dobj.catId, transform->dobj.dumpId,
- labelq->data,
- "pg_catalog", NULL, "",
- false, "TRANSFORM", SECTION_PRE_DATA,
- defqry->data, delqry->data, NULL,
- transform->dobj.dependencies, transform->dobj.nDeps,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = labelq->data,
+ .description = "TRANSFORM",
+ .section = SECTION_PRE_DATA,
+ .createStmt = defqry->data,
+ .dropStmt = delqry->data,
+ .deps = transform->dobj.dependencies,
+ .nDeps = transform->dobj.nDeps));
/* Dump Transform Comments */
if (transform->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
- "pg_catalog", "",
+ dumpComment(fout, "TRANSFORM", transformargs->data,
+ NULL, "",
transform->dobj.catId, 0, transform->dobj.dumpId);
free(lanname);
destroyPQExpBuffer(defqry);
destroyPQExpBuffer(delqry);
destroyPQExpBuffer(labelq);
+ destroyPQExpBuffer(transformargs);
}
PQExpBuffer query;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
PQExpBuffer oprid;
PQExpBuffer details;
PGresult *res;
query = createPQExpBuffer();
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
oprid = createPQExpBuffer();
details = createPQExpBuffer();
- /* Make sure we are in proper schema so regoperator works correctly */
- selectSourceSchema(fout, oprinfo->dobj.namespace->dobj.name);
-
if (fout->remoteVersion >= 80300)
{
appendPQExpBuffer(query, "SELECT oprkind, "
"oprcode::pg_catalog.regprocedure, "
"oprleft::pg_catalog.regtype, "
"oprright::pg_catalog.regtype, "
- "oprcom::pg_catalog.regoperator, "
- "oprnegate::pg_catalog.regoperator, "
+ "oprcom, "
+ "oprnegate, "
"oprrest::pg_catalog.regprocedure, "
"oprjoin::pg_catalog.regprocedure, "
"oprcanmerge, oprcanhash "
"oprcode::pg_catalog.regprocedure, "
"oprleft::pg_catalog.regtype, "
"oprright::pg_catalog.regtype, "
- "oprcom::pg_catalog.regoperator, "
- "oprnegate::pg_catalog.regoperator, "
+ "oprcom, "
+ "oprnegate, "
"oprrest::pg_catalog.regprocedure, "
"oprjoin::pg_catalog.regprocedure, "
"(oprlsortop != 0) AS oprcanmerge, "
oprregproc = convertRegProcReference(fout, oprcode);
if (oprregproc)
{
- appendPQExpBuffer(details, " PROCEDURE = %s", oprregproc);
+ appendPQExpBuffer(details, " FUNCTION = %s", oprregproc);
free(oprregproc);
}
else
appendPQExpBufferStr(oprid, ", NONE)");
- oprref = convertOperatorReference(fout, oprcom);
+ oprref = getFormattedOperatorName(fout, oprcom);
if (oprref)
{
appendPQExpBuffer(details, ",\n COMMUTATOR = %s", oprref);
free(oprref);
}
- oprref = convertOperatorReference(fout, oprnegate);
+ oprref = getFormattedOperatorName(fout, oprnegate);
if (oprref)
{
appendPQExpBuffer(details, ",\n NEGATOR = %s", oprref);
free(oprregproc);
}
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
appendPQExpBuffer(delq, "DROP OPERATOR %s.%s;\n",
fmtId(oprinfo->dobj.namespace->dobj.name),
oprid->data);
- appendPQExpBuffer(q, "CREATE OPERATOR %s (\n%s\n);\n",
+ appendPQExpBuffer(q, "CREATE OPERATOR %s.%s (\n%s\n);\n",
+ fmtId(oprinfo->dobj.namespace->dobj.name),
oprinfo->dobj.name, details->data);
- appendPQExpBuffer(labelq, "OPERATOR %s", oprid->data);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &oprinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &oprinfo->dobj,
+ "OPERATOR", oprid->data,
+ oprinfo->dobj.namespace->dobj.name);
if (oprinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId,
- oprinfo->dobj.name,
- oprinfo->dobj.namespace->dobj.name,
- NULL,
- oprinfo->rolname,
- false, "OPERATOR", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = oprinfo->dobj.name,
+ .namespace = oprinfo->dobj.namespace->dobj.name,
+ .owner = oprinfo->rolname,
+ .description = "OPERATOR",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Operator Comments */
if (oprinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "OPERATOR", oprid->data,
oprinfo->dobj.namespace->dobj.name, oprinfo->rolname,
oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId);
destroyPQExpBuffer(query);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(oprid);
destroyPQExpBuffer(details);
}
}
/*
- * Convert an operator cross-reference obtained from pg_operator
+ * getFormattedOperatorName - retrieve the operator name for the
+ * given operator OID (presented in string form).
*
- * Returns an allocated string of what to print, or NULL to print nothing.
+ * Returns an allocated string, or NULL if the given OID is invalid.
* Caller is responsible for free'ing result string.
*
- * The input is a REGOPERATOR display; we have to strip the argument-types
- * part, and add OPERATOR() decoration if the name is schema-qualified.
+ * What we produce has the format "OPERATOR(schema.oprname)". This is only
+ * useful in commands where the operator's argument types can be inferred from
+ * context. We always schema-qualify the name, though. The predecessor to
+ * this code tried to skip the schema qualification if possible, but that led
+ * to wrong results in corner cases, such as if an operator and its negator
+ * are in different schemas.
*/
static char *
-convertOperatorReference(Archive *fout, const char *opr)
+getFormattedOperatorName(Archive *fout, const char *oproid)
{
- char *name;
- char *oname;
- char *ptr;
- bool inquote;
- bool sawdot;
+ OprInfo *oprInfo;
/* In all cases "0" means a null reference */
- if (strcmp(opr, "0") == 0)
+ if (strcmp(oproid, "0") == 0)
return NULL;
- name = pg_strdup(opr);
- /* find non-double-quoted left paren, and check for non-quoted dot */
- inquote = false;
- sawdot = false;
- for (ptr = name; *ptr; ptr++)
+ oprInfo = findOprByOid(atooid(oproid));
+ if (oprInfo == NULL)
{
- if (*ptr == '"')
- inquote = !inquote;
- else if (*ptr == '.' && !inquote)
- sawdot = true;
- else if (*ptr == '(' && !inquote)
- {
- *ptr = '\0';
- break;
- }
+ pg_log_warning("could not find operator with OID %s",
+ oproid);
+ return NULL;
}
- /* If not schema-qualified, don't need to add OPERATOR() */
- if (!sawdot)
- return name;
- oname = psprintf("OPERATOR(%s)", name);
- free(name);
- return oname;
+
+ return psprintf("OPERATOR(%s.%s)",
+ fmtId(oprInfo->dobj.namespace->dobj.name),
+ oprInfo->dobj.name);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
char *qamname;
/* Skip if not to be dumped */
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
qamname = pg_strdup(fmtId(aminfo->dobj.name));
switch (aminfo->amtype)
{
case AMTYPE_INDEX:
- appendPQExpBuffer(q, "TYPE INDEX ");
+ appendPQExpBufferStr(q, "TYPE INDEX ");
+ break;
+ case AMTYPE_TABLE:
+ appendPQExpBufferStr(q, "TYPE TABLE ");
break;
default:
- write_msg(NULL, "WARNING: invalid type \"%c\" of access method \"%s\"\n",
- aminfo->amtype, qamname);
- pg_free(qamname);
+ pg_log_warning("invalid type \"%c\" of access method \"%s\"",
+ aminfo->amtype, qamname);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ free(qamname);
return;
}
appendPQExpBuffer(delq, "DROP ACCESS METHOD %s;\n",
qamname);
- appendPQExpBuffer(labelq, "ACCESS METHOD %s",
- qamname);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &aminfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &aminfo->dobj,
+ "ACCESS METHOD", qamname, NULL);
if (aminfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, aminfo->dobj.catId, aminfo->dobj.dumpId,
- aminfo->dobj.name,
- NULL,
- NULL,
- "",
- false, "ACCESS METHOD", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = aminfo->dobj.name,
+ .description = "ACCESS METHOD",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Access Method Comments */
if (aminfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "ACCESS METHOD", qamname,
NULL, "",
aminfo->dobj.catId, 0, aminfo->dobj.dumpId);
- pg_free(qamname);
-
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ free(qamname);
}
/*
PQExpBuffer query;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
+ PQExpBuffer nameusing;
PGresult *res;
int ntups;
int i_opcintype;
query = createPQExpBuffer();
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
-
- /* Make sure we are in proper schema so regoperator works correctly */
- selectSourceSchema(fout, opcinfo->dobj.namespace->dobj.name);
+ nameusing = createPQExpBuffer();
/* Get additional fields from the pg_opclass row */
if (fout->remoteVersion >= 80300)
/* amname will still be needed after we PQclear res */
amname = pg_strdup(PQgetvalue(res, 0, i_amname));
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
appendPQExpBuffer(delq, "DROP OPERATOR CLASS %s",
- fmtId(opcinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, ".%s",
- fmtId(opcinfo->dobj.name));
+ fmtQualifiedDumpable(opcinfo));
appendPQExpBuffer(delq, " USING %s;\n",
fmtId(amname));
/* Build the fixed portion of the CREATE command */
appendPQExpBuffer(q, "CREATE OPERATOR CLASS %s\n ",
- fmtId(opcinfo->dobj.name));
+ fmtQualifiedDumpable(opcinfo));
if (strcmp(opcdefault, "t") == 0)
appendPQExpBufferStr(q, "DEFAULT ");
appendPQExpBuffer(q, "FOR TYPE %s USING %s",
if (strlen(opcfamilyname) > 0)
{
appendPQExpBufferStr(q, " FAMILY ");
- if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
- appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
+ appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
appendPQExpBufferStr(q, fmtId(opcfamilyname));
}
appendPQExpBufferStr(q, " AS\n ");
if (strlen(sortfamily) > 0)
{
appendPQExpBufferStr(q, " FOR ORDER BY ");
- if (strcmp(sortfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
- appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
+ appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
appendPQExpBufferStr(q, fmtId(sortfamily));
}
appendPQExpBufferStr(q, ";\n");
- appendPQExpBuffer(labelq, "OPERATOR CLASS %s",
- fmtId(opcinfo->dobj.name));
- appendPQExpBuffer(labelq, " USING %s",
+ appendPQExpBufferStr(nameusing, fmtId(opcinfo->dobj.name));
+ appendPQExpBuffer(nameusing, " USING %s",
fmtId(amname));
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &opcinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &opcinfo->dobj,
+ "OPERATOR CLASS", nameusing->data,
+ opcinfo->dobj.namespace->dobj.name);
if (opcinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
- opcinfo->dobj.name,
- opcinfo->dobj.namespace->dobj.name,
- NULL,
- opcinfo->rolname,
- false, "OPERATOR CLASS", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = opcinfo->dobj.name,
+ .namespace = opcinfo->dobj.namespace->dobj.name,
+ .owner = opcinfo->rolname,
+ .description = "OPERATOR CLASS",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Operator Class Comments */
if (opcinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "OPERATOR CLASS", nameusing->data,
opcinfo->dobj.namespace->dobj.name, opcinfo->rolname,
opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId);
destroyPQExpBuffer(query);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ destroyPQExpBuffer(nameusing);
}
/*
PQExpBuffer query;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
+ PQExpBuffer nameusing;
PGresult *res;
PGresult *res_ops;
PGresult *res_procs;
query = createPQExpBuffer();
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
-
- /* Make sure we are in proper schema so regoperator works correctly */
- selectSourceSchema(fout, opfinfo->dobj.namespace->dobj.name);
+ nameusing = createPQExpBuffer();
/*
* Fetch only those opfamily members that are tied directly to the
/* amname will still be needed after we PQclear res */
amname = pg_strdup(PQgetvalue(res, 0, i_amname));
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
appendPQExpBuffer(delq, "DROP OPERATOR FAMILY %s",
- fmtId(opfinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, ".%s",
- fmtId(opfinfo->dobj.name));
+ fmtQualifiedDumpable(opfinfo));
appendPQExpBuffer(delq, " USING %s;\n",
fmtId(amname));
/* Build the fixed portion of the CREATE command */
appendPQExpBuffer(q, "CREATE OPERATOR FAMILY %s",
- fmtId(opfinfo->dobj.name));
+ fmtQualifiedDumpable(opfinfo));
appendPQExpBuffer(q, " USING %s;\n",
fmtId(amname));
if (PQntuples(res_ops) > 0 || PQntuples(res_procs) > 0)
{
appendPQExpBuffer(q, "ALTER OPERATOR FAMILY %s",
- fmtId(opfinfo->dobj.name));
+ fmtQualifiedDumpable(opfinfo));
appendPQExpBuffer(q, " USING %s ADD\n ",
fmtId(amname));
if (strlen(sortfamily) > 0)
{
appendPQExpBufferStr(q, " FOR ORDER BY ");
- if (strcmp(sortfamilynsp, opfinfo->dobj.namespace->dobj.name) != 0)
- appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
+ appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
appendPQExpBufferStr(q, fmtId(sortfamily));
}
appendPQExpBufferStr(q, ";\n");
}
- appendPQExpBuffer(labelq, "OPERATOR FAMILY %s",
- fmtId(opfinfo->dobj.name));
- appendPQExpBuffer(labelq, " USING %s",
+ appendPQExpBufferStr(nameusing, fmtId(opfinfo->dobj.name));
+ appendPQExpBuffer(nameusing, " USING %s",
fmtId(amname));
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &opfinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &opfinfo->dobj,
+ "OPERATOR FAMILY", nameusing->data,
+ opfinfo->dobj.namespace->dobj.name);
if (opfinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
- opfinfo->dobj.name,
- opfinfo->dobj.namespace->dobj.name,
- NULL,
- opfinfo->rolname,
- false, "OPERATOR FAMILY", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = opfinfo->dobj.name,
+ .namespace = opfinfo->dobj.namespace->dobj.name,
+ .owner = opfinfo->rolname,
+ .description = "OPERATOR FAMILY",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Operator Family Comments */
if (opfinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "OPERATOR FAMILY", nameusing->data,
opfinfo->dobj.namespace->dobj.name, opfinfo->rolname,
opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId);
destroyPQExpBuffer(query);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ destroyPQExpBuffer(nameusing);
}
/*
PQExpBuffer query;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
+ char *qcollname;
PGresult *res;
int i_collprovider;
+ int i_collisdeterministic;
int i_collcollate;
int i_collctype;
const char *collprovider;
query = createPQExpBuffer();
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, collinfo->dobj.namespace->dobj.name);
+ qcollname = pg_strdup(fmtId(collinfo->dobj.name));
/* Get collation-specific details */
+ appendPQExpBufferStr(query, "SELECT ");
+
if (fout->remoteVersion >= 100000)
- appendPQExpBuffer(query, "SELECT "
- "collprovider, "
- "collcollate, "
- "collctype, "
- "collversion "
- "FROM pg_catalog.pg_collation c "
- "WHERE c.oid = '%u'::pg_catalog.oid",
- collinfo->dobj.catId.oid);
+ appendPQExpBufferStr(query,
+ "collprovider, "
+ "collversion, ");
else
- appendPQExpBuffer(query, "SELECT "
- "'c'::char AS collprovider, "
- "collcollate, "
- "collctype, "
- "NULL AS collversion "
- "FROM pg_catalog.pg_collation c "
- "WHERE c.oid = '%u'::pg_catalog.oid",
- collinfo->dobj.catId.oid);
+ appendPQExpBufferStr(query,
+ "'c' AS collprovider, "
+ "NULL AS collversion, ");
+
+ if (fout->remoteVersion >= 120000)
+ appendPQExpBufferStr(query,
+ "collisdeterministic, ");
+ else
+ appendPQExpBufferStr(query,
+ "true AS collisdeterministic, ");
+
+ appendPQExpBuffer(query,
+ "collcollate, "
+ "collctype "
+ "FROM pg_catalog.pg_collation c "
+ "WHERE c.oid = '%u'::pg_catalog.oid",
+ collinfo->dobj.catId.oid);
res = ExecuteSqlQueryForSingleRow(fout, query->data);
i_collprovider = PQfnumber(res, "collprovider");
+ i_collisdeterministic = PQfnumber(res, "collisdeterministic");
i_collcollate = PQfnumber(res, "collcollate");
i_collctype = PQfnumber(res, "collctype");
collcollate = PQgetvalue(res, 0, i_collcollate);
collctype = PQgetvalue(res, 0, i_collctype);
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
- appendPQExpBuffer(delq, "DROP COLLATION %s",
- fmtId(collinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, ".%s;\n",
- fmtId(collinfo->dobj.name));
+ appendPQExpBuffer(delq, "DROP COLLATION %s;\n",
+ fmtQualifiedDumpable(collinfo));
appendPQExpBuffer(q, "CREATE COLLATION %s (",
- fmtId(collinfo->dobj.name));
+ fmtQualifiedDumpable(collinfo));
appendPQExpBufferStr(q, "provider = ");
if (collprovider[0] == 'c')
/* to allow dumping pg_catalog; not accepted on input */
appendPQExpBufferStr(q, "default");
else
- exit_horribly(NULL,
- "unrecognized collation provider: %s\n",
- collprovider);
+ fatal("unrecognized collation provider: %s",
+ collprovider);
+
+ if (strcmp(PQgetvalue(res, 0, i_collisdeterministic), "f") == 0)
+ appendPQExpBufferStr(q, ", deterministic = false");
if (strcmp(collcollate, collctype) == 0)
{
appendPQExpBufferStr(q, ");\n");
- appendPQExpBuffer(labelq, "COLLATION %s", fmtId(collinfo->dobj.name));
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &collinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &collinfo->dobj,
+ "COLLATION", qcollname,
+ collinfo->dobj.namespace->dobj.name);
if (collinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, collinfo->dobj.catId, collinfo->dobj.dumpId,
- collinfo->dobj.name,
- collinfo->dobj.namespace->dobj.name,
- NULL,
- collinfo->rolname,
- false, "COLLATION", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = collinfo->dobj.name,
+ .namespace = collinfo->dobj.namespace->dobj.name,
+ .owner = collinfo->rolname,
+ .description = "COLLATION",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Collation Comments */
if (collinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "COLLATION", qcollname,
collinfo->dobj.namespace->dobj.name, collinfo->rolname,
collinfo->dobj.catId, 0, collinfo->dobj.dumpId);
destroyPQExpBuffer(query);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ free(qcollname);
}
/*
PQExpBuffer query;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
+ char *qconvname;
PGresult *res;
int i_conforencoding;
int i_contoencoding;
query = createPQExpBuffer();
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, convinfo->dobj.namespace->dobj.name);
+ qconvname = pg_strdup(fmtId(convinfo->dobj.name));
/* Get conversion-specific details */
appendPQExpBuffer(query, "SELECT "
conproc = PQgetvalue(res, 0, i_conproc);
condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't');
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
- appendPQExpBuffer(delq, "DROP CONVERSION %s",
- fmtId(convinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, ".%s;\n",
- fmtId(convinfo->dobj.name));
+ appendPQExpBuffer(delq, "DROP CONVERSION %s;\n",
+ fmtQualifiedDumpable(convinfo));
appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
(condefault) ? "DEFAULT " : "",
- fmtId(convinfo->dobj.name));
+ fmtQualifiedDumpable(convinfo));
appendStringLiteralAH(q, conforencoding, fout);
appendPQExpBufferStr(q, " TO ");
appendStringLiteralAH(q, contoencoding, fout);
/* regproc output is already sufficiently quoted */
appendPQExpBuffer(q, " FROM %s;\n", conproc);
- appendPQExpBuffer(labelq, "CONVERSION %s", fmtId(convinfo->dobj.name));
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &convinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &convinfo->dobj,
+ "CONVERSION", qconvname,
+ convinfo->dobj.namespace->dobj.name);
if (convinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId,
- convinfo->dobj.name,
- convinfo->dobj.namespace->dobj.name,
- NULL,
- convinfo->rolname,
- false, "CONVERSION", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = convinfo->dobj.name,
+ .namespace = convinfo->dobj.namespace->dobj.name,
+ .owner = convinfo->rolname,
+ .description = "CONVERSION",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Conversion Comments */
if (convinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "CONVERSION", qconvname,
convinfo->dobj.namespace->dobj.name, convinfo->rolname,
convinfo->dobj.catId, 0, convinfo->dobj.dumpId);
destroyPQExpBuffer(query);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ free(qconvname);
}
/*
appendPQExpBufferStr(&buf, agginfo->aggfn.dobj.name);
if (agginfo->aggfn.nargs == 0)
- appendPQExpBuffer(&buf, "(*)");
+ appendPQExpBufferStr(&buf, "(*)");
else
{
appendPQExpBufferChar(&buf, '(');
PQExpBuffer query;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
PQExpBuffer details;
char *aggsig; /* identity signature */
char *aggfullsig = NULL; /* full signature */
int i_aggmfinalfn;
int i_aggfinalextra;
int i_aggmfinalextra;
+ int i_aggfinalmodify;
+ int i_aggmfinalmodify;
int i_aggsortop;
- int i_hypothetical;
+ int i_aggkind;
int i_aggtranstype;
int i_aggtransspace;
int i_aggmtranstype;
const char *aggmfinalfn;
bool aggfinalextra;
bool aggmfinalextra;
+ char aggfinalmodify;
+ char aggmfinalmodify;
const char *aggsortop;
char *aggsortconvop;
- bool hypothetical;
+ char aggkind;
const char *aggtranstype;
const char *aggtransspace;
const char *aggmtranstype;
const char *aggminitval;
bool convertok;
const char *proparallel;
+ char defaultfinalmodify;
/* Skip if not to be dumped */
if (!agginfo->aggfn.dobj.dump || dopt->dataOnly)
query = createPQExpBuffer();
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
details = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, agginfo->aggfn.dobj.namespace->dobj.name);
-
/* Get aggregate-specific details */
- if (fout->remoteVersion >= 90600)
+ if (fout->remoteVersion >= 110000)
+ {
+ appendPQExpBuffer(query, "SELECT aggtransfn, "
+ "aggfinalfn, aggtranstype::pg_catalog.regtype, "
+ "aggcombinefn, aggserialfn, aggdeserialfn, aggmtransfn, "
+ "aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
+ "aggfinalextra, aggmfinalextra, "
+ "aggfinalmodify, aggmfinalmodify, "
+ "aggsortop, "
+ "aggkind, "
+ "aggtransspace, agginitval, "
+ "aggmtransspace, aggminitval, "
+ "true AS convertok, "
+ "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs, "
+ "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs, "
+ "p.proparallel "
+ "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
+ "WHERE a.aggfnoid = p.oid "
+ "AND p.oid = '%u'::pg_catalog.oid",
+ agginfo->aggfn.dobj.catId.oid);
+ }
+ else if (fout->remoteVersion >= 90600)
{
appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, "
"aggcombinefn, aggserialfn, aggdeserialfn, aggmtransfn, "
"aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
"aggfinalextra, aggmfinalextra, "
- "aggsortop::pg_catalog.regoperator, "
- "(aggkind = 'h') AS hypothetical, "
+ "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
+ "aggsortop, "
+ "aggkind, "
"aggtransspace, agginitval, "
"aggmtransspace, aggminitval, "
"true AS convertok, "
"'-' AS aggdeserialfn, aggmtransfn, aggminvtransfn, "
"aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
"aggfinalextra, aggmfinalextra, "
- "aggsortop::pg_catalog.regoperator, "
- "(aggkind = 'h') AS hypothetical, "
+ "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
+ "aggsortop, "
+ "aggkind, "
"aggtransspace, agginitval, "
"aggmtransspace, aggminitval, "
"true AS convertok, "
"'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
"0 AS aggmtranstype, false AS aggfinalextra, "
"false AS aggmfinalextra, "
- "aggsortop::pg_catalog.regoperator, "
- "false AS hypothetical, "
+ "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
+ "aggsortop, "
+ "'n' AS aggkind, "
"0 AS aggtransspace, agginitval, "
"0 AS aggmtransspace, NULL AS aggminitval, "
"true AS convertok, "
"'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
"0 AS aggmtranstype, false AS aggfinalextra, "
"false AS aggmfinalextra, "
- "aggsortop::pg_catalog.regoperator, "
- "false AS hypothetical, "
+ "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
+ "aggsortop, "
+ "'n' AS aggkind, "
"0 AS aggtransspace, agginitval, "
"0 AS aggmtransspace, NULL AS aggminitval, "
"true AS convertok "
"'-' AS aggdeserialfn, '-' AS aggmtransfn, "
"'-' AS aggminvtransfn, '-' AS aggmfinalfn, "
"0 AS aggmtranstype, false AS aggfinalextra, "
- "false AS aggmfinalextra, 0 AS aggsortop, "
- "false AS hypothetical, "
+ "false AS aggmfinalextra, "
+ "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
+ "0 AS aggsortop, "
+ "'n' AS aggkind, "
"0 AS aggtransspace, agginitval, "
"0 AS aggmtransspace, NULL AS aggminitval, "
"true AS convertok "
i_aggmfinalfn = PQfnumber(res, "aggmfinalfn");
i_aggfinalextra = PQfnumber(res, "aggfinalextra");
i_aggmfinalextra = PQfnumber(res, "aggmfinalextra");
+ i_aggfinalmodify = PQfnumber(res, "aggfinalmodify");
+ i_aggmfinalmodify = PQfnumber(res, "aggmfinalmodify");
i_aggsortop = PQfnumber(res, "aggsortop");
- i_hypothetical = PQfnumber(res, "hypothetical");
+ i_aggkind = PQfnumber(res, "aggkind");
i_aggtranstype = PQfnumber(res, "aggtranstype");
i_aggtransspace = PQfnumber(res, "aggtransspace");
i_aggmtranstype = PQfnumber(res, "aggmtranstype");
aggmfinalfn = PQgetvalue(res, 0, i_aggmfinalfn);
aggfinalextra = (PQgetvalue(res, 0, i_aggfinalextra)[0] == 't');
aggmfinalextra = (PQgetvalue(res, 0, i_aggmfinalextra)[0] == 't');
+ aggfinalmodify = PQgetvalue(res, 0, i_aggfinalmodify)[0];
+ aggmfinalmodify = PQgetvalue(res, 0, i_aggmfinalmodify)[0];
aggsortop = PQgetvalue(res, 0, i_aggsortop);
- hypothetical = (PQgetvalue(res, 0, i_hypothetical)[0] == 't');
+ aggkind = PQgetvalue(res, 0, i_aggkind)[0];
aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
aggtransspace = PQgetvalue(res, 0, i_aggtransspace);
aggmtranstype = PQgetvalue(res, 0, i_aggmtranstype);
if (!convertok)
{
- write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
- aggsig);
+ pg_log_warning("aggregate function %s could not be dumped correctly for this database version; ignored",
+ aggsig);
if (aggfullsig)
free(aggfullsig);
return;
}
+ /* identify default modify flag for aggkind (must match DefineAggregate) */
+ defaultfinalmodify = (aggkind == AGGKIND_NORMAL) ? AGGMODIFY_READ_ONLY : AGGMODIFY_READ_WRITE;
+ /* replace omitted flags for old versions */
+ if (aggfinalmodify == '0')
+ aggfinalmodify = defaultfinalmodify;
+ if (aggmfinalmodify == '0')
+ aggmfinalmodify = defaultfinalmodify;
+
/* regproc and regtype output is already sufficiently quoted */
appendPQExpBuffer(details, " SFUNC = %s,\n STYPE = %s",
aggtransfn, aggtranstype);
aggfinalfn);
if (aggfinalextra)
appendPQExpBufferStr(details, ",\n FINALFUNC_EXTRA");
+ if (aggfinalmodify != defaultfinalmodify)
+ {
+ switch (aggfinalmodify)
+ {
+ case AGGMODIFY_READ_ONLY:
+ appendPQExpBufferStr(details, ",\n FINALFUNC_MODIFY = READ_ONLY");
+ break;
+ case AGGMODIFY_SHAREABLE:
+ appendPQExpBufferStr(details, ",\n FINALFUNC_MODIFY = SHAREABLE");
+ break;
+ case AGGMODIFY_READ_WRITE:
+ appendPQExpBufferStr(details, ",\n FINALFUNC_MODIFY = READ_WRITE");
+ break;
+ default:
+ fatal("unrecognized aggfinalmodify value for aggregate \"%s\"",
+ agginfo->aggfn.dobj.name);
+ break;
+ }
+ }
}
if (strcmp(aggcombinefn, "-") != 0)
aggmfinalfn);
if (aggmfinalextra)
appendPQExpBufferStr(details, ",\n MFINALFUNC_EXTRA");
+ if (aggmfinalmodify != defaultfinalmodify)
+ {
+ switch (aggmfinalmodify)
+ {
+ case AGGMODIFY_READ_ONLY:
+ appendPQExpBufferStr(details, ",\n MFINALFUNC_MODIFY = READ_ONLY");
+ break;
+ case AGGMODIFY_SHAREABLE:
+ appendPQExpBufferStr(details, ",\n MFINALFUNC_MODIFY = SHAREABLE");
+ break;
+ case AGGMODIFY_READ_WRITE:
+ appendPQExpBufferStr(details, ",\n MFINALFUNC_MODIFY = READ_WRITE");
+ break;
+ default:
+ fatal("unrecognized aggmfinalmodify value for aggregate \"%s\"",
+ agginfo->aggfn.dobj.name);
+ break;
+ }
+ }
}
- aggsortconvop = convertOperatorReference(fout, aggsortop);
+ aggsortconvop = getFormattedOperatorName(fout, aggsortop);
if (aggsortconvop)
{
appendPQExpBuffer(details, ",\n SORTOP = %s",
free(aggsortconvop);
}
- if (hypothetical)
+ if (aggkind == AGGKIND_HYPOTHETICAL)
appendPQExpBufferStr(details, ",\n HYPOTHETICAL");
if (proparallel != NULL && proparallel[0] != PROPARALLEL_UNSAFE)
else if (proparallel[0] == PROPARALLEL_RESTRICTED)
appendPQExpBufferStr(details, ",\n PARALLEL = restricted");
else if (proparallel[0] != PROPARALLEL_UNSAFE)
- exit_horribly(NULL, "unrecognized proparallel value for function \"%s\"\n",
- agginfo->aggfn.dobj.name);
+ fatal("unrecognized proparallel value for function \"%s\"",
+ agginfo->aggfn.dobj.name);
}
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
appendPQExpBuffer(delq, "DROP AGGREGATE %s.%s;\n",
fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
aggsig);
- appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n",
+ appendPQExpBuffer(q, "CREATE AGGREGATE %s.%s (\n%s\n);\n",
+ fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
aggfullsig ? aggfullsig : aggsig, details->data);
- appendPQExpBuffer(labelq, "AGGREGATE %s", aggsig);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &agginfo->aggfn.dobj, labelq->data);
+ binary_upgrade_extension_member(q, &agginfo->aggfn.dobj,
+ "AGGREGATE", aggsig,
+ agginfo->aggfn.dobj.namespace->dobj.name);
if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, agginfo->aggfn.dobj.catId,
agginfo->aggfn.dobj.dumpId,
- aggsig_tag,
- agginfo->aggfn.dobj.namespace->dobj.name,
- NULL,
- agginfo->aggfn.rolname,
- false, "AGGREGATE", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = aggsig_tag,
+ .namespace = agginfo->aggfn.dobj.namespace->dobj.name,
+ .owner = agginfo->aggfn.rolname,
+ .description = "AGGREGATE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Aggregate Comments */
if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "AGGREGATE", aggsig,
agginfo->aggfn.dobj.namespace->dobj.name,
agginfo->aggfn.rolname,
agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "AGGREGATE", aggsig,
agginfo->aggfn.dobj.namespace->dobj.name,
agginfo->aggfn.rolname,
agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
* syntax for zero-argument aggregates and ordered-set aggregates.
*/
free(aggsig);
- free(aggsig_tag);
aggsig = format_function_signature(fout, &agginfo->aggfn, true);
- aggsig_tag = format_function_signature(fout, &agginfo->aggfn, false);
if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
- "FUNCTION",
- aggsig, NULL, aggsig_tag,
+ "FUNCTION", aggsig, NULL,
agginfo->aggfn.dobj.namespace->dobj.name,
agginfo->aggfn.rolname, agginfo->aggfn.proacl,
agginfo->aggfn.rproacl,
destroyPQExpBuffer(query);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(details);
}
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
+ char *qprsname;
/* Skip if not to be dumped */
if (!prsinfo->dobj.dump || dopt->dataOnly)
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, prsinfo->dobj.namespace->dobj.name);
+ qprsname = pg_strdup(fmtId(prsinfo->dobj.name));
appendPQExpBuffer(q, "CREATE TEXT SEARCH PARSER %s (\n",
- fmtId(prsinfo->dobj.name));
+ fmtQualifiedDumpable(prsinfo));
appendPQExpBuffer(q, " START = %s,\n",
convertTSFunction(fout, prsinfo->prsstart));
appendPQExpBuffer(q, " LEXTYPES = %s );\n",
convertTSFunction(fout, prsinfo->prslextype));
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
- appendPQExpBuffer(delq, "DROP TEXT SEARCH PARSER %s",
- fmtId(prsinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, ".%s;\n",
- fmtId(prsinfo->dobj.name));
-
- appendPQExpBuffer(labelq, "TEXT SEARCH PARSER %s",
- fmtId(prsinfo->dobj.name));
+ appendPQExpBuffer(delq, "DROP TEXT SEARCH PARSER %s;\n",
+ fmtQualifiedDumpable(prsinfo));
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &prsinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &prsinfo->dobj,
+ "TEXT SEARCH PARSER", qprsname,
+ prsinfo->dobj.namespace->dobj.name);
if (prsinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId,
- prsinfo->dobj.name,
- prsinfo->dobj.namespace->dobj.name,
- NULL,
- "",
- false, "TEXT SEARCH PARSER", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = prsinfo->dobj.name,
+ .namespace = prsinfo->dobj.namespace->dobj.name,
+ .description = "TEXT SEARCH PARSER",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Parser Comments */
if (prsinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "TEXT SEARCH PARSER", qprsname,
prsinfo->dobj.namespace->dobj.name, "",
prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ free(qprsname);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
PQExpBuffer query;
+ char *qdictname;
PGresult *res;
char *nspname;
char *tmplname;
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
query = createPQExpBuffer();
+ qdictname = pg_strdup(fmtId(dictinfo->dobj.name));
+
/* Fetch name and namespace of the dictionary's template */
- selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT nspname, tmplname "
"FROM pg_ts_template p, pg_namespace n "
"WHERE p.oid = '%u' AND n.oid = tmplnamespace",
nspname = PQgetvalue(res, 0, 0);
tmplname = PQgetvalue(res, 0, 1);
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, dictinfo->dobj.namespace->dobj.name);
-
appendPQExpBuffer(q, "CREATE TEXT SEARCH DICTIONARY %s (\n",
- fmtId(dictinfo->dobj.name));
+ fmtQualifiedDumpable(dictinfo));
appendPQExpBufferStr(q, " TEMPLATE = ");
- if (strcmp(nspname, dictinfo->dobj.namespace->dobj.name) != 0)
- appendPQExpBuffer(q, "%s.", fmtId(nspname));
+ appendPQExpBuffer(q, "%s.", fmtId(nspname));
appendPQExpBufferStr(q, fmtId(tmplname));
PQclear(res);
appendPQExpBufferStr(q, " );\n");
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
- appendPQExpBuffer(delq, "DROP TEXT SEARCH DICTIONARY %s",
- fmtId(dictinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, ".%s;\n",
- fmtId(dictinfo->dobj.name));
-
- appendPQExpBuffer(labelq, "TEXT SEARCH DICTIONARY %s",
- fmtId(dictinfo->dobj.name));
+ appendPQExpBuffer(delq, "DROP TEXT SEARCH DICTIONARY %s;\n",
+ fmtQualifiedDumpable(dictinfo));
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &dictinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &dictinfo->dobj,
+ "TEXT SEARCH DICTIONARY", qdictname,
+ dictinfo->dobj.namespace->dobj.name);
if (dictinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId,
- dictinfo->dobj.name,
- dictinfo->dobj.namespace->dobj.name,
- NULL,
- dictinfo->rolname,
- false, "TEXT SEARCH DICTIONARY", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = dictinfo->dobj.name,
+ .namespace = dictinfo->dobj.namespace->dobj.name,
+ .owner = dictinfo->rolname,
+ .description = "TEXT SEARCH DICTIONARY",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Dictionary Comments */
if (dictinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "TEXT SEARCH DICTIONARY", qdictname,
dictinfo->dobj.namespace->dobj.name, dictinfo->rolname,
dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(query);
+ free(qdictname);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
+ char *qtmplname;
/* Skip if not to be dumped */
if (!tmplinfo->dobj.dump || dopt->dataOnly)
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, tmplinfo->dobj.namespace->dobj.name);
+ qtmplname = pg_strdup(fmtId(tmplinfo->dobj.name));
appendPQExpBuffer(q, "CREATE TEXT SEARCH TEMPLATE %s (\n",
- fmtId(tmplinfo->dobj.name));
+ fmtQualifiedDumpable(tmplinfo));
if (tmplinfo->tmplinit != InvalidOid)
appendPQExpBuffer(q, " INIT = %s,\n",
appendPQExpBuffer(q, " LEXIZE = %s );\n",
convertTSFunction(fout, tmplinfo->tmpllexize));
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
- appendPQExpBuffer(delq, "DROP TEXT SEARCH TEMPLATE %s",
- fmtId(tmplinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, ".%s;\n",
- fmtId(tmplinfo->dobj.name));
-
- appendPQExpBuffer(labelq, "TEXT SEARCH TEMPLATE %s",
- fmtId(tmplinfo->dobj.name));
+ appendPQExpBuffer(delq, "DROP TEXT SEARCH TEMPLATE %s;\n",
+ fmtQualifiedDumpable(tmplinfo));
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &tmplinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &tmplinfo->dobj,
+ "TEXT SEARCH TEMPLATE", qtmplname,
+ tmplinfo->dobj.namespace->dobj.name);
if (tmplinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId,
- tmplinfo->dobj.name,
- tmplinfo->dobj.namespace->dobj.name,
- NULL,
- "",
- false, "TEXT SEARCH TEMPLATE", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tmplinfo->dobj.name,
+ .namespace = tmplinfo->dobj.namespace->dobj.name,
+ .description = "TEXT SEARCH TEMPLATE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Template Comments */
if (tmplinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "TEXT SEARCH TEMPLATE", qtmplname,
tmplinfo->dobj.namespace->dobj.name, "",
tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ free(qtmplname);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
PQExpBuffer query;
+ char *qcfgname;
PGresult *res;
char *nspname;
char *prsname;
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
query = createPQExpBuffer();
+ qcfgname = pg_strdup(fmtId(cfginfo->dobj.name));
+
/* Fetch name and namespace of the config's parser */
- selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT nspname, prsname "
"FROM pg_ts_parser p, pg_namespace n "
"WHERE p.oid = '%u' AND n.oid = prsnamespace",
nspname = PQgetvalue(res, 0, 0);
prsname = PQgetvalue(res, 0, 1);
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, cfginfo->dobj.namespace->dobj.name);
-
appendPQExpBuffer(q, "CREATE TEXT SEARCH CONFIGURATION %s (\n",
- fmtId(cfginfo->dobj.name));
+ fmtQualifiedDumpable(cfginfo));
- appendPQExpBufferStr(q, " PARSER = ");
- if (strcmp(nspname, cfginfo->dobj.namespace->dobj.name) != 0)
- appendPQExpBuffer(q, "%s.", fmtId(nspname));
+ appendPQExpBuffer(q, " PARSER = %s.", fmtId(nspname));
appendPQExpBuffer(q, "%s );\n", fmtId(prsname));
PQclear(res);
if (i > 0)
appendPQExpBufferStr(q, ";\n");
appendPQExpBuffer(q, "\nALTER TEXT SEARCH CONFIGURATION %s\n",
- fmtId(cfginfo->dobj.name));
+ fmtQualifiedDumpable(cfginfo));
/* tokenname needs quoting, dictname does NOT */
appendPQExpBuffer(q, " ADD MAPPING FOR %s WITH %s",
fmtId(tokenname), dictname);
PQclear(res);
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
- appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s",
- fmtId(cfginfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, ".%s;\n",
- fmtId(cfginfo->dobj.name));
-
- appendPQExpBuffer(labelq, "TEXT SEARCH CONFIGURATION %s",
- fmtId(cfginfo->dobj.name));
+ appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s;\n",
+ fmtQualifiedDumpable(cfginfo));
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &cfginfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &cfginfo->dobj,
+ "TEXT SEARCH CONFIGURATION", qcfgname,
+ cfginfo->dobj.namespace->dobj.name);
if (cfginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId,
- cfginfo->dobj.name,
- cfginfo->dobj.namespace->dobj.name,
- NULL,
- cfginfo->rolname,
- false, "TEXT SEARCH CONFIGURATION", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = cfginfo->dobj.name,
+ .namespace = cfginfo->dobj.namespace->dobj.name,
+ .owner = cfginfo->rolname,
+ .description = "TEXT SEARCH CONFIGURATION",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Configuration Comments */
if (cfginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "TEXT SEARCH CONFIGURATION", qcfgname,
cfginfo->dobj.namespace->dobj.name, cfginfo->rolname,
cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(query);
+ free(qcfgname);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
char *qfdwname;
/* Skip if not to be dumped */
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
qfdwname = pg_strdup(fmtId(fdwinfo->dobj.name));
appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n",
qfdwname);
- appendPQExpBuffer(labelq, "FOREIGN DATA WRAPPER %s",
- qfdwname);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &fdwinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &fdwinfo->dobj,
+ "FOREIGN DATA WRAPPER", qfdwname,
+ NULL);
if (fdwinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
- fdwinfo->dobj.name,
- NULL,
- NULL,
- fdwinfo->rolname,
- false, "FOREIGN DATA WRAPPER", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = fdwinfo->dobj.name,
+ .owner = fdwinfo->rolname,
+ .description = "FOREIGN DATA WRAPPER",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
+
+ /* Dump Foreign Data Wrapper Comments */
+ if (fdwinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
+ dumpComment(fout, "FOREIGN DATA WRAPPER", qfdwname,
+ NULL, fdwinfo->rolname,
+ fdwinfo->dobj.catId, 0, fdwinfo->dobj.dumpId);
/* Handle the ACL */
if (fdwinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
- "FOREIGN DATA WRAPPER",
- qfdwname, NULL, fdwinfo->dobj.name,
+ "FOREIGN DATA WRAPPER", qfdwname, NULL,
NULL, fdwinfo->rolname,
fdwinfo->fdwacl, fdwinfo->rfdwacl,
fdwinfo->initfdwacl, fdwinfo->initrfdwacl);
- /* Dump Foreign Data Wrapper Comments */
- if (fdwinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
- NULL, fdwinfo->rolname,
- fdwinfo->dobj.catId, 0, fdwinfo->dobj.dumpId);
-
free(qfdwname);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
PQExpBuffer query;
PGresult *res;
char *qsrvname;
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
query = createPQExpBuffer();
qsrvname = pg_strdup(fmtId(srvinfo->dobj.name));
/* look up the foreign-data wrapper */
- selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT fdwname "
"FROM pg_foreign_data_wrapper w "
"WHERE w.oid = '%u'",
appendPQExpBuffer(delq, "DROP SERVER %s;\n",
qsrvname);
- appendPQExpBuffer(labelq, "SERVER %s", qsrvname);
-
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &srvinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &srvinfo->dobj,
+ "SERVER", qsrvname, NULL);
if (srvinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
- srvinfo->dobj.name,
- NULL,
- NULL,
- srvinfo->rolname,
- false, "SERVER", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = srvinfo->dobj.name,
+ .owner = srvinfo->rolname,
+ .description = "SERVER",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
+
+ /* Dump Foreign Server Comments */
+ if (srvinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
+ dumpComment(fout, "SERVER", qsrvname,
+ NULL, srvinfo->rolname,
+ srvinfo->dobj.catId, 0, srvinfo->dobj.dumpId);
/* Handle the ACL */
if (srvinfo->dobj.dump & DUMP_COMPONENT_ACL)
dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
- "FOREIGN SERVER",
- qsrvname, NULL, srvinfo->dobj.name,
+ "FOREIGN SERVER", qsrvname, NULL,
NULL, srvinfo->rolname,
srvinfo->srvacl, srvinfo->rsrvacl,
srvinfo->initsrvacl, srvinfo->initrsrvacl);
srvinfo->rolname,
srvinfo->dobj.catId, srvinfo->dobj.dumpId);
- /* Dump Foreign Server Comments */
- if (srvinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
- NULL, srvinfo->rolname,
- srvinfo->dobj.catId, 0, srvinfo->dobj.dumpId);
-
free(qsrvname);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
destroyPQExpBuffer(query);
}
* OPTIONS clause. A possible alternative is to skip such mappings
* altogether, but it's not clear that that's an improvement.
*/
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBuffer(query,
"SELECT usename, "
"array_to_string(ARRAY("
usename, servername);
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- tag->data,
- namespace,
- NULL,
- owner, false,
- "USER MAPPING", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- &dumpId, 1,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag->data,
+ .namespace = namespace,
+ .owner = owner,
+ .description = "USER MAPPING",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
}
PQclear(res);
break;
default:
/* shouldn't get here */
- exit_horribly(NULL,
- "unrecognized object type in default privileges: %d\n",
- (int) daclinfo->defaclobjtype);
+ fatal("unrecognized object type in default privileges: %d",
+ (int) daclinfo->defaclobjtype);
type = ""; /* keep compiler quiet */
}
daclinfo->defaclrole,
fout->remoteVersion,
q))
- exit_horribly(NULL, "could not parse default ACL list (%s)\n",
- daclinfo->defaclacl);
+ fatal("could not parse default ACL list (%s)",
+ daclinfo->defaclacl);
if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL)
ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
- tag->data,
- daclinfo->dobj.namespace ? daclinfo->dobj.namespace->dobj.name : NULL,
- NULL,
- daclinfo->defaclrole,
- false, "DEFAULT ACL", SECTION_POST_DATA,
- q->data, "", NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag->data,
+ .namespace = daclinfo->dobj.namespace ?
+ daclinfo->dobj.namespace->dobj.name : NULL,
+ .owner = daclinfo->defaclrole,
+ .description = "DEFAULT ACL",
+ .section = SECTION_POST_DATA,
+ .createStmt = q->data));
destroyPQExpBuffer(tag);
destroyPQExpBuffer(q);
* FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT.
* 'name' is the formatted name of the object. Must be quoted etc. already.
* 'subname' is the formatted name of the sub-object, if any. Must be quoted.
- * 'tag' is the tag for the archive entry (typ. unquoted name of object).
+ * (Currently we assume that subname is only provided for table columns.)
* 'nspname' is the namespace the object is in (NULL if none).
* 'owner' is the owner, NULL if there is no owner (for languages).
* 'acls' contains the ACL string of the object from the appropriate system
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 *nspname, const char *owner,
const char *acls, const char *racls,
const char *initacls, const char *initracls)
{
*/
if (strlen(initacls) != 0 || strlen(initracls) != 0)
{
- appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
- if (!buildACLCommands(name, subname, type, initacls, initracls, owner,
+ appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
+ if (!buildACLCommands(name, subname, nspname, type,
+ initacls, initracls, owner,
"", fout->remoteVersion, sql))
- exit_horribly(NULL,
- "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)\n",
- initacls, initracls, name, type);
- appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
+ fatal("could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)",
+ initacls, initracls, name, type);
+ appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
}
- if (!buildACLCommands(name, subname, type, acls, racls, owner,
+ if (!buildACLCommands(name, subname, nspname, type,
+ acls, racls, owner,
"", fout->remoteVersion, sql))
- exit_horribly(NULL,
- "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)\n",
- acls, racls, name, type);
+ fatal("could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)",
+ acls, racls, name, type);
if (sql->len > 0)
+ {
+ PQExpBuffer tag = createPQExpBuffer();
+
+ if (subname)
+ appendPQExpBuffer(tag, "COLUMN %s.%s", name, subname);
+ else
+ appendPQExpBuffer(tag, "%s %s", type, name);
+
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- tag, nspname,
- NULL,
- owner ? owner : "",
- false, "ACL", SECTION_NONE,
- sql->data, "", NULL,
- &(objDumpId), 1,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag->data,
+ .namespace = nspname,
+ .owner = owner,
+ .description = "ACL",
+ .section = SECTION_NONE,
+ .createStmt = sql->data,
+ .deps = &objDumpId,
+ .nDeps = 1));
+ destroyPQExpBuffer(tag);
+ }
destroyPQExpBuffer(sql);
}
* dumpSecLabel
*
* This routine is used to dump any security labels associated with the
- * object handed to this routine. The routine takes a constant character
- * string for the target part of the security-label command, plus
+ * object handed to this routine. The routine takes the object type
+ * and object name (ready to print, except for schema decoration), plus
* the namespace and owner of the object (for labeling the ArchiveEntry),
* plus catalog ID and subid which are the lookup key for pg_seclabel,
* plus the dump ID for the object (for setting a dependency).
* calling ArchiveEntry() for the specified object.
*/
static void
-dumpSecLabel(Archive *fout, const char *target,
+dumpSecLabel(Archive *fout, const char *type, const char *name,
const char *namespace, const char *owner,
CatalogId catalogId, int subid, DumpId dumpId)
{
if (dopt->no_security_labels)
return;
- /* Comments are schema not data ... except blob comments are data */
- if (strncmp(target, "LARGE OBJECT ", 13) != 0)
+ /* Security labels are schema not data ... except blob labels are data */
+ if (strcmp(type, "LARGE OBJECT") != 0)
{
if (dopt->dataOnly)
return;
continue;
appendPQExpBuffer(query,
- "SECURITY LABEL FOR %s ON %s IS ",
- fmtId(labels[i].provider), target);
+ "SECURITY LABEL FOR %s ON %s ",
+ fmtId(labels[i].provider), type);
+ if (namespace && *namespace)
+ appendPQExpBuffer(query, "%s.", fmtId(namespace));
+ appendPQExpBuffer(query, "%s IS ", name);
appendStringLiteralAH(query, labels[i].label, fout);
appendPQExpBufferStr(query, ";\n");
}
if (query->len > 0)
{
+ PQExpBuffer tag = createPQExpBuffer();
+
+ appendPQExpBuffer(tag, "%s %s", type, name);
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- target, namespace, NULL, owner,
- false, "SECURITY LABEL", SECTION_NONE,
- query->data, "", NULL,
- &(dumpId), 1,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag->data,
+ .namespace = namespace,
+ .owner = owner,
+ .description = "SECURITY LABEL",
+ .section = SECTION_NONE,
+ .createStmt = query->data,
+ .deps = &dumpId,
+ .nDeps = 1));
+ destroyPQExpBuffer(tag);
}
+
destroyPQExpBuffer(query);
}
if (objsubid == 0)
{
appendPQExpBuffer(target, "%s %s", reltypename,
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
}
else
{
colname = getAttrName(objsubid, tbinfo);
- /* first fmtId result must be consumed before calling it again */
- appendPQExpBuffer(target, "COLUMN %s", fmtId(tbinfo->dobj.name));
+ /* first fmtXXX result must be consumed before calling again */
+ appendPQExpBuffer(target, "COLUMN %s",
+ fmtQualifiedDumpable(tbinfo));
appendPQExpBuffer(target, ".%s", fmtId(colname));
}
appendPQExpBuffer(query, "SECURITY LABEL FOR %s ON %s IS ",
appendPQExpBuffer(target, "%s %s", reltypename,
fmtId(tbinfo->dobj.name));
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- target->data,
- tbinfo->dobj.namespace->dobj.name,
- NULL, tbinfo->rolname,
- false, "SECURITY LABEL", SECTION_NONE,
- query->data, "", NULL,
- &(tbinfo->dobj.dumpId), 1,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = target->data,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "SECURITY LABEL",
+ .section = SECTION_NONE,
+ .createStmt = query->data,
+ .deps = &(tbinfo->dobj.dumpId),
+ .nDeps = 1));
}
destroyPQExpBuffer(query);
destroyPQExpBuffer(target);
/* Handle the ACL here */
namecopy = pg_strdup(fmtId(tbinfo->dobj.name));
if (tbinfo->dobj.dump & DUMP_COMPONENT_ACL)
+ {
+ const char *objtype =
+ (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE";
+
dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
- (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" :
- "TABLE",
- namecopy, NULL, tbinfo->dobj.name,
+ objtype, namecopy, NULL,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
tbinfo->relacl, tbinfo->rrelacl,
tbinfo->initrelacl, tbinfo->initrrelacl);
+ }
/*
* Handle column ACLs, if any. Note: we pull these with a separate query
char *initattacl = PQgetvalue(res, i, 3);
char *initrattacl = PQgetvalue(res, i, 4);
char *attnamecopy;
- char *acltag;
attnamecopy = pg_strdup(fmtId(attname));
- acltag = psprintf("%s.%s", tbinfo->dobj.name, attname);
/* Column's GRANT type is always TABLE */
- dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
- namecopy, attnamecopy, acltag,
+ dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
+ "TABLE", namecopy, attnamecopy,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
attacl, rattacl, initattacl, initrattacl);
free(attnamecopy);
- free(acltag);
}
PQclear(res);
destroyPQExpBuffer(query);
if (PQntuples(res) != 1)
{
if (PQntuples(res) < 1)
- exit_horribly(NULL, "query to obtain definition of view \"%s\" returned no data\n",
- tbinfo->dobj.name);
+ fatal("query to obtain definition of view \"%s\" returned no data",
+ tbinfo->dobj.name);
else
- exit_horribly(NULL, "query to obtain definition of view \"%s\" returned more than one definition\n",
- tbinfo->dobj.name);
+ fatal("query to obtain definition of view \"%s\" returned more than one definition",
+ tbinfo->dobj.name);
}
len = PQgetlength(res, 0, 0);
if (len == 0)
- exit_horribly(NULL, "definition of view \"%s\" appears to be empty (length zero)\n",
- tbinfo->dobj.name);
+ fatal("definition of view \"%s\" appears to be empty (length zero)",
+ tbinfo->dobj.name);
/* Strip off the trailing semicolon so that other things may follow. */
Assert(PQgetvalue(res, 0, 0)[len - 1] == ';');
coll = findCollationByOid(tbinfo->attcollation[j]);
if (coll)
- {
- /* always schema-qualify, don't try to be smart */
- appendPQExpBuffer(result, " COLLATE %s.",
- fmtId(coll->dobj.namespace->dobj.name));
- appendPQExpBufferStr(result, fmtId(coll->dobj.name));
- }
+ appendPQExpBuffer(result, " COLLATE %s",
+ fmtQualifiedDumpable(coll));
}
appendPQExpBuffer(result, " AS %s", fmtId(tbinfo->attnames[j]));
DumpOptions *dopt = fout->dopt;
PQExpBuffer q = createPQExpBuffer();
PQExpBuffer delq = createPQExpBuffer();
- PQExpBuffer labelq = createPQExpBuffer();
+ char *qrelname;
+ char *qualrelname;
int numParents;
TableInfo **parents;
int actual_atts; /* number of attrs in this CREATE statement */
const char *reltypename;
char *storage;
- char *srvname;
- char *ftoptions;
int j,
k;
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+ qrelname = pg_strdup(fmtId(tbinfo->dobj.name));
+ qualrelname = pg_strdup(fmtQualifiedDumpable(tbinfo));
+
+
+ if (tbinfo->hasoids)
+ pg_log_warning("WITH OIDS is not supported anymore (table \"%s\")",
+ qrelname);
if (dopt->binary_upgrade)
binary_upgrade_set_type_oids_by_rel_oid(fout, q,
reltypename = "VIEW";
- /*
- * DROP must be fully qualified in case same name appears in
- * pg_catalog
- */
- appendPQExpBuffer(delq, "DROP VIEW %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s;\n",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delq, "DROP VIEW %s;\n", qualrelname);
if (dopt->binary_upgrade)
binary_upgrade_set_pg_class_oids(fout, q,
tbinfo->dobj.catId.oid, false);
- appendPQExpBuffer(q, "CREATE VIEW %s", fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(q, "CREATE VIEW %s", qualrelname);
+
if (tbinfo->dummy_view)
result = createDummyViewAsClause(fout, tbinfo);
else
if (tbinfo->checkoption != NULL && !tbinfo->dummy_view)
appendPQExpBuffer(q, "\n WITH %s CHECK OPTION", tbinfo->checkoption);
appendPQExpBufferStr(q, ";\n");
-
- appendPQExpBuffer(labelq, "VIEW %s",
- fmtId(tbinfo->dobj.name));
}
else
{
+ char *ftoptions = NULL;
+ char *srvname = NULL;
+
switch (tbinfo->relkind)
{
case RELKIND_FOREIGN_TABLE:
}
case RELKIND_MATVIEW:
reltypename = "MATERIALIZED VIEW";
- srvname = NULL;
- ftoptions = NULL;
break;
default:
reltypename = "TABLE";
- srvname = NULL;
- ftoptions = NULL;
}
numParents = tbinfo->numParents;
parents = tbinfo->parents;
- /*
- * DROP must be fully qualified in case same name appears in
- * pg_catalog
- */
- appendPQExpBuffer(delq, "DROP %s %s.", reltypename,
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s;\n",
- fmtId(tbinfo->dobj.name));
-
- appendPQExpBuffer(labelq, "%s %s", reltypename,
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delq, "DROP %s %s;\n", reltypename, qualrelname);
if (dopt->binary_upgrade)
binary_upgrade_set_pg_class_oids(fout, q,
tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ?
"UNLOGGED " : "",
reltypename,
- fmtId(tbinfo->dobj.name));
+ qualrelname);
/*
* Attach to type, if reloftype; except in case of a binary upgrade,
if (tbinfo->reloftype && !dopt->binary_upgrade)
appendPQExpBuffer(q, " OF %s", tbinfo->reloftype);
- /*
- * If the table is a partition, dump it as such; except in the case of
- * a binary upgrade, we dump the table normally and attach it to the
- * parent afterward.
- */
- if (tbinfo->ispartition && !dopt->binary_upgrade)
- {
- TableInfo *parentRel = tbinfo->parents[0];
-
- /*
- * With partitions, unlike inheritance, there can only be one
- * parent.
- */
- if (tbinfo->numParents != 1)
- exit_horribly(NULL, "invalid number of parents %d for table \"%s\"\n",
- tbinfo->numParents, tbinfo->dobj.name);
-
- appendPQExpBuffer(q, " PARTITION OF ");
- if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
- appendPQExpBuffer(q, "%s.",
- fmtId(parentRel->dobj.namespace->dobj.name));
- appendPQExpBufferStr(q, fmtId(parentRel->dobj.name));
- }
-
if (tbinfo->relkind != RELKIND_MATVIEW)
{
/* Dump the attributes */
*/
if (shouldPrintColumn(dopt, tbinfo, j))
{
+ bool print_default;
+ bool print_notnull;
+
/*
* Default value --- suppress if to be printed separately.
*/
- bool has_default = (tbinfo->attrdefs[j] != NULL &&
- !tbinfo->attrdefs[j]->separate);
+ print_default = (tbinfo->attrdefs[j] != NULL &&
+ !tbinfo->attrdefs[j]->separate);
/*
* Not Null constraint --- suppress if inherited, except
- * in binary-upgrade case where that won't work.
+ * if partition, or in binary-upgrade case where that
+ * won't work.
*/
- bool has_notnull = (tbinfo->notnull[j] &&
- (!tbinfo->inhNotNull[j] ||
- dopt->binary_upgrade));
+ print_notnull = (tbinfo->notnull[j] &&
+ (!tbinfo->inhNotNull[j] ||
+ tbinfo->ispartition || dopt->binary_upgrade));
/*
- * Skip column if fully defined by reloftype or the
- * partition parent.
+ * Skip column if fully defined by reloftype, except in
+ * binary upgrade
*/
- if ((tbinfo->reloftype || tbinfo->ispartition) &&
- !has_default && !has_notnull && !dopt->binary_upgrade)
+ if (tbinfo->reloftype && !print_default && !print_notnull &&
+ !dopt->binary_upgrade)
continue;
/* Format properly if not first attr */
* clean things up later.
*/
appendPQExpBufferStr(q, " INTEGER /* dummy */");
- /* Skip all the rest, too */
+ /* and skip to the next column */
continue;
}
/*
- * Attribute type
- *
- * In binary-upgrade mode, we always include the type. If
- * we aren't in binary-upgrade mode, then we skip the type
- * when creating a typed table ('OF type_name') or a
- * partition ('PARTITION OF'), since the type comes from
- * the parent/partitioned table.
+ * Attribute type; print it except when creating a typed
+ * table ('OF type_name'), but in binary-upgrade mode,
+ * print it in that case too.
*/
- if (dopt->binary_upgrade || (!tbinfo->reloftype && !tbinfo->ispartition))
+ if (dopt->binary_upgrade || !tbinfo->reloftype)
{
appendPQExpBuffer(q, " %s",
tbinfo->atttypnames[j]);
}
+ if (print_default)
+ {
+ if (tbinfo->attgenerated[j] == ATTRIBUTE_GENERATED_STORED)
+ appendPQExpBuffer(q, " GENERATED ALWAYS AS (%s) STORED",
+ tbinfo->attrdefs[j]->adef_expr);
+ else
+ appendPQExpBuffer(q, " DEFAULT %s",
+ tbinfo->attrdefs[j]->adef_expr);
+ }
+
+
+ if (print_notnull)
+ appendPQExpBufferStr(q, " NOT NULL");
+
/* Add collation if not default for the type */
if (OidIsValid(tbinfo->attcollation[j]))
{
coll = findCollationByOid(tbinfo->attcollation[j]);
if (coll)
- {
- /* always schema-qualify, don't try to be smart */
- appendPQExpBuffer(q, " COLLATE %s.",
- fmtId(coll->dobj.namespace->dobj.name));
- appendPQExpBufferStr(q, fmtId(coll->dobj.name));
- }
+ appendPQExpBuffer(q, " COLLATE %s",
+ fmtQualifiedDumpable(coll));
}
-
- if (has_default)
- appendPQExpBuffer(q, " DEFAULT %s",
- tbinfo->attrdefs[j]->adef_expr);
-
- if (has_notnull)
- appendPQExpBufferStr(q, " NOT NULL");
}
}
/*
* Add non-inherited CHECK constraints, if any.
+ *
+ * For partitions, we need to include check constraints even if
+ * they're not defined locally, because the ALTER TABLE ATTACH
+ * PARTITION that we'll emit later expects the constraint to be
+ * there. (No need to fix conislocal: ATTACH PARTITION does that)
*/
for (j = 0; j < tbinfo->ncheck; j++)
{
ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
- if (constr->separate || !constr->conislocal)
+ if (constr->separate ||
+ (!constr->conislocal && !tbinfo->ispartition))
continue;
if (actual_atts == 0)
if (actual_atts)
appendPQExpBufferStr(q, "\n)");
- else if (!((tbinfo->reloftype || tbinfo->ispartition) &&
- !dopt->binary_upgrade))
+ else if (!(tbinfo->reloftype && !dopt->binary_upgrade))
{
/*
- * We must have a parenthesized attribute list, even though
- * empty, when not using the OF TYPE or PARTITION OF syntax.
+ * No attributes? we must have a parenthesized attribute list,
+ * even though empty, when not using the OF TYPE syntax.
*/
appendPQExpBufferStr(q, " (\n)");
}
- if (tbinfo->ispartition && !dopt->binary_upgrade)
- {
- appendPQExpBufferChar(q, '\n');
- appendPQExpBufferStr(q, tbinfo->partbound);
- }
-
- /* Emit the INHERITS clause, except if this is a partition. */
- if (numParents > 0 &&
- !tbinfo->ispartition &&
+ /*
+ * Emit the INHERITS clause (not for partitions), except in
+ * binary-upgrade mode.
+ */
+ if (numParents > 0 && !tbinfo->ispartition &&
!dopt->binary_upgrade)
{
appendPQExpBufferStr(q, "\nINHERITS (");
if (k > 0)
appendPQExpBufferStr(q, ", ");
- if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
- appendPQExpBuffer(q, "%s.",
- fmtId(parentRel->dobj.namespace->dobj.name));
- appendPQExpBufferStr(q, fmtId(parentRel->dobj.name));
+ appendPQExpBufferStr(q, fmtQualifiedDumpable(parentRel));
}
appendPQExpBufferChar(q, ')');
}
else
appendPQExpBufferStr(q, ";\n");
+ /*
+ * in binary upgrade mode, update the catalog with any missing values
+ * that might be present.
+ */
+ if (dopt->binary_upgrade)
+ {
+ for (j = 0; j < tbinfo->numatts; j++)
+ {
+ if (tbinfo->attmissingval[j][0] != '\0')
+ {
+ appendPQExpBufferStr(q, "\n-- set missing value.\n");
+ appendPQExpBufferStr(q,
+ "SELECT pg_catalog.binary_upgrade_set_missing_value(");
+ appendStringLiteralAH(q, qualrelname, fout);
+ appendPQExpBufferStr(q, "::pg_catalog.regclass,");
+ appendStringLiteralAH(q, tbinfo->attnames[j], fout);
+ appendPQExpBufferStr(q, ",");
+ appendStringLiteralAH(q, tbinfo->attmissingval[j], fout);
+ appendPQExpBufferStr(q, ");\n\n");
+ }
+ }
+ }
+
/*
* To create binary-compatible heap files, we have to ensure the same
* physical column order, including dropped columns, as in the
* column order. That also means we have to take care about setting
* attislocal correctly, plus fix up any inherited CHECK constraints.
* Analogously, we set up typed tables using ALTER TABLE / OF here.
+ *
+ * We process foreign and partitioned tables here, even though they
+ * lack heap storage, because they can participate in inheritance
+ * relationships and we want this stuff to be consistent across the
+ * inheritance tree. We can exclude indexes, toast tables, sequences
+ * and matviews, even though they have storage, because we don't
+ * support altering or dropping columns in them, nor can they be part
+ * of inheritance trees.
*/
if (dopt->binary_upgrade &&
(tbinfo->relkind == RELKIND_RELATION ||
tbinfo->attalign[j]);
appendStringLiteralAH(q, tbinfo->attnames[j], fout);
appendPQExpBufferStr(q, "\n AND attrelid = ");
- appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+ appendStringLiteralAH(q, qualrelname, fout);
appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
if (tbinfo->relkind == RELKIND_RELATION ||
tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
else
appendPQExpBuffer(q, "ALTER FOREIGN TABLE ONLY %s ",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
appendPQExpBuffer(q, "DROP COLUMN %s;\n",
fmtId(tbinfo->attnames[j]));
}
"WHERE attname = ");
appendStringLiteralAH(q, tbinfo->attnames[j], fout);
appendPQExpBufferStr(q, "\n AND attrelid = ");
- appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+ appendStringLiteralAH(q, qualrelname, fout);
appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
}
}
+ /*
+ * Add inherited CHECK constraints, if any.
+ *
+ * For partitions, they were already dumped, and conislocal
+ * doesn't need fixing.
+ */
for (k = 0; k < tbinfo->ncheck; k++)
{
ConstraintInfo *constr = &(tbinfo->checkexprs[k]);
- if (constr->separate || constr->conislocal)
+ if (constr->separate || constr->conislocal || tbinfo->ispartition)
continue;
appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inherited constraint.\n");
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
appendPQExpBuffer(q, " ADD CONSTRAINT %s ",
fmtId(constr->dobj.name));
appendPQExpBuffer(q, "%s;\n", constr->condef);
"WHERE contype = 'c' AND conname = ");
appendStringLiteralAH(q, constr->dobj.name, fout);
appendPQExpBufferStr(q, "\n AND conrelid = ");
- appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+ appendStringLiteralAH(q, qualrelname, fout);
appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
}
- if (numParents > 0)
+ if (numParents > 0 && !tbinfo->ispartition)
{
- appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance and partitioning this way.\n");
+ appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance this way.\n");
for (k = 0; k < numParents; k++)
{
TableInfo *parentRel = parents[k];
- PQExpBuffer parentname = createPQExpBuffer();
-
- /* Schema-qualify the parent table, if necessary */
- if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
- appendPQExpBuffer(parentname, "%s.",
- fmtId(parentRel->dobj.namespace->dobj.name));
- appendPQExpBuffer(parentname, "%s",
- fmtId(parentRel->dobj.name));
-
- /* In the partitioning case, we alter the parent */
- if (tbinfo->ispartition)
- appendPQExpBuffer(q,
- "ALTER TABLE ONLY %s ATTACH PARTITION ",
- parentname->data);
- else
- appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT ",
- fmtId(tbinfo->dobj.name));
-
- /* Partition needs specifying the bounds */
- if (tbinfo->ispartition)
- appendPQExpBuffer(q, "%s %s;\n",
- fmtId(tbinfo->dobj.name),
- tbinfo->partbound);
- else
- appendPQExpBuffer(q, "%s;\n", parentname->data);
-
- destroyPQExpBuffer(parentname);
+ appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT %s;\n",
+ qualrelname,
+ fmtQualifiedDumpable(parentRel));
}
}
{
appendPQExpBufferStr(q, "\n-- For binary upgrade, set up typed tables this way.\n");
appendPQExpBuffer(q, "ALTER TABLE ONLY %s OF %s;\n",
- fmtId(tbinfo->dobj.name),
+ qualrelname,
tbinfo->reloftype);
}
+ }
+ /*
+ * For partitioned tables, emit the ATTACH PARTITION clause. Note
+ * that we always want to create partitions this way instead of using
+ * CREATE TABLE .. PARTITION OF, mainly to preserve a possible column
+ * layout discrepancy with the parent, but also to ensure it gets the
+ * correct tablespace setting if it differs from the parent's.
+ */
+ if (tbinfo->ispartition)
+ {
+ /* With partitions there can only be one parent */
+ if (tbinfo->numParents != 1)
+ fatal("invalid number of parents %d for table \"%s\"",
+ tbinfo->numParents, tbinfo->dobj.name);
+
+ /* Perform ALTER TABLE on the parent */
+ appendPQExpBuffer(q,
+ "ALTER TABLE ONLY %s ATTACH PARTITION %s %s;\n",
+ fmtQualifiedDumpable(parents[0]),
+ qualrelname, tbinfo->partbound);
+ }
+
+ /*
+ * In binary_upgrade mode, arrange to restore the old relfrozenxid and
+ * relminmxid of all vacuumable relations. (While vacuum.c processes
+ * TOAST tables semi-independently, here we see them only as children
+ * of other relations; so this "if" lacks RELKIND_TOASTVALUE, and the
+ * child toast table is handled below.)
+ */
+ if (dopt->binary_upgrade &&
+ (tbinfo->relkind == RELKIND_RELATION ||
+ tbinfo->relkind == RELKIND_MATVIEW))
+ {
appendPQExpBufferStr(q, "\n-- For binary upgrade, set heap's relfrozenxid and relminmxid\n");
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
"SET relfrozenxid = '%u', relminmxid = '%u'\n"
"WHERE oid = ",
tbinfo->frozenxid, tbinfo->minmxid);
- appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+ appendStringLiteralAH(q, qualrelname, fout);
appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
if (tbinfo->toast_oid)
{
- /* We preserve the toast oids, so we can use it during restore */
+ /*
+ * The toast table will have the same OID at restore, so we
+ * can safely target it by OID.
+ */
appendPQExpBufferStr(q, "\n-- For binary upgrade, set toast's relfrozenxid and relminmxid\n");
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
"SET relfrozenxid = '%u', relminmxid = '%u'\n"
* In binary_upgrade mode, restore matviews' populated status by
* poking pg_class directly. This is pretty ugly, but we can't use
* REFRESH MATERIALIZED VIEW since it's possible that some underlying
- * matview is not populated even though this matview is.
+ * matview is not populated even though this matview is; in any case,
+ * we want to transfer the matview's heap storage, not run REFRESH.
*/
if (dopt->binary_upgrade && tbinfo->relkind == RELKIND_MATVIEW &&
tbinfo->relispopulated)
appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_class\n"
"SET relispopulated = 't'\n"
"WHERE oid = ");
- appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+ appendStringLiteralAH(q, qualrelname, fout);
appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
}
tbinfo->notnull[j] && !tbinfo->inhNotNull[j])
{
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
appendPQExpBuffer(q, "ALTER COLUMN %s SET NOT NULL;\n",
fmtId(tbinfo->attnames[j]));
}
if (tbinfo->attstattarget[j] >= 0)
{
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
appendPQExpBuffer(q, "ALTER COLUMN %s ",
fmtId(tbinfo->attnames[j]));
appendPQExpBuffer(q, "SET STATISTICS %d;\n",
if (storage != NULL)
{
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
appendPQExpBuffer(q, "ALTER COLUMN %s ",
fmtId(tbinfo->attnames[j]));
appendPQExpBuffer(q, "SET STORAGE %s;\n",
/*
* Dump per-column attributes.
*/
- if (tbinfo->attoptions[j] && tbinfo->attoptions[j][0] != '\0')
+ if (tbinfo->attoptions[j][0] != '\0')
{
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
appendPQExpBuffer(q, "ALTER COLUMN %s ",
fmtId(tbinfo->attnames[j]));
appendPQExpBuffer(q, "SET (%s);\n",
* Dump per-column fdw options.
*/
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE &&
- tbinfo->attfdwoptions[j] &&
tbinfo->attfdwoptions[j][0] != '\0')
{
appendPQExpBuffer(q, "ALTER FOREIGN TABLE %s ",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
appendPQExpBuffer(q, "ALTER COLUMN %s ",
fmtId(tbinfo->attnames[j]));
appendPQExpBuffer(q, "OPTIONS (\n %s\n);\n",
tbinfo->attfdwoptions[j]);
}
}
+
+ if (ftoptions)
+ free(ftoptions);
+ if (srvname)
+ free(srvname);
}
/*
else if (tbinfo->relreplident == REPLICA_IDENTITY_NOTHING)
{
appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY NOTHING;\n",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
}
else if (tbinfo->relreplident == REPLICA_IDENTITY_FULL)
{
appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY FULL;\n",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
}
}
- if (tbinfo->relkind == RELKIND_FOREIGN_TABLE && tbinfo->hasoids)
- appendPQExpBuffer(q, "\nALTER TABLE ONLY %s SET WITH OIDS;\n",
- fmtId(tbinfo->dobj.name));
-
if (tbinfo->forcerowsec)
appendPQExpBuffer(q, "\nALTER TABLE ONLY %s FORCE ROW LEVEL SECURITY;\n",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
if (dopt->binary_upgrade)
- binary_upgrade_extension_member(q, &tbinfo->dobj, labelq->data);
+ binary_upgrade_extension_member(q, &tbinfo->dobj,
+ reltypename, qrelname,
+ tbinfo->dobj.namespace->dobj.name);
if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
- ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
- tbinfo->dobj.name,
- tbinfo->dobj.namespace->dobj.name,
- (tbinfo->relkind == RELKIND_VIEW) ? NULL : tbinfo->reltablespace,
- tbinfo->rolname,
- (strcmp(reltypename, "TABLE") == 0) ? tbinfo->hasoids : false,
- reltypename,
- tbinfo->postponed_def ?
- SECTION_POST_DATA : SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ {
+ char *tableam = NULL;
+
+ if (tbinfo->relkind == RELKIND_RELATION ||
+ tbinfo->relkind == RELKIND_MATVIEW)
+ tableam = tbinfo->amname;
+ ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
+ ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .tablespace = (tbinfo->relkind == RELKIND_VIEW) ?
+ NULL : tbinfo->reltablespace,
+ .tableam = tableam,
+ .owner = tbinfo->rolname,
+ .description = reltypename,
+ .section = tbinfo->postponed_def ?
+ SECTION_POST_DATA : SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
+ }
/* Dump Table Comments */
if (tbinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ free(qrelname);
+ free(qualrelname);
}
/*
int adnum = adinfo->adnum;
PQExpBuffer q;
PQExpBuffer delq;
+ char *qualrelname;
char *tag;
/* Skip if table definition not to be dumped */
q = createPQExpBuffer();
delq = createPQExpBuffer();
+ qualrelname = pg_strdup(fmtQualifiedDumpable(tbinfo));
+
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
- fmtId(tbinfo->dobj.name));
+ qualrelname);
appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
fmtId(tbinfo->attnames[adnum - 1]),
adinfo->adef_expr);
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
- appendPQExpBuffer(delq, "ALTER TABLE %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s ",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delq, "ALTER TABLE %s ",
+ qualrelname);
appendPQExpBuffer(delq, "ALTER COLUMN %s DROP DEFAULT;\n",
fmtId(tbinfo->attnames[adnum - 1]));
if (adinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId,
- tag,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname,
- false, "DEFAULT", SECTION_PRE_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "DEFAULT",
+ .section = SECTION_PRE_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
free(tag);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
+ free(qualrelname);
}
/*
{
case SelfItemPointerAttributeNumber:
return "ctid";
- case ObjectIdAttributeNumber:
- return "oid";
case MinTransactionIdAttributeNumber:
return "xmin";
case MinCommandIdAttributeNumber:
case TableOidAttributeNumber:
return "tableoid";
}
- exit_horribly(NULL, "invalid column number %d for table \"%s\"\n",
- attrnum, tblInfo->dobj.name);
+ fatal("invalid column number %d for table \"%s\"",
+ attrnum, tblInfo->dobj.name);
return NULL; /* keep compiler quiet */
}
bool is_constraint = (indxinfo->indexconstraint != 0);
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
+ char *qindxname;
if (dopt->dataOnly)
return;
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
- appendPQExpBuffer(labelq, "INDEX %s",
- fmtId(indxinfo->dobj.name));
+ qindxname = pg_strdup(fmtId(indxinfo->dobj.name));
/*
* If there's an associated constraint, don't dump the index per se, but
*/
if (!is_constraint)
{
+ char *indstatcols = indxinfo->indstatcols;
+ char *indstatvals = indxinfo->indstatvals;
+ char **indstatcolsarray = NULL;
+ char **indstatvalsarray = NULL;
+ int nstatcols;
+ int nstatvals;
+
if (dopt->binary_upgrade)
binary_upgrade_set_pg_class_oids(fout, q,
indxinfo->dobj.catId.oid, true);
/* Plain secondary index */
appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef);
+ /*
+ * Append ALTER TABLE commands as needed to set properties that we
+ * only have ALTER TABLE syntax for. Keep this in sync with the
+ * similar code in dumpConstraint!
+ */
+
/* If the index is clustered, we need to record that. */
if (indxinfo->indisclustered)
{
appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
+ /* index name is not qualified in this syntax */
appendPQExpBuffer(q, " ON %s;\n",
- fmtId(indxinfo->dobj.name));
+ qindxname);
+ }
+
+ /*
+ * If the index has any statistics on some of its columns, generate
+ * the associated ALTER INDEX queries.
+ */
+ if (parsePGArray(indstatcols, &indstatcolsarray, &nstatcols) &&
+ parsePGArray(indstatvals, &indstatvalsarray, &nstatvals) &&
+ nstatcols == nstatvals)
+ {
+ int j;
+
+ for (j = 0; j < nstatcols; j++)
+ {
+ appendPQExpBuffer(q, "ALTER INDEX %s ",
+ fmtQualifiedDumpable(indxinfo));
+
+ /*
+ * Note that this is a column number, so no quotes should be
+ * used.
+ */
+ appendPQExpBuffer(q, "ALTER COLUMN %s ",
+ indstatcolsarray[j]);
+ appendPQExpBuffer(q, "SET STATISTICS %s;\n",
+ indstatvalsarray[j]);
+ }
}
/* If the index defines identity, we need to record that. */
if (indxinfo->indisreplident)
{
appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
+ /* index name is not qualified in this syntax */
appendPQExpBuffer(q, " INDEX %s;\n",
- fmtId(indxinfo->dobj.name));
+ qindxname);
}
- /*
- * DROP must be fully qualified in case same name appears in
- * pg_catalog
- */
- appendPQExpBuffer(delq, "DROP INDEX %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s;\n",
- fmtId(indxinfo->dobj.name));
+ appendPQExpBuffer(delq, "DROP INDEX %s;\n",
+ fmtQualifiedDumpable(indxinfo));
if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
- indxinfo->dobj.name,
- tbinfo->dobj.namespace->dobj.name,
- indxinfo->tablespace,
- tbinfo->rolname, false,
- "INDEX", SECTION_POST_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = indxinfo->dobj.name,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .tablespace = indxinfo->tablespace,
+ .owner = tbinfo->rolname,
+ .description = "INDEX",
+ .section = SECTION_POST_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
+
+ if (indstatcolsarray)
+ free(indstatcolsarray);
+ if (indstatvalsarray)
+ free(indstatvalsarray);
}
/* Dump Index Comments */
if (indxinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "INDEX", qindxname,
tbinfo->dobj.namespace->dobj.name,
tbinfo->rolname,
indxinfo->dobj.catId, 0,
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ free(qindxname);
+}
+
+/*
+ * dumpIndexAttach
+ * write out to fout a partitioned-index attachment clause
+ */
+static void
+dumpIndexAttach(Archive *fout, IndexAttachInfo *attachinfo)
+{
+ if (fout->dopt->dataOnly)
+ return;
+
+ if (attachinfo->partitionIdx->dobj.dump & DUMP_COMPONENT_DEFINITION)
+ {
+ PQExpBuffer q = createPQExpBuffer();
+
+ appendPQExpBuffer(q, "ALTER INDEX %s ",
+ fmtQualifiedDumpable(attachinfo->parentIdx));
+ appendPQExpBuffer(q, "ATTACH PARTITION %s;\n",
+ fmtQualifiedDumpable(attachinfo->partitionIdx));
+
+ ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId,
+ ARCHIVE_OPTS(.tag = attachinfo->dobj.name,
+ .namespace = attachinfo->dobj.namespace->dobj.name,
+ .description = "INDEX ATTACH",
+ .section = SECTION_POST_DATA,
+ .createStmt = q->data));
+
+ destroyPQExpBuffer(q);
+ }
}
/*
dumpStatisticsExt(Archive *fout, StatsExtInfo *statsextinfo)
{
DumpOptions *dopt = fout->dopt;
- TableInfo *tbinfo = statsextinfo->statsexttable;
PQExpBuffer q;
PQExpBuffer delq;
- PQExpBuffer labelq;
+ PQExpBuffer query;
+ char *qstatsextname;
+ PGresult *res;
+ char *stxdef;
- if (dopt->dataOnly)
+ /* Skip if not to be dumped */
+ if (!statsextinfo->dobj.dump || dopt->dataOnly)
return;
q = createPQExpBuffer();
delq = createPQExpBuffer();
- labelq = createPQExpBuffer();
+ query = createPQExpBuffer();
- appendPQExpBuffer(labelq, "STATISTICS %s",
- fmtId(statsextinfo->dobj.name));
+ qstatsextname = pg_strdup(fmtId(statsextinfo->dobj.name));
- appendPQExpBuffer(q, "%s;\n", statsextinfo->statsextdef);
+ appendPQExpBuffer(query, "SELECT "
+ "pg_catalog.pg_get_statisticsobjdef('%u'::pg_catalog.oid)",
+ statsextinfo->dobj.catId.oid);
+
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
+
+ stxdef = PQgetvalue(res, 0, 0);
- appendPQExpBuffer(delq, "DROP STATISTICS %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s;\n",
- fmtId(statsextinfo->dobj.name));
+ /* Result of pg_get_statisticsobjdef is complete except for semicolon */
+ appendPQExpBuffer(q, "%s;\n", stxdef);
+
+ appendPQExpBuffer(delq, "DROP STATISTICS %s;\n",
+ fmtQualifiedDumpable(statsextinfo));
if (statsextinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, statsextinfo->dobj.catId,
statsextinfo->dobj.dumpId,
- statsextinfo->dobj.name,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname, false,
- "STATISTICS", SECTION_POST_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = statsextinfo->dobj.name,
+ .namespace = statsextinfo->dobj.namespace->dobj.name,
+ .owner = statsextinfo->rolname,
+ .description = "STATISTICS",
+ .section = SECTION_POST_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
/* Dump Statistics Comments */
if (statsextinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
- tbinfo->dobj.namespace->dobj.name,
- tbinfo->rolname,
+ dumpComment(fout, "STATISTICS", qstatsextname,
+ statsextinfo->dobj.namespace->dobj.name,
+ statsextinfo->rolname,
statsextinfo->dobj.catId, 0,
statsextinfo->dobj.dumpId);
+ PQclear(res);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
- destroyPQExpBuffer(labelq);
+ destroyPQExpBuffer(query);
+ free(qstatsextname);
}
/*
indxinfo = (IndxInfo *) findObjectByDumpId(coninfo->conindex);
if (indxinfo == NULL)
- exit_horribly(NULL, "missing index for constraint \"%s\"\n",
- coninfo->dobj.name);
+ fatal("missing index for constraint \"%s\"",
+ coninfo->dobj.name);
if (dopt->binary_upgrade)
binary_upgrade_set_pg_class_oids(fout, q,
indxinfo->dobj.catId.oid, true);
appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
appendPQExpBuffer(q, " ADD CONSTRAINT %s ",
fmtId(coninfo->dobj.name));
{
appendPQExpBuffer(q, "%s (",
coninfo->contype == 'p' ? "PRIMARY KEY" : "UNIQUE");
- for (k = 0; k < indxinfo->indnkeys; k++)
+ for (k = 0; k < indxinfo->indnkeyattrs; k++)
{
int indkey = (int) indxinfo->indkeys[k];
const char *attname;
fmtId(attname));
}
+ if (indxinfo->indnkeyattrs < indxinfo->indnattrs)
+ appendPQExpBufferStr(q, ") INCLUDE (");
+
+ for (k = indxinfo->indnkeyattrs; k < indxinfo->indnattrs; k++)
+ {
+ int indkey = (int) indxinfo->indkeys[k];
+ const char *attname;
+
+ if (indkey == InvalidAttrNumber)
+ break;
+ attname = getAttrName(indkey, tbinfo);
+
+ appendPQExpBuffer(q, "%s%s",
+ (k == indxinfo->indnkeyattrs) ? "" : ", ",
+ fmtId(attname));
+ }
+
appendPQExpBufferChar(q, ')');
if (nonemptyReloptions(indxinfo->indreloptions))
appendPQExpBufferStr(q, ";\n");
}
+ /*
+ * Append ALTER TABLE commands as needed to set properties that we
+ * only have ALTER TABLE syntax for. Keep this in sync with the
+ * similar code in dumpIndex!
+ */
+
/* If the index is clustered, we need to record that. */
if (indxinfo->indisclustered)
{
appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
+ /* index name is not qualified in this syntax */
appendPQExpBuffer(q, " ON %s;\n",
fmtId(indxinfo->dobj.name));
}
- /*
- * DROP must be fully qualified in case same name appears in
- * pg_catalog
- */
- appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s ",
- fmtId(tbinfo->dobj.name));
+ /* If the index defines identity, we need to record that. */
+ if (indxinfo->indisreplident)
+ {
+ appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING",
+ fmtQualifiedDumpable(tbinfo));
+ /* index name is not qualified in this syntax */
+ appendPQExpBuffer(q, " INDEX %s;\n",
+ fmtId(indxinfo->dobj.name));
+ }
+
+ appendPQExpBuffer(delq, "ALTER TABLE ONLY %s ",
+ fmtQualifiedDumpable(tbinfo));
appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
fmtId(coninfo->dobj.name));
if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
- tag,
- tbinfo->dobj.namespace->dobj.name,
- indxinfo->tablespace,
- tbinfo->rolname, false,
- "CONSTRAINT", SECTION_POST_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .tablespace = indxinfo->tablespace,
+ .owner = tbinfo->rolname,
+ .description = "CONSTRAINT",
+ .section = SECTION_POST_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
}
else if (coninfo->contype == 'f')
{
+ char *only;
+
+ /*
+ * Foreign keys on partitioned tables are always declared as
+ * inheriting to partitions; for all other cases, emit them as
+ * applying ONLY directly to the named table, because that's how they
+ * work for regular inherited tables.
+ */
+ only = tbinfo->relkind == RELKIND_PARTITIONED_TABLE ? "" : "ONLY ";
+
/*
* XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that the
* current table data is not processed
*/
- appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(q, "ALTER TABLE %s%s\n",
+ only, fmtQualifiedDumpable(tbinfo));
appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
fmtId(coninfo->dobj.name),
coninfo->condef);
- /*
- * DROP must be fully qualified in case same name appears in
- * pg_catalog
- */
- appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s ",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delq, "ALTER TABLE %s%s ",
+ only, fmtQualifiedDumpable(tbinfo));
appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
fmtId(coninfo->dobj.name));
if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
- tag,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname, false,
- "FK CONSTRAINT", SECTION_POST_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "FK CONSTRAINT",
+ .section = SECTION_POST_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
}
else if (coninfo->contype == 'c' && tbinfo)
{
{
/* not ONLY since we want it to propagate to children */
appendPQExpBuffer(q, "ALTER TABLE %s\n",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
fmtId(coninfo->dobj.name),
coninfo->condef);
- /*
- * DROP must be fully qualified in case same name appears in
- * pg_catalog
- */
- appendPQExpBuffer(delq, "ALTER TABLE %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s ",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delq, "ALTER TABLE %s ",
+ fmtQualifiedDumpable(tbinfo));
appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
fmtId(coninfo->dobj.name));
if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
- tag,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname, false,
- "CHECK CONSTRAINT", SECTION_POST_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "CHECK CONSTRAINT",
+ .section = SECTION_POST_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
}
}
else if (coninfo->contype == 'c' && tbinfo == NULL)
if (coninfo->separate)
{
appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
- fmtId(tyinfo->dobj.name));
+ fmtQualifiedDumpable(tyinfo));
appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
fmtId(coninfo->dobj.name),
coninfo->condef);
- /*
- * DROP must be fully qualified in case same name appears in
- * pg_catalog
- */
- appendPQExpBuffer(delq, "ALTER DOMAIN %s.",
- fmtId(tyinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delq, "%s ",
- fmtId(tyinfo->dobj.name));
+ appendPQExpBuffer(delq, "ALTER DOMAIN %s ",
+ fmtQualifiedDumpable(tyinfo));
appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
fmtId(coninfo->dobj.name));
if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
- tag,
- tyinfo->dobj.namespace->dobj.name,
- NULL,
- tyinfo->rolname, false,
- "CHECK CONSTRAINT", SECTION_POST_DATA,
- q->data, delq->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = tyinfo->dobj.namespace->dobj.name,
+ .owner = tyinfo->rolname,
+ .description = "CHECK CONSTRAINT",
+ .section = SECTION_POST_DATA,
+ .createStmt = q->data,
+ .dropStmt = delq->data));
}
}
else
{
- exit_horribly(NULL, "unrecognized constraint type: %c\n",
- coninfo->contype);
+ fatal("unrecognized constraint type: %c",
+ coninfo->contype);
}
/* Dump Constraint Comments --- only works for table constraints */
dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo)
{
TableInfo *tbinfo = coninfo->contable;
- PQExpBuffer labelq = createPQExpBuffer();
+ PQExpBuffer conprefix = createPQExpBuffer();
+ char *qtabname;
- appendPQExpBuffer(labelq, "CONSTRAINT %s ",
+ qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
+
+ appendPQExpBuffer(conprefix, "CONSTRAINT %s ON",
fmtId(coninfo->dobj.name));
- appendPQExpBuffer(labelq, "ON %s",
- fmtId(tbinfo->dobj.name));
if (coninfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, conprefix->data, qtabname,
tbinfo->dobj.namespace->dobj.name,
tbinfo->rolname,
coninfo->dobj.catId, 0,
coninfo->separate ? coninfo->dobj.dumpId : tbinfo->dobj.dumpId);
- destroyPQExpBuffer(labelq);
+ destroyPQExpBuffer(conprefix);
+ free(qtabname);
}
/*
* find the last built in oid
*
* For 7.1 through 8.0, we do this by retrieving datlastsysoid from the
- * pg_database entry for the current database.
+ * pg_database entry for the current database. (Note: current_database()
+ * requires 7.3; pg_dump requires 8.0 now.)
*/
static Oid
-findLastBuiltinOid_V71(Archive *fout, const char *dbname)
+findLastBuiltinOid_V71(Archive *fout)
{
PGresult *res;
Oid last_oid;
- PQExpBuffer query = createPQExpBuffer();
-
- resetPQExpBuffer(query);
- appendPQExpBufferStr(query, "SELECT datlastsysoid from pg_database where datname = ");
- appendStringLiteralAH(query, dbname, fout);
- res = ExecuteSqlQueryForSingleRow(fout, query->data);
+ res = ExecuteSqlQueryForSingleRow(fout,
+ "SELECT datlastsysoid FROM pg_database WHERE datname = current_database()");
last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "datlastsysoid")));
PQclear(res);
- destroyPQExpBuffer(query);
return last_oid;
}
*seqtype;
bool cycled;
bool is_ascending;
+ int64 default_minv,
+ default_maxv;
+ char bufm[32],
+ bufx[32];
PQExpBuffer query = createPQExpBuffer();
PQExpBuffer delqry = createPQExpBuffer();
- PQExpBuffer labelq = createPQExpBuffer();
+ char *qseqname;
+
+ qseqname = pg_strdup(fmtId(tbinfo->dobj.name));
if (fout->remoteVersion >= 100000)
{
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
appendPQExpBuffer(query,
"SELECT format_type(seqtypid, NULL), "
"seqstart, seqincrement, "
"seqmax, seqmin, "
"seqcache, seqcycle "
- "FROM pg_class c "
- "JOIN pg_sequence s ON (s.seqrelid = c.oid) "
- "WHERE c.oid = '%u'::oid",
+ "FROM pg_catalog.pg_sequence "
+ "WHERE seqrelid = '%u'::oid",
tbinfo->dobj.catId.oid);
}
else if (fout->remoteVersion >= 80400)
{
/*
- * Before PostgreSQL 10, sequence metadata is in the sequence itself,
- * so switch to the sequence's schema instead of pg_catalog.
+ * Before PostgreSQL 10, sequence metadata is in the sequence itself.
+ *
+ * Note: it might seem that 'bigint' potentially needs to be
+ * schema-qualified, but actually that's a keyword.
*/
-
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
appendPQExpBuffer(query,
- "SELECT 'bigint'::name AS sequence_type, "
+ "SELECT 'bigint' AS sequence_type, "
"start_value, increment_by, max_value, min_value, "
"cache_value, is_cycled FROM %s",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
}
else
{
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
appendPQExpBuffer(query,
- "SELECT 'bigint'::name AS sequence_type, "
+ "SELECT 'bigint' AS sequence_type, "
"0 AS start_value, increment_by, max_value, min_value, "
"cache_value, is_cycled FROM %s",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
}
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
if (PQntuples(res) != 1)
{
- write_msg(NULL, ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)\n",
- "query to get data of sequence \"%s\" returned %d rows (expected 1)\n",
- PQntuples(res)),
- tbinfo->dobj.name, PQntuples(res));
+ pg_log_error(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)",
+ "query to get data of sequence \"%s\" returned %d rows (expected 1)",
+ PQntuples(res)),
+ tbinfo->dobj.name, PQntuples(res));
exit_nicely(1);
}
cache = PQgetvalue(res, 0, 5);
cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0);
- is_ascending = incby[0] != '-';
-
- if (is_ascending && atoi(minv) == 1)
- minv = NULL;
- if (!is_ascending && atoi(maxv) == -1)
- maxv = NULL;
-
+ /* Calculate default limits for a sequence of this type */
+ is_ascending = (incby[0] != '-');
if (strcmp(seqtype, "smallint") == 0)
{
- if (!is_ascending && atoi(minv) == PG_INT16_MIN)
- minv = NULL;
- if (is_ascending && atoi(maxv) == PG_INT16_MAX)
- maxv = NULL;
+ default_minv = is_ascending ? 1 : PG_INT16_MIN;
+ default_maxv = is_ascending ? PG_INT16_MAX : -1;
}
else if (strcmp(seqtype, "integer") == 0)
{
- if (!is_ascending && atoi(minv) == PG_INT32_MIN)
- minv = NULL;
- if (is_ascending && atoi(maxv) == PG_INT32_MAX)
- maxv = NULL;
+ default_minv = is_ascending ? 1 : PG_INT32_MIN;
+ default_maxv = is_ascending ? PG_INT32_MAX : -1;
}
else if (strcmp(seqtype, "bigint") == 0)
{
- char bufm[100],
- bufx[100];
+ default_minv = is_ascending ? 1 : PG_INT64_MIN;
+ default_maxv = is_ascending ? PG_INT64_MAX : -1;
+ }
+ else
+ {
+ fatal("unrecognized sequence type: %s", seqtype);
+ default_minv = default_maxv = 0; /* keep compiler quiet */
+ }
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, PG_INT64_MIN);
- snprintf(bufx, sizeof(bufx), INT64_FORMAT, PG_INT64_MAX);
+ /*
+ * 64-bit strtol() isn't very portable, so convert the limits to strings
+ * and compare that way.
+ */
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, default_minv);
+ snprintf(bufx, sizeof(bufx), INT64_FORMAT, default_maxv);
- if (!is_ascending && strcmp(minv, bufm) == 0)
- minv = NULL;
- if (is_ascending && strcmp(maxv, bufx) == 0)
- maxv = NULL;
- }
+ /* Don't print minv/maxv if they match the respective default limit */
+ if (strcmp(minv, bufm) == 0)
+ minv = NULL;
+ if (strcmp(maxv, bufx) == 0)
+ maxv = NULL;
/*
- * DROP must be fully qualified in case same name appears in pg_catalog
+ * Identity sequences are not to be dropped separately.
*/
if (!tbinfo->is_identity_sequence)
{
- appendPQExpBuffer(delqry, "DROP SEQUENCE %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delqry, "%s;\n",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delqry, "DROP SEQUENCE %s;\n",
+ fmtQualifiedDumpable(tbinfo));
}
resetPQExpBuffer(query);
appendPQExpBuffer(query,
"ALTER TABLE %s ",
- fmtId(owning_tab->dobj.name));
+ fmtQualifiedDumpable(owning_tab));
appendPQExpBuffer(query,
"ALTER COLUMN %s ADD GENERATED ",
fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
if (owning_tab->attidentity[tbinfo->owning_col - 1] == ATTRIBUTE_IDENTITY_ALWAYS)
- appendPQExpBuffer(query, "ALWAYS");
+ appendPQExpBufferStr(query, "ALWAYS");
else if (owning_tab->attidentity[tbinfo->owning_col - 1] == ATTRIBUTE_IDENTITY_BY_DEFAULT)
- appendPQExpBuffer(query, "BY DEFAULT");
+ appendPQExpBufferStr(query, "BY DEFAULT");
appendPQExpBuffer(query, " AS IDENTITY (\n SEQUENCE NAME %s\n",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
}
else
{
appendPQExpBuffer(query,
"CREATE SEQUENCE %s\n",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
if (strcmp(seqtype, "bigint") != 0)
appendPQExpBuffer(query, " AS %s\n", seqtype);
else
appendPQExpBufferStr(query, ";\n");
- appendPQExpBuffer(labelq, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
-
/* binary_upgrade: no need to clear TOAST table oid */
if (dopt->binary_upgrade)
binary_upgrade_extension_member(query, &tbinfo->dobj,
- labelq->data);
+ "SEQUENCE", qseqname,
+ tbinfo->dobj.namespace->dobj.name);
if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
- tbinfo->dobj.name,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname,
- false, "SEQUENCE", SECTION_PRE_DATA,
- query->data, delqry->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "SEQUENCE",
+ .section = SECTION_PRE_DATA,
+ .createStmt = query->data,
+ .dropStmt = delqry->data));
/*
* If the sequence is owned by a table column, emit the ALTER for it as a
TableInfo *owning_tab = findTableByOid(tbinfo->owning_tab);
if (owning_tab == NULL)
- exit_horribly(NULL, "failed sanity check, parent table with OID %u of sequence with OID %u not found\n",
- tbinfo->owning_tab, tbinfo->dobj.catId.oid);
+ fatal("failed sanity check, parent table with OID %u of sequence with OID %u not found",
+ tbinfo->owning_tab, tbinfo->dobj.catId.oid);
if (owning_tab->dobj.dump & DUMP_COMPONENT_DEFINITION)
{
resetPQExpBuffer(query);
appendPQExpBuffer(query, "ALTER SEQUENCE %s",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
appendPQExpBuffer(query, " OWNED BY %s",
- fmtId(owning_tab->dobj.name));
+ fmtQualifiedDumpable(owning_tab));
appendPQExpBuffer(query, ".%s;\n",
fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- tbinfo->dobj.name,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname,
- false, "SEQUENCE OWNED BY", SECTION_PRE_DATA,
- query->data, "", NULL,
- &(tbinfo->dobj.dumpId), 1,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "SEQUENCE OWNED BY",
+ .section = SECTION_PRE_DATA,
+ .createStmt = query->data,
+ .deps = &(tbinfo->dobj.dumpId),
+ .nDeps = 1));
}
}
/* Dump Sequence Comments and Security Labels */
if (tbinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "SEQUENCE", qseqname,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
if (tbinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
- dumpSecLabel(fout, labelq->data,
+ dumpSecLabel(fout, "SEQUENCE", qseqname,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
destroyPQExpBuffer(query);
destroyPQExpBuffer(delqry);
- destroyPQExpBuffer(labelq);
+ free(qseqname);
}
/*
bool called;
PQExpBuffer query = createPQExpBuffer();
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
appendPQExpBuffer(query,
"SELECT last_value, is_called FROM %s",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
if (PQntuples(res) != 1)
{
- write_msg(NULL, ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)\n",
- "query to get data of sequence \"%s\" returned %d rows (expected 1)\n",
- PQntuples(res)),
- tbinfo->dobj.name, PQntuples(res));
+ pg_log_error(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)",
+ "query to get data of sequence \"%s\" returned %d rows (expected 1)",
+ PQntuples(res)),
+ tbinfo->dobj.name, PQntuples(res));
exit_nicely(1);
}
resetPQExpBuffer(query);
appendPQExpBufferStr(query, "SELECT pg_catalog.setval(");
- appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
+ appendStringLiteralAH(query, fmtQualifiedDumpable(tbinfo), fout);
appendPQExpBuffer(query, ", %s, %s);\n",
last, (called ? "true" : "false"));
if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
ArchiveEntry(fout, nilCatalogId, createDumpId(),
- tbinfo->dobj.name,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname,
- false, "SEQUENCE SET", SECTION_DATA,
- query->data, "", NULL,
- &(tbinfo->dobj.dumpId), 1,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "SEQUENCE SET",
+ .section = SECTION_DATA,
+ .createStmt = query->data,
+ .deps = &(tbinfo->dobj.dumpId),
+ .nDeps = 1));
PQclear(res);
TableInfo *tbinfo = tginfo->tgtable;
PQExpBuffer query;
PQExpBuffer delqry;
- PQExpBuffer labelq;
+ PQExpBuffer trigprefix;
+ char *qtabname;
char *tgargs;
size_t lentgargs;
const char *p;
query = createPQExpBuffer();
delqry = createPQExpBuffer();
- labelq = createPQExpBuffer();
+ trigprefix = createPQExpBuffer();
+
+ qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
appendPQExpBuffer(delqry, "DROP TRIGGER %s ",
fmtId(tginfo->dobj.name));
- appendPQExpBuffer(delqry, "ON %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delqry, "%s;\n",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delqry, "ON %s;\n",
+ fmtQualifiedDumpable(tbinfo));
if (tginfo->tgdef)
{
appendPQExpBufferStr(query, "INSTEAD OF");
else
{
- write_msg(NULL, "unexpected tgtype value: %d\n", tginfo->tgtype);
+ pg_log_error("unexpected tgtype value: %d", tginfo->tgtype);
exit_nicely(1);
}
findx++;
}
appendPQExpBuffer(query, " ON %s\n",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
if (tginfo->tgisconstraint)
{
appendPQExpBufferStr(query, " FOR EACH STATEMENT\n ");
/* regproc output is already sufficiently quoted */
- appendPQExpBuffer(query, "EXECUTE PROCEDURE %s(",
+ appendPQExpBuffer(query, "EXECUTE FUNCTION %s(",
tginfo->tgfname);
tgargs = (char *) PQunescapeBytea((unsigned char *) tginfo->tgargs,
if (p + tlen >= tgargs + lentgargs)
{
/* hm, not found before end of bytea value... */
- write_msg(NULL, "invalid argument string (%s) for trigger \"%s\" on table \"%s\"\n",
- tginfo->tgargs,
- tginfo->dobj.name,
- tbinfo->dobj.name);
+ pg_log_error("invalid argument string (%s) for trigger \"%s\" on table \"%s\"",
+ tginfo->tgargs,
+ tginfo->dobj.name,
+ tbinfo->dobj.name);
exit_nicely(1);
}
if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
{
appendPQExpBuffer(query, "\nALTER TABLE %s ",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
switch (tginfo->tgenabled)
{
case 'D':
fmtId(tginfo->dobj.name));
}
- appendPQExpBuffer(labelq, "TRIGGER %s ",
+ appendPQExpBuffer(trigprefix, "TRIGGER %s ON",
fmtId(tginfo->dobj.name));
- appendPQExpBuffer(labelq, "ON %s",
- fmtId(tbinfo->dobj.name));
tag = psprintf("%s %s", tbinfo->dobj.name, tginfo->dobj.name);
if (tginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
- tag,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname, false,
- "TRIGGER", SECTION_POST_DATA,
- query->data, delqry->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "TRIGGER",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .dropStmt = delqry->data));
if (tginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, trigprefix->data, qtabname,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
tginfo->dobj.catId, 0, tginfo->dobj.dumpId);
free(tag);
destroyPQExpBuffer(query);
destroyPQExpBuffer(delqry);
- destroyPQExpBuffer(labelq);
+ destroyPQExpBuffer(trigprefix);
+ free(qtabname);
}
/*
DumpOptions *dopt = fout->dopt;
PQExpBuffer query;
PQExpBuffer delqry;
- PQExpBuffer labelq;
+ char *qevtname;
/* Skip if not to be dumped */
if (!evtinfo->dobj.dump || dopt->dataOnly)
query = createPQExpBuffer();
delqry = createPQExpBuffer();
- labelq = createPQExpBuffer();
+
+ qevtname = pg_strdup(fmtId(evtinfo->dobj.name));
appendPQExpBufferStr(query, "CREATE EVENT TRIGGER ");
- appendPQExpBufferStr(query, fmtId(evtinfo->dobj.name));
+ appendPQExpBufferStr(query, qevtname);
appendPQExpBufferStr(query, " ON ");
appendPQExpBufferStr(query, fmtId(evtinfo->evtevent));
appendPQExpBufferChar(query, ')');
}
- appendPQExpBufferStr(query, "\n EXECUTE PROCEDURE ");
+ appendPQExpBufferStr(query, "\n EXECUTE FUNCTION ");
appendPQExpBufferStr(query, evtinfo->evtfname);
appendPQExpBufferStr(query, "();\n");
if (evtinfo->evtenabled != 'O')
{
appendPQExpBuffer(query, "\nALTER EVENT TRIGGER %s ",
- fmtId(evtinfo->dobj.name));
+ qevtname);
switch (evtinfo->evtenabled)
{
case 'D':
}
appendPQExpBuffer(delqry, "DROP EVENT TRIGGER %s;\n",
- fmtId(evtinfo->dobj.name));
+ qevtname);
- appendPQExpBuffer(labelq, "EVENT TRIGGER %s",
- fmtId(evtinfo->dobj.name));
+ if (dopt->binary_upgrade)
+ binary_upgrade_extension_member(query, &evtinfo->dobj,
+ "EVENT TRIGGER", qevtname, NULL);
if (evtinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, evtinfo->dobj.catId, evtinfo->dobj.dumpId,
- evtinfo->dobj.name, NULL, NULL,
- evtinfo->evtowner, false,
- "EVENT TRIGGER", SECTION_POST_DATA,
- query->data, delqry->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = evtinfo->dobj.name,
+ .owner = evtinfo->evtowner,
+ .description = "EVENT TRIGGER",
+ .section = SECTION_POST_DATA,
+ .createStmt = query->data,
+ .dropStmt = delqry->data));
if (evtinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, "EVENT TRIGGER", qevtname,
NULL, evtinfo->evtowner,
evtinfo->dobj.catId, 0, evtinfo->dobj.dumpId);
destroyPQExpBuffer(query);
destroyPQExpBuffer(delqry);
- destroyPQExpBuffer(labelq);
+ free(qevtname);
}
/*
PQExpBuffer query;
PQExpBuffer cmd;
PQExpBuffer delcmd;
- PQExpBuffer labelq;
+ PQExpBuffer ruleprefix;
+ char *qtabname;
PGresult *res;
char *tag;
*/
is_view = (rinfo->ev_type == '1' && rinfo->is_instead);
- /*
- * Make sure we are in proper schema.
- */
- selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
query = createPQExpBuffer();
cmd = createPQExpBuffer();
delcmd = createPQExpBuffer();
- labelq = createPQExpBuffer();
+ ruleprefix = createPQExpBuffer();
+
+ qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
if (is_view)
{
* Otherwise this should look largely like the regular view dump code.
*/
appendPQExpBuffer(cmd, "CREATE OR REPLACE VIEW %s",
- fmtId(tbinfo->dobj.name));
+ fmtQualifiedDumpable(tbinfo));
if (nonemptyReloptions(tbinfo->reloptions))
{
appendPQExpBufferStr(cmd, " WITH (");
if (PQntuples(res) != 1)
{
- write_msg(NULL, "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned\n",
- rinfo->dobj.name, tbinfo->dobj.name);
+ pg_log_error("query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned",
+ rinfo->dobj.name, tbinfo->dobj.name);
exit_nicely(1);
}
*/
if (rinfo->ev_enabled != 'O')
{
- appendPQExpBuffer(cmd, "ALTER TABLE %s ", fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(cmd, "ALTER TABLE %s ", fmtQualifiedDumpable(tbinfo));
switch (rinfo->ev_enabled)
{
case 'A':
}
}
- /*
- * DROP must be fully qualified in case same name appears in pg_catalog
- */
if (is_view)
{
/*
*/
PQExpBuffer result;
- appendPQExpBuffer(delcmd, "CREATE OR REPLACE VIEW %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBufferStr(delcmd, fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delcmd, "CREATE OR REPLACE VIEW %s",
+ fmtQualifiedDumpable(tbinfo));
result = createDummyViewAsClause(fout, tbinfo);
appendPQExpBuffer(delcmd, " AS\n%s;\n", result->data);
destroyPQExpBuffer(result);
{
appendPQExpBuffer(delcmd, "DROP RULE %s ",
fmtId(rinfo->dobj.name));
- appendPQExpBuffer(delcmd, "ON %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delcmd, "%s;\n",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delcmd, "ON %s;\n",
+ fmtQualifiedDumpable(tbinfo));
}
- appendPQExpBuffer(labelq, "RULE %s",
+ appendPQExpBuffer(ruleprefix, "RULE %s ON",
fmtId(rinfo->dobj.name));
- appendPQExpBuffer(labelq, " ON %s",
- fmtId(tbinfo->dobj.name));
tag = psprintf("%s %s", tbinfo->dobj.name, rinfo->dobj.name);
if (rinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
- tag,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname, false,
- "RULE", SECTION_POST_DATA,
- cmd->data, delcmd->data, NULL,
- NULL, 0,
- NULL, NULL);
+ ARCHIVE_OPTS(.tag = tag,
+ .namespace = tbinfo->dobj.namespace->dobj.name,
+ .owner = tbinfo->rolname,
+ .description = "RULE",
+ .section = SECTION_POST_DATA,
+ .createStmt = cmd->data,
+ .dropStmt = delcmd->data));
/* Dump rule comments */
if (rinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
- dumpComment(fout, labelq->data,
+ dumpComment(fout, ruleprefix->data, qtabname,
tbinfo->dobj.namespace->dobj.name,
tbinfo->rolname,
rinfo->dobj.catId, 0, rinfo->dobj.dumpId);
destroyPQExpBuffer(query);
destroyPQExpBuffer(cmd);
destroyPQExpBuffer(delcmd);
- destroyPQExpBuffer(labelq);
+ destroyPQExpBuffer(ruleprefix);
+ free(qtabname);
}
/*
if (numExtensions == 0)
return;
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
query = createPQExpBuffer();
/* refclassid constraint is redundant but may speed the search */
if (ext == NULL)
{
/* shouldn't happen */
- fprintf(stderr, "could not find referenced extension %u\n", extId);
+ pg_log_warning("could not find referenced extension %u", extId);
continue;
}
if (dumpobj)
{
- /*
- * Note: config tables are dumped without OIDs regardless
- * of the --oids setting. This is because row filtering
- * conditions aren't compatible with dumping OIDs.
- */
- makeTableDataInfo(dopt, configtbl, false);
+ makeTableDataInfo(dopt, configtbl);
if (configtbl->dataObj != NULL)
{
if (strlen(extconditionarray[j]) > 0)
* recreated after the data has been loaded.
*/
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
-
query = createPQExpBuffer();
printfPQExpBuffer(query,
DumpableObject *dobj,
*refdobj;
- if (g_verbose)
- write_msg(NULL, "reading dependency data\n");
-
- /* Make sure we are in proper schema */
- selectSourceSchema(fout, "pg_catalog");
+ pg_log_info("reading dependency data");
query = createPQExpBuffer();
/*
+ * Messy query to collect the dependency data we need. Note that we
+ * ignore the sub-object column, so that dependencies of or on a column
+ * look the same as dependencies of or on a whole table.
+ *
* PIN dependencies aren't interesting, and EXTENSION dependencies were
* already processed by getExtensionMembership.
*/
appendPQExpBufferStr(query, "SELECT "
"classid, objid, refclassid, refobjid, deptype "
"FROM pg_depend "
- "WHERE deptype != 'p' AND deptype != 'e' "
- "ORDER BY 1,2");
+ "WHERE deptype != 'p' AND deptype != 'e'\n");
+
+ /*
+ * Since we don't treat pg_amop entries as separate DumpableObjects, we
+ * have to translate their dependencies into dependencies of their parent
+ * opfamily. Ignore internal dependencies though, as those will point to
+ * their parent opclass, which we needn't consider here (and if we did,
+ * it'd just result in circular dependencies). Also, "loose" opfamily
+ * entries will have dependencies on their parent opfamily, which we
+ * should drop since they'd likewise become useless self-dependencies.
+ * (But be sure to keep deps on *other* opfamilies; see amopsortfamily.)
+ *
+ * Skip this for pre-8.3 source servers: pg_opfamily doesn't exist there,
+ * and the (known) cases where it would matter to have these dependencies
+ * can't arise anyway.
+ */
+ if (fout->remoteVersion >= 80300)
+ {
+ appendPQExpBufferStr(query, "UNION ALL\n"
+ "SELECT 'pg_opfamily'::regclass AS classid, amopfamily AS objid, refclassid, refobjid, deptype "
+ "FROM pg_depend d, pg_amop o "
+ "WHERE deptype NOT IN ('p', 'e', 'i') AND "
+ "classid = 'pg_amop'::regclass AND objid = o.oid "
+ "AND NOT (refclassid = 'pg_opfamily'::regclass AND amopfamily = refobjid)\n");
+
+ /* Likewise for pg_amproc entries */
+ appendPQExpBufferStr(query, "UNION ALL\n"
+ "SELECT 'pg_opfamily'::regclass AS classid, amprocfamily AS objid, refclassid, refobjid, deptype "
+ "FROM pg_depend d, pg_amproc p "
+ "WHERE deptype NOT IN ('p', 'e', 'i') AND "
+ "classid = 'pg_amproc'::regclass AND objid = p.oid "
+ "AND NOT (refclassid = 'pg_opfamily'::regclass AND amprocfamily = refobjid)\n");
+ }
+
+ /* Sort the output for efficiency below */
+ appendPQExpBufferStr(query, "ORDER BY 1,2");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
if (dobj == NULL)
{
#ifdef NOT_USED
- fprintf(stderr, "no referencing object %u %u\n",
- objId.tableoid, objId.oid);
+ pg_log_warning("no referencing object %u %u",
+ objId.tableoid, objId.oid);
#endif
continue;
}
if (refdobj == NULL)
{
#ifdef NOT_USED
- fprintf(stderr, "no referenced object %u %u\n",
- refobjId.tableoid, refobjId.oid);
+ pg_log_warning("no referenced object %u %u",
+ refobjId.tableoid, refobjId.oid);
#endif
continue;
}
addObjectDependency(postDataBound, dobj->dumpId);
break;
case DO_INDEX:
+ case DO_INDEX_ATTACH:
case DO_STATSEXT:
case DO_REFRESH_MATVIEW:
case DO_TRIGGER:
}
-/*
- * selectSourceSchema - make the specified schema the active search path
- * in the source database.
- *
- * NB: pg_catalog is explicitly searched after the specified schema;
- * so user names are only qualified if they are cross-schema references,
- * and system names are only qualified if they conflict with a user name
- * in the current schema.
- *
- * Whenever the selected schema is not pg_catalog, be careful to qualify
- * references to system catalogs and types in our emitted commands!
- *
- * This function is called only from selectSourceSchemaOnAH and
- * selectSourceSchema.
- */
-static void
-selectSourceSchema(Archive *fout, const char *schemaName)
-{
- PQExpBuffer query;
-
- /* This is checked by the callers already */
- Assert(schemaName != NULL && *schemaName != '\0');
-
- query = createPQExpBuffer();
- appendPQExpBuffer(query, "SET search_path = %s",
- fmtId(schemaName));
- if (strcmp(schemaName, "pg_catalog") != 0)
- appendPQExpBufferStr(query, ", pg_catalog");
-
- ExecuteSqlStatement(fout, query->data);
-
- destroyPQExpBuffer(query);
-}
-
/*
* getFormattedTypeName - retrieve a nicely-formatted type name for the
- * given type name.
+ * given type OID.
+ *
+ * This does not guarantee to schema-qualify the output, so it should not
+ * be used to create the target object name for CREATE or ALTER commands.
*
- * NB: the result may depend on the currently-selected search_path; this is
- * why we don't try to cache the names.
+ * TODO: there might be some value in caching the results.
*/
static char *
getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts)
int numatts = ti->numatts;
char **attnames = ti->attnames;
bool *attisdropped = ti->attisdropped;
+ char *attgenerated = ti->attgenerated;
bool needComma;
int i;
{
if (attisdropped[i])
continue;
+ if (attgenerated[i])
+ continue;
if (needComma)
appendPQExpBufferStr(buffer, ", ");
appendPQExpBufferStr(buffer, fmtId(attnames[i]));
res = appendReloptionsArray(buffer, reloptions, prefix, fout->encoding,
fout->std_strings);
if (!res)
- write_msg(NULL, "WARNING: could not parse reloptions array\n");
+ pg_log_warning("could not parse reloptions array");
}