* pg_dump is a utility for dumping out a postgres database
* into a script file.
*
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* pg_dump will read the system catalogs in a database and dump out a
* Note that pg_dump runs in a transaction-snapshot mode transaction,
* so it sees a consistent snapshot of the database including system
* catalogs. However, it relies in part on various specialized backend
- * functions like pg_get_indexdef(), and those things tend to run on
- * SnapshotNow time, ie they look at the currently committed state. So
- * it is possible to get 'cache lookup failed' error if someone
- * performs DDL changes while a dump is happening. The window for this
- * sort of thing is from the acquisition of the transaction snapshot to
- * getSchemaData() (when pg_dump acquires AccessShareLock on every
- * table it intends to dump). It isn't very large, but it can happen.
+ * functions like pg_get_indexdef(), and those things tend to look at
+ * the currently committed state. So it is possible to get 'cache
+ * lookup failed' error if someone performs DDL changes while a dump is
+ * happening. The window for this sort of thing is from the acquisition
+ * of the transaction snapshot to getSchemaData() (when pg_dump acquires
+ * AccessShareLock on every table it intends to dump). It isn't very large,
+ * but it can happen.
*
* http://archives.postgresql.org/pgsql-bugs/2010-02/msg00187.php
*
#include "catalog/pg_cast.h"
#include "catalog/pg_class.h"
#include "catalog/pg_default_acl.h"
+#include "catalog/pg_event_trigger.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_largeobject_metadata.h"
#include "catalog/pg_proc.h"
#include "libpq/libpq-fs.h"
#include "pg_backup_archiver.h"
-#include "dumpmem.h"
+#include "pg_backup_db.h"
+#include "pg_backup_utils.h"
#include "dumputils.h"
-
-extern char *optarg;
-extern int optind,
- opterr;
+#include "parallel.h"
typedef struct
/* global decls */
bool g_verbose; /* User wants verbose narration of our
* activities. */
-Archive *g_fout; /* the script file */
-PGconn *g_conn; /* the database connection */
/* various user-settable parameters */
-bool schemaOnly;
-bool dataOnly;
-int dumpSections; /* bitmask of chosen sections */
-bool aclsSkip;
-const char *lockWaitTimeout;
+static bool schemaOnly;
+static bool dataOnly;
+static int dumpSections; /* bitmask of chosen sections */
+static bool aclsSkip;
+static const char *lockWaitTimeout;
/* subquery used to convert user ID (eg, datdba) to user name */
static const char *username_subquery;
static const CatalogId nilCatalogId = {0, 0};
-/* these are to avoid passing around info for findNamespace() */
-static NamespaceInfo *g_namespaces;
-static int g_numNamespaces;
-
/* flags for various command-line long options */
static int binary_upgrade = 0;
static int disable_dollar_quoting = 0;
static int dump_inserts = 0;
static int column_inserts = 0;
+static int if_exists = 0;
static int no_security_labels = 0;
+static int no_synchronized_snapshots = 0;
static int no_unlogged_table_data = 0;
static int serializable_deferrable = 0;
static void help(const char *progname);
+static void setup_connection(Archive *AH, const char *dumpencoding,
+ char *use_role);
static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
-static void expand_schema_name_patterns(SimpleStringList *patterns,
+static void expand_schema_name_patterns(Archive *fout,
+ SimpleStringList *patterns,
SimpleOidList *oids);
-static void expand_table_name_patterns(SimpleStringList *patterns,
+static void expand_table_name_patterns(Archive *fout,
+ SimpleStringList *patterns,
SimpleOidList *oids);
-static NamespaceInfo *findNamespace(Oid nsoid, Oid objoid);
+static NamespaceInfo *findNamespace(Archive *fout, Oid nsoid, Oid objoid);
static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
+static void refreshMatViewData(Archive *fout, TableDataInfo *tdinfo);
static void guessConstraintInheritance(TableInfo *tblinfo, int numTables);
static void dumpComment(Archive *fout, const char *target,
const char *namespace, const char *owner,
static void dumpRule(Archive *fout, RuleInfo *rinfo);
static void dumpAgg(Archive *fout, AggInfo *agginfo);
static void dumpTrigger(Archive *fout, TriggerInfo *tginfo);
+static void dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo);
static void dumpTable(Archive *fout, TableInfo *tbinfo);
static void dumpTableSchema(Archive *fout, TableInfo *tbinfo);
static void dumpAttrDef(Archive *fout, AttrDefInfo *adinfo);
static void dumpSequence(Archive *fout, TableInfo *tbinfo);
+static void dumpSequenceData(Archive *fout, TableDataInfo *tdinfo);
static void dumpIndex(Archive *fout, IndxInfo *indxinfo);
static void dumpConstraint(Archive *fout, ConstraintInfo *coninfo);
static void dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo);
const char *tag, const char *nspname, const char *owner,
const char *acls);
-static void getDependencies(void);
-static void getDomainConstraints(TypeInfo *tyinfo);
+static void getDependencies(Archive *fout);
+static void BuildArchiveDependencies(Archive *fout);
+static void findDumpableDependencies(ArchiveHandle *AH, DumpableObject *dobj,
+ DumpId **dependencies, int *nDeps, int *allocDeps);
+
+static DumpableObject *createBoundaryObjects(void);
+static void addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
+ DumpableObject *boundaryObjs);
+
+static void getDomainConstraints(Archive *fout, TypeInfo *tyinfo);
static void getTableData(TableInfo *tblinfo, int numTables, bool oids);
static void makeTableDataInfo(TableInfo *tbinfo, bool oids);
+static void buildMatViewRefreshDependencies(Archive *fout);
static void getTableDataFKConstraints(void);
-static char *format_function_arguments(FuncInfo *finfo, char *funcargs);
-static char *format_function_arguments_old(FuncInfo *finfo, int nallargs,
+static char *format_function_arguments(FuncInfo *finfo, char *funcargs,
+ bool is_agg);
+static char *format_function_arguments_old(Archive *fout,
+ FuncInfo *finfo, int nallargs,
char **allargtypes,
char **argmodes,
char **argnames);
-static char *format_function_signature(FuncInfo *finfo, bool honor_quotes);
-static const char *convertRegProcReference(const char *proc);
-static const char *convertOperatorReference(const char *opr);
-static const char *convertTSFunction(Oid funcOid);
-static Oid findLastBuiltinOid_V71(const char *);
-static Oid findLastBuiltinOid_V70(void);
-static void selectSourceSchema(const char *schemaName);
-static char *getFormattedTypeName(Oid oid, OidOptions opts);
+static char *format_function_signature(Archive *fout,
+ FuncInfo *finfo, bool honor_quotes);
+static char *convertRegProcReference(Archive *fout,
+ const char *proc);
+static char *convertOperatorReference(Archive *fout, const char *opr);
+static const char *convertTSFunction(Archive *fout, Oid funcOid);
+static Oid findLastBuiltinOid_V71(Archive *fout, const char *);
+static Oid findLastBuiltinOid_V70(Archive *fout);
+static void selectSourceSchema(Archive *fout, const char *schemaName);
+static char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts);
static char *myFormatType(const char *typname, int32 typmod);
-static const char *fmtQualifiedId(const char *schema, const char *id);
-static void getBlobs(Archive *AH);
-static void dumpBlob(Archive *AH, BlobInfo *binfo);
-static int dumpBlobs(Archive *AH, void *arg);
+static void getBlobs(Archive *fout);
+static void dumpBlob(Archive *fout, BlobInfo *binfo);
+static int dumpBlobs(Archive *fout, void *arg);
static void dumpDatabase(Archive *AH);
static void dumpEncoding(Archive *AH);
static void dumpStdStrings(Archive *AH);
-static void binary_upgrade_set_type_oids_by_type_oid(
+static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
PQExpBuffer upgrade_buffer, Oid pg_type_oid);
-static bool binary_upgrade_set_type_oids_by_rel_oid(
+static bool binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
-static void binary_upgrade_set_pg_class_oids(PQExpBuffer upgrade_buffer,
+static void binary_upgrade_set_pg_class_oids(Archive *fout,
+ PQExpBuffer upgrade_buffer,
Oid pg_class_oid, bool is_index);
static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
DumpableObject *dobj,
const char *objlabel);
static const char *getAttrName(int attrnum, TableInfo *tblInfo);
-static const char *fmtCopyColumnList(const TableInfo *ti);
-static void do_sql_command(PGconn *conn, const char *query);
-static void check_sql_result(PGresult *res, PGconn *conn, const char *query,
- ExecStatusType expected);
+static const char *fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer);
+static char *get_synchronized_snapshot(Archive *fout);
+static PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
+static void setupDumpWorker(Archive *AHX, RestoreOptions *ropt);
+
int
main(int argc, char **argv)
const char *pgport = NULL;
const char *username = NULL;
const char *dumpencoding = NULL;
- const char *std_strings;
bool oids = false;
TableInfo *tblinfo;
int numTables;
DumpableObject **dobjs;
int numObjs;
+ DumpableObject *boundaryObjs;
int i;
+ int numWorkers = 1;
enum trivalue prompt_password = TRI_DEFAULT;
int compressLevel = -1;
int plainText = 0;
int outputNoOwner = 0;
char *outputSuperuser = NULL;
char *use_role = NULL;
- int my_version;
int optindex;
RestoreOptions *ropt;
ArchiveFormat archiveFormat = archUnknown;
ArchiveMode archiveMode;
+ Archive *fout; /* the script file */
static int disable_triggers = 0;
static int outputNoTablespaces = 0;
{"blobs", no_argument, NULL, 'b'},
{"clean", no_argument, NULL, 'c'},
{"create", no_argument, NULL, 'C'},
+ {"dbname", required_argument, NULL, 'd'},
{"file", required_argument, NULL, 'f'},
{"format", required_argument, NULL, 'F'},
{"host", required_argument, NULL, 'h'},
{"ignore-version", no_argument, NULL, 'i'},
+ {"jobs", 1, NULL, 'j'},
{"no-reconnect", no_argument, NULL, 'R'},
{"oids", no_argument, NULL, 'o'},
{"no-owner", no_argument, NULL, 'O'},
{"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
{"disable-triggers", no_argument, &disable_triggers, 1},
{"exclude-table-data", required_argument, NULL, 4},
+ {"if-exists", no_argument, &if_exists, 1},
{"inserts", no_argument, &dump_inserts, 1},
{"lock-wait-timeout", required_argument, NULL, 2},
{"no-tablespaces", no_argument, &outputNoTablespaces, 1},
{"serializable-deferrable", no_argument, &serializable_deferrable, 1},
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
{"no-security-labels", no_argument, &no_security_labels, 1},
+ {"no-synchronized-snapshots", no_argument, &no_synchronized_snapshots, 1},
{"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
{NULL, 0, NULL, 0}
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
+ /*
+ * Initialize what we need for parallel execution, especially for thread
+ * support on Windows.
+ */
+ init_parallel_dump_utils();
+
g_verbose = false;
strcpy(g_comment_start, "-- ");
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
{
help(progname);
- exit(0);
+ exit_nicely(0);
}
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
{
puts("pg_dump (PostgreSQL) " PG_VERSION);
- exit(0);
+ exit_nicely(0);
}
}
- while ((c = getopt_long(argc, argv, "abcCE:f:F:h:in:N:oOp:RsS:t:T:U:vwWxZ:",
+ while ((c = getopt_long(argc, argv, "abcCd:E:f:F:h:ij:n:N:oOp:RsS:t:T:U:vwWxZ:",
long_options, &optindex)) != -1)
{
switch (c)
outputCreateDB = 1;
break;
+ case 'd': /* database name */
+ dbname = pg_strdup(optarg);
+ break;
+
case 'E': /* Dump encoding */
- dumpencoding = optarg;
+ dumpencoding = pg_strdup(optarg);
break;
case 'f':
- filename = optarg;
+ filename = pg_strdup(optarg);
break;
case 'F':
- format = optarg;
+ format = pg_strdup(optarg);
break;
case 'h': /* server host */
- pghost = optarg;
+ pghost = pg_strdup(optarg);
break;
case 'i':
/* ignored, deprecated option */
break;
+ case 'j': /* number of dump jobs */
+ numWorkers = atoi(optarg);
+ break;
+
case 'n': /* include schema(s) */
simple_string_list_append(&schema_include_patterns, optarg);
include_everything = false;
break;
case 'p': /* server port */
- pgport = optarg;
+ pgport = pg_strdup(optarg);
break;
case 'R':
break;
case 'U':
- username = optarg;
+ username = pg_strdup(optarg);
break;
case 'v': /* verbose */
break;
case 2: /* lock-wait-timeout */
- lockWaitTimeout = optarg;
+ lockWaitTimeout = pg_strdup(optarg);
break;
case 3: /* SET ROLE */
- use_role = optarg;
+ use_role = pg_strdup(optarg);
break;
- case 4: /* exclude table(s) data */
+ case 4: /* exclude table(s) data */
simple_string_list_append(&tabledata_exclude_patterns, optarg);
break;
case 5: /* section */
- set_section(optarg, &dumpSections);
+ set_dump_section(optarg, &dumpSections);
break;
default:
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
- exit(1);
+ exit_nicely(1);
}
}
- /* Get database name from command line */
- if (optind < argc)
+ /*
+ * Non-option argument specifies database name as long as it wasn't
+ * already specified with -d / --dbname
+ */
+ if (optind < argc && dbname == NULL)
dbname = argv[optind++];
/* Complain if any arguments remain */
progname, argv[optind]);
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
progname);
- exit(1);
+ exit_nicely(1);
}
/* --column-inserts implies --inserts */
if (dataOnly && schemaOnly)
{
write_msg(NULL, "options -s/--schema-only and -a/--data-only cannot be used together\n");
- exit(1);
- }
-
- if ((dataOnly || schemaOnly) && dumpSections != DUMP_UNSECTIONED)
- {
- write_msg(NULL, "options -s/--schema-only and -a/--data-only cannot be used with --section\n");
- exit(1);
- }
-
- if (dataOnly)
- dumpSections = DUMP_DATA;
- else if (schemaOnly)
- dumpSections = DUMP_PRE_DATA | DUMP_POST_DATA;
- else if ( dumpSections != DUMP_UNSECTIONED)
- {
- dataOnly = dumpSections == DUMP_DATA;
- schemaOnly = !(dumpSections & DUMP_DATA);
+ exit_nicely(1);
}
if (dataOnly && outputClean)
{
write_msg(NULL, "options -c/--clean and -a/--data-only cannot be used together\n");
- exit(1);
+ exit_nicely(1);
}
if (dump_inserts && oids)
{
write_msg(NULL, "options --inserts/--column-inserts and -o/--oids cannot be used together\n");
write_msg(NULL, "(The INSERT command cannot set OIDs.)\n");
- exit(1);
+ exit_nicely(1);
}
+ if (if_exists && !outputClean)
+ exit_horribly(NULL, "option --if-exists requires -c/--clean option\n");
+
/* Identify archive format to emit */
archiveFormat = parseArchiveFormat(format, &archiveMode);
compressLevel = 0;
}
- /* Open the output file */
- g_fout = CreateArchive(filename, archiveFormat, compressLevel, archiveMode);
-
- if (g_fout == NULL)
- {
- write_msg(NULL, "could not open output file \"%s\" for writing\n", filename);
- exit(1);
- }
-
- /* Let the archiver know how noisy to be */
- g_fout->verbose = g_verbose;
-
- my_version = parse_version(PG_VERSION);
- if (my_version < 0)
- {
- write_msg(NULL, "could not parse version string \"%s\"\n", PG_VERSION);
- exit(1);
- }
-
- /*
- * We allow the server to be back to 7.0, and up to any minor release of
- * our own major version. (See also version check in pg_dumpall.c.)
- */
- g_fout->minRemoteVersion = 70000;
- g_fout->maxRemoteVersion = (my_version / 100) * 100 + 99;
-
- /*
- * Open the database using the Archiver, so it knows about it. Errors mean
- * death.
- */
- g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport,
- username, prompt_password);
-
- /* Set the client encoding if requested */
- if (dumpencoding)
- {
- if (PQsetClientEncoding(g_conn, dumpencoding) < 0)
- {
- write_msg(NULL, "invalid client encoding \"%s\" specified\n",
- dumpencoding);
- exit(1);
- }
- }
-
/*
- * Get the active encoding and the standard_conforming_strings setting, so
- * we know how to escape strings.
+ * On Windows we can only have at most MAXIMUM_WAIT_OBJECTS (= 64 usually)
+ * parallel jobs because that's the maximum limit for the
+ * WaitForMultipleObjects() call.
*/
- g_fout->encoding = PQclientEncoding(g_conn);
-
- std_strings = PQparameterStatus(g_conn, "standard_conforming_strings");
- g_fout->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
+ if (numWorkers <= 0
+#ifdef WIN32
+ || numWorkers > MAXIMUM_WAIT_OBJECTS
+#endif
+ )
+ exit_horribly(NULL, "%s: invalid number of parallel jobs\n", progname);
- /* Set the role if requested */
- if (use_role && g_fout->remoteVersion >= 80100)
- {
- PQExpBuffer query = createPQExpBuffer();
+ /* 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");
- appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
- do_sql_command(g_conn, query->data);
- destroyPQExpBuffer(query);
- }
+ /* Open the output file */
+ fout = CreateArchive(filename, archiveFormat, compressLevel, archiveMode,
+ setupDumpWorker);
- /* Set the datestyle to ISO to ensure the dump's portability */
- do_sql_command(g_conn, "SET DATESTYLE = ISO");
+ /* Register the cleanup hook */
+ on_exit_close_archive(fout);
- /* Likewise, avoid using sql_standard intervalstyle */
- if (g_fout->remoteVersion >= 80400)
- do_sql_command(g_conn, "SET INTERVALSTYLE = POSTGRES");
+ if (fout == NULL)
+ exit_horribly(NULL, "could not open output file \"%s\" for writing\n", filename);
- /*
- * If supported, set extra_float_digits so that we can dump float data
- * exactly (given correctly implemented float I/O code, anyway)
- */
- if (g_fout->remoteVersion >= 90000)
- do_sql_command(g_conn, "SET extra_float_digits TO 3");
- else if (g_fout->remoteVersion >= 70400)
- do_sql_command(g_conn, "SET extra_float_digits TO 2");
+ /* Let the archiver know how noisy to be */
+ fout->verbose = g_verbose;
/*
- * If synchronized scanning is supported, disable it, to prevent
- * unpredictable changes in row ordering across a dump and reload.
+ * We allow the server to be back to 7.0, and up to any minor release of
+ * our own major version. (See also version check in pg_dumpall.c.)
*/
- if (g_fout->remoteVersion >= 80300)
- do_sql_command(g_conn, "SET synchronize_seqscans TO off");
+ fout->minRemoteVersion = 70000;
+ fout->maxRemoteVersion = (PG_VERSION_NUM / 100) * 100 + 99;
- /*
- * Disable timeouts if supported.
- */
- if (g_fout->remoteVersion >= 70300)
- do_sql_command(g_conn, "SET statement_timeout = 0");
+ fout->numWorkers = numWorkers;
/*
- * Quote all identifiers, if requested.
+ * Open the database using the Archiver, so it knows about it. Errors mean
+ * death.
*/
- if (quote_all_identifiers && g_fout->remoteVersion >= 90100)
- do_sql_command(g_conn, "SET quote_all_identifiers = true");
+ ConnectDatabase(fout, dbname, pghost, pgport, username, prompt_password);
+ setup_connection(fout, dumpencoding, use_role);
/*
* Disable security label support if server version < v9.1.x (prevents
* access to nonexistent pg_seclabel catalog)
*/
- if (g_fout->remoteVersion < 90100)
+ if (fout->remoteVersion < 90100)
no_security_labels = 1;
/*
- * Start transaction-snapshot mode transaction to dump consistent data.
+ * When running against 9.0 or later, check if we are in recovery mode,
+ * which means we are on a hot standby.
*/
- do_sql_command(g_conn, "BEGIN");
- if (g_fout->remoteVersion >= 90100)
+ if (fout->remoteVersion >= 90000)
{
- if (serializable_deferrable)
- do_sql_command(g_conn,
- "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, "
- "READ ONLY, DEFERRABLE");
- else
- do_sql_command(g_conn,
- "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ");
+ PGresult *res = ExecuteSqlQueryForSingleRow(fout, "SELECT pg_catalog.pg_is_in_recovery()");
+
+ if (strcmp(PQgetvalue(res, 0, 0), "t") == 0)
+ {
+ /*
+ * On hot standby slaves, never try to dump unlogged table data,
+ * since it will just throw an error.
+ */
+ no_unlogged_table_data = true;
+ }
+ PQclear(res);
}
- else
- do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
/* Select the appropriate subquery to convert user IDs to names */
- if (g_fout->remoteVersion >= 80100)
+ if (fout->remoteVersion >= 80100)
username_subquery = "SELECT rolname FROM pg_catalog.pg_roles WHERE oid =";
- else if (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
username_subquery = "SELECT usename FROM pg_catalog.pg_user WHERE usesysid =";
else
username_subquery = "SELECT usename FROM pg_user WHERE usesysid =";
+ /* check the version for the synchronized snapshots feature */
+ if (numWorkers > 1 && fout->remoteVersion < 90200
+ && !no_synchronized_snapshots)
+ exit_horribly(NULL,
+ "Synchronized snapshots are not supported by this server version.\n"
+ "Run with --no-synchronized-snapshots instead if you do not need\n"
+ "synchronized snapshots.\n");
+
/* Find the last built-in OID, if needed */
- if (g_fout->remoteVersion < 70300)
+ if (fout->remoteVersion < 70300)
{
- if (g_fout->remoteVersion >= 70100)
- g_last_builtin_oid = findLastBuiltinOid_V71(PQdb(g_conn));
+ if (fout->remoteVersion >= 70100)
+ g_last_builtin_oid = findLastBuiltinOid_V71(fout,
+ PQdb(GetConnection(fout)));
else
- g_last_builtin_oid = findLastBuiltinOid_V70();
+ g_last_builtin_oid = findLastBuiltinOid_V70(fout);
if (g_verbose)
write_msg(NULL, "last built-in OID is %u\n", g_last_builtin_oid);
}
/* Expand schema selection patterns into OID lists */
if (schema_include_patterns.head != NULL)
{
- expand_schema_name_patterns(&schema_include_patterns,
+ expand_schema_name_patterns(fout, &schema_include_patterns,
&schema_include_oids);
if (schema_include_oids.head == NULL)
- {
- write_msg(NULL, "No matching schemas were found\n");
- exit_nicely();
- }
+ exit_horribly(NULL, "No matching schemas were found\n");
}
- expand_schema_name_patterns(&schema_exclude_patterns,
+ expand_schema_name_patterns(fout, &schema_exclude_patterns,
&schema_exclude_oids);
/* non-matching exclusion patterns aren't an error */
/* Expand table selection patterns into OID lists */
if (table_include_patterns.head != NULL)
{
- expand_table_name_patterns(&table_include_patterns,
+ expand_table_name_patterns(fout, &table_include_patterns,
&table_include_oids);
if (table_include_oids.head == NULL)
- {
- write_msg(NULL, "No matching tables were found\n");
- exit_nicely();
- }
+ exit_horribly(NULL, "No matching tables were found\n");
}
- expand_table_name_patterns(&table_exclude_patterns,
+ expand_table_name_patterns(fout, &table_exclude_patterns,
&table_exclude_oids);
- expand_table_name_patterns(&tabledata_exclude_patterns,
+ expand_table_name_patterns(fout, &tabledata_exclude_patterns,
&tabledata_exclude_oids);
/* non-matching exclusion patterns aren't an error */
* Now scan the database and create DumpableObject structs for all the
* objects we intend to dump.
*/
- tblinfo = getSchemaData(&numTables);
+ tblinfo = getSchemaData(fout, &numTables);
- if (g_fout->remoteVersion < 80400)
+ if (fout->remoteVersion < 80400)
guessConstraintInheritance(tblinfo, numTables);
if (!schemaOnly)
{
getTableData(tblinfo, numTables, oids);
+ buildMatViewRefreshDependencies(fout);
if (dataOnly)
getTableDataFKConstraints();
}
if (outputBlobs)
- getBlobs(g_fout);
+ getBlobs(fout);
/*
* Collect dependency data to assist in ordering the objects.
*/
- getDependencies();
+ getDependencies(fout);
+
+ /* Lastly, create dummy objects to represent the section boundaries */
+ boundaryObjs = createBoundaryObjects();
+
+ /* Get pointers to all the known DumpableObjects */
+ getDumpableObjects(&dobjs, &numObjs);
+
+ /*
+ * Add dummy dependencies to enforce the dump section ordering.
+ */
+ addBoundaryDependencies(dobjs, numObjs, boundaryObjs);
/*
* Sort the objects into a safe dump order (no forward references).
* will dump identically. Before 7.3 we don't have dependencies and we
* use OID ordering as an (unreliable) guide to creation order.
*/
- getDumpableObjects(&dobjs, &numObjs);
-
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
sortDumpableObjectsByTypeName(dobjs, numObjs);
else
sortDumpableObjectsByTypeOid(dobjs, numObjs);
- sortDumpableObjects(dobjs, numObjs);
+ /* If we do a parallel dump, we want the largest tables to go first */
+ if (archiveFormat == archDirectory && numWorkers > 1)
+ sortDataAndIndexObjectsBySize(dobjs, numObjs);
+
+ sortDumpableObjects(dobjs, numObjs,
+ boundaryObjs[0].dumpId, boundaryObjs[1].dumpId);
/*
* Create archive TOC entries for all the objects to be dumped, in a safe
*/
/* First the special ENCODING and STDSTRINGS entries. */
- dumpEncoding(g_fout);
- dumpStdStrings(g_fout);
+ dumpEncoding(fout);
+ dumpStdStrings(fout);
/* The database item is always next, unless we don't want it at all */
if (include_everything && !dataOnly)
- dumpDatabase(g_fout);
+ dumpDatabase(fout);
/* Now the rearrangeable objects. */
for (i = 0; i < numObjs; i++)
- dumpDumpableObject(g_fout, dobjs[i]);
+ dumpDumpableObject(fout, dobjs[i]);
/*
- * And finally we can do the actual output.
+ * Set up options info to ensure we dump what we want.
*/
- if (plainText)
- {
- ropt = NewRestoreOptions();
- ropt->filename = (char *) filename;
- ropt->dropSchema = outputClean;
- ropt->aclsSkip = aclsSkip;
- ropt->superuser = outputSuperuser;
- ropt->createDB = outputCreateDB;
- ropt->noOwner = outputNoOwner;
- ropt->noTablespace = outputNoTablespaces;
- ropt->disable_triggers = disable_triggers;
- ropt->use_setsessauth = use_setsessauth;
- ropt->dataOnly = dataOnly;
-
- if (compressLevel == -1)
- ropt->compression = 0;
- else
- ropt->compression = compressLevel;
+ ropt = NewRestoreOptions();
+ ropt->filename = filename;
+ ropt->dropSchema = outputClean;
+ ropt->dataOnly = dataOnly;
+ ropt->schemaOnly = schemaOnly;
+ ropt->if_exists = if_exists;
+ ropt->dumpSections = dumpSections;
+ ropt->aclsSkip = aclsSkip;
+ ropt->superuser = outputSuperuser;
+ ropt->createDB = outputCreateDB;
+ ropt->noOwner = outputNoOwner;
+ ropt->noTablespace = outputNoTablespaces;
+ ropt->disable_triggers = disable_triggers;
+ ropt->use_setsessauth = use_setsessauth;
- ropt->suppressDumpWarnings = true; /* We've already shown them */
+ if (compressLevel == -1)
+ ropt->compression = 0;
+ else
+ ropt->compression = compressLevel;
- RestoreArchive(g_fout, ropt);
- }
+ ropt->suppressDumpWarnings = true; /* We've already shown them */
+
+ SetArchiveRestoreOptions(fout, ropt);
- CloseArchive(g_fout);
+ /*
+ * The archive's TOC entries are now marked as to which ones will actually
+ * be output, so we can set up their dependency lists properly. This isn't
+ * necessary for plain-text output, though.
+ */
+ if (!plainText)
+ BuildArchiveDependencies(fout);
+
+ /*
+ * And finally we can do the actual output.
+ *
+ * Note: for non-plain-text output formats, the output file is written
+ * inside CloseArchive(). This is, um, bizarre; but not worth changing
+ * right now.
+ */
+ if (plainText)
+ RestoreArchive(fout);
- PQfinish(g_conn);
+ CloseArchive(fout);
- exit(0);
+ exit_nicely(0);
}
printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
printf(_("\nGeneral options:\n"));
- printf(_(" -f, --file=FILENAME output file or directory name\n"));
- printf(_(" -F, --format=c|d|t|p output file format (custom, directory, tar,\n"
- " plain text (default))\n"));
- printf(_(" -v, --verbose verbose mode\n"));
- printf(_(" -Z, --compress=0-9 compression level for compressed formats\n"));
- printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
- printf(_(" --help show this help, then exit\n"));
- printf(_(" --version output version information, then exit\n"));
+ printf(_(" -f, --file=FILENAME output file or directory name\n"));
+ printf(_(" -F, --format=c|d|t|p output file format (custom, directory, tar,\n"
+ " plain text (default))\n"));
+ printf(_(" -j, --jobs=NUM use this many parallel jobs to dump\n"));
+ printf(_(" -v, --verbose verbose mode\n"));
+ printf(_(" -V, --version output version information, then exit\n"));
+ printf(_(" -Z, --compress=0-9 compression level for compressed formats\n"));
+ printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
+ printf(_(" -?, --help show this help, then exit\n"));
printf(_("\nOptions controlling the output content:\n"));
- printf(_(" -a, --data-only dump only the data, not the schema\n"));
- printf(_(" -b, --blobs include large objects in dump\n"));
- printf(_(" -c, --clean clean (drop) database objects before recreating\n"));
- printf(_(" -C, --create include commands to create database in dump\n"));
- printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
- printf(_(" -n, --schema=SCHEMA dump the named schema(s) only\n"));
- printf(_(" -N, --exclude-schema=SCHEMA do NOT dump the named schema(s)\n"));
- printf(_(" -o, --oids include OIDs in dump\n"));
- printf(_(" -O, --no-owner skip restoration of object ownership in\n"
- " plain-text format\n"));
- printf(_(" -s, --schema-only dump only the schema, no data\n"));
- printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n"));
- printf(_(" -t, --table=TABLE dump the named table(s) only\n"));
- printf(_(" -T, --exclude-table=TABLE do NOT dump the named table(s)\n"));
- printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
- printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
- printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
- printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
- printf(_(" --disable-triggers disable triggers during data-only restore\n"));
- printf(_(" --exclude-table-data=TABLE do NOT dump data for the named table(s)\n"));
- printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
- printf(_(" --no-security-labels do not dump security label assignments\n"));
- printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
- printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
- printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
- printf(_(" --section=SECTION dump named section (pre-data, data or post-data)\n"));
- printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n"));
+ printf(_(" -a, --data-only dump only the data, not the schema\n"));
+ printf(_(" -b, --blobs include large objects in dump\n"));
+ printf(_(" -c, --clean clean (drop) database objects before recreating\n"));
+ printf(_(" -C, --create include commands to create database in dump\n"));
+ printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
+ printf(_(" -n, --schema=SCHEMA dump the named schema(s) only\n"));
+ printf(_(" -N, --exclude-schema=SCHEMA do NOT dump the named schema(s)\n"));
+ printf(_(" -o, --oids include OIDs in dump\n"));
+ printf(_(" -O, --no-owner skip restoration of object ownership in\n"
+ " plain-text format\n"));
+ printf(_(" -s, --schema-only dump only the schema, no data\n"));
+ printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n"));
+ printf(_(" -t, --table=TABLE dump the named table(s) only\n"));
+ printf(_(" -T, --exclude-table=TABLE do NOT dump the named table(s)\n"));
+ printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
+ printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
+ printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
+ printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
+ printf(_(" --disable-triggers disable triggers during data-only restore\n"));
+ printf(_(" --exclude-table-data=TABLE do NOT dump data for the named table(s)\n"));
+ printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
+ printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
+ printf(_(" --no-security-labels do not dump security label assignments\n"));
+ printf(_(" --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n"));
+ printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
+ printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
+ printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
+ printf(_(" --section=SECTION dump named section (pre-data, data, or post-data)\n"));
+ printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n"));
printf(_(" --use-set-session-authorization\n"
- " use SET SESSION AUTHORIZATION commands instead of\n"
- " ALTER OWNER commands to set ownership\n"));
+ " use SET SESSION AUTHORIZATION commands instead of\n"
+ " ALTER OWNER commands to set ownership\n"));
printf(_("\nConnection options:\n"));
+ printf(_(" -d, --dbname=DBNAME database to dump\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
printf(_(" -p, --port=PORT database server port number\n"));
printf(_(" -U, --username=NAME connect as specified database user\n"));
printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
}
-void
-exit_nicely(void)
+static void
+setup_connection(Archive *AH, const char *dumpencoding, char *use_role)
{
- PQfinish(g_conn);
- if (g_verbose)
- write_msg(NULL, "*** aborted because of error\n");
- exit(1);
+ PGconn *conn = GetConnection(AH);
+ const char *std_strings;
+
+ /*
+ * Set the client encoding if requested. If dumpencoding == NULL then
+ * either it hasn't been requested or we're a cloned connection and then
+ * this has already been set in CloneArchive according to the original
+ * connection encoding.
+ */
+ if (dumpencoding)
+ {
+ if (PQsetClientEncoding(conn, dumpencoding) < 0)
+ exit_horribly(NULL, "invalid client encoding \"%s\" specified\n",
+ dumpencoding);
+ }
+
+ /*
+ * Get the active encoding and the standard_conforming_strings setting, so
+ * we know how to escape strings.
+ */
+ AH->encoding = PQclientEncoding(conn);
+
+ std_strings = PQparameterStatus(conn, "standard_conforming_strings");
+ AH->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
+
+ /* Set the role if requested */
+ if (!use_role && AH->use_role)
+ use_role = AH->use_role;
+
+ /* Set the role if requested */
+ if (use_role && AH->remoteVersion >= 80100)
+ {
+ PQExpBuffer query = createPQExpBuffer();
+
+ appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
+ ExecuteSqlStatement(AH, query->data);
+ destroyPQExpBuffer(query);
+
+ /* save this for later use on parallel connections */
+ if (!AH->use_role)
+ AH->use_role = strdup(use_role);
+ }
+
+ /* Set the datestyle to ISO to ensure the dump's portability */
+ ExecuteSqlStatement(AH, "SET DATESTYLE = ISO");
+
+ /* Likewise, avoid using sql_standard intervalstyle */
+ if (AH->remoteVersion >= 80400)
+ ExecuteSqlStatement(AH, "SET INTERVALSTYLE = POSTGRES");
+
+ /*
+ * If supported, set extra_float_digits so that we can dump float data
+ * exactly (given correctly implemented float I/O code, anyway)
+ */
+ if (AH->remoteVersion >= 90000)
+ ExecuteSqlStatement(AH, "SET extra_float_digits TO 3");
+ else if (AH->remoteVersion >= 70400)
+ ExecuteSqlStatement(AH, "SET extra_float_digits TO 2");
+
+ /*
+ * If synchronized scanning is supported, disable it, to prevent
+ * unpredictable changes in row ordering across a dump and reload.
+ */
+ if (AH->remoteVersion >= 80300)
+ ExecuteSqlStatement(AH, "SET synchronize_seqscans TO off");
+
+ /*
+ * Disable timeouts if supported.
+ */
+ if (AH->remoteVersion >= 70300)
+ ExecuteSqlStatement(AH, "SET statement_timeout = 0");
+ if (AH->remoteVersion >= 90300)
+ ExecuteSqlStatement(AH, "SET lock_timeout = 0");
+
+ /*
+ * Quote all identifiers, if requested.
+ */
+ if (quote_all_identifiers && AH->remoteVersion >= 90100)
+ ExecuteSqlStatement(AH, "SET quote_all_identifiers = true");
+
+ /*
+ * Start transaction-snapshot mode transaction to dump consistent data.
+ */
+ ExecuteSqlStatement(AH, "BEGIN");
+ if (AH->remoteVersion >= 90100)
+ {
+ if (serializable_deferrable)
+ ExecuteSqlStatement(AH,
+ "SET TRANSACTION ISOLATION LEVEL "
+ "SERIALIZABLE, READ ONLY, DEFERRABLE");
+ else
+ ExecuteSqlStatement(AH,
+ "SET TRANSACTION ISOLATION LEVEL "
+ "REPEATABLE READ, READ ONLY");
+ }
+ else if (AH->remoteVersion >= 70400)
+ {
+ /* note: comma was not accepted in SET TRANSACTION before 8.0 */
+ ExecuteSqlStatement(AH,
+ "SET TRANSACTION ISOLATION LEVEL "
+ "SERIALIZABLE READ ONLY");
+ }
+ else
+ ExecuteSqlStatement(AH,
+ "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
+
+
+
+ if (AH->numWorkers > 1 && AH->remoteVersion >= 90200 && !no_synchronized_snapshots)
+ {
+ if (AH->sync_snapshot_id)
+ {
+ PQExpBuffer query = createPQExpBuffer();
+
+ appendPQExpBufferStr(query, "SET TRANSACTION SNAPSHOT ");
+ appendStringLiteralConn(query, AH->sync_snapshot_id, conn);
+ ExecuteSqlStatement(AH, query->data);
+ destroyPQExpBuffer(query);
+ }
+ else
+ AH->sync_snapshot_id = get_synchronized_snapshot(AH);
+ }
+}
+
+static void
+setupDumpWorker(Archive *AHX, RestoreOptions *ropt)
+{
+ setup_connection(AHX, NULL, NULL);
+}
+
+static char *
+get_synchronized_snapshot(Archive *fout)
+{
+ char *query = "SELECT pg_export_snapshot()";
+ char *result;
+ PGresult *res;
+
+ res = ExecuteSqlQueryForSingleRow(fout, query);
+ result = strdup(PQgetvalue(res, 0, 0));
+ PQclear(res);
+
+ return result;
}
static ArchiveFormat
archiveFormat = archDirectory;
else if (pg_strcasecmp(format, "directory") == 0)
archiveFormat = archDirectory;
- else if (pg_strcasecmp(format, "f") == 0 || pg_strcasecmp(format, "file") == 0)
-
- /*
- * Dump files into the current directory; for demonstration only, not
- * documented.
- */
- archiveFormat = archFiles;
else if (pg_strcasecmp(format, "p") == 0)
archiveFormat = archNull;
else if (pg_strcasecmp(format, "plain") == 0)
else if (pg_strcasecmp(format, "tar") == 0)
archiveFormat = archTar;
else
- {
- write_msg(NULL, "invalid output format \"%s\" specified\n", format);
- exit(1);
- }
+ exit_horribly(NULL, "invalid output format \"%s\" specified\n", format);
return archiveFormat;
}
* and append them to the given OID list.
*/
static void
-expand_schema_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
+expand_schema_name_patterns(Archive *fout,
+ SimpleStringList *patterns,
+ SimpleOidList *oids)
{
PQExpBuffer query;
PGresult *res;
if (patterns->head == NULL)
return; /* nothing to do */
- if (g_fout->remoteVersion < 70300)
- {
- write_msg(NULL, "server version must be at least 7.3 to use schema selection switches\n");
- exit_nicely();
- }
+ if (fout->remoteVersion < 70300)
+ exit_horribly(NULL, "server version must be at least 7.3 to use schema selection switches\n");
query = createPQExpBuffer();
for (cell = patterns->head; cell; cell = cell->next)
{
if (cell != patterns->head)
- appendPQExpBuffer(query, "UNION ALL\n");
+ appendPQExpBufferStr(query, "UNION ALL\n");
appendPQExpBuffer(query,
"SELECT oid FROM pg_catalog.pg_namespace n\n");
- processSQLNamePattern(g_conn, query, cell->val, false, false,
- NULL, "n.nspname", NULL,
- NULL);
+ processSQLNamePattern(GetConnection(fout), query, cell->val, false,
+ false, NULL, "n.nspname", NULL, NULL);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
for (i = 0; i < PQntuples(res); i++)
{
* and append them to the given OID list.
*/
static void
-expand_table_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
+expand_table_name_patterns(Archive *fout,
+ SimpleStringList *patterns, SimpleOidList *oids)
{
PQExpBuffer query;
PGresult *res;
for (cell = patterns->head; cell; cell = cell->next)
{
if (cell != patterns->head)
- appendPQExpBuffer(query, "UNION ALL\n");
+ appendPQExpBufferStr(query, "UNION ALL\n");
appendPQExpBuffer(query,
"SELECT c.oid"
"\nFROM pg_catalog.pg_class c"
"\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
- "\nWHERE c.relkind in ('%c', '%c', '%c', '%c')\n",
+ "\nWHERE c.relkind in ('%c', '%c', '%c', '%c', '%c')\n",
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
- RELKIND_FOREIGN_TABLE);
- processSQLNamePattern(g_conn, query, cell->val, true, false,
- "n.nspname", "c.relname", NULL,
+ RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
+ processSQLNamePattern(GetConnection(fout), query, cell->val, true,
+ false, "n.nspname", "c.relname", NULL,
"pg_catalog.pg_table_is_visible(c.oid)");
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
for (i = 0; i < PQntuples(res); i++)
{
simple_oid_list_member(&table_exclude_oids,
tbinfo->dobj.catId.oid))
tbinfo->dobj.dump = false;
-
- /* If table is to be dumped, check that the data is not excluded */
- if (tbinfo->dobj.dump && !
- simple_oid_list_member(&tabledata_exclude_oids,
- tbinfo->dobj.catId.oid))
- tbinfo->dobj.dumpdata = true;
- else
- tbinfo->dobj.dumpdata = false;
-
}
/*
if (tyinfo->isArray)
{
tyinfo->dobj.objType = DO_DUMMY_TYPE;
+
/*
* Fall through to set the dump flag; we assume that the subsequent
* rules will do the same thing as they would for the array's base
const bool hasoids = tbinfo->hasoids;
const bool oids = tdinfo->oids;
PQExpBuffer q = createPQExpBuffer();
+
+ /*
+ * Note: can't use getThreadLocalPQExpBuffer() here, we're calling fmtId
+ * which uses it already.
+ */
+ PQExpBuffer clistBuf = createPQExpBuffer();
+ PGconn *conn = GetConnection(fout);
PGresult *res;
int ret;
char *copybuf;
* this ensures reproducible results in case the table contains regproc,
* regclass, etc columns.
*/
- selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
/*
* If possible, specify the column list explicitly so that we have no
* column ordering of COPY will not be what we want in certain corner
* cases involving ADD COLUMN and inheritance.)
*/
- if (g_fout->remoteVersion >= 70300)
- column_list = fmtCopyColumnList(tbinfo);
+ if (fout->remoteVersion >= 70300)
+ column_list = fmtCopyColumnList(tbinfo, clistBuf);
else
column_list = ""; /* can't select columns in COPY */
if (oids && hasoids)
{
appendPQExpBuffer(q, "COPY %s %s WITH OIDS TO stdout;",
- fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
+ fmtQualifiedId(fout->remoteVersion,
+ tbinfo->dobj.namespace->dobj.name,
classname),
column_list);
}
else
appendPQExpBufferStr(q, "* ");
appendPQExpBuffer(q, "FROM %s %s) TO stdout;",
- fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
+ fmtQualifiedId(fout->remoteVersion,
+ tbinfo->dobj.namespace->dobj.name,
classname),
tdinfo->filtercond);
}
else
{
appendPQExpBuffer(q, "COPY %s %s TO stdout;",
- fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
+ fmtQualifiedId(fout->remoteVersion,
+ tbinfo->dobj.namespace->dobj.name,
classname),
column_list);
}
- res = PQexec(g_conn, q->data);
- check_sql_result(res, g_conn, q->data, PGRES_COPY_OUT);
+ res = ExecuteSqlQuery(fout, q->data, PGRES_COPY_OUT);
PQclear(res);
+ destroyPQExpBuffer(clistBuf);
for (;;)
{
- ret = PQgetCopyData(g_conn, ©buf, 0);
+ ret = PQgetCopyData(conn, ©buf, 0);
if (ret < 0)
break; /* done or error */
{
/* 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(g_conn));
+ write_msg(NULL, "Error message from server: %s", PQerrorMessage(conn));
write_msg(NULL, "The command was: %s\n", q->data);
- exit_nicely();
+ exit_nicely(1);
}
/* Check command status and return to normal libpq state */
- res = PQgetResult(g_conn);
- check_sql_result(res, g_conn, q->data, PGRES_COMMAND_OK);
+ 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);
+ exit_nicely(1);
+ }
PQclear(res);
destroyPQExpBuffer(q);
return 1;
}
+/*
+ * Dump table data using INSERT commands.
+ *
+ * Caution: when we restore from an archive file direct to database, the
+ * INSERT commands emitted by this function have to be parsed by
+ * pg_backup_db.c's ExecuteInsertCommands(), which will not handle comments,
+ * E'' strings, or dollar-quoted strings. So don't emit anything like that.
+ */
static int
dumpTableData_insert(Archive *fout, void *dcontext)
{
TableInfo *tbinfo = tdinfo->tdtable;
const char *classname = tbinfo->dobj.name;
PQExpBuffer q = createPQExpBuffer();
+ PQExpBuffer insertStmt = NULL;
PGresult *res;
int tuple;
int nfields;
* this ensures reproducible results in case the table contains regproc,
* regclass, etc columns.
*/
- selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
"SELECT * FROM ONLY %s",
- fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
+ fmtQualifiedId(fout->remoteVersion,
+ tbinfo->dobj.namespace->dobj.name,
classname));
}
else
{
appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
"SELECT * FROM %s",
- fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
+ fmtQualifiedId(fout->remoteVersion,
+ tbinfo->dobj.namespace->dobj.name,
classname));
}
if (tdinfo->filtercond)
appendPQExpBuffer(q, " %s", tdinfo->filtercond);
- res = PQexec(g_conn, q->data);
- check_sql_result(res, g_conn, q->data, PGRES_COMMAND_OK);
+ ExecuteSqlStatement(fout, q->data);
- do
+ while (1)
{
- PQclear(res);
-
- res = PQexec(g_conn, "FETCH 100 FROM _pg_dump_cursor");
- check_sql_result(res, g_conn, "FETCH 100 FROM _pg_dump_cursor",
- PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, "FETCH 100 FROM _pg_dump_cursor",
+ PGRES_TUPLES_OK);
nfields = PQnfields(res);
for (tuple = 0; tuple < PQntuples(res); tuple++)
{
- archprintf(fout, "INSERT INTO %s ", fmtId(classname));
- if (nfields == 0)
+ /*
+ * 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();
+ appendPQExpBuffer(insertStmt, "INSERT INTO %s ",
+ fmtId(classname));
+
/* corner case for zero-column table */
- archprintf(fout, "DEFAULT VALUES;\n");
- continue;
- }
- if (column_inserts)
- {
- resetPQExpBuffer(q);
- appendPQExpBuffer(q, "(");
- for (field = 0; field < nfields; field++)
+ if (nfields == 0)
+ {
+ appendPQExpBufferStr(insertStmt, "DEFAULT VALUES;\n");
+ }
+ else
{
- if (field > 0)
- appendPQExpBuffer(q, ", ");
- appendPQExpBufferStr(q, fmtId(PQfname(res, field)));
+ /* append the list of column names if required */
+ if (column_inserts)
+ {
+ appendPQExpBufferStr(insertStmt, "(");
+ for (field = 0; field < nfields; field++)
+ {
+ if (field > 0)
+ appendPQExpBufferStr(insertStmt, ", ");
+ appendPQExpBufferStr(insertStmt,
+ fmtId(PQfname(res, field)));
+ }
+ appendPQExpBufferStr(insertStmt, ") ");
+ }
+
+ appendPQExpBufferStr(insertStmt, "VALUES (");
}
- appendPQExpBuffer(q, ") ");
- archputs(q->data, fout);
}
- archprintf(fout, "VALUES (");
+
+ archputs(insertStmt->data, fout);
+
+ /* if it is zero-column table then we're done */
+ if (nfields == 0)
+ continue;
+
for (field = 0; field < nfields; field++)
{
if (field > 0)
- archprintf(fout, ", ");
+ archputs(", ", fout);
if (PQgetisnull(res, tuple, field))
{
- archprintf(fout, "NULL");
+ archputs("NULL", fout);
continue;
}
const char *s = PQgetvalue(res, tuple, field);
if (strspn(s, "0123456789 +-eE.") == strlen(s))
- archprintf(fout, "%s", s);
+ archputs(s, fout);
else
archprintf(fout, "'%s'", s);
}
case BOOLOID:
if (strcmp(PQgetvalue(res, tuple, field), "t") == 0)
- archprintf(fout, "true");
+ archputs("true", fout);
else
- archprintf(fout, "false");
+ archputs("false", fout);
break;
default:
break;
}
}
- archprintf(fout, ");\n");
+ archputs(");\n", fout);
}
- } while (PQntuples(res) > 0);
-
- PQclear(res);
-
- archprintf(fout, "\n\n");
- do_sql_command(g_conn, "CLOSE _pg_dump_cursor");
-
- destroyPQExpBuffer(q);
+ if (PQntuples(res) <= 0)
+ {
+ PQclear(res);
+ break;
+ }
+ PQclear(res);
+ }
+
+ archputs("\n\n", fout);
+
+ ExecuteSqlStatement(fout, "CLOSE _pg_dump_cursor");
+
+ destroyPQExpBuffer(q);
+ if (insertStmt != NULL)
+ destroyPQExpBuffer(insertStmt);
+
return 1;
}
{
TableInfo *tbinfo = tdinfo->tdtable;
PQExpBuffer copyBuf = createPQExpBuffer();
+ PQExpBuffer clistBuf = createPQExpBuffer();
DataDumperPtr dumpFn;
char *copyStmt;
- /* don't do anything if the data isn't wanted */
- if (!tbinfo->dobj.dumpdata)
- return;
-
if (!dump_inserts)
{
/* Dump/restore using COPY */
appendPQExpBuffer(copyBuf, "COPY %s ",
fmtId(tbinfo->dobj.name));
appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n",
- fmtCopyColumnList(tbinfo),
+ fmtCopyColumnList(tbinfo, clistBuf),
(tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "");
copyStmt = copyBuf->data;
}
copyStmt = NULL;
}
+ /*
+ * Note: although the TableDataInfo is a full DumpableObject, we treat its
+ * dependency on its table as "special" and pass it to ArchiveEntry now.
+ * See comments for BuildArchiveDependencies.
+ */
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,
- tdinfo->dobj.dependencies, tdinfo->dobj.nDeps,
+ &(tbinfo->dobj.dumpId), 1,
dumpFn, tdinfo);
destroyPQExpBuffer(copyBuf);
+ destroyPQExpBuffer(clistBuf);
+}
+
+/*
+ * refreshMatViewData -
+ * load or refresh the contents of a single materialized view
+ *
+ * Actually, this just makes an ArchiveEntry for the REFRESH MATERIALIZED VIEW
+ * statement.
+ */
+static void
+refreshMatViewData(Archive *fout, TableDataInfo *tdinfo)
+{
+ TableInfo *tbinfo = tdinfo->tdtable;
+ PQExpBuffer q;
+
+ /* If the materialized view is not flagged as populated, skip this. */
+ if (!tbinfo->relispopulated)
+ return;
+
+ q = createPQExpBuffer();
+
+ appendPQExpBuffer(q, "REFRESH MATERIALIZED VIEW %s;\n",
+ fmtId(tbinfo->dobj.name));
+
+ 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 */
+
+ destroyPQExpBuffer(q);
}
/*
for (i = 0; i < numTables; i++)
{
- /* Skip VIEWs (no data to dump) */
- if (tblinfo[i].relkind == RELKIND_VIEW)
- continue;
- /* Skip SEQUENCEs (handled elsewhere) */
- if (tblinfo[i].relkind == RELKIND_SEQUENCE)
- continue;
- /* Skip FOREIGN TABLEs (no data to dump) */
- if (tblinfo[i].relkind == RELKIND_FOREIGN_TABLE)
- continue;
- /* Skip unlogged tables if so requested */
- if (tblinfo[i].relpersistence == RELPERSISTENCE_UNLOGGED
- && no_unlogged_table_data)
- continue;
-
- if (tblinfo[i].dobj.dump && tblinfo[i].dataObj == NULL)
+ if (tblinfo[i].dobj.dump)
makeTableDataInfo(&(tblinfo[i]), oids);
}
}
/*
* Make a dumpable object for the data of this specific table
+ *
+ * Note: we make a TableDataInfo if and only if we are going to dump the
+ * table data; the "dump" flag in such objects isn't used.
*/
static void
makeTableDataInfo(TableInfo *tbinfo, bool oids)
{
TableDataInfo *tdinfo;
+ /*
+ * Nothing to do if we already decided to dump the table. This will
+ * happen for "config" tables.
+ */
+ if (tbinfo->dataObj != NULL)
+ return;
+
+ /* Skip VIEWs (no data to dump) */
+ if (tbinfo->relkind == RELKIND_VIEW)
+ return;
+ /* Skip FOREIGN TABLEs (no data to dump) */
+ if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
+ return;
+
+ /* Don't dump data in unlogged tables, if so requested */
+ if (tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED &&
+ no_unlogged_table_data)
+ return;
+
+ /* Check that the data is not explicitly excluded */
+ if (simple_oid_list_member(&tabledata_exclude_oids,
+ tbinfo->dobj.catId.oid))
+ return;
+
+ /* OK, let's dump it */
tdinfo = (TableDataInfo *) pg_malloc(sizeof(TableDataInfo));
- tdinfo->dobj.objType = DO_TABLE_DATA;
+ if (tbinfo->relkind == RELKIND_MATVIEW)
+ tdinfo->dobj.objType = DO_REFRESH_MATVIEW;
+ else
+ tdinfo->dobj.objType = DO_TABLE_DATA;
/*
* Note: use tableoid 0 so that this object won't be mistaken for
tbinfo->dataObj = tdinfo;
}
+/*
+ * The refresh for a materialized view must be dependent on the refresh for
+ * any materialized view that this one is dependent on.
+ *
+ * This must be called after all the objects are created, but before they are
+ * sorted.
+ */
+static void
+buildMatViewRefreshDependencies(Archive *fout)
+{
+ PQExpBuffer query;
+ PGresult *res;
+ int ntups,
+ i;
+ int i_classid,
+ i_objid,
+ i_refobjid;
+
+ /* No Mat Views before 9.3. */
+ if (fout->remoteVersion < 90300)
+ return;
+
+ /* Make sure we are in proper schema */
+ selectSourceSchema(fout, "pg_catalog");
+
+ query = createPQExpBuffer();
+
+ appendPQExpBufferStr(query, "WITH RECURSIVE w AS "
+ "( "
+ "SELECT d1.objid, d2.refobjid, c2.relkind AS refrelkind "
+ "FROM pg_depend d1 "
+ "JOIN pg_class c1 ON c1.oid = d1.objid "
+ "AND c1.relkind = 'm' "
+ "JOIN pg_rewrite r1 ON r1.ev_class = d1.objid "
+ "JOIN pg_depend d2 ON d2.classid = 'pg_rewrite'::regclass "
+ "AND d2.objid = r1.oid "
+ "AND d2.refobjid <> d1.objid "
+ "JOIN pg_class c2 ON c2.oid = d2.refobjid "
+ "AND c2.relkind IN ('m','v') "
+ "WHERE d1.classid = 'pg_class'::regclass "
+ "UNION "
+ "SELECT w.objid, d3.refobjid, c3.relkind "
+ "FROM w "
+ "JOIN pg_rewrite r3 ON r3.ev_class = w.refobjid "
+ "JOIN pg_depend d3 ON d3.classid = 'pg_rewrite'::regclass "
+ "AND d3.objid = r3.oid "
+ "AND d3.refobjid <> w.refobjid "
+ "JOIN pg_class c3 ON c3.oid = d3.refobjid "
+ "AND c3.relkind IN ('m','v') "
+ ") "
+ "SELECT 'pg_class'::regclass::oid AS classid, objid, refobjid "
+ "FROM w "
+ "WHERE refrelkind = 'm'");
+
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+ ntups = PQntuples(res);
+
+ i_classid = PQfnumber(res, "classid");
+ i_objid = PQfnumber(res, "objid");
+ i_refobjid = PQfnumber(res, "refobjid");
+
+ for (i = 0; i < ntups; i++)
+ {
+ CatalogId objId;
+ CatalogId refobjId;
+ DumpableObject *dobj;
+ DumpableObject *refdobj;
+ TableInfo *tbinfo;
+ TableInfo *reftbinfo;
+
+ objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
+ objId.oid = atooid(PQgetvalue(res, i, i_objid));
+ refobjId.tableoid = objId.tableoid;
+ refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid));
+
+ dobj = findObjectByCatalogId(objId);
+ if (dobj == NULL)
+ continue;
+
+ Assert(dobj->objType == DO_TABLE);
+ tbinfo = (TableInfo *) dobj;
+ Assert(tbinfo->relkind == RELKIND_MATVIEW);
+ dobj = (DumpableObject *) tbinfo->dataObj;
+ if (dobj == NULL)
+ continue;
+ Assert(dobj->objType == DO_REFRESH_MATVIEW);
+
+ refdobj = findObjectByCatalogId(refobjId);
+ if (refdobj == NULL)
+ continue;
+
+ Assert(refdobj->objType == DO_TABLE);
+ reftbinfo = (TableInfo *) refdobj;
+ Assert(reftbinfo->relkind == RELKIND_MATVIEW);
+ refdobj = (DumpableObject *) reftbinfo->dataObj;
+ if (refdobj == NULL)
+ continue;
+ Assert(refdobj->objType == DO_REFRESH_MATVIEW);
+
+ addObjectDependency(dobj, refdobj->dumpId);
+
+ if (!reftbinfo->relispopulated)
+ tbinfo->relispopulated = false;
+ }
+
+ PQclear(res);
+
+ destroyPQExpBuffer(query);
+}
+
/*
* getTableDataFKConstraints -
* add dump-order dependencies reflecting foreign key constraints
* dump the database definition
*/
static void
-dumpDatabase(Archive *AH)
+dumpDatabase(Archive *fout)
{
PQExpBuffer dbQry = createPQExpBuffer();
PQExpBuffer delQry = createPQExpBuffer();
PQExpBuffer creaQry = createPQExpBuffer();
+ PGconn *conn = GetConnection(fout);
PGresult *res;
- int ntups;
int i_tableoid,
i_oid,
i_dba,
*tablespace;
uint32 frozenxid;
- datname = PQdb(g_conn);
+ datname = PQdb(conn);
if (g_verbose)
write_msg(NULL, "saving database definition\n");
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
/* Get the database owner and parameters from pg_database */
- if (g_fout->remoteVersion >= 80400)
+ if (fout->remoteVersion >= 80400)
{
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
"(%s datdba) AS dba, "
"FROM pg_database "
"WHERE datname = ",
username_subquery);
- appendStringLiteralAH(dbQry, datname, AH);
+ appendStringLiteralAH(dbQry, datname, fout);
}
- else if (g_fout->remoteVersion >= 80200)
+ else if (fout->remoteVersion >= 80200)
{
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
"(%s datdba) AS dba, "
"FROM pg_database "
"WHERE datname = ",
username_subquery);
- appendStringLiteralAH(dbQry, datname, AH);
+ appendStringLiteralAH(dbQry, datname, fout);
}
- else if (g_fout->remoteVersion >= 80000)
+ else if (fout->remoteVersion >= 80000)
{
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
"(%s datdba) AS dba, "
"FROM pg_database "
"WHERE datname = ",
username_subquery);
- appendStringLiteralAH(dbQry, datname, AH);
+ appendStringLiteralAH(dbQry, datname, fout);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
"(%s datdba) AS dba, "
"FROM pg_database "
"WHERE datname = ",
username_subquery);
- appendStringLiteralAH(dbQry, datname, AH);
+ appendStringLiteralAH(dbQry, datname, fout);
}
else
{
"FROM pg_database "
"WHERE datname = ",
username_subquery);
- appendStringLiteralAH(dbQry, datname, AH);
- }
-
- res = PQexec(g_conn, dbQry->data);
- check_sql_result(res, g_conn, dbQry->data, PGRES_TUPLES_OK);
-
- ntups = PQntuples(res);
-
- if (ntups <= 0)
- {
- write_msg(NULL, "missing pg_database entry for database \"%s\"\n",
- datname);
- exit_nicely();
+ appendStringLiteralAH(dbQry, datname, fout);
}
- if (ntups != 1)
- {
- write_msg(NULL, "query returned more than one (%d) pg_database entry for database \"%s\"\n",
- ntups, datname);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, dbQry->data);
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
fmtId(datname));
if (strlen(encoding) > 0)
{
- appendPQExpBuffer(creaQry, " ENCODING = ");
- appendStringLiteralAH(creaQry, encoding, AH);
+ appendPQExpBufferStr(creaQry, " ENCODING = ");
+ appendStringLiteralAH(creaQry, encoding, fout);
}
if (strlen(collate) > 0)
{
- appendPQExpBuffer(creaQry, " LC_COLLATE = ");
- appendStringLiteralAH(creaQry, collate, AH);
+ appendPQExpBufferStr(creaQry, " LC_COLLATE = ");
+ appendStringLiteralAH(creaQry, collate, fout);
}
if (strlen(ctype) > 0)
{
- appendPQExpBuffer(creaQry, " LC_CTYPE = ");
- appendStringLiteralAH(creaQry, ctype, AH);
+ appendPQExpBufferStr(creaQry, " LC_CTYPE = ");
+ appendStringLiteralAH(creaQry, ctype, fout);
}
if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
appendPQExpBuffer(creaQry, " TABLESPACE = %s",
fmtId(tablespace));
- appendPQExpBuffer(creaQry, ";\n");
+ appendPQExpBufferStr(creaQry, ";\n");
if (binary_upgrade)
{
- appendPQExpBuffer(creaQry, "\n-- For binary upgrade, set datfrozenxid.\n");
+ appendPQExpBufferStr(creaQry, "\n-- For binary upgrade, set datfrozenxid.\n");
appendPQExpBuffer(creaQry, "UPDATE pg_catalog.pg_database\n"
"SET datfrozenxid = '%u'\n"
"WHERE datname = ",
frozenxid);
- appendStringLiteralAH(creaQry, datname, AH);
- appendPQExpBuffer(creaQry, ";\n");
+ appendStringLiteralAH(creaQry, datname, fout);
+ appendPQExpBufferStr(creaQry, ";\n");
}
dbDumpId = createDumpId();
- ArchiveEntry(AH,
+ ArchiveEntry(fout,
dbCatId, /* catalog ID */
dbDumpId, /* dump ID */
datname, /* Name */
"WHERE oid = %u;\n",
LargeObjectRelationId);
- lo_res = PQexec(g_conn, loFrozenQry->data);
- check_sql_result(lo_res, g_conn, loFrozenQry->data, PGRES_TUPLES_OK);
-
- if (PQntuples(lo_res) != 1)
- {
- write_msg(NULL, "dumpDatabase(): could not find pg_largeobject.relfrozenxid\n");
- exit_nicely();
- }
+ lo_res = ExecuteSqlQueryForSingleRow(fout, loFrozenQry->data);
i_relfrozenxid = PQfnumber(lo_res, "relfrozenxid");
- appendPQExpBuffer(loOutQry, "\n-- For binary upgrade, set pg_largeobject.relfrozenxid\n");
+ appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, set pg_largeobject.relfrozenxid\n");
appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n"
"SET relfrozenxid = '%u'\n"
"WHERE oid = %u;\n",
atoi(PQgetvalue(lo_res, 0, i_relfrozenxid)),
LargeObjectRelationId);
- ArchiveEntry(AH, nilCatalogId, createDumpId(),
+ ArchiveEntry(fout, nilCatalogId, createDumpId(),
"pg_largeobject", NULL, NULL, "",
false, "pg_largeobject", SECTION_PRE_DATA,
loOutQry->data, "", NULL,
/*
* pg_largeobject_metadata
*/
- if (g_fout->remoteVersion >= 90000)
+ if (fout->remoteVersion >= 90000)
{
resetPQExpBuffer(loFrozenQry);
resetPQExpBuffer(loOutQry);
"WHERE oid = %u;\n",
LargeObjectMetadataRelationId);
- lo_res = PQexec(g_conn, loFrozenQry->data);
- check_sql_result(lo_res, g_conn, loFrozenQry->data, PGRES_TUPLES_OK);
-
- if (PQntuples(lo_res) != 1)
- {
- write_msg(NULL, "dumpDatabase(): could not find pg_largeobject_metadata.relfrozenxid\n");
- exit_nicely();
- }
+ lo_res = ExecuteSqlQueryForSingleRow(fout, loFrozenQry->data);
i_relfrozenxid = PQfnumber(lo_res, "relfrozenxid");
- appendPQExpBuffer(loOutQry, "\n-- For binary upgrade, set pg_largeobject_metadata.relfrozenxid\n");
+ appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, set pg_largeobject_metadata.relfrozenxid\n");
appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n"
"SET relfrozenxid = '%u'\n"
"WHERE oid = %u;\n",
atoi(PQgetvalue(lo_res, 0, i_relfrozenxid)),
LargeObjectMetadataRelationId);
- ArchiveEntry(AH, nilCatalogId, createDumpId(),
+ ArchiveEntry(fout, nilCatalogId, createDumpId(),
"pg_largeobject_metadata", NULL, NULL, "",
false, "pg_largeobject_metadata", SECTION_PRE_DATA,
loOutQry->data, "", NULL,
}
/* Dump DB comment if any */
- if (g_fout->remoteVersion >= 80200)
+ if (fout->remoteVersion >= 80200)
{
/*
* 8.2 keeps comments on shared objects in a shared table, so we
* database.
*/
appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
- appendStringLiteralAH(dbQry, comment, AH);
- appendPQExpBuffer(dbQry, ";\n");
+ appendStringLiteralAH(dbQry, comment, fout);
+ appendPQExpBufferStr(dbQry, ";\n");
- ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
+ ArchiveEntry(fout, dbCatId, createDumpId(), datname, NULL, NULL,
dba, false, "COMMENT", SECTION_NONE,
dbQry->data, "", NULL,
&dbDumpId, 1, NULL, NULL);
{
resetPQExpBuffer(dbQry);
appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
- dumpComment(AH, dbQry->data, NULL, "",
+ dumpComment(fout, dbQry->data, NULL, "",
dbCatId, 0, dbDumpId);
}
PQclear(res);
/* Dump shared security label. */
- if (!no_security_labels && g_fout->remoteVersion >= 90200)
+ if (!no_security_labels && fout->remoteVersion >= 90200)
{
PQExpBuffer seclabelQry = createPQExpBuffer();
- buildShSecLabelQuery(g_conn, "pg_database", dbCatId.oid, seclabelQry);
- res = PQexec(g_conn, seclabelQry->data);
- check_sql_result(res, g_conn, seclabelQry->data, PGRES_TUPLES_OK);
+ buildShSecLabelQuery(conn, "pg_database", dbCatId.oid, seclabelQry);
+ res = ExecuteSqlQuery(fout, seclabelQry->data, PGRES_TUPLES_OK);
resetPQExpBuffer(seclabelQry);
- emitShSecLabels(g_conn, res, seclabelQry, "DATABASE", datname);
+ emitShSecLabels(conn, res, seclabelQry, "DATABASE", datname);
if (strlen(seclabelQry->data))
- ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
+ ArchiveEntry(fout, dbCatId, createDumpId(), datname, NULL, NULL,
dba, false, "SECURITY LABEL", SECTION_NONE,
seclabelQry->data, "", NULL,
&dbDumpId, 1, NULL, NULL);
if (g_verbose)
write_msg(NULL, "saving encoding = %s\n", encname);
- appendPQExpBuffer(qry, "SET client_encoding = ");
+ appendPQExpBufferStr(qry, "SET client_encoding = ");
appendStringLiteralAH(qry, encname, AH);
- appendPQExpBuffer(qry, ";\n");
+ appendPQExpBufferStr(qry, ";\n");
ArchiveEntry(AH, nilCatalogId, createDumpId(),
"ENCODING", NULL, NULL, "",
* Collect schema-level data about large objects
*/
static void
-getBlobs(Archive *AH)
+getBlobs(Archive *fout)
{
PQExpBuffer blobQry = createPQExpBuffer();
BlobInfo *binfo;
write_msg(NULL, "reading large objects\n");
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
/* Fetch BLOB OIDs, and owner/ACL data if >= 9.0 */
- if (AH->remoteVersion >= 90000)
+ if (fout->remoteVersion >= 90000)
appendPQExpBuffer(blobQry,
"SELECT oid, (%s lomowner) AS rolname, lomacl"
" FROM pg_largeobject_metadata",
username_subquery);
- else if (AH->remoteVersion >= 70100)
- appendPQExpBuffer(blobQry,
- "SELECT DISTINCT loid, NULL::oid, NULL::oid"
- " FROM pg_largeobject");
+ else if (fout->remoteVersion >= 70100)
+ appendPQExpBufferStr(blobQry,
+ "SELECT DISTINCT loid, NULL::oid, NULL::oid"
+ " FROM pg_largeobject");
else
- appendPQExpBuffer(blobQry,
- "SELECT oid, NULL::oid, NULL::oid"
- " FROM pg_class WHERE relkind = 'l'");
+ appendPQExpBufferStr(blobQry,
+ "SELECT oid, NULL::oid, NULL::oid"
+ " FROM pg_class WHERE relkind = 'l'");
- res = PQexec(g_conn, blobQry->data);
- check_sql_result(res, g_conn, blobQry->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, blobQry->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
if (ntups > 0)
* dump the definition (metadata) of the given large object
*/
static void
-dumpBlob(Archive *AH, BlobInfo *binfo)
+dumpBlob(Archive *fout, BlobInfo *binfo)
{
PQExpBuffer cquery = createPQExpBuffer();
PQExpBuffer dquery = createPQExpBuffer();
"SELECT pg_catalog.lo_unlink('%s');\n",
binfo->dobj.name);
- ArchiveEntry(AH, binfo->dobj.catId, binfo->dobj.dumpId,
+ 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,
- binfo->dobj.dependencies, binfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* set up tag for comment and/or ACL */
appendPQExpBuffer(cquery, "LARGE OBJECT %s", binfo->dobj.name);
/* Dump comment if any */
- dumpComment(AH, cquery->data,
+ dumpComment(fout, cquery->data,
NULL, binfo->rolname,
binfo->dobj.catId, 0, binfo->dobj.dumpId);
/* Dump security label if any */
- dumpSecLabel(AH, cquery->data,
+ dumpSecLabel(fout, cquery->data,
NULL, binfo->rolname,
binfo->dobj.catId, 0, binfo->dobj.dumpId);
/* Dump ACL if any */
if (binfo->blobacl)
- dumpACL(AH, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
+ dumpACL(fout, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
binfo->dobj.name, NULL, cquery->data,
NULL, binfo->rolname, binfo->blobacl);
* dump the data contents of all large objects
*/
static int
-dumpBlobs(Archive *AH, void *arg)
+dumpBlobs(Archive *fout, void *arg)
{
const char *blobQry;
const char *blobFetchQry;
+ PGconn *conn = GetConnection(fout);
PGresult *res;
char buf[LOBBUFSIZE];
int ntups;
write_msg(NULL, "saving large objects\n");
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
/*
* Currently, we re-fetch all BLOB OIDs using a cursor. Consider scanning
* the already-in-memory dumpable objects instead...
*/
- if (AH->remoteVersion >= 90000)
+ if (fout->remoteVersion >= 90000)
blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_largeobject_metadata";
- else if (AH->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
blobQry = "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
else
blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class WHERE relkind = 'l'";
- res = PQexec(g_conn, blobQry);
- check_sql_result(res, g_conn, blobQry, PGRES_COMMAND_OK);
+ ExecuteSqlStatement(fout, blobQry);
/* Command to fetch from cursor */
blobFetchQry = "FETCH 1000 IN bloboid";
do
{
- PQclear(res);
-
/* Do a fetch */
- res = PQexec(g_conn, blobFetchQry);
- check_sql_result(res, g_conn, blobFetchQry, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, blobFetchQry, PGRES_TUPLES_OK);
/* Process the tuples, if any */
ntups = PQntuples(res);
blobOid = atooid(PQgetvalue(res, i, 0));
/* Open the BLOB */
- loFd = lo_open(g_conn, blobOid, INV_READ);
+ loFd = lo_open(conn, blobOid, INV_READ);
if (loFd == -1)
- {
- write_msg(NULL, "could not open large object %u: %s",
- blobOid, PQerrorMessage(g_conn));
- exit_nicely();
- }
+ exit_horribly(NULL, "could not open large object %u: %s",
+ blobOid, PQerrorMessage(conn));
- StartBlob(AH, blobOid);
+ StartBlob(fout, blobOid);
/* Now read it in chunks, sending data to archive */
do
{
- cnt = lo_read(g_conn, loFd, buf, LOBBUFSIZE);
+ cnt = lo_read(conn, loFd, buf, LOBBUFSIZE);
if (cnt < 0)
- {
- write_msg(NULL, "error reading large object %u: %s",
- blobOid, PQerrorMessage(g_conn));
- exit_nicely();
- }
+ exit_horribly(NULL, "error reading large object %u: %s",
+ blobOid, PQerrorMessage(conn));
- WriteData(AH, buf, cnt);
+ WriteData(fout, buf, cnt);
} while (cnt > 0);
- lo_close(g_conn, loFd);
+ lo_close(conn, loFd);
- EndBlob(AH, blobOid);
+ EndBlob(fout, blobOid);
}
- } while (ntups > 0);
- PQclear(res);
+ PQclear(res);
+ } while (ntups > 0);
return 1;
}
static void
-binary_upgrade_set_type_oids_by_type_oid(PQExpBuffer upgrade_buffer,
+binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
+ PQExpBuffer upgrade_buffer,
Oid pg_type_oid)
{
PQExpBuffer upgrade_query = createPQExpBuffer();
- int ntups;
PGresult *upgrade_res;
Oid pg_type_array_oid;
- appendPQExpBuffer(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type oid\n");
+ appendPQExpBufferStr(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type oid\n");
appendPQExpBuffer(upgrade_buffer,
"SELECT binary_upgrade.set_next_pg_type_oid('%u'::pg_catalog.oid);\n\n",
pg_type_oid);
"WHERE pg_type.oid = '%u'::pg_catalog.oid;",
pg_type_oid);
- upgrade_res = PQexec(g_conn, upgrade_query->data);
- check_sql_result(upgrade_res, g_conn, upgrade_query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(upgrade_res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, upgrade_query->data);
- exit_nicely();
- }
+ upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
pg_type_array_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "typarray")));
if (OidIsValid(pg_type_array_oid))
{
- appendPQExpBuffer(upgrade_buffer,
+ appendPQExpBufferStr(upgrade_buffer,
"\n-- For binary upgrade, must preserve pg_type array oid\n");
appendPQExpBuffer(upgrade_buffer,
"SELECT binary_upgrade.set_next_array_pg_type_oid('%u'::pg_catalog.oid);\n\n",
}
static bool
-binary_upgrade_set_type_oids_by_rel_oid(PQExpBuffer upgrade_buffer,
+binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
+ PQExpBuffer upgrade_buffer,
Oid pg_rel_oid)
{
PQExpBuffer upgrade_query = createPQExpBuffer();
- int ntups;
PGresult *upgrade_res;
Oid pg_type_oid;
bool toast_set = false;
"WHERE c.oid = '%u'::pg_catalog.oid;",
pg_rel_oid);
- upgrade_res = PQexec(g_conn, upgrade_query->data);
- check_sql_result(upgrade_res, g_conn, upgrade_query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(upgrade_res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, upgrade_query->data);
- exit_nicely();
- }
+ upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
pg_type_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "crel")));
- binary_upgrade_set_type_oids_by_type_oid(upgrade_buffer, pg_type_oid);
+ binary_upgrade_set_type_oids_by_type_oid(fout, upgrade_buffer,
+ pg_type_oid);
if (!PQgetisnull(upgrade_res, 0, PQfnumber(upgrade_res, "trel")))
{
Oid pg_type_toast_oid = atooid(PQgetvalue(upgrade_res, 0,
PQfnumber(upgrade_res, "trel")));
- appendPQExpBuffer(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type toast oid\n");
+ appendPQExpBufferStr(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type toast oid\n");
appendPQExpBuffer(upgrade_buffer,
"SELECT binary_upgrade.set_next_toast_pg_type_oid('%u'::pg_catalog.oid);\n\n",
pg_type_toast_oid);
}
static void
-binary_upgrade_set_pg_class_oids(PQExpBuffer upgrade_buffer, Oid pg_class_oid,
+binary_upgrade_set_pg_class_oids(Archive *fout,
+ PQExpBuffer upgrade_buffer, Oid pg_class_oid,
bool is_index)
{
PQExpBuffer upgrade_query = createPQExpBuffer();
- int ntups;
PGresult *upgrade_res;
Oid pg_class_reltoastrelid;
- Oid pg_class_reltoastidxid;
+ Oid pg_index_indexrelid;
appendPQExpBuffer(upgrade_query,
- "SELECT c.reltoastrelid, t.reltoastidxid "
+ "SELECT c.reltoastrelid, i.indexrelid "
"FROM pg_catalog.pg_class c LEFT JOIN "
- "pg_catalog.pg_class t ON (c.reltoastrelid = t.oid) "
+ "pg_catalog.pg_index i ON (c.reltoastrelid = i.indrelid AND i.indisvalid) "
"WHERE c.oid = '%u'::pg_catalog.oid;",
pg_class_oid);
- upgrade_res = PQexec(g_conn, upgrade_query->data);
- check_sql_result(upgrade_res, g_conn, upgrade_query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(upgrade_res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, upgrade_query->data);
- exit_nicely();
- }
+ upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
pg_class_reltoastrelid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "reltoastrelid")));
- pg_class_reltoastidxid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "reltoastidxid")));
+ pg_index_indexrelid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "indexrelid")));
- appendPQExpBuffer(upgrade_buffer,
- "\n-- For binary upgrade, must preserve pg_class oids\n");
+ appendPQExpBufferStr(upgrade_buffer,
+ "\n-- For binary upgrade, must preserve pg_class oids\n");
if (!is_index)
{
/* every toast table has an index */
appendPQExpBuffer(upgrade_buffer,
"SELECT binary_upgrade.set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n",
- pg_class_reltoastidxid);
+ pg_index_indexrelid);
}
}
else
"SELECT binary_upgrade.set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n",
pg_class_oid);
- appendPQExpBuffer(upgrade_buffer, "\n");
+ appendPQExpBufferChar(upgrade_buffer, '\n');
PQclear(upgrade_res);
destroyPQExpBuffer(upgrade_query);
extobj = NULL;
}
if (extobj == NULL)
- {
- write_msg(NULL, "could not find parent extension for %s", objlabel);
- exit_nicely();
- }
+ exit_horribly(NULL, "could not find parent extension for %s\n", objlabel);
- appendPQExpBuffer(upgrade_buffer,
+ appendPQExpBufferStr(upgrade_buffer,
"\n-- For binary upgrade, handle extension membership the hard way\n");
appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s;\n",
fmtId(extobj->name),
* numNamespaces is set to the number of namespaces read in
*/
NamespaceInfo *
-getNamespaces(int *numNamespaces)
+getNamespaces(Archive *fout, int *numNamespaces)
{
PGresult *res;
int ntups;
* Before 7.3, there are no real namespaces; create two dummy entries, one
* for user stuff and one for system stuff.
*/
- if (g_fout->remoteVersion < 70300)
+ if (fout->remoteVersion < 70300)
{
nsinfo = (NamespaceInfo *) pg_malloc(2 * sizeof(NamespaceInfo));
selectDumpableNamespace(&nsinfo[1]);
- g_namespaces = nsinfo;
- g_numNamespaces = *numNamespaces = 2;
+ *numNamespaces = 2;
return nsinfo;
}
query = createPQExpBuffer();
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
/*
* we fetch all namespaces including system ones, so that every object we
"nspacl FROM pg_namespace",
username_subquery);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
PQclear(res);
destroyPQExpBuffer(query);
- g_namespaces = nsinfo;
- g_numNamespaces = *numNamespaces = ntups;
+ *numNamespaces = ntups;
return nsinfo;
}
* getNamespaces
*
* NB: for pre-7.3 source database, we use object OID to guess whether it's
- * a system object or not. In 7.3 and later there is no guessing.
+ * a system object or not. In 7.3 and later there is no guessing, and we
+ * don't use objoid at all.
*/
static NamespaceInfo *
-findNamespace(Oid nsoid, Oid objoid)
+findNamespace(Archive *fout, Oid nsoid, Oid objoid)
{
- int i;
+ NamespaceInfo *nsinfo;
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
- for (i = 0; i < g_numNamespaces; i++)
- {
- NamespaceInfo *nsinfo = &g_namespaces[i];
-
- if (nsoid == nsinfo->dobj.catId.oid)
- return nsinfo;
- }
- write_msg(NULL, "schema with OID %u does not exist\n", nsoid);
- exit_nicely();
+ nsinfo = findNamespaceByOid(nsoid);
}
else
{
- /* This code depends on the layout set up by getNamespaces. */
+ /* This code depends on the dummy objects set up by getNamespaces. */
+ Oid i;
+
if (objoid > g_last_builtin_oid)
i = 0; /* user object */
else
i = 1; /* system object */
- return &g_namespaces[i];
+ nsinfo = findNamespaceByOid(i);
}
- return NULL; /* keep compiler quiet */
+ if (nsinfo == NULL)
+ exit_horribly(NULL, "schema with OID %u does not exist\n", nsoid);
+
+ return nsinfo;
}
/*
* numExtensions is set to the number of extensions read in
*/
ExtensionInfo *
-getExtensions(int *numExtensions)
+getExtensions(Archive *fout, int *numExtensions)
{
PGresult *res;
int ntups;
/*
* Before 9.1, there are no extensions.
*/
- if (g_fout->remoteVersion < 90100)
+ if (fout->remoteVersion < 90100)
{
*numExtensions = 0;
return NULL;
query = createPQExpBuffer();
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
- appendPQExpBuffer(query, "SELECT x.tableoid, x.oid, "
- "x.extname, n.nspname, x.extrelocatable, x.extversion, x.extconfig, x.extcondition "
- "FROM pg_extension x "
- "JOIN pg_namespace n ON n.oid = x.extnamespace");
+ appendPQExpBufferStr(query, "SELECT x.tableoid, x.oid, "
+ "x.extname, n.nspname, x.extrelocatable, x.extversion, x.extconfig, x.extcondition "
+ "FROM pg_extension x "
+ "JOIN pg_namespace n ON n.oid = x.extnamespace");
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
* findFuncByOid().
*/
TypeInfo *
-getTypes(int *numTypes)
+getTypes(Archive *fout, int *numTypes)
{
PGresult *res;
int ntups;
int i_oid;
int i_typname;
int i_typnamespace;
+ int i_typacl;
int i_rolname;
int i_typinput;
int i_typoutput;
*/
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
- if (g_fout->remoteVersion >= 80300)
+ if (fout->remoteVersion >= 90200)
+ {
+ appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
+ "typnamespace, typacl, "
+ "(%s typowner) AS rolname, "
+ "typinput::oid AS typinput, "
+ "typoutput::oid AS typoutput, typelem, typrelid, "
+ "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
+ "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
+ "typtype, typisdefined, "
+ "typname[0] = '_' AND typelem != 0 AND "
+ "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
+ "FROM pg_type",
+ username_subquery);
+ }
+ else if (fout->remoteVersion >= 80300)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
- "typnamespace, "
+ "typnamespace, '{=U}' AS typacl, "
"(%s typowner) AS rolname, "
"typinput::oid AS typinput, "
"typoutput::oid AS typoutput, typelem, typrelid, "
"FROM pg_type",
username_subquery);
}
- else if (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
- "typnamespace, "
+ "typnamespace, '{=U}' AS typacl, "
"(%s typowner) AS rolname, "
"typinput::oid AS typinput, "
"typoutput::oid AS typoutput, typelem, typrelid, "
"FROM pg_type",
username_subquery);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
- "0::oid AS typnamespace, "
+ "0::oid AS typnamespace, '{=U}' AS typacl, "
"(%s typowner) AS rolname, "
"typinput::oid AS typinput, "
"typoutput::oid AS typoutput, typelem, typrelid, "
appendPQExpBuffer(query, "SELECT "
"(SELECT oid FROM pg_class WHERE relname = 'pg_type') AS tableoid, "
"oid, typname, "
- "0::oid AS typnamespace, "
+ "0::oid AS typnamespace, '{=U}' AS typacl, "
"(%s typowner) AS rolname, "
"typinput::oid AS typinput, "
"typoutput::oid AS typoutput, typelem, typrelid, "
username_subquery);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
i_oid = PQfnumber(res, "oid");
i_typname = PQfnumber(res, "typname");
i_typnamespace = PQfnumber(res, "typnamespace");
+ i_typacl = PQfnumber(res, "typacl");
i_rolname = PQfnumber(res, "rolname");
i_typinput = PQfnumber(res, "typinput");
i_typoutput = PQfnumber(res, "typoutput");
tyinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&tyinfo[i].dobj);
tyinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_typname));
- tyinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_typnamespace)),
- tyinfo[i].dobj.catId.oid);
+ tyinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_typnamespace)),
+ tyinfo[i].dobj.catId.oid);
tyinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
+ tyinfo[i].typacl = pg_strdup(PQgetvalue(res, i, i_typacl));
tyinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem));
tyinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid));
tyinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
tyinfo[i].nDomChecks = 0;
tyinfo[i].domChecks = NULL;
if (tyinfo[i].dobj.dump && tyinfo[i].typtype == TYPTYPE_DOMAIN)
- getDomainConstraints(&(tyinfo[i]));
+ getDomainConstraints(fout, &(tyinfo[i]));
/*
* If it's a base type, make a DumpableObject representing a shell
* definition of the type. We will need to dump that ahead of the I/O
- * functions for the type. Similarly, range types need a shell
+ * functions for the type. Similarly, range types need a shell
* definition in case they have a canonicalize function.
*
* Note: the shell type doesn't have a catId. You might think it
* typinput and typoutput since the other functions only exist
* post-7.3.
*/
- if (g_fout->remoteVersion < 70300)
+ if (fout->remoteVersion < 70300)
{
Oid typinput;
Oid typoutput;
* numOprs is set to the number of operators read in
*/
OprInfo *
-getOperators(int *numOprs)
+getOperators(Archive *fout, int *numOprs)
{
PGresult *res;
int ntups;
*/
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
"oprnamespace, "
"FROM pg_operator",
username_subquery);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
"0::oid AS oprnamespace, "
username_subquery);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numOprs = ntups;
oprinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&oprinfo[i].dobj);
oprinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oprname));
- oprinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_oprnamespace)),
- oprinfo[i].dobj.catId.oid);
+ oprinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_oprnamespace)),
+ oprinfo[i].dobj.catId.oid);
oprinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
oprinfo[i].oprkind = (PQgetvalue(res, i, i_oprkind))[0];
oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
* numCollations is set to the number of collations read in
*/
CollInfo *
-getCollations(int *numCollations)
+getCollations(Archive *fout, int *numCollations)
{
PGresult *res;
int ntups;
int i;
- PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer query;
CollInfo *collinfo;
int i_tableoid;
int i_oid;
int i_rolname;
/* Collations didn't exist pre-9.1 */
- if (g_fout->remoteVersion < 90100)
+ if (fout->remoteVersion < 90100)
{
*numCollations = 0;
return NULL;
}
+ query = createPQExpBuffer();
+
/*
* find all collations, including builtin collations; we filter out
* system-defined collations at dump-out time.
*/
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT tableoid, oid, collname, "
"collnamespace, "
"FROM pg_collation",
username_subquery);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numCollations = ntups;
collinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&collinfo[i].dobj);
collinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_collname));
- collinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_collnamespace)),
- collinfo[i].dobj.catId.oid);
+ collinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_collnamespace)),
+ collinfo[i].dobj.catId.oid);
collinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
/* Decide whether we want to dump it */
* numConversions is set to the number of conversions read in
*/
ConvInfo *
-getConversions(int *numConversions)
+getConversions(Archive *fout, int *numConversions)
{
PGresult *res;
int ntups;
int i;
- PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer query;
ConvInfo *convinfo;
int i_tableoid;
int i_oid;
int i_rolname;
/* Conversions didn't exist pre-7.3 */
- if (g_fout->remoteVersion < 70300)
+ if (fout->remoteVersion < 70300)
{
*numConversions = 0;
return NULL;
}
+ query = createPQExpBuffer();
+
/*
* find all conversions, including builtin conversions; we filter out
* system-defined conversions at dump-out time.
*/
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
"connamespace, "
"FROM pg_conversion",
username_subquery);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numConversions = ntups;
convinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&convinfo[i].dobj);
convinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
- convinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_connamespace)),
- convinfo[i].dobj.catId.oid);
+ convinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_connamespace)),
+ convinfo[i].dobj.catId.oid);
convinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
/* Decide whether we want to dump it */
* numOpclasses is set to the number of opclasses read in
*/
OpclassInfo *
-getOpclasses(int *numOpclasses)
+getOpclasses(Archive *fout, int *numOpclasses)
{
PGresult *res;
int ntups;
*/
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
"opcnamespace, "
"FROM pg_opclass",
username_subquery);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
- appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
- "0::oid AS opcnamespace, "
- "''::name AS rolname "
- "FROM pg_opclass");
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, opcname, "
+ "0::oid AS opcnamespace, "
+ "''::name AS rolname "
+ "FROM pg_opclass");
}
else
{
- appendPQExpBuffer(query, "SELECT "
- "(SELECT oid FROM pg_class WHERE relname = 'pg_opclass') AS tableoid, "
- "oid, opcname, "
- "0::oid AS opcnamespace, "
- "''::name AS rolname "
- "FROM pg_opclass");
+ appendPQExpBufferStr(query, "SELECT "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_opclass') AS tableoid, "
+ "oid, opcname, "
+ "0::oid AS opcnamespace, "
+ "''::name AS rolname "
+ "FROM pg_opclass");
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numOpclasses = ntups;
opcinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&opcinfo[i].dobj);
opcinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opcname));
- opcinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_opcnamespace)),
- opcinfo[i].dobj.catId.oid);
+ opcinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_opcnamespace)),
+ opcinfo[i].dobj.catId.oid);
opcinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
/* Decide whether we want to dump it */
selectDumpableObject(&(opcinfo[i].dobj));
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
if (strlen(opcinfo[i].rolname) == 0)
write_msg(NULL, "WARNING: owner of operator class \"%s\" appears to be invalid\n",
* numOpfamilies is set to the number of opfamilies read in
*/
OpfamilyInfo *
-getOpfamilies(int *numOpfamilies)
+getOpfamilies(Archive *fout, int *numOpfamilies)
{
PGresult *res;
int ntups;
int i_rolname;
/* Before 8.3, there is no separate concept of opfamilies */
- if (g_fout->remoteVersion < 80300)
+ if (fout->remoteVersion < 80300)
{
*numOpfamilies = 0;
return NULL;
*/
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, "
"opfnamespace, "
"FROM pg_opfamily",
username_subquery);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numOpfamilies = ntups;
opfinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&opfinfo[i].dobj);
opfinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opfname));
- opfinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_opfnamespace)),
- opfinfo[i].dobj.catId.oid);
+ opfinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_opfnamespace)),
+ opfinfo[i].dobj.catId.oid);
opfinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
/* Decide whether we want to dump it */
selectDumpableObject(&(opfinfo[i].dobj));
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
if (strlen(opfinfo[i].rolname) == 0)
write_msg(NULL, "WARNING: owner of operator family \"%s\" appears to be invalid\n",
* numAggs is set to the number of aggregates read in
*/
AggInfo *
-getAggregates(int *numAggs)
+getAggregates(Archive *fout, int *numAggs)
{
PGresult *res;
int ntups;
int i_proargtypes;
int i_rolname;
int i_aggacl;
+ int i_proiargs;
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
/*
* Find all user-defined aggregates. See comment in getFuncs() for the
* rationale behind the filtering logic.
*/
- if (g_fout->remoteVersion >= 80200)
+ if (fout->remoteVersion >= 80400)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
"pronamespace AS aggnamespace, "
"pronargs, proargtypes, "
+ "pg_catalog.pg_get_function_identity_arguments(oid) AS proiargs,"
"(%s proowner) AS rolname, "
"proacl AS aggacl "
"FROM pg_proc p "
"(SELECT oid FROM pg_namespace "
"WHERE nspname = 'pg_catalog')",
username_subquery);
- if (binary_upgrade && g_fout->remoteVersion >= 90100)
- appendPQExpBuffer(query,
- " OR EXISTS(SELECT 1 FROM pg_depend WHERE "
- "classid = 'pg_proc'::regclass AND "
- "objid = p.oid AND "
- "refclassid = 'pg_extension'::regclass AND "
- "deptype = 'e')");
- appendPQExpBuffer(query, ")");
+ if (binary_upgrade && fout->remoteVersion >= 90100)
+ appendPQExpBufferStr(query,
+ " OR EXISTS(SELECT 1 FROM pg_depend WHERE "
+ "classid = 'pg_proc'::regclass AND "
+ "objid = p.oid AND "
+ "refclassid = 'pg_extension'::regclass AND "
+ "deptype = 'e')");
+ appendPQExpBufferChar(query, ')');
+ }
+ else if (fout->remoteVersion >= 80200)
+ {
+ appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
+ "pronamespace AS aggnamespace, "
+ "pronargs, proargtypes, "
+ "NULL::text AS proiargs,"
+ "(%s proowner) AS rolname, "
+ "proacl AS aggacl "
+ "FROM pg_proc p "
+ "WHERE proisagg AND ("
+ "pronamespace != "
+ "(SELECT oid FROM pg_namespace "
+ "WHERE nspname = 'pg_catalog'))",
+ username_subquery);
}
- else if (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
"pronamespace AS aggnamespace, "
"CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, "
"proargtypes, "
+ "NULL::text AS proiargs, "
"(%s proowner) AS rolname, "
"proacl AS aggacl "
"FROM pg_proc "
"(SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog')",
username_subquery);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, aggname, "
"0::oid AS aggnamespace, "
"CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
"aggbasetype AS proargtypes, "
+ "NULL::text AS proiargs, "
"(%s aggowner) AS rolname, "
"'{=X}' AS aggacl "
"FROM pg_aggregate "
"0::oid AS aggnamespace, "
"CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
"aggbasetype AS proargtypes, "
+ "NULL::text AS proiargs, "
"(%s aggowner) AS rolname, "
"'{=X}' AS aggacl "
"FROM pg_aggregate "
g_last_builtin_oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numAggs = ntups;
i_proargtypes = PQfnumber(res, "proargtypes");
i_rolname = PQfnumber(res, "rolname");
i_aggacl = PQfnumber(res, "aggacl");
+ i_proiargs = PQfnumber(res, "proiargs");
for (i = 0; i < ntups; i++)
{
agginfo[i].aggfn.dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&agginfo[i].aggfn.dobj);
agginfo[i].aggfn.dobj.name = pg_strdup(PQgetvalue(res, i, i_aggname));
- agginfo[i].aggfn.dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_aggnamespace)),
- agginfo[i].aggfn.dobj.catId.oid);
+ agginfo[i].aggfn.dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_aggnamespace)),
+ agginfo[i].aggfn.dobj.catId.oid);
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.lang = InvalidOid; /* not currently interesting */
agginfo[i].aggfn.prorettype = InvalidOid; /* not saved */
agginfo[i].aggfn.proacl = pg_strdup(PQgetvalue(res, i, i_aggacl));
+ agginfo[i].aggfn.proiargs = pg_strdup(PQgetvalue(res, i, i_proiargs));
agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs));
if (agginfo[i].aggfn.nargs == 0)
agginfo[i].aggfn.argtypes = NULL;
else
{
agginfo[i].aggfn.argtypes = (Oid *) pg_malloc(agginfo[i].aggfn.nargs * sizeof(Oid));
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
parseOidArray(PQgetvalue(res, i, i_proargtypes),
agginfo[i].aggfn.argtypes,
agginfo[i].aggfn.nargs);
* numFuncs is set to the number of functions read in
*/
FuncInfo *
-getFuncs(int *numFuncs)
+getFuncs(Archive *fout, int *numFuncs)
{
PGresult *res;
int ntups;
int i_proargtypes;
int i_prorettype;
int i_proacl;
+ int i_proiargs;
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
/*
* Find all user-defined functions. Normally we can exclude functions in
* doesn't have; otherwise we might not get creation ordering correct.
*/
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 80400)
{
appendPQExpBuffer(query,
"SELECT tableoid, oid, proname, prolang, "
"pronargs, proargtypes, prorettype, proacl, "
"pronamespace, "
+ "pg_catalog.pg_get_function_identity_arguments(oid) AS proiargs,"
"(%s proowner) AS rolname "
"FROM pg_proc p "
"WHERE NOT proisagg AND ("
"(SELECT oid FROM pg_namespace "
"WHERE nspname = 'pg_catalog')",
username_subquery);
- if (g_fout->remoteVersion >= 90200)
- appendPQExpBuffer(query,
- "\n AND NOT EXISTS (SELECT 1 FROM pg_depend "
- "WHERE classid = 'pg_proc'::regclass AND "
- "objid = p.oid AND deptype = 'i')");
- if (binary_upgrade && g_fout->remoteVersion >= 90100)
- appendPQExpBuffer(query,
- "\n OR EXISTS(SELECT 1 FROM pg_depend WHERE "
- "classid = 'pg_proc'::regclass AND "
- "objid = p.oid AND "
- "refclassid = 'pg_extension'::regclass AND "
- "deptype = 'e')");
- appendPQExpBuffer(query, ")");
+ if (fout->remoteVersion >= 90200)
+ appendPQExpBufferStr(query,
+ "\n AND NOT EXISTS (SELECT 1 FROM pg_depend "
+ "WHERE classid = 'pg_proc'::regclass AND "
+ "objid = p.oid AND deptype = 'i')");
+ if (binary_upgrade && fout->remoteVersion >= 90100)
+ appendPQExpBufferStr(query,
+ "\n OR EXISTS(SELECT 1 FROM pg_depend WHERE "
+ "classid = 'pg_proc'::regclass AND "
+ "objid = p.oid AND "
+ "refclassid = 'pg_extension'::regclass AND "
+ "deptype = 'e')");
+ appendPQExpBufferChar(query, ')');
+ }
+ else if (fout->remoteVersion >= 70300)
+ {
+ appendPQExpBuffer(query,
+ "SELECT tableoid, oid, proname, prolang, "
+ "pronargs, proargtypes, prorettype, proacl, "
+ "pronamespace, "
+ "NULL::text AS proiargs,"
+ "(%s proowner) AS rolname "
+ "FROM pg_proc p "
+ "WHERE NOT proisagg AND ("
+ "pronamespace != "
+ "(SELECT oid FROM pg_namespace "
+ "WHERE nspname = 'pg_catalog'))",
+ username_subquery);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query,
"SELECT tableoid, oid, proname, prolang, "
"pronargs, proargtypes, prorettype, "
"'{=X}' AS proacl, "
"0::oid AS pronamespace, "
+ "NULL::text AS proiargs,"
"(%s proowner) AS rolname "
"FROM pg_proc "
"WHERE pg_proc.oid > '%u'::oid",
"pronargs, proargtypes, prorettype, "
"'{=X}' AS proacl, "
"0::oid AS pronamespace, "
+ "NULL::text AS proiargs,"
"(%s proowner) AS rolname "
"FROM pg_proc "
"where pg_proc.oid > '%u'::oid",
g_last_builtin_oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numFuncs = ntups;
- finfo = (FuncInfo *) pg_calloc(ntups, sizeof(FuncInfo));
+ finfo = (FuncInfo *) pg_malloc0(ntups * sizeof(FuncInfo));
i_tableoid = PQfnumber(res, "tableoid");
i_oid = PQfnumber(res, "oid");
i_proargtypes = PQfnumber(res, "proargtypes");
i_prorettype = PQfnumber(res, "prorettype");
i_proacl = PQfnumber(res, "proacl");
+ i_proiargs = PQfnumber(res, "proiargs");
for (i = 0; i < ntups; i++)
{
AssignDumpId(&finfo[i].dobj);
finfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_proname));
finfo[i].dobj.namespace =
- findNamespace(atooid(PQgetvalue(res, i, i_pronamespace)),
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_pronamespace)),
finfo[i].dobj.catId.oid);
finfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
+ finfo[i].proiargs = pg_strdup(PQgetvalue(res, i, i_proiargs));
finfo[i].proacl = pg_strdup(PQgetvalue(res, i, i_proacl));
finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
if (finfo[i].nargs == 0)
* numTables is set to the number of tables read in
*/
TableInfo *
-getTables(int *numTables)
+getTables(Archive *fout, int *numTables)
{
PGresult *res;
int ntups;
int i_toastoid;
int i_toastfrozenxid;
int i_relpersistence;
+ int i_relispopulated;
+ int i_relreplident;
int i_owning_tab;
int i_owning_col;
int i_reltablespace;
int i_reloptions;
+ int i_checkoption;
int i_toastreloptions;
int i_reloftype;
+ int i_relpages;
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
/*
- * Find all the tables (including views and sequences).
+ * Find all the tables and table-like objects.
*
* We include system catalogs, so that we can work if a user table is
* defined to inherit from a system catalog (pretty weird, but...)
*
- * We ignore tables that are not type 'r' (ordinary relation), 'S'
- * (sequence), 'v' (view), or 'c' (composite type).
+ * We ignore relations that are not ordinary tables, sequences, views,
+ * materialized views, composite types, or foreign tables.
*
* Composite-type table entries won't be dumped as such, but we have to
* make a DumpableObject for them so that we can track dependencies of the
* we cannot correctly identify inherited columns, owned sequences, etc.
*/
- if (g_fout->remoteVersion >= 90100)
+ if (fout->remoteVersion >= 90400)
{
/*
* Left join to pick up dependency info linking sequences to their
"c.relhasindex, c.relhasrules, c.relhasoids, "
"c.relfrozenxid, tc.oid AS toid, "
"tc.relfrozenxid AS tfrozenxid, "
- "c.relpersistence, "
+ "c.relpersistence, c.relispopulated, "
+ "c.relreplident, c.relpages, "
"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, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
- "array_to_string(c.reloptions, ', ') AS reloptions, "
+ "array_to_string(array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded'), ', ') AS reloptions, "
+ "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
+ "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
"array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"d.objsubid = 0 AND "
"d.refclassid = c.tableoid AND d.deptype = 'a') "
"LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
- "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c') "
+ "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
"ORDER BY c.oid",
username_subquery,
RELKIND_SEQUENCE,
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
- RELKIND_FOREIGN_TABLE);
+ RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
}
- else if (g_fout->remoteVersion >= 90000)
+ else if (fout->remoteVersion >= 90300)
{
/*
* Left join to pick up dependency info linking sequences to their
"c.relhasindex, c.relhasrules, c.relhasoids, "
"c.relfrozenxid, tc.oid AS toid, "
"tc.relfrozenxid AS tfrozenxid, "
- "'p' AS relpersistence, "
+ "c.relpersistence, c.relispopulated, "
+ "'d' AS relreplident, c.relpages, "
"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, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
- "array_to_string(c.reloptions, ', ') AS reloptions, "
+ "array_to_string(array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded'), ', ') AS reloptions, "
+ "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
+ "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
"array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"d.objsubid = 0 AND "
"d.refclassid = c.tableoid AND d.deptype = 'a') "
"LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
- "WHERE c.relkind in ('%c', '%c', '%c', '%c') "
+ "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
"ORDER BY c.oid",
username_subquery,
RELKIND_SEQUENCE,
RELKIND_RELATION, RELKIND_SEQUENCE,
- RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
+ RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
+ RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
}
- else if (g_fout->remoteVersion >= 80400)
+ else if (fout->remoteVersion >= 90100)
{
/*
* Left join to pick up dependency info linking sequences to their
"c.relhasindex, c.relhasrules, c.relhasoids, "
"c.relfrozenxid, tc.oid AS toid, "
"tc.relfrozenxid AS tfrozenxid, "
- "'p' AS relpersistence, "
- "NULL AS reloftype, "
+ "c.relpersistence, 't' as relispopulated, "
+ "'d' AS relreplident, c.relpages, "
+ "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, "
+ "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
+ "array_to_string(c.reloptions, ', ') AS reloptions, "
+ "array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions "
+ "FROM pg_class c "
+ "LEFT JOIN pg_depend d ON "
+ "(c.relkind = '%c' AND "
+ "d.classid = c.tableoid AND d.objid = c.oid AND "
+ "d.objsubid = 0 AND "
+ "d.refclassid = c.tableoid AND d.deptype = 'a') "
+ "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
+ "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
+ "ORDER BY c.oid",
+ username_subquery,
+ RELKIND_SEQUENCE,
+ RELKIND_RELATION, RELKIND_SEQUENCE,
+ RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
+ RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
+ }
+ else if (fout->remoteVersion >= 90000)
+ {
+ /*
+ * Left join to pick up dependency info linking sequences to their
+ * owning column, if any (note this dependency is AUTO as of 8.2)
+ */
+ appendPQExpBuffer(query,
+ "SELECT c.tableoid, c.oid, c.relname, "
+ "c.relacl, c.relkind, c.relnamespace, "
+ "(%s c.relowner) AS rolname, "
+ "c.relchecks, c.relhastriggers, "
+ "c.relhasindex, c.relhasrules, c.relhasoids, "
+ "c.relfrozenxid, tc.oid AS toid, "
+ "tc.relfrozenxid AS tfrozenxid, "
+ "'p' AS relpersistence, 't' as relispopulated, "
+ "'d' AS relreplident, c.relpages, "
+ "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, "
+ "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
+ "array_to_string(c.reloptions, ', ') AS reloptions, "
+ "array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions "
+ "FROM pg_class c "
+ "LEFT JOIN pg_depend d ON "
+ "(c.relkind = '%c' AND "
+ "d.classid = c.tableoid AND d.objid = c.oid AND "
+ "d.objsubid = 0 AND "
+ "d.refclassid = c.tableoid AND d.deptype = 'a') "
+ "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
+ "WHERE c.relkind in ('%c', '%c', '%c', '%c') "
+ "ORDER BY c.oid",
+ username_subquery,
+ RELKIND_SEQUENCE,
+ RELKIND_RELATION, RELKIND_SEQUENCE,
+ RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
+ }
+ else if (fout->remoteVersion >= 80400)
+ {
+ /*
+ * Left join to pick up dependency info linking sequences to their
+ * owning column, if any (note this dependency is AUTO as of 8.2)
+ */
+ appendPQExpBuffer(query,
+ "SELECT c.tableoid, c.oid, c.relname, "
+ "c.relacl, c.relkind, c.relnamespace, "
+ "(%s c.relowner) AS rolname, "
+ "c.relchecks, c.relhastriggers, "
+ "c.relhasindex, c.relhasrules, c.relhasoids, "
+ "c.relfrozenxid, tc.oid AS toid, "
+ "tc.relfrozenxid AS tfrozenxid, "
+ "'p' AS relpersistence, 't' as relispopulated, "
+ "'d' AS relreplident, c.relpages, "
+ "NULL AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
}
- else if (g_fout->remoteVersion >= 80200)
+ else if (fout->remoteVersion >= 80200)
{
/*
* Left join to pick up dependency info linking sequences to their
"SELECT c.tableoid, c.oid, c.relname, "
"c.relacl, c.relkind, c.relnamespace, "
"(%s c.relowner) AS rolname, "
- "c.relchecks, (c.reltriggers <> 0) AS relhastriggers, "
+ "c.relchecks, (c.reltriggers <> 0) AS relhastriggers, "
"c.relhasindex, c.relhasrules, c.relhasoids, "
"c.relfrozenxid, tc.oid AS toid, "
"tc.relfrozenxid AS tfrozenxid, "
- "'p' AS relpersistence, "
+ "'p' AS relpersistence, 't' as relispopulated, "
+ "'d' AS relreplident, c.relpages, "
"NULL AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
}
- else if (g_fout->remoteVersion >= 80000)
+ else if (fout->remoteVersion >= 80000)
{
/*
* Left join to pick up dependency info linking sequences to their
"0 AS relfrozenxid, "
"0 AS toid, "
"0 AS tfrozenxid, "
- "'p' AS relpersistence, "
+ "'p' AS relpersistence, 't' as relispopulated, "
+ "'d' AS relreplident, relpages, "
"NULL AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
}
- else if (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
{
/*
* Left join to pick up dependency info linking sequences to their
"0 AS relfrozenxid, "
"0 AS toid, "
"0 AS tfrozenxid, "
- "'p' AS relpersistence, "
+ "'p' AS relpersistence, 't' as relispopulated, "
+ "'d' AS relreplident, relpages, "
"NULL AS reloftype, "
"d.refobjid AS owning_tab, "
"d.refobjsubid AS owning_col, "
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
}
- else if (g_fout->remoteVersion >= 70200)
+ else if (fout->remoteVersion >= 70200)
{
appendPQExpBuffer(query,
"SELECT tableoid, oid, relname, relacl, relkind, "
"0 AS relfrozenxid, "
"0 AS toid, "
"0 AS tfrozenxid, "
- "'p' AS relpersistence, "
+ "'p' AS relpersistence, 't' as relispopulated, "
+ "'d' AS relreplident, relpages, "
"NULL AS reloftype, "
"NULL::oid AS owning_tab, "
"NULL::int4 AS owning_col, "
username_subquery,
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
/* all tables have oids in 7.1 */
appendPQExpBuffer(query,
"0 AS relfrozenxid, "
"0 AS toid, "
"0 AS tfrozenxid, "
- "'p' AS relpersistence, "
+ "'p' AS relpersistence, 't' as relispopulated, "
+ "'d' AS relreplident, relpages, "
"NULL AS reloftype, "
"NULL::oid AS owning_tab, "
"NULL::int4 AS owning_col, "
"0 as relfrozenxid, "
"0 AS toid, "
"0 AS tfrozenxid, "
- "'p' AS relpersistence, "
+ "'p' AS relpersistence, 't' as relispopulated, "
+ "'d' AS relreplident, 0 AS relpages, "
"NULL AS reloftype, "
"NULL::oid AS owning_tab, "
"NULL::int4 AS owning_col, "
RELKIND_RELATION, RELKIND_SEQUENCE);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
* only one, because we don't yet know which tables might be inheritance
* ancestors of the target table.
*/
- tblinfo = (TableInfo *) pg_calloc(ntups, sizeof(TableInfo));
+ tblinfo = (TableInfo *) pg_malloc0(ntups * sizeof(TableInfo));
i_reltableoid = PQfnumber(res, "tableoid");
i_reloid = PQfnumber(res, "oid");
i_toastoid = PQfnumber(res, "toid");
i_toastfrozenxid = PQfnumber(res, "tfrozenxid");
i_relpersistence = PQfnumber(res, "relpersistence");
+ i_relispopulated = PQfnumber(res, "relispopulated");
+ i_relreplident = PQfnumber(res, "relreplident");
+ i_relpages = PQfnumber(res, "relpages");
i_owning_tab = PQfnumber(res, "owning_tab");
i_owning_col = PQfnumber(res, "owning_col");
i_reltablespace = PQfnumber(res, "reltablespace");
i_reloptions = PQfnumber(res, "reloptions");
+ i_checkoption = PQfnumber(res, "checkoption");
i_toastreloptions = PQfnumber(res, "toast_reloptions");
i_reloftype = PQfnumber(res, "reloftype");
- if (lockWaitTimeout && g_fout->remoteVersion >= 70300)
+ if (lockWaitTimeout && fout->remoteVersion >= 70300)
{
/*
* Arrange to fail instead of waiting forever for a table lock.
* applied to other things too.
*/
resetPQExpBuffer(query);
- appendPQExpBuffer(query, "SET statement_timeout = ");
- appendStringLiteralConn(query, lockWaitTimeout, g_conn);
- do_sql_command(g_conn, query->data);
+ appendPQExpBufferStr(query, "SET statement_timeout = ");
+ appendStringLiteralConn(query, lockWaitTimeout, GetConnection(fout));
+ ExecuteSqlStatement(fout, query->data);
}
for (i = 0; i < ntups; i++)
tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid));
AssignDumpId(&tblinfo[i].dobj);
tblinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_relname));
- tblinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_relnamespace)),
- tblinfo[i].dobj.catId.oid);
+ tblinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_relnamespace)),
+ tblinfo[i].dobj.catId.oid);
tblinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
tblinfo[i].relacl = pg_strdup(PQgetvalue(res, i, i_relacl));
tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
tblinfo[i].hasrules = (strcmp(PQgetvalue(res, i, i_relhasrules), "t") == 0);
tblinfo[i].hastriggers = (strcmp(PQgetvalue(res, i, i_relhastriggers), "t") == 0);
tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
+ tblinfo[i].relispopulated = (strcmp(PQgetvalue(res, i, i_relispopulated), "t") == 0);
+ tblinfo[i].relreplident = *(PQgetvalue(res, i, i_relreplident));
+ tblinfo[i].relpages = atoi(PQgetvalue(res, i, i_relpages));
tblinfo[i].frozenxid = atooid(PQgetvalue(res, i, i_relfrozenxid));
tblinfo[i].toast_oid = atooid(PQgetvalue(res, i, i_toastoid));
tblinfo[i].toast_frozenxid = atooid(PQgetvalue(res, i, i_toastfrozenxid));
}
tblinfo[i].reltablespace = pg_strdup(PQgetvalue(res, i, i_reltablespace));
tblinfo[i].reloptions = pg_strdup(PQgetvalue(res, i, i_reloptions));
+ if (i_checkoption == -1 || PQgetisnull(res, i, i_checkoption))
+ tblinfo[i].checkoption = NULL;
+ else
+ tblinfo[i].checkoption = pg_strdup(PQgetvalue(res, i, i_checkoption));
tblinfo[i].toast_reloptions = pg_strdup(PQgetvalue(res, i, i_toastreloptions));
/* other fields were zeroed above */
selectDumpableTable(&tblinfo[i]);
tblinfo[i].interesting = tblinfo[i].dobj.dump;
+ tblinfo[i].postponed_def = false; /* might get set during sort */
+
/*
* Read-lock target tables to make sure they aren't DROPPED or altered
* in schema before we get around to dumping them.
resetPQExpBuffer(query);
appendPQExpBuffer(query,
"LOCK TABLE %s IN ACCESS SHARE MODE",
- fmtQualifiedId(tblinfo[i].dobj.namespace->dobj.name,
- tblinfo[i].dobj.name));
- do_sql_command(g_conn, query->data);
+ fmtQualifiedId(fout->remoteVersion,
+ tblinfo[i].dobj.namespace->dobj.name,
+ tblinfo[i].dobj.name));
+ ExecuteSqlStatement(fout, query->data);
}
/* Emit notice if join for owner failed */
tblinfo[i].dobj.name);
}
- if (lockWaitTimeout && g_fout->remoteVersion >= 70300)
+ if (lockWaitTimeout && fout->remoteVersion >= 70300)
{
- do_sql_command(g_conn, "SET statement_timeout = 0");
+ ExecuteSqlStatement(fout, "SET statement_timeout = 0");
}
PQclear(res);
+ destroyPQExpBuffer(query);
+
+ return tblinfo;
+}
+
+/*
+ * getOwnedSeqs
+ * identify owned sequences and mark them as dumpable if owning table is
+ *
+ * We used to do this in getTables(), but it's better to do it after the
+ * index used by findTableByOid() has been set up.
+ */
+void
+getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables)
+{
+ int i;
+
/*
* Force sequences that are "owned" by table columns to be dumped whenever
* their owning table is being dumped.
*/
- for (i = 0; i < ntups; i++)
+ for (i = 0; i < numTables; i++)
{
TableInfo *seqinfo = &tblinfo[i];
- int j;
+ TableInfo *owning_tab;
if (!OidIsValid(seqinfo->owning_tab))
continue; /* not an owned sequence */
if (seqinfo->dobj.dump)
continue; /* no need to search */
-
- /* can't use findTableByOid yet, unfortunately */
- for (j = 0; j < ntups; j++)
+ owning_tab = findTableByOid(seqinfo->owning_tab);
+ if (owning_tab && owning_tab->dobj.dump)
{
- if (tblinfo[j].dobj.catId.oid == seqinfo->owning_tab)
- {
- if (tblinfo[j].dobj.dump)
- {
- seqinfo->interesting = true;
- seqinfo->dobj.dump = true;
- }
- break;
- }
+ seqinfo->interesting = true;
+ seqinfo->dobj.dump = true;
}
}
-
- destroyPQExpBuffer(query);
-
- return tblinfo;
}
/*
* numInherits is set to the number of pairs read in
*/
InhInfo *
-getInherits(int *numInherits)
+getInherits(Archive *fout, int *numInherits)
{
PGresult *res;
int ntups;
int i_inhparent;
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
/* find all the inheritance information */
- appendPQExpBuffer(query, "SELECT inhrelid, inhparent FROM pg_inherits");
+ appendPQExpBufferStr(query, "SELECT inhrelid, inhparent FROM pg_inherits");
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
* does get entered into the DumpableObject tables.
*/
void
-getIndexes(TableInfo tblinfo[], int numTables)
+getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
{
int i,
j;
i_indnkeys,
i_indkey,
i_indisclustered,
+ i_indisreplident,
i_contype,
i_conname,
i_condeferrable,
i_conoid,
i_condef,
i_tablespace,
- i_options;
+ i_options,
+ i_relpages;
int ntups;
for (i = 0; i < numTables; i++)
{
TableInfo *tbinfo = &tblinfo[i];
- /* Only plain tables have indexes */
- if (tbinfo->relkind != RELKIND_RELATION || !tbinfo->hasindex)
+ /* 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 not to be dumped */
tbinfo->dobj.name);
/* Make sure we are in proper schema so indexdef is right */
- selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
/*
* The point of the messy-looking outer join is to find a constraint
* is not.
*/
resetPQExpBuffer(query);
- if (g_fout->remoteVersion >= 90000)
+ if (fout->remoteVersion >= 90400)
+ {
+ /*
+ * the test on indisready is necessary in 9.2, and harmless in
+ * earlier/later versions
+ */
+ appendPQExpBuffer(query,
+ "SELECT t.tableoid, t.oid, "
+ "t.relname AS indexname, "
+ "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
+ "t.relnatts AS indnkeys, "
+ "i.indkey, i.indisclustered, "
+ "i.indisreplident, t.relpages, "
+ "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, "
+ "array_to_string(t.reloptions, ', ') AS options "
+ "FROM pg_catalog.pg_index i "
+ "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
+ "LEFT JOIN pg_catalog.pg_constraint c "
+ "ON (i.indrelid = c.conrelid AND "
+ "i.indexrelid = c.conindid AND "
+ "c.contype IN ('p','u','x')) "
+ "WHERE i.indrelid = '%u'::pg_catalog.oid "
+ "AND i.indisvalid AND i.indisready "
+ "ORDER BY indexname",
+ tbinfo->dobj.catId.oid);
+ }
+ else if (fout->remoteVersion >= 90000)
{
+ /*
+ * the test on indisready is necessary in 9.2, and harmless in
+ * earlier/later versions
+ */
appendPQExpBuffer(query,
"SELECT t.tableoid, t.oid, "
"t.relname AS indexname, "
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
"t.relnatts AS indnkeys, "
"i.indkey, i.indisclustered, "
+ "false AS indisreplident, t.relpages, "
"c.contype, c.conname, "
"c.condeferrable, c.condeferred, "
"c.tableoid AS contableoid, "
"i.indexrelid = c.conindid AND "
"c.contype IN ('p','u','x')) "
"WHERE i.indrelid = '%u'::pg_catalog.oid "
+ "AND i.indisvalid AND i.indisready "
"ORDER BY indexname",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 80200)
+ else if (fout->remoteVersion >= 80200)
{
appendPQExpBuffer(query,
"SELECT t.tableoid, t.oid, "
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
"t.relnatts AS indnkeys, "
"i.indkey, i.indisclustered, "
+ "false AS indisreplident, t.relpages, "
"c.contype, c.conname, "
"c.condeferrable, c.condeferred, "
"c.tableoid AS contableoid, "
"ON (d.refclassid = c.tableoid "
"AND d.refobjid = c.oid) "
"WHERE i.indrelid = '%u'::pg_catalog.oid "
+ "AND i.indisvalid "
"ORDER BY indexname",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 80000)
+ else if (fout->remoteVersion >= 80000)
{
appendPQExpBuffer(query,
"SELECT t.tableoid, t.oid, "
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
"t.relnatts AS indnkeys, "
"i.indkey, i.indisclustered, "
+ "false AS indisreplident, t.relpages, "
"c.contype, c.conname, "
"c.condeferrable, c.condeferred, "
"c.tableoid AS contableoid, "
"ORDER BY indexname",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query,
"SELECT t.tableoid, t.oid, "
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
"t.relnatts AS indnkeys, "
"i.indkey, i.indisclustered, "
+ "false AS indisreplident, t.relpages, "
"c.contype, c.conname, "
"c.condeferrable, c.condeferred, "
"c.tableoid AS contableoid, "
"ORDER BY indexname",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query,
"SELECT t.tableoid, t.oid, "
"pg_get_indexdef(i.indexrelid) AS indexdef, "
"t.relnatts AS indnkeys, "
"i.indkey, false AS indisclustered, "
+ "false AS indisreplident, t.relpages, "
"CASE WHEN i.indisprimary THEN 'p'::char "
"ELSE '0'::char END AS contype, "
"t.relname AS conname, "
"pg_get_indexdef(i.indexrelid) AS indexdef, "
"t.relnatts AS indnkeys, "
"i.indkey, false AS indisclustered, "
+ "false AS indisreplident, t.relpages, "
"CASE WHEN i.indisprimary THEN 'p'::char "
"ELSE '0'::char END AS contype, "
"t.relname AS conname, "
tbinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
i_indnkeys = PQfnumber(res, "indnkeys");
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");
parseOidArray(PQgetvalue(res, j, i_indkey),
indxinfo[j].indkeys, INDEX_MAX_KEYS);
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));
contype = *(PQgetvalue(res, j, i_contype));
if (contype == 'p' || contype == 'u' || contype == 'x')
* while check constraints are processed in getTableAttrs().
*/
void
-getConstraints(TableInfo tblinfo[], int numTables)
+getConstraints(Archive *fout, TableInfo tblinfo[], int numTables)
{
int i,
j;
int ntups;
/* pg_constraint was created in 7.3, so nothing to do if older */
- if (g_fout->remoteVersion < 70300)
+ if (fout->remoteVersion < 70300)
return;
query = createPQExpBuffer();
* select table schema to ensure constraint expr is qualified if
* needed
*/
- selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
resetPQExpBuffer(query);
appendPQExpBuffer(query,
"WHERE conrelid = '%u'::pg_catalog.oid "
"AND contype = 'f'",
tbinfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
* Get info about constraints on a domain.
*/
static void
-getDomainConstraints(TypeInfo *tyinfo)
+getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
{
int i;
ConstraintInfo *constrinfo;
int ntups;
/* pg_constraint was created in 7.3, so nothing to do if older */
- if (g_fout->remoteVersion < 70300)
+ if (fout->remoteVersion < 70300)
return;
/*
* select appropriate schema to ensure names in constraint are properly
* qualified
*/
- selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
query = createPQExpBuffer();
- if (g_fout->remoteVersion >= 90100)
+ if (fout->remoteVersion >= 90100)
appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
"pg_catalog.pg_get_constraintdef(oid) AS consrc, "
"convalidated "
"ORDER BY conname",
tyinfo->dobj.catId.oid);
- else if (g_fout->remoteVersion >= 70400)
+ else if (fout->remoteVersion >= 70400)
appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
"pg_catalog.pg_get_constraintdef(oid) AS consrc, "
"true as convalidated "
"ORDER BY conname",
tyinfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
for (i = 0; i < ntups; i++)
{
- bool validated = PQgetvalue(res, i, 4)[0] == 't';
+ bool validated = PQgetvalue(res, i, 4)[0] == 't';
constrinfo[i].dobj.objType = DO_CONSTRAINT;
constrinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
/*
* Make the domain depend on the constraint, ensuring it won't be
- * output till any constraint dependencies are OK. If the constraint
+ * output till any constraint dependencies are OK. If the constraint
* has not been validated, it's going to be dumped after the domain
* anyway, so this doesn't matter.
*/
* numRules is set to the number of rules read in
*/
RuleInfo *
-getRules(int *numRules)
+getRules(Archive *fout, int *numRules)
{
PGresult *res;
int ntups;
int i_ev_enabled;
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
- if (g_fout->remoteVersion >= 80300)
+ if (fout->remoteVersion >= 80300)
{
- appendPQExpBuffer(query, "SELECT "
- "tableoid, oid, rulename, "
- "ev_class AS ruletable, ev_type, is_instead, "
- "ev_enabled "
- "FROM pg_rewrite "
- "ORDER BY oid");
+ appendPQExpBufferStr(query, "SELECT "
+ "tableoid, oid, rulename, "
+ "ev_class AS ruletable, ev_type, is_instead, "
+ "ev_enabled "
+ "FROM pg_rewrite "
+ "ORDER BY oid");
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
- appendPQExpBuffer(query, "SELECT "
- "tableoid, oid, rulename, "
- "ev_class AS ruletable, ev_type, is_instead, "
- "'O'::char AS ev_enabled "
- "FROM pg_rewrite "
- "ORDER BY oid");
+ appendPQExpBufferStr(query, "SELECT "
+ "tableoid, oid, rulename, "
+ "ev_class AS ruletable, ev_type, is_instead, "
+ "'O'::char AS ev_enabled "
+ "FROM pg_rewrite "
+ "ORDER BY oid");
}
else
{
- appendPQExpBuffer(query, "SELECT "
- "(SELECT oid FROM pg_class WHERE relname = 'pg_rewrite') AS tableoid, "
- "oid, rulename, "
- "ev_class AS ruletable, ev_type, is_instead, "
- "'O'::char AS ev_enabled "
- "FROM pg_rewrite "
- "ORDER BY oid");
+ appendPQExpBufferStr(query, "SELECT "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_rewrite') AS tableoid, "
+ "oid, rulename, "
+ "ev_class AS ruletable, ev_type, is_instead, "
+ "'O'::char AS ev_enabled "
+ "FROM pg_rewrite "
+ "ORDER BY oid");
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
ruletableoid = atooid(PQgetvalue(res, i, i_ruletable));
ruleinfo[i].ruletable = findTableByOid(ruletableoid);
if (ruleinfo[i].ruletable == NULL)
- {
- write_msg(NULL, "failed sanity check, parent table OID %u of pg_rewrite entry OID %u not found\n",
- ruletableoid,
- ruleinfo[i].dobj.catId.oid);
- exit_nicely();
- }
+ exit_horribly(NULL, "failed sanity check, parent table OID %u of pg_rewrite entry OID %u not found\n",
+ 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));
if (ruleinfo[i].ruletable)
{
/*
- * If the table is a view, force its ON SELECT rule to be sorted
- * before the view itself --- this ensures that any dependencies
- * for the rule affect the table's positioning. Other rules are
- * forced to appear after their table.
+ * If the table is a view or materialized view, force its ON
+ * SELECT rule to be sorted before the view itself --- this
+ * ensures that any dependencies for the rule affect the table's
+ * positioning. Other rules are forced to appear after their
+ * table.
*/
- if (ruleinfo[i].ruletable->relkind == RELKIND_VIEW &&
+ if ((ruleinfo[i].ruletable->relkind == RELKIND_VIEW ||
+ ruleinfo[i].ruletable->relkind == RELKIND_MATVIEW) &&
ruleinfo[i].ev_type == '1' && ruleinfo[i].is_instead)
{
addObjectDependency(&ruleinfo[i].ruletable->dobj,
}
else
ruleinfo[i].separate = true;
+
+ /*
+ * If we're forced to break a dependency loop by dumping a view as a
+ * table and separate _RETURN rule, we'll move the view's reloptions
+ * to the rule. (This is necessary because tables and views have
+ * different valid reloptions, so we can't apply the options until the
+ * backend knows it's a view.) Otherwise the rule's reloptions stay
+ * NULL.
+ */
+ ruleinfo[i].reloptions = NULL;
}
PQclear(res);
* does get entered into the DumpableObject tables.
*/
void
-getTriggers(TableInfo tblinfo[], int numTables)
+getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
{
int i,
j;
/*
* select table schema to ensure regproc name is qualified if needed
*/
- selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
resetPQExpBuffer(query);
- if (g_fout->remoteVersion >= 90000)
+ if (fout->remoteVersion >= 90000)
{
/*
* NB: think not to use pretty=true in pg_get_triggerdef. It
"AND NOT tgisinternal",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 80300)
+ else if (fout->remoteVersion >= 80300)
{
/*
* We ignore triggers that are tied to a foreign-key constraint
"AND tgconstraint = 0",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
{
/*
* We ignore triggers that are tied to a foreign-key constraint,
" WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query,
"SELECT tgname, tgfoid::regproc AS tgfname, "
"WHERE tgrelid = '%u'::oid",
tbinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
if (OidIsValid(tginfo[j].tgconstrrelid))
{
if (PQgetisnull(res, j, i_tgconstrrelname))
- {
- write_msg(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);
- exit_nicely();
- }
+ 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);
tginfo[j].tgconstrrelname = pg_strdup(PQgetvalue(res, j, i_tgconstrrelname));
}
else
destroyPQExpBuffer(query);
}
+/*
+ * getEventTriggers
+ * get information about event triggers
+ */
+EventTriggerInfo *
+getEventTriggers(Archive *fout, int *numEventTriggers)
+{
+ int i;
+ PQExpBuffer query;
+ PGresult *res;
+ EventTriggerInfo *evtinfo;
+ int i_tableoid,
+ i_oid,
+ i_evtname,
+ i_evtevent,
+ i_evtowner,
+ i_evttags,
+ i_evtfname,
+ i_evtenabled;
+ int ntups;
+
+ /* Before 9.3, there are no event triggers */
+ if (fout->remoteVersion < 90300)
+ {
+ *numEventTriggers = 0;
+ return NULL;
+ }
+
+ 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, "
+ "array_to_string(array("
+ "select quote_literal(x) "
+ " from unnest(evttags) as t(x)), ', ') as evttags, "
+ "e.evtfoid::regproc as evtfname "
+ "FROM pg_event_trigger e "
+ "ORDER BY e.oid",
+ username_subquery);
+
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+ ntups = PQntuples(res);
+
+ *numEventTriggers = ntups;
+
+ evtinfo = (EventTriggerInfo *) pg_malloc(ntups * sizeof(EventTriggerInfo));
+
+ i_tableoid = PQfnumber(res, "tableoid");
+ i_oid = PQfnumber(res, "oid");
+ i_evtname = PQfnumber(res, "evtname");
+ i_evtevent = PQfnumber(res, "evtevent");
+ i_evtowner = PQfnumber(res, "evtowner");
+ i_evttags = PQfnumber(res, "evttags");
+ i_evtfname = PQfnumber(res, "evtfname");
+ i_evtenabled = PQfnumber(res, "evtenabled");
+
+ for (i = 0; i < ntups; i++)
+ {
+ evtinfo[i].dobj.objType = DO_EVENT_TRIGGER;
+ evtinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+ evtinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+ AssignDumpId(&evtinfo[i].dobj);
+ evtinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_evtname));
+ evtinfo[i].evtname = pg_strdup(PQgetvalue(res, i, i_evtname));
+ evtinfo[i].evtevent = pg_strdup(PQgetvalue(res, i, i_evtevent));
+ evtinfo[i].evtowner = pg_strdup(PQgetvalue(res, i, i_evtowner));
+ evtinfo[i].evttags = pg_strdup(PQgetvalue(res, i, i_evttags));
+ evtinfo[i].evtfname = pg_strdup(PQgetvalue(res, i, i_evtfname));
+ evtinfo[i].evtenabled = *(PQgetvalue(res, i, i_evtenabled));
+ }
+
+ PQclear(res);
+
+ destroyPQExpBuffer(query);
+
+ return evtinfo;
+}
+
/*
* getProcLangs
* get basic information about every procedural language in the system
* findFuncByOid().
*/
ProcLangInfo *
-getProcLangs(int *numProcLangs)
+getProcLangs(Archive *fout, int *numProcLangs)
{
PGresult *res;
int ntups;
int i_lanowner;
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
- if (g_fout->remoteVersion >= 90000)
+ if (fout->remoteVersion >= 90000)
{
/* pg_language has a laninline column */
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"ORDER BY oid",
username_subquery);
}
- else if (g_fout->remoteVersion >= 80300)
+ else if (fout->remoteVersion >= 80300)
{
/* pg_language has a lanowner column */
appendPQExpBuffer(query, "SELECT tableoid, oid, "
"ORDER BY oid",
username_subquery);
}
- else if (g_fout->remoteVersion >= 80100)
+ else if (fout->remoteVersion >= 80100)
{
/* Languages are owned by the bootstrap superuser, OID 10 */
appendPQExpBuffer(query, "SELECT tableoid, oid, *, "
"ORDER BY oid",
username_subquery);
}
- else if (g_fout->remoteVersion >= 70400)
+ else if (fout->remoteVersion >= 70400)
{
/* Languages are owned by the bootstrap superuser, sysid 1 */
appendPQExpBuffer(query, "SELECT tableoid, oid, *, "
"ORDER BY oid",
username_subquery);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
/* No clear notion of an owner at all before 7.4 ... */
- appendPQExpBuffer(query, "SELECT tableoid, oid, * FROM pg_language "
- "WHERE lanispl "
- "ORDER BY oid");
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, * FROM pg_language "
+ "WHERE lanispl "
+ "ORDER BY oid");
}
else
{
- appendPQExpBuffer(query, "SELECT "
- "(SELECT oid FROM pg_class WHERE relname = 'pg_language') AS tableoid, "
- "oid, * FROM pg_language "
- "WHERE lanispl "
- "ORDER BY oid");
+ appendPQExpBufferStr(query, "SELECT "
+ "(SELECT oid FROM pg_class WHERE relname = 'pg_language') AS tableoid, "
+ "oid, * FROM pg_language "
+ "WHERE lanispl "
+ "ORDER BY oid");
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
else
planginfo[i].lanowner = pg_strdup("");
- if (g_fout->remoteVersion < 70300)
+ if (fout->remoteVersion < 70300)
{
/*
* We need to make a dependency to ensure the function will be
* numCasts is set to the number of casts read in
*/
CastInfo *
-getCasts(int *numCasts)
+getCasts(Archive *fout, int *numCasts)
{
PGresult *res;
int ntups;
int i_castmethod;
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
- if (g_fout->remoteVersion >= 80400)
+ if (fout->remoteVersion >= 80400)
{
- appendPQExpBuffer(query, "SELECT tableoid, oid, "
- "castsource, casttarget, castfunc, castcontext, "
- "castmethod "
- "FROM pg_cast ORDER BY 3,4");
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, "
+ "castsource, casttarget, castfunc, castcontext, "
+ "castmethod "
+ "FROM pg_cast ORDER BY 3,4");
}
- else if (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
{
- appendPQExpBuffer(query, "SELECT tableoid, oid, "
- "castsource, casttarget, castfunc, castcontext, "
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, "
+ "castsource, casttarget, castfunc, castcontext, "
"CASE WHEN castfunc = 0 THEN 'b' ELSE 'f' END AS castmethod "
- "FROM pg_cast ORDER BY 3,4");
+ "FROM pg_cast ORDER BY 3,4");
}
else
{
- appendPQExpBuffer(query, "SELECT 0 AS tableoid, p.oid, "
- "t1.oid AS castsource, t2.oid AS casttarget, "
- "p.oid AS castfunc, 'e' AS castcontext, "
- "'f' AS castmethod "
- "FROM pg_type t1, pg_type t2, pg_proc p "
- "WHERE p.pronargs = 1 AND "
- "p.proargtypes[0] = t1.oid AND "
- "p.prorettype = t2.oid AND p.proname = t2.typname "
- "ORDER BY 3,4");
+ appendPQExpBufferStr(query, "SELECT 0 AS tableoid, p.oid, "
+ "t1.oid AS castsource, t2.oid AS casttarget, "
+ "p.oid AS castfunc, 'e' AS castcontext, "
+ "'f' AS castmethod "
+ "FROM pg_type t1, pg_type t2, pg_proc p "
+ "WHERE p.pronargs = 1 AND "
+ "p.proargtypes[0] = t1.oid AND "
+ "p.prorettype = t2.oid AND p.proname = t2.typname "
+ "ORDER BY 3,4");
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
* modifies tblinfo
*/
void
-getTableAttrs(TableInfo *tblinfo, int numTables)
+getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
{
int i,
j;
* Make sure we are in proper schema for this table; this allows
* correct retrieval of formatted type names and default exprs
*/
- selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
/* find all the user attributes and their types */
resetPQExpBuffer(q);
- if (g_fout->remoteVersion >= 90200)
+ if (fout->remoteVersion >= 90200)
{
/*
* attfdwoptions is new in 9.2.
"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, "
+ "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)"
+ "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 "
"ORDER BY a.attrelid, a.attnum",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 90100)
+ else if (fout->remoteVersion >= 90100)
{
/*
* attcollation is new in 9.1. Since we only want to dump COLLATE
"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, "
+ "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 "
"ORDER BY a.attrelid, a.attnum",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 90000)
+ else if (fout->remoteVersion >= 90000)
{
/* attoptions is new in 9.0 */
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
"ORDER BY a.attrelid, a.attnum",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
{
/* need left join here to not fail on dropped columns ... */
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
"ORDER BY a.attrelid, a.attnum",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
/*
* attstattarget doesn't exist in 7.1. It does exist in 7.2, but
* we don't dump it because we can't tell whether it's been
* explicitly set or was just a default.
+ *
+ * attislocal doesn't exist before 7.3, either; in older databases
+ * we assume it's TRUE, else we'd fail to dump non-inherited atts.
*/
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
"-1 AS attstattarget, a.attstorage, "
"t.typstorage, a.attnotnull, a.atthasdef, "
"false AS attisdropped, a.attlen, "
- "a.attalign, false AS attislocal, "
+ "a.attalign, true AS attislocal, "
"format_type(t.oid,a.atttypmod) AS atttypname, "
"'' AS attoptions, 0 AS attcollation, "
"NULL AS attfdwoptions "
"attstorage, attstorage AS typstorage, "
"attnotnull, atthasdef, false AS attisdropped, "
"attlen, attalign, "
- "false AS attislocal, "
+ "true AS attislocal, "
"(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname, "
"'' AS attoptions, 0 AS attcollation, "
"NULL AS attfdwoptions "
tbinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, q->data);
- check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
tbinfo->attlen = (int *) pg_malloc(ntups * sizeof(int));
tbinfo->attalign = (char *) pg_malloc(ntups * sizeof(char));
tbinfo->attislocal = (bool *) pg_malloc(ntups * sizeof(bool));
- tbinfo->notnull = (bool *) pg_malloc(ntups * sizeof(bool));
- tbinfo->attrdefs = (AttrDefInfo **) pg_malloc(ntups * sizeof(AttrDefInfo *));
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->inhAttrs = (bool *) pg_malloc(ntups * sizeof(bool));
- tbinfo->inhAttrDef = (bool *) pg_malloc(ntups * sizeof(bool));
+ tbinfo->notnull = (bool *) pg_malloc(ntups * sizeof(bool));
tbinfo->inhNotNull = (bool *) pg_malloc(ntups * sizeof(bool));
+ tbinfo->attrdefs = (AttrDefInfo **) pg_malloc(ntups * sizeof(AttrDefInfo *));
hasdefaults = false;
for (j = 0; j < ntups; j++)
{
if (j + 1 != atoi(PQgetvalue(res, j, i_attnum)))
- {
- write_msg(NULL, "invalid column numbering in table \"%s\"\n",
- tbinfo->dobj.name);
- exit_nicely();
- }
+ exit_horribly(NULL,
+ "invalid column numbering in table \"%s\"\n",
+ 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));
if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
hasdefaults = true;
/* these flags will be set in flagInhAttrs() */
- tbinfo->inhAttrs[j] = false;
- tbinfo->inhAttrDef[j] = false;
tbinfo->inhNotNull[j] = false;
}
tbinfo->dobj.name);
resetPQExpBuffer(q);
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(q, "SELECT tableoid, oid, adnum, "
"pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
"WHERE adrelid = '%u'::pg_catalog.oid",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70200)
+ else if (fout->remoteVersion >= 70200)
{
/* 7.2 did not have OIDs in pg_attrdef */
appendPQExpBuffer(q, "SELECT tableoid, 0 AS oid, adnum, "
"WHERE adrelid = '%u'::oid",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
/* no pg_get_expr, so must rely on adsrc */
appendPQExpBuffer(q, "SELECT tableoid, oid, adnum, adsrc "
"WHERE adrelid = '%u'::oid",
tbinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, q->data);
- check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
numDefaults = PQntuples(res);
attrdefs = (AttrDefInfo *) pg_malloc(numDefaults * sizeof(AttrDefInfo));
{
int adnum;
+ 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);
+
+ /*
+ * dropped columns shouldn't have defaults, but just in case,
+ * ignore 'em
+ */
+ if (tbinfo->attisdropped[adnum - 1])
+ continue;
+
attrdefs[j].dobj.objType = DO_ATTRDEF;
attrdefs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
attrdefs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
AssignDumpId(&attrdefs[j].dobj);
attrdefs[j].adtable = tbinfo;
- attrdefs[j].adnum = adnum = atoi(PQgetvalue(res, j, 2));
+ attrdefs[j].adnum = adnum;
attrdefs[j].adef_expr = pg_strdup(PQgetvalue(res, j, 3));
attrdefs[j].dobj.name = pg_strdup(tbinfo->dobj.name);
/*
* Defaults on a VIEW must always be dumped as separate ALTER
* TABLE commands. Defaults on regular tables are dumped as
- * part of the CREATE TABLE if possible. To check if it's
- * safe, we mark the default as needing to appear before the
- * CREATE.
+ * part of the CREATE TABLE if possible, which it won't be if
+ * the column is not going to be emitted explicitly.
*/
if (tbinfo->relkind == RELKIND_VIEW)
{
addObjectDependency(&attrdefs[j].dobj,
tbinfo->dobj.dumpId);
}
+ else if (!shouldPrintColumn(tbinfo, adnum - 1))
+ {
+ /* column will be suppressed, print default separately */
+ attrdefs[j].separate = true;
+ /* needed in case pre-7.3 DB: */
+ addObjectDependency(&attrdefs[j].dobj,
+ tbinfo->dobj.dumpId);
+ }
else
{
attrdefs[j].separate = false;
+
+ /*
+ * Mark the default as needing to appear before the table,
+ * so that any dependencies it has must be emitted before
+ * the CREATE TABLE. If this is not possible, we'll
+ * change to "separate" mode while sorting dependencies.
+ */
addObjectDependency(&tbinfo->dobj,
attrdefs[j].dobj.dumpId);
}
- if (adnum <= 0 || adnum > ntups)
- {
- write_msg(NULL, "invalid adnum value %d for table \"%s\"\n",
- adnum, tbinfo->dobj.name);
- exit_nicely();
- }
tbinfo->attrdefs[adnum - 1] = &attrdefs[j];
}
PQclear(res);
tbinfo->dobj.name);
resetPQExpBuffer(q);
- if (g_fout->remoteVersion >= 90200)
+ if (fout->remoteVersion >= 90200)
{
/*
- * conisonly and convalidated are new in 9.2 (actually, the latter
- * is there in 9.1, but it wasn't ever false for check constraints
- * until 9.2).
+ * convalidated is new in 9.2 (actually, it is there in 9.1,
+ * but it wasn't ever false for check constraints until 9.2).
*/
appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
"pg_catalog.pg_get_constraintdef(oid) AS consrc, "
- "conislocal, convalidated, conisonly "
+ "conislocal, convalidated "
"FROM pg_catalog.pg_constraint "
"WHERE conrelid = '%u'::pg_catalog.oid "
" AND contype = 'c' "
"ORDER BY conname",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 80400)
+ else if (fout->remoteVersion >= 80400)
{
+ /* conislocal is new in 8.4 */
appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
"pg_catalog.pg_get_constraintdef(oid) AS consrc, "
- "conislocal, true AS convalidated, "
- "false as conisonly "
+ "conislocal, true AS convalidated "
"FROM pg_catalog.pg_constraint "
"WHERE conrelid = '%u'::pg_catalog.oid "
" AND contype = 'c' "
"ORDER BY conname",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70400)
+ else if (fout->remoteVersion >= 70400)
{
appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
"pg_catalog.pg_get_constraintdef(oid) AS consrc, "
- "true AS conislocal, true AS convalidated, "
- "false as conisonly "
+ "true AS conislocal, true AS convalidated "
"FROM pg_catalog.pg_constraint "
"WHERE conrelid = '%u'::pg_catalog.oid "
" AND contype = 'c' "
"ORDER BY conname",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
{
/* no pg_get_constraintdef, must use consrc */
appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
"'CHECK (' || consrc || ')' AS consrc, "
- "true AS conislocal, true AS convalidated, "
- "false as conisonly "
+ "true AS conislocal, true AS convalidated "
"FROM pg_catalog.pg_constraint "
"WHERE conrelid = '%u'::pg_catalog.oid "
" AND contype = 'c' "
"ORDER BY conname",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70200)
+ else if (fout->remoteVersion >= 70200)
{
/* 7.2 did not have OIDs in pg_relcheck */
appendPQExpBuffer(q, "SELECT tableoid, 0 AS oid, "
"rcname AS conname, "
"'CHECK (' || rcsrc || ')' AS consrc, "
- "true AS conislocal, true AS convalidated, "
- "false as conisonly "
+ "true AS conislocal, true AS convalidated "
"FROM pg_relcheck "
"WHERE rcrelid = '%u'::oid "
"ORDER BY rcname",
tbinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(q, "SELECT tableoid, oid, "
"rcname AS conname, "
"'CHECK (' || rcsrc || ')' AS consrc, "
- "true AS conislocal, true AS convalidated, "
- "false as conisonly "
+ "true AS conislocal, true AS convalidated "
"FROM pg_relcheck "
"WHERE rcrelid = '%u'::oid "
"ORDER BY rcname",
"(SELECT oid FROM pg_class WHERE relname = 'pg_relcheck') AS tableoid, "
"oid, rcname AS conname, "
"'CHECK (' || rcsrc || ')' AS consrc, "
- "true AS conislocal, true AS convalidated, "
- "false as conisonly "
+ "true AS conislocal, true AS convalidated "
"FROM pg_relcheck "
"WHERE rcrelid = '%u'::oid "
"ORDER BY rcname",
tbinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, q->data);
- check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
numConstrs = PQntuples(res);
if (numConstrs != tbinfo->ncheck)
tbinfo->ncheck),
tbinfo->ncheck, tbinfo->dobj.name, numConstrs);
write_msg(NULL, "(The system catalogs might be corrupted.)\n");
- exit_nicely();
+ exit_nicely(1);
}
constrs = (ConstraintInfo *) pg_malloc(numConstrs * sizeof(ConstraintInfo));
for (j = 0; j < numConstrs; j++)
{
- bool validated = PQgetvalue(res, j, 5)[0] == 't';
- bool isonly = PQgetvalue(res, j, 6)[0] == 't';
+ bool validated = PQgetvalue(res, j, 5)[0] == 't';
constrs[j].dobj.objType = DO_CONSTRAINT;
constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
constrs[j].condeferrable = false;
constrs[j].condeferred = false;
constrs[j].conislocal = (PQgetvalue(res, j, 4)[0] == 't');
- constrs[j].conisonly = isonly;
+
/*
* An unvalidated constraint needs to be dumped separately, so
* that potentially-violating existing data is loaded before
- * the constraint. An ONLY constraint needs to be dumped
- * separately too.
+ * the constraint.
*/
- constrs[j].separate = !validated || isonly;
+ constrs[j].separate = !validated;
constrs[j].dobj.dump = tbinfo->dobj.dump;
* Mark the constraint as needing to appear before the table
* --- this is so that any other dependencies of the
* constraint will be emitted before we try to create the
- * table. If the constraint is to be dumped separately, it will be
- * dumped after data is loaded anyway, so don't do it. (There's
- * an automatic dependency in the opposite direction anyway, so
- * don't need to add one manually here.)
+ * table. If the constraint is to be dumped separately, it
+ * will be dumped after data is loaded anyway, so don't do it.
+ * (There's an automatic dependency in the opposite direction
+ * anyway, so don't need to add one manually here.)
*/
if (!constrs[j].separate)
addObjectDependency(&tbinfo->dobj,
destroyPQExpBuffer(q);
}
+/*
+ * Test whether a column should be printed as part of table's CREATE TABLE.
+ * Column number is zero-based.
+ *
+ * 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.
+ *
+ * This function exists because there are scattered nonobvious places that
+ * must be kept in sync with this decision.
+ */
+bool
+shouldPrintColumn(TableInfo *tbinfo, int colno)
+{
+ if (binary_upgrade)
+ return true;
+ return (tbinfo->attislocal[colno] && !tbinfo->attisdropped[colno]);
+}
+
/*
* getTSParsers:
* numTSParsers is set to the number of parsers read in
*/
TSParserInfo *
-getTSParsers(int *numTSParsers)
+getTSParsers(Archive *fout, int *numTSParsers)
{
PGresult *res;
int ntups;
int i;
- PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer query;
TSParserInfo *prsinfo;
int i_tableoid;
int i_oid;
int i_prslextype;
/* Before 8.3, there is no built-in text search support */
- if (g_fout->remoteVersion < 80300)
+ if (fout->remoteVersion < 80300)
{
*numTSParsers = 0;
return NULL;
}
+ query = createPQExpBuffer();
+
/*
* find all text search objects, including builtin ones; we filter out
* system-defined objects at dump-out time.
*/
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
- appendPQExpBuffer(query, "SELECT tableoid, oid, prsname, prsnamespace, "
- "prsstart::oid, prstoken::oid, "
- "prsend::oid, prsheadline::oid, prslextype::oid "
- "FROM pg_ts_parser");
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, prsname, prsnamespace, "
+ "prsstart::oid, prstoken::oid, "
+ "prsend::oid, prsheadline::oid, prslextype::oid "
+ "FROM pg_ts_parser");
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numTSParsers = ntups;
prsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&prsinfo[i].dobj);
prsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_prsname));
- prsinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_prsnamespace)),
- prsinfo[i].dobj.catId.oid);
+ prsinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_prsnamespace)),
+ prsinfo[i].dobj.catId.oid);
prsinfo[i].prsstart = atooid(PQgetvalue(res, i, i_prsstart));
prsinfo[i].prstoken = atooid(PQgetvalue(res, i, i_prstoken));
prsinfo[i].prsend = atooid(PQgetvalue(res, i, i_prsend));
* numTSDicts is set to the number of dictionaries read in
*/
TSDictInfo *
-getTSDictionaries(int *numTSDicts)
+getTSDictionaries(Archive *fout, int *numTSDicts)
{
PGresult *res;
int ntups;
int i;
- PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer query;
TSDictInfo *dictinfo;
int i_tableoid;
int i_oid;
int i_dictinitoption;
/* Before 8.3, there is no built-in text search support */
- if (g_fout->remoteVersion < 80300)
+ if (fout->remoteVersion < 80300)
{
*numTSDicts = 0;
return NULL;
}
+ query = createPQExpBuffer();
+
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT tableoid, oid, dictname, "
"dictnamespace, (%s dictowner) AS rolname, "
"FROM pg_ts_dict",
username_subquery);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numTSDicts = ntups;
dictinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&dictinfo[i].dobj);
dictinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_dictname));
- dictinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_dictnamespace)),
- dictinfo[i].dobj.catId.oid);
+ dictinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_dictnamespace)),
+ dictinfo[i].dobj.catId.oid);
dictinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
dictinfo[i].dicttemplate = atooid(PQgetvalue(res, i, i_dicttemplate));
if (PQgetisnull(res, i, i_dictinitoption))
* numTSTemplates is set to the number of templates read in
*/
TSTemplateInfo *
-getTSTemplates(int *numTSTemplates)
+getTSTemplates(Archive *fout, int *numTSTemplates)
{
PGresult *res;
int ntups;
int i;
- PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer query;
TSTemplateInfo *tmplinfo;
int i_tableoid;
int i_oid;
int i_tmpllexize;
/* Before 8.3, there is no built-in text search support */
- if (g_fout->remoteVersion < 80300)
+ if (fout->remoteVersion < 80300)
{
*numTSTemplates = 0;
return NULL;
}
+ query = createPQExpBuffer();
+
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
- appendPQExpBuffer(query, "SELECT tableoid, oid, tmplname, "
- "tmplnamespace, tmplinit::oid, tmpllexize::oid "
- "FROM pg_ts_template");
+ appendPQExpBufferStr(query, "SELECT tableoid, oid, tmplname, "
+ "tmplnamespace, tmplinit::oid, tmpllexize::oid "
+ "FROM pg_ts_template");
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numTSTemplates = ntups;
tmplinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&tmplinfo[i].dobj);
tmplinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_tmplname));
- tmplinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_tmplnamespace)),
- tmplinfo[i].dobj.catId.oid);
+ tmplinfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_tmplnamespace)),
+ tmplinfo[i].dobj.catId.oid);
tmplinfo[i].tmplinit = atooid(PQgetvalue(res, i, i_tmplinit));
tmplinfo[i].tmpllexize = atooid(PQgetvalue(res, i, i_tmpllexize));
* numTSConfigs is set to the number of configurations read in
*/
TSConfigInfo *
-getTSConfigurations(int *numTSConfigs)
+getTSConfigurations(Archive *fout, int *numTSConfigs)
{
PGresult *res;
int ntups;
int i;
- PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer query;
TSConfigInfo *cfginfo;
int i_tableoid;
int i_oid;
int i_cfgparser;
/* Before 8.3, there is no built-in text search support */
- if (g_fout->remoteVersion < 80300)
+ if (fout->remoteVersion < 80300)
{
*numTSConfigs = 0;
return NULL;
}
+ query = createPQExpBuffer();
+
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT tableoid, oid, cfgname, "
"cfgnamespace, (%s cfgowner) AS rolname, cfgparser "
"FROM pg_ts_config",
username_subquery);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numTSConfigs = ntups;
cfginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&cfginfo[i].dobj);
cfginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_cfgname));
- cfginfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_cfgnamespace)),
- cfginfo[i].dobj.catId.oid);
+ cfginfo[i].dobj.namespace =
+ findNamespace(fout,
+ atooid(PQgetvalue(res, i, i_cfgnamespace)),
+ cfginfo[i].dobj.catId.oid);
cfginfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));
* numForeignDataWrappers is set to the number of fdws read in
*/
FdwInfo *
-getForeignDataWrappers(int *numForeignDataWrappers)
+getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
{
PGresult *res;
int ntups;
int i;
- PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer query;
FdwInfo *fdwinfo;
int i_tableoid;
int i_oid;
int i_fdwoptions;
/* Before 8.4, there are no foreign-data wrappers */
- if (g_fout->remoteVersion < 80400)
+ if (fout->remoteVersion < 80400)
{
*numForeignDataWrappers = 0;
return NULL;
}
+ query = createPQExpBuffer();
+
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
- if (g_fout->remoteVersion >= 90100)
+ if (fout->remoteVersion >= 90100)
{
appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
"(%s fdwowner) AS rolname, "
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
- "FROM pg_options_to_table(fdwoptions)"
+ "FROM pg_options_to_table(fdwoptions) "
+ "ORDER BY option_name"
"), E',\n ') AS fdwoptions "
"FROM pg_foreign_data_wrapper",
username_subquery);
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
- "FROM pg_options_to_table(fdwoptions)"
+ "FROM pg_options_to_table(fdwoptions) "
+ "ORDER BY option_name"
"), E',\n ') AS fdwoptions "
"FROM pg_foreign_data_wrapper",
username_subquery);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numForeignDataWrappers = ntups;
* numForeignServers is set to the number of servers read in
*/
ForeignServerInfo *
-getForeignServers(int *numForeignServers)
+getForeignServers(Archive *fout, int *numForeignServers)
{
PGresult *res;
int ntups;
int i;
- PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer query;
ForeignServerInfo *srvinfo;
int i_tableoid;
int i_oid;
int i_srvoptions;
/* Before 8.4, there are no foreign servers */
- if (g_fout->remoteVersion < 80400)
+ if (fout->remoteVersion < 80400)
{
*numForeignServers = 0;
return NULL;
}
+ query = createPQExpBuffer();
+
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT tableoid, oid, srvname, "
"(%s srvowner) AS rolname, "
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
- "FROM pg_options_to_table(srvoptions)"
+ "FROM pg_options_to_table(srvoptions) "
+ "ORDER BY option_name"
"), E',\n ') AS srvoptions "
"FROM pg_foreign_server",
username_subquery);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numForeignServers = ntups;
* numDefaultACLs is set to the number of ACLs read in
*/
DefaultACLInfo *
-getDefaultACLs(int *numDefaultACLs)
+getDefaultACLs(Archive *fout, int *numDefaultACLs)
{
DefaultACLInfo *daclinfo;
PQExpBuffer query;
int i,
ntups;
- if (g_fout->remoteVersion < 90000)
+ if (fout->remoteVersion < 90000)
{
*numDefaultACLs = 0;
return NULL;
query = createPQExpBuffer();
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT oid, tableoid, "
"(%s defaclrole) AS defaclrole, "
"FROM pg_default_acl",
username_subquery);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numDefaultACLs = ntups;
daclinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_defaclobjtype));
if (nspid != InvalidOid)
- daclinfo[i].dobj.namespace = findNamespace(nspid,
+ daclinfo[i].dobj.namespace = findNamespace(fout, nspid,
daclinfo[i].dobj.catId.oid);
else
daclinfo[i].dobj.namespace = NULL;
appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
appendStringLiteralAH(query, comments->descr, fout);
- appendPQExpBuffer(query, ";\n");
+ appendPQExpBufferStr(query, ";\n");
/*
* We mark comments as SECTION_NONE because they really belong in the
resetPQExpBuffer(query);
appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
appendStringLiteralAH(query, descr, fout);
- appendPQExpBuffer(query, ";\n");
+ appendPQExpBufferStr(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(),
target->data,
resetPQExpBuffer(target);
appendPQExpBuffer(target, "COLUMN %s.",
fmtId(tbinfo->dobj.name));
- appendPQExpBuffer(target, "%s",
- fmtId(tbinfo->attnames[objsubid - 1]));
+ appendPQExpBufferStr(target, fmtId(tbinfo->attnames[objsubid - 1]));
resetPQExpBuffer(query);
appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
appendStringLiteralAH(query, descr, fout);
- appendPQExpBuffer(query, ";\n");
+ appendPQExpBufferStr(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(),
target->data,
if (fout->remoteVersion >= 70300)
{
- appendPQExpBuffer(query, "SELECT description, classoid, objoid, objsubid "
- "FROM pg_catalog.pg_description "
- "ORDER BY classoid, objoid, objsubid");
+ appendPQExpBufferStr(query, "SELECT description, classoid, objoid, objsubid "
+ "FROM pg_catalog.pg_description "
+ "ORDER BY classoid, objoid, objsubid");
}
else if (fout->remoteVersion >= 70200)
{
- appendPQExpBuffer(query, "SELECT description, classoid, objoid, objsubid "
- "FROM pg_description "
- "ORDER BY classoid, objoid, objsubid");
+ appendPQExpBufferStr(query, "SELECT description, classoid, objoid, objsubid "
+ "FROM pg_description "
+ "ORDER BY classoid, objoid, objsubid");
}
else
{
/* Note: this will fail to find attribute comments in pre-7.2... */
- appendPQExpBuffer(query, "SELECT description, 0 AS classoid, objoid, 0 AS objsubid "
- "FROM pg_description "
- "ORDER BY objoid");
+ appendPQExpBufferStr(query, "SELECT description, 0 AS classoid, objoid, 0 AS objsubid "
+ "FROM pg_description "
+ "ORDER BY objoid");
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
/* Construct lookup table containing OIDs in numeric form */
static void
dumpDumpableObject(Archive *fout, DumpableObject *dobj)
{
-
- bool skip = false;
-
- switch (dobj->objType)
- {
- case DO_INDEX:
- case DO_TRIGGER:
- case DO_CONSTRAINT:
- case DO_FK_CONSTRAINT:
- case DO_RULE:
- skip = !(dumpSections & DUMP_POST_DATA);
- break;
- case DO_TABLE_DATA:
- skip = !(dumpSections & DUMP_DATA);
- break;
- default:
- skip = !(dumpSections & DUMP_PRE_DATA);
- }
-
- if (skip)
- return;
-
switch (dobj->objType)
{
case DO_NAMESPACE:
case DO_INDEX:
dumpIndex(fout, (IndxInfo *) dobj);
break;
+ case DO_REFRESH_MATVIEW:
+ refreshMatViewData(fout, (TableDataInfo *) dobj);
+ break;
case DO_RULE:
dumpRule(fout, (RuleInfo *) dobj);
break;
case DO_TRIGGER:
dumpTrigger(fout, (TriggerInfo *) dobj);
break;
+ case DO_EVENT_TRIGGER:
+ dumpEventTrigger(fout, (EventTriggerInfo *) dobj);
+ break;
case DO_CONSTRAINT:
dumpConstraint(fout, (ConstraintInfo *) dobj);
break;
dumpCast(fout, (CastInfo *) dobj);
break;
case DO_TABLE_DATA:
- dumpTableData(fout, (TableDataInfo *) dobj);
+ if (((TableDataInfo *) dobj)->tdtable->relkind == RELKIND_SEQUENCE)
+ dumpSequenceData(fout, (TableDataInfo *) dobj);
+ else
+ dumpTableData(fout, (TableDataInfo *) dobj);
break;
case DO_DUMMY_TYPE:
/* table rowtypes and array types are never dumped separately */
dobj->name, NULL, NULL, "",
false, "BLOBS", SECTION_DATA,
"", "", NULL,
- dobj->dependencies, dobj->nDeps,
+ NULL, 0,
dumpBlobs, NULL);
break;
+ case DO_PRE_DATA_BOUNDARY:
+ case DO_POST_DATA_BOUNDARY:
+ /* never dumped, nothing to do */
+ break;
}
}
nspinfo->rolname,
false, "SCHEMA", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- nspinfo->dobj.dependencies, nspinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Schema Comments and Security Labels */
int i;
int n;
- appendPQExpBuffer(q, "-- For binary upgrade, create an empty extension and insert objects into it\n");
- appendPQExpBuffer(q,
+ appendPQExpBufferStr(q, "-- For binary upgrade, create an empty extension and insert objects into it\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 FirstNormalObjectId.
+ * The FirstNormalObjectId test was kept to avoid repeatedly dropping
+ * and recreating extensions like 'plpgsql'.
+ */
+ appendPQExpBuffer(q, "DROP EXTENSION IF EXISTS %s;\n", qextname);
+
+ appendPQExpBufferStr(q,
"SELECT binary_upgrade.create_empty_extension(");
appendStringLiteralAH(q, extinfo->dobj.name, fout);
- appendPQExpBuffer(q, ", ");
+ appendPQExpBufferStr(q, ", ");
appendStringLiteralAH(q, extinfo->namespace, fout);
- appendPQExpBuffer(q, ", ");
+ appendPQExpBufferStr(q, ", ");
appendPQExpBuffer(q, "%s, ", extinfo->relocatable ? "true" : "false");
appendStringLiteralAH(q, extinfo->extversion, fout);
- appendPQExpBuffer(q, ", ");
+ appendPQExpBufferStr(q, ", ");
/*
* Note that we're pushing extconfig (an OID array) back into
if (strlen(extinfo->extconfig) > 2)
appendStringLiteralAH(q, extinfo->extconfig, fout);
else
- appendPQExpBuffer(q, "NULL");
- appendPQExpBuffer(q, ", ");
+ appendPQExpBufferStr(q, "NULL");
+ appendPQExpBufferStr(q, ", ");
if (strlen(extinfo->extcondition) > 2)
appendStringLiteralAH(q, extinfo->extcondition, fout);
else
- appendPQExpBuffer(q, "NULL");
- appendPQExpBuffer(q, ", ");
- appendPQExpBuffer(q, "ARRAY[");
+ appendPQExpBufferStr(q, "NULL");
+ appendPQExpBufferStr(q, ", ");
+ appendPQExpBufferStr(q, "ARRAY[");
n = 0;
for (i = 0; i < extinfo->dobj.nDeps; i++)
{
if (extobj && extobj->objType == DO_EXTENSION)
{
if (n++ > 0)
- appendPQExpBuffer(q, ",");
+ appendPQExpBufferChar(q, ',');
appendStringLiteralAH(q, extobj->name, fout);
}
}
- appendPQExpBuffer(q, "]::pg_catalog.text[]");
- appendPQExpBuffer(q, ");\n");
+ appendPQExpBufferStr(q, "]::pg_catalog.text[]");
+ appendPQExpBufferStr(q, ");\n");
}
appendPQExpBuffer(labelq, "EXTENSION %s", qextname);
"",
false, "EXTENSION", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- extinfo->dobj.dependencies, extinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Extension Comments and Security Labels */
int num,
i;
Oid enum_oid;
+ char *qtypname;
char *label;
/* Set proper schema search path */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
if (fout->remoteVersion >= 90100)
appendPQExpBuffer(query, "SELECT oid, enumlabel "
"ORDER BY oid",
tyinfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
num = PQntuples(res);
+ qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+
/*
* 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
appendPQExpBuffer(delq, "DROP TYPE %s.",
fmtId(tyinfo->dobj.namespace->dobj.name));
appendPQExpBuffer(delq, "%s;\n",
- fmtId(tyinfo->dobj.name));
+ qtypname);
if (binary_upgrade)
- binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
+ binary_upgrade_set_type_oids_by_type_oid(fout, q,
+ tyinfo->dobj.catId.oid);
appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (",
- fmtId(tyinfo->dobj.name));
+ qtypname);
if (!binary_upgrade)
{
{
label = PQgetvalue(res, i, PQfnumber(res, "enumlabel"));
if (i > 0)
- appendPQExpBuffer(q, ",");
- appendPQExpBuffer(q, "\n ");
+ appendPQExpBufferChar(q, ',');
+ appendPQExpBufferStr(q, "\n ");
appendStringLiteralAH(q, label, fout);
}
}
- appendPQExpBuffer(q, "\n);\n");
+ appendPQExpBufferStr(q, "\n);\n");
if (binary_upgrade)
{
label = PQgetvalue(res, i, PQfnumber(res, "enumlabel"));
if (i == 0)
- appendPQExpBuffer(q, "\n-- For binary upgrade, must preserve pg_enum oids\n");
+ appendPQExpBufferStr(q, "\n-- For binary upgrade, must preserve pg_enum oids\n");
appendPQExpBuffer(q,
"SELECT 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 ",
- fmtId(tyinfo->dobj.name));
+ qtypname);
appendStringLiteralAH(q, label, fout);
- appendPQExpBuffer(q, ";\n\n");
+ appendPQExpBufferStr(q, ";\n\n");
}
}
- appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
+ appendPQExpBuffer(labelq, "TYPE %s", qtypname);
if (binary_upgrade)
binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
tyinfo->rolname, false,
"TYPE", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- tyinfo->dobj.dependencies, tyinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Type Comments and Security Labels */
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
+ dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
+ qtypname, NULL, tyinfo->dobj.name,
+ tyinfo->dobj.namespace->dobj.name,
+ tyinfo->rolname, tyinfo->typacl);
+
PQclear(res);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
Oid collationOid;
+ char *qtypname;
char *procname;
/*
* select appropriate schema to ensure names in CREATE are properly
* qualified
*/
- selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
appendPQExpBuffer(query,
- "SELECT pg_catalog.format_type(rngsubtype, NULL) AS rngsubtype, "
+ "SELECT pg_catalog.format_type(rngsubtype, NULL) AS rngsubtype, "
"opc.opcname AS opcname, "
"(SELECT nspname FROM pg_catalog.pg_namespace nsp "
" WHERE nsp.oid = opc.opcnamespace) AS opcnsp, "
"rngtypid = '%u'",
tyinfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
- if (PQntuples(res) != 1)
- {
- write_msg(NULL, "query returned %d pg_range entries for range type \"%s\"\n",
- PQntuples(res), tyinfo->dobj.name);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
+
+ qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
/*
* 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",
- fmtId(tyinfo->dobj.name));
+ qtypname);
if (binary_upgrade)
- binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
+ binary_upgrade_set_type_oids_by_type_oid(fout,
+ q, tyinfo->dobj.catId.oid);
appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (",
- fmtId(tyinfo->dobj.name));
+ qtypname);
appendPQExpBuffer(q, "\n subtype = %s",
PQgetvalue(res, 0, PQfnumber(res, "rngsubtype")));
/* print subtype_opclass only if not default for subtype */
if (PQgetvalue(res, 0, PQfnumber(res, "opcdefault"))[0] != 't')
{
- char *opcname = PQgetvalue(res, 0, PQfnumber(res, "opcname"));
- char *nspname = PQgetvalue(res, 0, PQfnumber(res, "opcnsp"));
+ 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));
- appendPQExpBuffer(q, "%s", fmtId(opcname));
+ appendPQExpBufferStr(q, fmtId(opcname));
}
collationOid = atooid(PQgetvalue(res, 0, PQfnumber(res, "collation")));
/* always schema-qualify, don't try to be smart */
appendPQExpBuffer(q, ",\n collation = %s.",
fmtId(coll->dobj.namespace->dobj.name));
- appendPQExpBuffer(q, "%s",
- fmtId(coll->dobj.name));
+ appendPQExpBufferStr(q, fmtId(coll->dobj.name));
}
}
if (strcmp(procname, "-") != 0)
appendPQExpBuffer(q, ",\n subtype_diff = %s", procname);
- appendPQExpBuffer(q, "\n);\n");
+ appendPQExpBufferStr(q, "\n);\n");
- appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
+ appendPQExpBuffer(labelq, "TYPE %s", qtypname);
if (binary_upgrade)
binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
tyinfo->rolname, false,
"TYPE", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- tyinfo->dobj.dependencies, tyinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Type Comments and Security Labels */
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
+ dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
+ qtypname, NULL, tyinfo->dobj.name,
+ tyinfo->dobj.namespace->dobj.name,
+ tyinfo->rolname, tyinfo->typacl);
+
PQclear(res);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
PQExpBuffer labelq = createPQExpBuffer();
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
- int ntups;
+ char *qtypname;
char *typlen;
char *typinput;
char *typoutput;
bool typdefault_is_literal = false;
/* Set proper schema search path so regproc references list correctly */
- selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
/* Fetch type-specific details */
if (fout->remoteVersion >= 90100)
tyinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
typlen = PQgetvalue(res, 0, PQfnumber(res, "typlen"));
typinput = PQgetvalue(res, 0, PQfnumber(res, "typinput"));
else
typdefault = NULL;
+ qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+
/*
* DROP must be fully qualified in case same name appears in pg_catalog.
* The reason we include CASCADE is that the circular dependency between
appendPQExpBuffer(delq, "DROP TYPE %s.",
fmtId(tyinfo->dobj.namespace->dobj.name));
appendPQExpBuffer(delq, "%s CASCADE;\n",
- fmtId(tyinfo->dobj.name));
+ qtypname);
/* We might already have a shell type, but setting pg_type_oid is harmless */
if (binary_upgrade)
- binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
+ binary_upgrade_set_type_oids_by_type_oid(fout, q,
+ tyinfo->dobj.catId.oid);
appendPQExpBuffer(q,
"CREATE TYPE %s (\n"
" INTERNALLENGTH = %s",
- fmtId(tyinfo->dobj.name),
+ qtypname,
(strcmp(typlen, "-1") == 0) ? "variable" : typlen);
if (fout->remoteVersion >= 70300)
}
if (strcmp(typcollatable, "t") == 0)
- appendPQExpBuffer(q, ",\n COLLATABLE = true");
+ appendPQExpBufferStr(q, ",\n COLLATABLE = true");
if (typdefault != NULL)
{
- appendPQExpBuffer(q, ",\n DEFAULT = ");
+ appendPQExpBufferStr(q, ",\n DEFAULT = ");
if (typdefault_is_literal)
appendStringLiteralAH(q, typdefault, fout);
else
char *elemType;
/* reselect schema in case changed by function dump */
- selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
- elemType = getFormattedTypeName(tyinfo->typelem, zeroAsOpaque);
+ selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
+ elemType = getFormattedTypeName(fout, tyinfo->typelem, zeroAsOpaque);
appendPQExpBuffer(q, ",\n ELEMENT = %s", elemType);
free(elemType);
}
if (strcmp(typcategory, "U") != 0)
{
- appendPQExpBuffer(q, ",\n CATEGORY = ");
+ appendPQExpBufferStr(q, ",\n CATEGORY = ");
appendStringLiteralAH(q, typcategory, fout);
}
if (strcmp(typispreferred, "t") == 0)
- appendPQExpBuffer(q, ",\n PREFERRED = true");
+ appendPQExpBufferStr(q, ",\n PREFERRED = true");
if (typdelim && strcmp(typdelim, ",") != 0)
{
- appendPQExpBuffer(q, ",\n DELIMITER = ");
+ appendPQExpBufferStr(q, ",\n DELIMITER = ");
appendStringLiteralAH(q, typdelim, fout);
}
if (strcmp(typalign, "c") == 0)
- appendPQExpBuffer(q, ",\n ALIGNMENT = char");
+ appendPQExpBufferStr(q, ",\n ALIGNMENT = char");
else if (strcmp(typalign, "s") == 0)
- appendPQExpBuffer(q, ",\n ALIGNMENT = int2");
+ appendPQExpBufferStr(q, ",\n ALIGNMENT = int2");
else if (strcmp(typalign, "i") == 0)
- appendPQExpBuffer(q, ",\n ALIGNMENT = int4");
+ appendPQExpBufferStr(q, ",\n ALIGNMENT = int4");
else if (strcmp(typalign, "d") == 0)
- appendPQExpBuffer(q, ",\n ALIGNMENT = double");
+ appendPQExpBufferStr(q, ",\n ALIGNMENT = double");
if (strcmp(typstorage, "p") == 0)
- appendPQExpBuffer(q, ",\n STORAGE = plain");
+ appendPQExpBufferStr(q, ",\n STORAGE = plain");
else if (strcmp(typstorage, "e") == 0)
- appendPQExpBuffer(q, ",\n STORAGE = external");
+ appendPQExpBufferStr(q, ",\n STORAGE = external");
else if (strcmp(typstorage, "x") == 0)
- appendPQExpBuffer(q, ",\n STORAGE = extended");
+ appendPQExpBufferStr(q, ",\n STORAGE = extended");
else if (strcmp(typstorage, "m") == 0)
- appendPQExpBuffer(q, ",\n STORAGE = main");
+ appendPQExpBufferStr(q, ",\n STORAGE = main");
if (strcmp(typbyval, "t") == 0)
- appendPQExpBuffer(q, ",\n PASSEDBYVALUE");
+ appendPQExpBufferStr(q, ",\n PASSEDBYVALUE");
- appendPQExpBuffer(q, "\n);\n");
+ appendPQExpBufferStr(q, "\n);\n");
- appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
+ appendPQExpBuffer(labelq, "TYPE %s", qtypname);
if (binary_upgrade)
binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
tyinfo->rolname, false,
"TYPE", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- tyinfo->dobj.dependencies, tyinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Type Comments and Security Labels */
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
+ dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
+ qtypname, NULL, tyinfo->dobj.name,
+ tyinfo->dobj.namespace->dobj.name,
+ tyinfo->rolname, tyinfo->typacl);
+
PQclear(res);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
PQExpBuffer labelq = createPQExpBuffer();
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
- int ntups;
int i;
+ char *qtypname;
char *typnotnull;
char *typdefn;
char *typdefault;
bool typdefault_is_literal = false;
/* Set proper schema search path so type references list correctly */
- selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
/* Fetch domain specific details */
- if (g_fout->remoteVersion >= 90100)
+ if (fout->remoteVersion >= 90100)
{
/* typcollation is new in 9.1 */
appendPQExpBuffer(query, "SELECT t.typnotnull, "
tyinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
typnotnull = PQgetvalue(res, 0, PQfnumber(res, "typnotnull"));
typdefn = PQgetvalue(res, 0, PQfnumber(res, "typdefn"));
typcollation = atooid(PQgetvalue(res, 0, PQfnumber(res, "typcollation")));
if (binary_upgrade)
- binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
+ binary_upgrade_set_type_oids_by_type_oid(fout, q,
+ tyinfo->dobj.catId.oid);
+
+ qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
appendPQExpBuffer(q,
"CREATE DOMAIN %s AS %s",
- fmtId(tyinfo->dobj.name),
+ qtypname,
typdefn);
/* Print collation only if different from base type's collation */
/* always schema-qualify, don't try to be smart */
appendPQExpBuffer(q, " COLLATE %s.",
fmtId(coll->dobj.namespace->dobj.name));
- appendPQExpBuffer(q, "%s",
- fmtId(coll->dobj.name));
+ appendPQExpBufferStr(q, fmtId(coll->dobj.name));
}
}
if (typnotnull[0] == 't')
- appendPQExpBuffer(q, " NOT NULL");
+ appendPQExpBufferStr(q, " NOT NULL");
if (typdefault != NULL)
{
- appendPQExpBuffer(q, " DEFAULT ");
+ appendPQExpBufferStr(q, " DEFAULT ");
if (typdefault_is_literal)
appendStringLiteralAH(q, typdefault, fout);
else
fmtId(domcheck->dobj.name), domcheck->condef);
}
- appendPQExpBuffer(q, ";\n");
+ 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",
- fmtId(tyinfo->dobj.name));
+ qtypname);
- appendPQExpBuffer(labelq, "DOMAIN %s", fmtId(tyinfo->dobj.name));
+ appendPQExpBuffer(labelq, "DOMAIN %s", qtypname);
if (binary_upgrade)
binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
tyinfo->rolname, false,
"DOMAIN", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- tyinfo->dobj.dependencies, tyinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Domain Comments and Security Labels */
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
+ dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
+ qtypname, NULL, tyinfo->dobj.name,
+ tyinfo->dobj.namespace->dobj.name,
+ tyinfo->rolname, tyinfo->typacl);
+
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
destroyPQExpBuffer(labelq);
PQExpBuffer labelq = createPQExpBuffer();
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
+ char *qtypname;
int ntups;
int i_attname;
int i_atttypdefn;
int actual_atts;
/* Set proper schema search path so type references list correctly */
- selectSourceSchema(tyinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
/* Fetch type specific details */
if (fout->remoteVersion >= 90100)
tyinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
{
Oid typrelid = atooid(PQgetvalue(res, 0, i_typrelid));
- binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
- binary_upgrade_set_pg_class_oids(q, typrelid, false);
+ binary_upgrade_set_type_oids_by_type_oid(fout, q,
+ tyinfo->dobj.catId.oid);
+ binary_upgrade_set_pg_class_oids(fout, q, typrelid, false);
}
+ qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+
appendPQExpBuffer(q, "CREATE TYPE %s AS (",
- fmtId(tyinfo->dobj.name));
+ qtypname);
actual_atts = 0;
for (i = 0; i < ntups; i++)
/* Format properly if not first attr */
if (actual_atts++ > 0)
- appendPQExpBuffer(q, ",");
- appendPQExpBuffer(q, "\n\t");
+ appendPQExpBufferChar(q, ',');
+ appendPQExpBufferStr(q, "\n\t");
if (!attisdropped)
{
/* always schema-qualify, don't try to be smart */
appendPQExpBuffer(q, " COLLATE %s.",
fmtId(coll->dobj.namespace->dobj.name));
- appendPQExpBuffer(q, "%s",
- fmtId(coll->dobj.name));
+ appendPQExpBufferStr(q, fmtId(coll->dobj.name));
}
}
}
appendPQExpBuffer(q, "%s INTEGER /* dummy */", fmtId(attname));
/* stash separately for insertion after the CREATE TYPE */
- appendPQExpBuffer(dropped,
+ appendPQExpBufferStr(dropped,
"\n-- For binary upgrade, recreate dropped column.\n");
appendPQExpBuffer(dropped, "UPDATE pg_catalog.pg_attribute\n"
"SET attlen = %s, "
"attalign = '%s', attbyval = false\n"
"WHERE attname = ", attlen, attalign);
appendStringLiteralAH(dropped, attname, fout);
- appendPQExpBuffer(dropped, "\n AND attrelid = ");
- appendStringLiteralAH(dropped, fmtId(tyinfo->dobj.name), fout);
- appendPQExpBuffer(dropped, "::pg_catalog.regclass;\n");
+ appendPQExpBufferStr(dropped, "\n AND attrelid = ");
+ appendStringLiteralAH(dropped, qtypname, fout);
+ appendPQExpBufferStr(dropped, "::pg_catalog.regclass;\n");
appendPQExpBuffer(dropped, "ALTER TYPE %s ",
- fmtId(tyinfo->dobj.name));
+ qtypname);
appendPQExpBuffer(dropped, "DROP ATTRIBUTE %s;\n",
fmtId(attname));
}
}
- appendPQExpBuffer(q, "\n);\n");
+ appendPQExpBufferStr(q, "\n);\n");
appendPQExpBufferStr(q, dropped->data);
/*
appendPQExpBuffer(delq, "DROP TYPE %s.",
fmtId(tyinfo->dobj.namespace->dobj.name));
appendPQExpBuffer(delq, "%s;\n",
- fmtId(tyinfo->dobj.name));
+ qtypname);
- appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
+ appendPQExpBuffer(labelq, "TYPE %s", qtypname);
if (binary_upgrade)
binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
tyinfo->rolname, false,
"TYPE", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- tyinfo->dobj.dependencies, tyinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
+ dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
+ qtypname, NULL, tyinfo->dobj.name,
+ tyinfo->dobj.namespace->dobj.name,
+ tyinfo->rolname, tyinfo->typacl);
+
PQclear(res);
destroyPQExpBuffer(q);
destroyPQExpBuffer(dropped);
tyinfo->typrelid);
/* Fetch column attnames */
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
if (ntups < 1)
resetPQExpBuffer(target);
appendPQExpBuffer(target, "COLUMN %s.",
fmtId(tyinfo->dobj.name));
- appendPQExpBuffer(target, "%s",
- fmtId(attname));
+ appendPQExpBufferStr(target, fmtId(attname));
resetPQExpBuffer(query);
appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
appendStringLiteralAH(query, descr, fout);
- appendPQExpBuffer(query, ";\n");
+ appendPQExpBufferStr(query, ";\n");
ArchiveEntry(fout, nilCatalogId, createDumpId(),
target->data,
*/
if (binary_upgrade)
- binary_upgrade_set_type_oids_by_type_oid(q,
+ binary_upgrade_set_type_oids_by_type_oid(fout, q,
stinfo->baseType->dobj.catId.oid);
appendPQExpBuffer(q, "CREATE TYPE %s;\n",
stinfo->baseType->rolname, false,
"SHELL TYPE", SECTION_PRE_DATA,
q->data, "", NULL,
- stinfo->dobj.dependencies, stinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
destroyPQExpBuffer(q);
fmtId(funcInfo->dobj.name));
if (OidIsValid(plang->laninline))
{
- appendPQExpBuffer(defqry, " INLINE ");
+ 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));
- appendPQExpBuffer(defqry, "%s",
- fmtId(inlineInfo->dobj.name));
+ appendPQExpBufferStr(defqry, fmtId(inlineInfo->dobj.name));
}
if (OidIsValid(plang->lanvalidator))
{
- appendPQExpBuffer(defqry, " VALIDATOR ");
+ 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));
- appendPQExpBuffer(defqry, "%s",
- fmtId(validatorInfo->dobj.name));
+ appendPQExpBufferStr(defqry, fmtId(validatorInfo->dobj.name));
}
}
else
appendPQExpBuffer(defqry, "CREATE OR REPLACE PROCEDURAL LANGUAGE %s",
qlanname);
}
- appendPQExpBuffer(defqry, ";\n");
+ appendPQExpBufferStr(defqry, ";\n");
appendPQExpBuffer(labelq, "LANGUAGE %s", qlanname);
lanschema, NULL, plang->lanowner,
false, "PROCEDURAL LANGUAGE", SECTION_PRE_DATA,
defqry->data, delqry->data, NULL,
- plang->dobj.dependencies, plang->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Proc Lang Comments and Security Labels */
* format_function_arguments: generate function name and argument list
*
* This is used when we can rely on pg_get_function_arguments to format
- * the argument list.
+ * the argument list. Note, however, that pg_get_function_arguments
+ * does not special-case zero-argument aggregates.
*/
static char *
-format_function_arguments(FuncInfo *finfo, char *funcargs)
+format_function_arguments(FuncInfo *finfo, char *funcargs, bool is_agg)
{
PQExpBufferData fn;
initPQExpBuffer(&fn);
- appendPQExpBuffer(&fn, "%s(%s)", fmtId(finfo->dobj.name), funcargs);
+ appendPQExpBufferStr(&fn, fmtId(finfo->dobj.name));
+ if (is_agg && finfo->nargs == 0)
+ appendPQExpBufferStr(&fn, "(*)");
+ else
+ appendPQExpBuffer(&fn, "(%s)", funcargs);
return fn.data;
}
* Any or all of allargtypes, argmodes, argnames may be NULL.
*/
static char *
-format_function_arguments_old(FuncInfo *finfo, int nallargs,
+format_function_arguments_old(Archive *fout,
+ FuncInfo *finfo, int nallargs,
char **allargtypes,
char **argmodes,
char **argnames)
const char *argname;
typid = allargtypes ? atooid(allargtypes[j]) : finfo->argtypes[j];
- typname = getFormattedTypeName(typid, zeroAsOpaque);
+ typname = getFormattedTypeName(fout, typid, zeroAsOpaque);
if (argmodes)
{
typname);
free(typname);
}
- appendPQExpBuffer(&fn, ")");
+ appendPQExpBufferChar(&fn, ')');
return fn.data;
}
* This is appropriate for use in TOC tags, but not in SQL commands.
*/
static char *
-format_function_signature(FuncInfo *finfo, bool honor_quotes)
+format_function_signature(Archive *fout, FuncInfo *finfo, bool honor_quotes)
{
PQExpBufferData fn;
int j;
{
char *typname;
- typname = getFormattedTypeName(finfo->argtypes[j], zeroAsOpaque);
+ if (j > 0)
+ appendPQExpBufferStr(&fn, ", ");
- appendPQExpBuffer(&fn, "%s%s",
- (j > 0) ? ", " : "",
- typname);
+ typname = getFormattedTypeName(fout, finfo->argtypes[j],
+ zeroAsOpaque);
+ appendPQExpBufferStr(&fn, typname);
free(typname);
}
- appendPQExpBuffer(&fn, ")");
+ appendPQExpBufferChar(&fn, ')');
return fn.data;
}
PQExpBuffer asPart;
PGresult *res;
char *funcsig; /* identity signature */
- char *funcfullsig; /* full signature */
+ char *funcfullsig = NULL; /* full signature */
char *funcsig_tag;
- int ntups;
char *proretset;
char *prosrc;
char *probin;
char *provolatile;
char *proisstrict;
char *prosecdef;
+ char *proleakproof;
char *proconfig;
char *procost;
char *prorows;
asPart = createPQExpBuffer();
/* Set proper schema search path so type references list correctly */
- selectSourceSchema(finfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, finfo->dobj.namespace->dobj.name);
/* Fetch function-specific details */
- if (g_fout->remoteVersion >= 80400)
+ if (fout->remoteVersion >= 90200)
+ {
+ /*
+ * proleakproof was added at v9.2
+ */
+ 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, "
+ "proiswindow, provolatile, proisstrict, prosecdef, "
+ "proleakproof, proconfig, procost, prorows, "
+ "(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 >= 80400)
{
/*
* In 8.4 and up we rely on pg_get_function_arguments and
"pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
"pg_catalog.pg_get_function_result(oid) AS funcresult, "
"proiswindow, provolatile, proisstrict, prosecdef, "
- "proconfig, procost, prorows, "
+ "false AS proleakproof, "
+ " proconfig, procost, prorows, "
"(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 (g_fout->remoteVersion >= 80300)
+ else if (fout->remoteVersion >= 80300)
{
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
"proallargtypes, proargmodes, proargnames, "
"false AS proiswindow, "
"provolatile, proisstrict, prosecdef, "
+ "false AS proleakproof, "
"proconfig, procost, prorows, "
"(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 (g_fout->remoteVersion >= 80100)
+ else if (fout->remoteVersion >= 80100)
{
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
"proallargtypes, proargmodes, proargnames, "
"false AS proiswindow, "
"provolatile, proisstrict, prosecdef, "
+ "false AS proleakproof, "
"null AS proconfig, 0 AS procost, 0 AS prorows, "
"(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 (g_fout->remoteVersion >= 80000)
+ else if (fout->remoteVersion >= 80000)
{
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
"proargnames, "
"false AS proiswindow, "
"provolatile, proisstrict, prosecdef, "
+ "false AS proleakproof, "
"null AS proconfig, 0 AS procost, 0 AS prorows, "
"(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 (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
"null AS proargnames, "
"false AS proiswindow, "
"provolatile, proisstrict, prosecdef, "
+ "false AS proleakproof, "
"null AS proconfig, 0 AS procost, 0 AS prorows, "
"(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 (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
"case when proiscachable then 'i' else 'v' end AS provolatile, "
"proisstrict, "
"false AS prosecdef, "
+ "false AS proleakproof, "
"null AS proconfig, 0 AS procost, 0 AS prorows, "
"(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname "
"FROM pg_proc "
"CASE WHEN proiscachable THEN 'i' ELSE 'v' END AS provolatile, "
"false AS proisstrict, "
"false AS prosecdef, "
+ "false AS proleakproof, "
"NULL AS proconfig, 0 AS procost, 0 AS prorows, "
"(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname "
"FROM pg_proc "
finfo->dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset"));
prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
probin = PQgetvalue(res, 0, PQfnumber(res, "probin"));
- if (g_fout->remoteVersion >= 80400)
+ if (fout->remoteVersion >= 80400)
{
funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs"));
funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs"));
provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
+ proleakproof = PQgetvalue(res, 0, PQfnumber(res, "proleakproof"));
proconfig = PQgetvalue(res, 0, PQfnumber(res, "proconfig"));
procost = PQgetvalue(res, 0, PQfnumber(res, "procost"));
prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
*/
if (probin[0] != '\0' && strcmp(probin, "-") != 0)
{
- appendPQExpBuffer(asPart, "AS ");
+ appendPQExpBufferStr(asPart, "AS ");
appendStringLiteralAH(asPart, probin, fout);
if (strcmp(prosrc, "-") != 0)
{
- appendPQExpBuffer(asPart, ", ");
+ appendPQExpBufferStr(asPart, ", ");
/*
* where we have bin, use dollar quoting if allowed and src
{
if (strcmp(prosrc, "-") != 0)
{
- appendPQExpBuffer(asPart, "AS ");
+ appendPQExpBufferStr(asPart, "AS ");
/* with no bin, dollar quote src unconditionally if allowed */
if (disable_dollar_quoting)
appendStringLiteralAH(asPart, prosrc, fout);
if (funcargs)
{
/* 8.4 or later; we rely on server-side code for most of the work */
- funcfullsig = format_function_arguments(finfo, funcargs);
- funcsig = format_function_arguments(finfo, funciargs);
+ funcfullsig = format_function_arguments(finfo, funcargs, false);
+ funcsig = format_function_arguments(finfo, funciargs, false);
}
else
- {
/* pre-8.4, do it ourselves */
- funcsig = format_function_arguments_old(finfo, nallargs, allargtypes,
+ funcsig = format_function_arguments_old(fout,
+ finfo, nallargs, allargtypes,
argmodes, argnames);
- funcfullsig = funcsig;
- }
- funcsig_tag = format_function_signature(finfo, false);
+ funcsig_tag = format_function_signature(fout, finfo, false);
/*
* DROP must be fully qualified in case same name appears in pg_catalog
fmtId(finfo->dobj.namespace->dobj.name),
funcsig);
- appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcfullsig);
+ appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcfullsig ? funcfullsig :
+ funcsig);
if (funcresult)
appendPQExpBuffer(q, "RETURNS %s", funcresult);
else
{
- rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque);
+ rettypename = getFormattedTypeName(fout, finfo->prorettype,
+ zeroAsOpaque);
appendPQExpBuffer(q, "RETURNS %s%s",
(proretset[0] == 't') ? "SETOF " : "",
rettypename);
appendPQExpBuffer(q, "\n LANGUAGE %s", fmtId(lanname));
if (proiswindow[0] == 't')
- appendPQExpBuffer(q, " WINDOW");
+ appendPQExpBufferStr(q, " WINDOW");
if (provolatile[0] != PROVOLATILE_VOLATILE)
{
if (provolatile[0] == PROVOLATILE_IMMUTABLE)
- appendPQExpBuffer(q, " IMMUTABLE");
+ appendPQExpBufferStr(q, " IMMUTABLE");
else if (provolatile[0] == PROVOLATILE_STABLE)
- appendPQExpBuffer(q, " STABLE");
+ appendPQExpBufferStr(q, " STABLE");
else if (provolatile[0] != PROVOLATILE_VOLATILE)
- {
- write_msg(NULL, "unrecognized provolatile value for function \"%s\"\n",
- finfo->dobj.name);
- exit_nicely();
- }
+ exit_horribly(NULL, "unrecognized provolatile value for function \"%s\"\n",
+ finfo->dobj.name);
}
if (proisstrict[0] == 't')
- appendPQExpBuffer(q, " STRICT");
+ appendPQExpBufferStr(q, " STRICT");
if (prosecdef[0] == 't')
- appendPQExpBuffer(q, " SECURITY DEFINER");
+ appendPQExpBufferStr(q, " SECURITY DEFINER");
+
+ if (proleakproof[0] == 't')
+ appendPQExpBufferStr(q, " LEAKPROOF");
/*
* COST and ROWS are emitted only if present and not default, so as not to
*/
if (pg_strcasecmp(configitem, "DateStyle") == 0
|| pg_strcasecmp(configitem, "search_path") == 0)
- appendPQExpBuffer(q, "%s", pos);
+ appendPQExpBufferStr(q, pos);
else
appendStringLiteralAH(q, pos, fout);
}
finfo->rolname, false,
"FUNCTION", SECTION_PRE_DATA,
q->data, delqry->data, NULL,
- finfo->dobj.dependencies, finfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Function Comments and Security Labels */
destroyPQExpBuffer(labelq);
destroyPQExpBuffer(asPart);
free(funcsig);
+ if (funcfullsig)
+ free(funcfullsig);
free(funcsig_tag);
if (allargtypes)
free(allargtypes);
}
/* Make sure we are in proper schema (needed for getFormattedTypeName) */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
defqry = createPQExpBuffer();
delqry = createPQExpBuffer();
labelq = createPQExpBuffer();
appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n",
- getFormattedTypeName(cast->castsource, zeroAsNone),
- getFormattedTypeName(cast->casttarget, zeroAsNone));
+ getFormattedTypeName(fout, cast->castsource, zeroAsNone),
+ getFormattedTypeName(fout, cast->casttarget, zeroAsNone));
appendPQExpBuffer(defqry, "CREATE CAST (%s AS %s) ",
- getFormattedTypeName(cast->castsource, zeroAsNone),
- getFormattedTypeName(cast->casttarget, zeroAsNone));
+ getFormattedTypeName(fout, cast->castsource, zeroAsNone),
+ getFormattedTypeName(fout, cast->casttarget, zeroAsNone));
switch (cast->castmethod)
{
case COERCION_METHOD_BINARY:
- appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
+ appendPQExpBufferStr(defqry, "WITHOUT FUNCTION");
break;
case COERCION_METHOD_INOUT:
- appendPQExpBuffer(defqry, "WITH INOUT");
+ appendPQExpBufferStr(defqry, "WITH INOUT");
break;
case COERCION_METHOD_FUNCTION:
+ if (funcInfo)
+ {
+ 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).
- */
- appendPQExpBuffer(defqry, "WITH FUNCTION %s.",
- fmtId(funcInfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(defqry, "%s",
- format_function_signature(funcInfo, true));
+ /*
+ * Always qualify the function name, in case it is not in
+ * pg_catalog schema (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");
break;
default:
write_msg(NULL, "WARNING: bogus value in pg_cast.castmethod field\n");
}
if (cast->castcontext == 'a')
- appendPQExpBuffer(defqry, " AS ASSIGNMENT");
+ appendPQExpBufferStr(defqry, " AS ASSIGNMENT");
else if (cast->castcontext == 'i')
- appendPQExpBuffer(defqry, " AS IMPLICIT");
- appendPQExpBuffer(defqry, ";\n");
+ appendPQExpBufferStr(defqry, " AS IMPLICIT");
+ appendPQExpBufferStr(defqry, ";\n");
appendPQExpBuffer(labelq, "CAST (%s AS %s)",
- getFormattedTypeName(cast->castsource, zeroAsNone),
- getFormattedTypeName(cast->casttarget, zeroAsNone));
+ getFormattedTypeName(fout, cast->castsource, zeroAsNone),
+ getFormattedTypeName(fout, cast->casttarget, zeroAsNone));
if (binary_upgrade)
binary_upgrade_extension_member(defqry, &cast->dobj, labelq->data);
"pg_catalog", NULL, "",
false, "CAST", SECTION_PRE_DATA,
defqry->data, delqry->data, NULL,
- cast->dobj.dependencies, cast->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Cast Comments */
PQExpBuffer details;
const char *name;
PGresult *res;
- int ntups;
int i_oprkind;
int i_oprcode;
int i_oprleft;
char *oprjoin;
char *oprcanmerge;
char *oprcanhash;
+ char *oprregproc;
+ char *oprref;
/* Skip if not to be dumped */
if (!oprinfo->dobj.dump || dataOnly)
details = createPQExpBuffer();
/* Make sure we are in proper schema so regoperator works correctly */
- selectSourceSchema(oprinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, oprinfo->dobj.namespace->dobj.name);
- if (g_fout->remoteVersion >= 80300)
+ if (fout->remoteVersion >= 80300)
{
appendPQExpBuffer(query, "SELECT oprkind, "
"oprcode::pg_catalog.regprocedure, "
"WHERE oid = '%u'::pg_catalog.oid",
oprinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query, "SELECT oprkind, "
"oprcode::pg_catalog.regprocedure, "
"WHERE oid = '%u'::pg_catalog.oid",
oprinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query, "SELECT oprkind, oprcode, "
"CASE WHEN oprleft = 0 THEN '-' "
oprinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
i_oprkind = PQfnumber(res, "oprkind");
i_oprcode = PQfnumber(res, "oprcode");
oprcanmerge = PQgetvalue(res, 0, i_oprcanmerge);
oprcanhash = PQgetvalue(res, 0, i_oprcanhash);
- appendPQExpBuffer(details, " PROCEDURE = %s",
- convertRegProcReference(oprcode));
+ oprregproc = convertRegProcReference(fout, oprcode);
+ if (oprregproc)
+ {
+ appendPQExpBuffer(details, " PROCEDURE = %s", oprregproc);
+ free(oprregproc);
+ }
appendPQExpBuffer(oprid, "%s (",
oprinfo->dobj.name);
if (strcmp(oprkind, "r") == 0 ||
strcmp(oprkind, "b") == 0)
{
- if (g_fout->remoteVersion >= 70100)
+ if (fout->remoteVersion >= 70100)
name = oprleft;
else
name = fmtId(oprleft);
appendPQExpBuffer(details, ",\n LEFTARG = %s", name);
- appendPQExpBuffer(oprid, "%s", name);
+ appendPQExpBufferStr(oprid, name);
}
else
- appendPQExpBuffer(oprid, "NONE");
+ appendPQExpBufferStr(oprid, "NONE");
if (strcmp(oprkind, "l") == 0 ||
strcmp(oprkind, "b") == 0)
{
- if (g_fout->remoteVersion >= 70100)
+ if (fout->remoteVersion >= 70100)
name = oprright;
else
name = fmtId(oprright);
appendPQExpBuffer(oprid, ", %s)", name);
}
else
- appendPQExpBuffer(oprid, ", NONE)");
+ appendPQExpBufferStr(oprid, ", NONE)");
- name = convertOperatorReference(oprcom);
- if (name)
- appendPQExpBuffer(details, ",\n COMMUTATOR = %s", name);
+ oprref = convertOperatorReference(fout, oprcom);
+ if (oprref)
+ {
+ appendPQExpBuffer(details, ",\n COMMUTATOR = %s", oprref);
+ free(oprref);
+ }
- name = convertOperatorReference(oprnegate);
- if (name)
- appendPQExpBuffer(details, ",\n NEGATOR = %s", name);
+ oprref = convertOperatorReference(fout, oprnegate);
+ if (oprref)
+ {
+ appendPQExpBuffer(details, ",\n NEGATOR = %s", oprref);
+ free(oprref);
+ }
if (strcmp(oprcanmerge, "t") == 0)
- appendPQExpBuffer(details, ",\n MERGES");
+ appendPQExpBufferStr(details, ",\n MERGES");
if (strcmp(oprcanhash, "t") == 0)
- appendPQExpBuffer(details, ",\n HASHES");
+ appendPQExpBufferStr(details, ",\n HASHES");
- name = convertRegProcReference(oprrest);
- if (name)
- appendPQExpBuffer(details, ",\n RESTRICT = %s", name);
+ oprregproc = convertRegProcReference(fout, oprrest);
+ if (oprregproc)
+ {
+ appendPQExpBuffer(details, ",\n RESTRICT = %s", oprregproc);
+ free(oprregproc);
+ }
- name = convertRegProcReference(oprjoin);
- if (name)
- appendPQExpBuffer(details, ",\n JOIN = %s", name);
+ oprregproc = convertRegProcReference(fout, oprjoin);
+ if (oprregproc)
+ {
+ appendPQExpBuffer(details, ",\n JOIN = %s", oprregproc);
+ free(oprregproc);
+ }
/*
* DROP must be fully qualified in case same name appears in pg_catalog
oprinfo->rolname,
false, "OPERATOR", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- oprinfo->dobj.dependencies, oprinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Operator Comments */
/*
* Convert a function reference obtained from pg_operator
*
- * Returns what to print, or NULL if function references is InvalidOid
+ * Returns allocated string of what to print, or NULL if function references
+ * is InvalidOid. Returned string is expected to be free'd by the caller.
*
* In 7.3 the input is a REGPROCEDURE display; we have to strip the
* argument-types part. In prior versions, the input is a REGPROC display.
*/
-static const char *
-convertRegProcReference(const char *proc)
+static char *
+convertRegProcReference(Archive *fout, const char *proc)
{
/* In all cases "-" means a null reference */
if (strcmp(proc, "-") == 0)
return NULL;
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
char *name;
char *paren;
}
/* REGPROC before 7.3 does not quote its result */
- return fmtId(proc);
+ return pg_strdup(fmtId(proc));
}
/*
* Convert an operator cross-reference obtained from pg_operator
*
- * Returns what to print, or NULL to print nothing
+ * Returns an allocated string of what to print, or NULL to print nothing.
+ * Caller is responsible for free'ing result string.
*
* In 7.3 and up the input is a REGOPERATOR display; we have to strip the
* argument-types part, and add OPERATOR() decoration if the name is
* schema-qualified. In older versions, the input is just a numeric OID,
* which we search our operator list for.
*/
-static const char *
-convertOperatorReference(const char *opr)
+static char *
+convertOperatorReference(Archive *fout, const char *opr)
{
OprInfo *oprInfo;
if (strcmp(opr, "0") == 0)
return NULL;
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
char *name;
char *oname;
/* If not schema-qualified, don't need to add OPERATOR() */
if (!sawdot)
return name;
- oname = pg_malloc(strlen(name) + 11);
- sprintf(oname, "OPERATOR(%s)", name);
+ oname = psprintf("OPERATOR(%s)", name);
free(name);
return oname;
}
opr);
return NULL;
}
- return oprInfo->dobj.name;
+ return pg_strdup(oprInfo->dobj.name);
}
/*
* are search path dependent!
*/
static const char *
-convertTSFunction(Oid funcOid)
+convertTSFunction(Archive *fout, Oid funcOid)
{
char *result;
char query[128];
PGresult *res;
- int ntups;
snprintf(query, sizeof(query),
"SELECT '%u'::pg_catalog.regproc", funcOid);
- res = PQexec(g_conn, query);
- check_sql_result(res, g_conn, query, PGRES_TUPLES_OK);
-
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query);
result = pg_strdup(PQgetvalue(res, 0, 0));
* pre-7.3 databases. This could be done but it seems not worth the
* trouble.
*/
- if (g_fout->remoteVersion < 70300)
+ if (fout->remoteVersion < 70300)
return;
query = createPQExpBuffer();
labelq = createPQExpBuffer();
/* Make sure we are in proper schema so regoperator works correctly */
- selectSourceSchema(opcinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, opcinfo->dobj.namespace->dobj.name);
/* Get additional fields from the pg_opclass row */
- if (g_fout->remoteVersion >= 80300)
+ if (fout->remoteVersion >= 80300)
{
appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
"opckeytype::pg_catalog.regtype, "
opcinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
i_opcintype = PQfnumber(res, "opcintype");
i_opckeytype = PQfnumber(res, "opckeytype");
appendPQExpBuffer(q, "CREATE OPERATOR CLASS %s\n ",
fmtId(opcinfo->dobj.name));
if (strcmp(opcdefault, "t") == 0)
- appendPQExpBuffer(q, "DEFAULT ");
+ appendPQExpBufferStr(q, "DEFAULT ");
appendPQExpBuffer(q, "FOR TYPE %s USING %s",
opcintype,
fmtId(amname));
(strcmp(opcfamilyname, opcinfo->dobj.name) != 0 ||
strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0))
{
- appendPQExpBuffer(q, " FAMILY ");
+ appendPQExpBufferStr(q, " FAMILY ");
if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
appendPQExpBuffer(q, "%s", fmtId(opcfamilyname));
}
- appendPQExpBuffer(q, " AS\n ");
+ appendPQExpBufferStr(q, " AS\n ");
needComma = false;
*/
resetPQExpBuffer(query);
- if (g_fout->remoteVersion >= 90100)
+ if (fout->remoteVersion >= 90100)
{
appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
"amopopr::pg_catalog.regoperator, "
opcinfo->dobj.catId.oid,
opcfamily);
}
- else if (g_fout->remoteVersion >= 80400)
+ else if (fout->remoteVersion >= 80400)
{
appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
"amopopr::pg_catalog.regoperator, "
"ORDER BY amopstrategy",
opcinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 80300)
+ else if (fout->remoteVersion >= 80300)
{
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
"amopopr::pg_catalog.regoperator, "
opcinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
sortfamilynsp = PQgetvalue(res, i, i_sortfamilynsp);
if (needComma)
- appendPQExpBuffer(q, " ,\n ");
+ appendPQExpBufferStr(q, " ,\n ");
appendPQExpBuffer(q, "OPERATOR %s %s",
amopstrategy, amopopr);
if (strlen(sortfamily) > 0)
{
- appendPQExpBuffer(q, " FOR ORDER BY ");
+ appendPQExpBufferStr(q, " FOR ORDER BY ");
if (strcmp(sortfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
- appendPQExpBuffer(q, "%s", fmtId(sortfamily));
+ appendPQExpBufferStr(q, fmtId(sortfamily));
}
if (strcmp(amopreqcheck, "t") == 0)
- appendPQExpBuffer(q, " RECHECK");
+ appendPQExpBufferStr(q, " RECHECK");
needComma = true;
}
*/
resetPQExpBuffer(query);
- if (g_fout->remoteVersion >= 80300)
+ if (fout->remoteVersion >= 80300)
{
appendPQExpBuffer(query, "SELECT amprocnum, "
"amproc::pg_catalog.regprocedure, "
opcinfo->dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
amprocrighttype = PQgetvalue(res, i, i_amprocrighttype);
if (needComma)
- appendPQExpBuffer(q, " ,\n ");
+ appendPQExpBufferStr(q, " ,\n ");
appendPQExpBuffer(q, "FUNCTION %s", amprocnum);
PQclear(res);
- appendPQExpBuffer(q, ";\n");
+ appendPQExpBufferStr(q, ";\n");
appendPQExpBuffer(labelq, "OPERATOR CLASS %s",
fmtId(opcinfo->dobj.name));
opcinfo->rolname,
false, "OPERATOR CLASS", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- opcinfo->dobj.dependencies, opcinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Operator Class Comments */
labelq = createPQExpBuffer();
/* Make sure we are in proper schema so regoperator works correctly */
- selectSourceSchema(opfinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, opfinfo->dobj.namespace->dobj.name);
/*
* Fetch only those opfamily members that are tied directly to the
* older server and then reload into that old version. This can go away
* once 8.3 is so old as to not be of interest to anyone.
*/
- if (g_fout->remoteVersion >= 90100)
+ if (fout->remoteVersion >= 90100)
{
appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
"amopopr::pg_catalog.regoperator, "
opfinfo->dobj.catId.oid,
opfinfo->dobj.catId.oid);
}
- else if (g_fout->remoteVersion >= 80400)
+ else if (fout->remoteVersion >= 80400)
{
appendPQExpBuffer(query, "SELECT amopstrategy, false AS amopreqcheck, "
"amopopr::pg_catalog.regoperator, "
opfinfo->dobj.catId.oid);
}
- res_ops = PQexec(g_conn, query->data);
- check_sql_result(res_ops, g_conn, query->data, PGRES_TUPLES_OK);
+ res_ops = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
resetPQExpBuffer(query);
"ORDER BY amprocnum",
opfinfo->dobj.catId.oid);
- res_procs = PQexec(g_conn, query->data);
- check_sql_result(res_procs, g_conn, query->data, PGRES_TUPLES_OK);
+ res_procs = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
if (PQntuples(res_ops) == 0 && PQntuples(res_procs) == 0)
{
"LIMIT 1",
opfinfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
if (PQntuples(res) == 0)
{
"WHERE oid = '%u'::pg_catalog.oid",
opfinfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
i_amname = PQfnumber(res, "amname");
sortfamilynsp = PQgetvalue(res_ops, i, i_sortfamilynsp);
if (needComma)
- appendPQExpBuffer(q, " ,\n ");
+ appendPQExpBufferStr(q, " ,\n ");
appendPQExpBuffer(q, "OPERATOR %s %s",
amopstrategy, amopopr);
if (strlen(sortfamily) > 0)
{
- appendPQExpBuffer(q, " FOR ORDER BY ");
+ appendPQExpBufferStr(q, " FOR ORDER BY ");
if (strcmp(sortfamilynsp, opfinfo->dobj.namespace->dobj.name) != 0)
appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
- appendPQExpBuffer(q, "%s", fmtId(sortfamily));
+ appendPQExpBufferStr(q, fmtId(sortfamily));
}
if (strcmp(amopreqcheck, "t") == 0)
- appendPQExpBuffer(q, " RECHECK");
+ appendPQExpBufferStr(q, " RECHECK");
needComma = true;
}
amprocrighttype = PQgetvalue(res_procs, i, i_amprocrighttype);
if (needComma)
- appendPQExpBuffer(q, " ,\n ");
+ appendPQExpBufferStr(q, " ,\n ");
appendPQExpBuffer(q, "FUNCTION %s (%s, %s) %s",
amprocnum, amproclefttype, amprocrighttype,
needComma = true;
}
- appendPQExpBuffer(q, ";\n");
+ appendPQExpBufferStr(q, ";\n");
}
appendPQExpBuffer(labelq, "OPERATOR FAMILY %s",
opfinfo->rolname,
false, "OPERATOR FAMILY", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- opfinfo->dobj.dependencies, opfinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Operator Family Comments */
PQExpBuffer delq;
PQExpBuffer labelq;
PGresult *res;
- int ntups;
int i_collcollate;
int i_collctype;
const char *collcollate;
labelq = createPQExpBuffer();
/* Make sure we are in proper schema */
- selectSourceSchema(collinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, collinfo->dobj.namespace->dobj.name);
/* Get conversion-specific details */
appendPQExpBuffer(query, "SELECT "
"WHERE c.oid = '%u'::pg_catalog.oid",
collinfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
i_collcollate = PQfnumber(res, "collcollate");
i_collctype = PQfnumber(res, "collctype");
appendPQExpBuffer(q, "CREATE COLLATION %s (lc_collate = ",
fmtId(collinfo->dobj.name));
appendStringLiteralAH(q, collcollate, fout);
- appendPQExpBuffer(q, ", lc_ctype = ");
+ appendPQExpBufferStr(q, ", lc_ctype = ");
appendStringLiteralAH(q, collctype, fout);
- appendPQExpBuffer(q, ");\n");
+ appendPQExpBufferStr(q, ");\n");
appendPQExpBuffer(labelq, "COLLATION %s", fmtId(collinfo->dobj.name));
collinfo->rolname,
false, "COLLATION", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- collinfo->dobj.dependencies, collinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Collation Comments */
PQExpBuffer delq;
PQExpBuffer labelq;
PGresult *res;
- int ntups;
int i_conforencoding;
int i_contoencoding;
int i_conproc;
labelq = createPQExpBuffer();
/* Make sure we are in proper schema */
- selectSourceSchema(convinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, convinfo->dobj.namespace->dobj.name);
/* Get conversion-specific details */
appendPQExpBuffer(query, "SELECT "
"WHERE c.oid = '%u'::pg_catalog.oid",
convinfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
i_conforencoding = PQfnumber(res, "conforencoding");
i_contoencoding = PQfnumber(res, "contoencoding");
(condefault) ? "DEFAULT " : "",
fmtId(convinfo->dobj.name));
appendStringLiteralAH(q, conforencoding, fout);
- appendPQExpBuffer(q, " TO ");
+ appendPQExpBufferStr(q, " TO ");
appendStringLiteralAH(q, contoencoding, fout);
/* regproc is automatically quoted in 7.3 and above */
appendPQExpBuffer(q, " FROM %s;\n", conproc);
convinfo->rolname,
false, "CONVERSION", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- convinfo->dobj.dependencies, convinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Conversion Comments */
initPQExpBuffer(&buf);
if (honor_quotes)
- appendPQExpBuffer(&buf, "%s",
- fmtId(agginfo->aggfn.dobj.name));
+ appendPQExpBufferStr(&buf, fmtId(agginfo->aggfn.dobj.name));
else
- appendPQExpBuffer(&buf, "%s", agginfo->aggfn.dobj.name);
+ appendPQExpBufferStr(&buf, agginfo->aggfn.dobj.name);
if (agginfo->aggfn.nargs == 0)
appendPQExpBuffer(&buf, "(*)");
else
{
- appendPQExpBuffer(&buf, "(");
+ appendPQExpBufferChar(&buf, '(');
for (j = 0; j < agginfo->aggfn.nargs; j++)
{
char *typname;
- typname = getFormattedTypeName(agginfo->aggfn.argtypes[j], zeroAsOpaque);
+ typname = getFormattedTypeName(fout, agginfo->aggfn.argtypes[j],
+ zeroAsOpaque);
appendPQExpBuffer(&buf, "%s%s",
(j > 0) ? ", " : "",
typname);
free(typname);
}
- appendPQExpBuffer(&buf, ")");
+ appendPQExpBufferChar(&buf, ')');
}
return buf.data;
}
PQExpBuffer delq;
PQExpBuffer labelq;
PQExpBuffer details;
- char *aggsig;
+ char *aggsig; /* identity signature */
+ char *aggfullsig = NULL; /* full signature */
char *aggsig_tag;
PGresult *res;
- int ntups;
int i_aggtransfn;
int i_aggfinalfn;
+ int i_aggmtransfn;
+ int i_aggminvtransfn;
+ int i_aggmfinalfn;
+ int i_aggfinalextra;
+ int i_aggmfinalextra;
int i_aggsortop;
+ int i_hypothetical;
int i_aggtranstype;
+ int i_aggtransspace;
+ int i_aggmtranstype;
+ int i_aggmtransspace;
int i_agginitval;
+ int i_aggminitval;
int i_convertok;
const char *aggtransfn;
const char *aggfinalfn;
+ const char *aggmtransfn;
+ const char *aggminvtransfn;
+ const char *aggmfinalfn;
+ bool aggfinalextra;
+ bool aggmfinalextra;
const char *aggsortop;
+ char *aggsortconvop;
+ bool hypothetical;
const char *aggtranstype;
+ const char *aggtransspace;
+ const char *aggmtranstype;
+ const char *aggmtransspace;
const char *agginitval;
+ const char *aggminitval;
bool convertok;
/* Skip if not to be dumped */
details = createPQExpBuffer();
/* Make sure we are in proper schema */
- selectSourceSchema(agginfo->aggfn.dobj.namespace->dobj.name);
+ selectSourceSchema(fout, agginfo->aggfn.dobj.namespace->dobj.name);
/* Get aggregate-specific details */
- if (g_fout->remoteVersion >= 80100)
+ if (fout->remoteVersion >= 90400)
+ {
+ appendPQExpBuffer(query, "SELECT aggtransfn, "
+ "aggfinalfn, aggtranstype::pg_catalog.regtype, "
+ "aggmtransfn, aggminvtransfn, aggmfinalfn, "
+ "aggmtranstype::pg_catalog.regtype, "
+ "aggfinalextra, aggmfinalextra, "
+ "aggsortop::pg_catalog.regoperator, "
+ "(aggkind = 'h') AS hypothetical, "
+ "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 "
+ "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 >= 80400)
{
appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, "
+ "'-' AS aggmtransfn, '-' AS aggminvtransfn, "
+ "'-' AS aggmfinalfn, 0 AS aggmtranstype, "
+ "false AS aggfinalextra, false AS aggmfinalextra, "
"aggsortop::pg_catalog.regoperator, "
- "agginitval, "
- "'t'::boolean AS convertok "
+ "false AS hypothetical, "
+ "0 AS aggtransspace, agginitval, "
+ "0 AS aggmtransspace, NULL AS 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 "
"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 (g_fout->remoteVersion >= 70300)
+ else if (fout->remoteVersion >= 80100)
+ {
+ appendPQExpBuffer(query, "SELECT aggtransfn, "
+ "aggfinalfn, aggtranstype::pg_catalog.regtype, "
+ "'-' AS aggmtransfn, '-' AS aggminvtransfn, "
+ "'-' AS aggmfinalfn, 0 AS aggmtranstype, "
+ "false AS aggfinalextra, false AS aggmfinalextra, "
+ "aggsortop::pg_catalog.regoperator, "
+ "false AS hypothetical, "
+ "0 AS aggtransspace, agginitval, "
+ "0 AS aggmtransspace, NULL AS aggminitval, "
+ "true AS convertok "
+ "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 >= 70300)
{
appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, "
+ "'-' AS aggmtransfn, '-' AS aggminvtransfn, "
+ "'-' AS aggmfinalfn, 0 AS aggmtranstype, "
+ "false AS aggfinalextra, false AS aggmfinalextra, "
"0 AS aggsortop, "
- "agginitval, "
- "'t'::boolean AS convertok "
+ "false AS hypothetical, "
+ "0 AS aggtransspace, agginitval, "
+ "0 AS aggmtransspace, NULL AS aggminitval, "
+ "true AS convertok "
"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 (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
"format_type(aggtranstype, NULL) AS aggtranstype, "
+ "'-' AS aggmtransfn, '-' AS aggminvtransfn, "
+ "'-' AS aggmfinalfn, 0 AS aggmtranstype, "
+ "false AS aggfinalextra, false AS aggmfinalextra, "
"0 AS aggsortop, "
- "agginitval, "
- "'t'::boolean AS convertok "
+ "false AS hypothetical, "
+ "0 AS aggtransspace, agginitval, "
+ "0 AS aggmtransspace, NULL AS aggminitval, "
+ "true AS convertok "
"FROM pg_aggregate "
"WHERE oid = '%u'::oid",
agginfo->aggfn.dobj.catId.oid);
appendPQExpBuffer(query, "SELECT aggtransfn1 AS aggtransfn, "
"aggfinalfn, "
"(SELECT typname FROM pg_type WHERE oid = aggtranstype1) AS aggtranstype, "
+ "'-' AS aggmtransfn, '-' AS aggminvtransfn, "
+ "'-' AS aggmfinalfn, 0 AS aggmtranstype, "
+ "false AS aggfinalextra, false AS aggmfinalextra, "
"0 AS aggsortop, "
- "agginitval1 AS agginitval, "
+ "false AS hypothetical, "
+ "0 AS aggtransspace, agginitval1 AS agginitval, "
+ "0 AS aggmtransspace, NULL AS aggminitval, "
"(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) AS convertok "
"FROM pg_aggregate "
"WHERE oid = '%u'::oid",
agginfo->aggfn.dobj.catId.oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- /* Expecting a single result only */
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
i_aggtransfn = PQfnumber(res, "aggtransfn");
i_aggfinalfn = PQfnumber(res, "aggfinalfn");
+ i_aggmtransfn = PQfnumber(res, "aggmtransfn");
+ i_aggminvtransfn = PQfnumber(res, "aggminvtransfn");
+ i_aggmfinalfn = PQfnumber(res, "aggmfinalfn");
+ i_aggfinalextra = PQfnumber(res, "aggfinalextra");
+ i_aggmfinalextra = PQfnumber(res, "aggmfinalextra");
i_aggsortop = PQfnumber(res, "aggsortop");
+ i_hypothetical = PQfnumber(res, "hypothetical");
i_aggtranstype = PQfnumber(res, "aggtranstype");
+ i_aggtransspace = PQfnumber(res, "aggtransspace");
+ i_aggmtranstype = PQfnumber(res, "aggmtranstype");
+ i_aggmtransspace = PQfnumber(res, "aggmtransspace");
i_agginitval = PQfnumber(res, "agginitval");
+ i_aggminitval = PQfnumber(res, "aggminitval");
i_convertok = PQfnumber(res, "convertok");
aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
+ aggmtransfn = PQgetvalue(res, 0, i_aggmtransfn);
+ aggminvtransfn = PQgetvalue(res, 0, i_aggminvtransfn);
+ aggmfinalfn = PQgetvalue(res, 0, i_aggmfinalfn);
+ aggfinalextra = (PQgetvalue(res, 0, i_aggfinalextra)[0] == 't');
+ aggmfinalextra = (PQgetvalue(res, 0, i_aggmfinalextra)[0] == 't');
aggsortop = PQgetvalue(res, 0, i_aggsortop);
+ hypothetical = (PQgetvalue(res, 0, i_hypothetical)[0] == 't');
aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
+ aggtransspace = PQgetvalue(res, 0, i_aggtransspace);
+ aggmtranstype = PQgetvalue(res, 0, i_aggmtranstype);
+ aggmtransspace = PQgetvalue(res, 0, i_aggmtransspace);
agginitval = PQgetvalue(res, 0, i_agginitval);
+ aggminitval = PQgetvalue(res, 0, i_aggminitval);
convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
- aggsig = format_aggregate_signature(agginfo, fout, true);
+ if (fout->remoteVersion >= 80400)
+ {
+ /* 8.4 or later; we rely on server-side code for most of the work */
+ char *funcargs;
+ char *funciargs;
+
+ funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs"));
+ funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs"));
+ aggfullsig = format_function_arguments(&agginfo->aggfn, funcargs, true);
+ aggsig = format_function_arguments(&agginfo->aggfn, funciargs, true);
+ }
+ else
+ /* pre-8.4, do it ourselves */
+ aggsig = format_aggregate_signature(agginfo, fout, true);
+
aggsig_tag = format_aggregate_signature(agginfo, fout, false);
if (!convertok)
{
write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
aggsig);
+
+ if (aggfullsig)
+ free(aggfullsig);
+
+ free(aggsig);
+
return;
}
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
/* If using 7.3's regproc or regtype, data is already quoted */
appendPQExpBuffer(details, " SFUNC = %s,\n STYPE = %s",
aggtransfn,
aggtranstype);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
/* format_type quotes, regproc does not */
appendPQExpBuffer(details, " SFUNC = %s,\n STYPE = %s",
fmtId(aggtranstype));
}
+ if (strcmp(aggtransspace, "0") != 0)
+ {
+ appendPQExpBuffer(details, ",\n SSPACE = %s",
+ aggtransspace);
+ }
+
if (!PQgetisnull(res, 0, i_agginitval))
{
- appendPQExpBuffer(details, ",\n INITCOND = ");
+ appendPQExpBufferStr(details, ",\n INITCOND = ");
appendStringLiteralAH(details, agginitval, fout);
}
{
appendPQExpBuffer(details, ",\n FINALFUNC = %s",
aggfinalfn);
+ if (aggfinalextra)
+ appendPQExpBufferStr(details, ",\n FINALFUNC_EXTRA");
+ }
+
+ if (strcmp(aggmtransfn, "-") != 0)
+ {
+ appendPQExpBuffer(details, ",\n MSFUNC = %s,\n MINVFUNC = %s,\n MSTYPE = %s",
+ aggmtransfn,
+ aggminvtransfn,
+ aggmtranstype);
+ }
+
+ if (strcmp(aggmtransspace, "0") != 0)
+ {
+ appendPQExpBuffer(details, ",\n MSSPACE = %s",
+ aggmtransspace);
+ }
+
+ if (!PQgetisnull(res, 0, i_aggminitval))
+ {
+ appendPQExpBufferStr(details, ",\n MINITCOND = ");
+ appendStringLiteralAH(details, aggminitval, fout);
+ }
+
+ if (strcmp(aggmfinalfn, "-") != 0)
+ {
+ appendPQExpBuffer(details, ",\n MFINALFUNC = %s",
+ aggmfinalfn);
+ if (aggmfinalextra)
+ appendPQExpBufferStr(details, ",\n MFINALFUNC_EXTRA");
}
- aggsortop = convertOperatorReference(aggsortop);
- if (aggsortop)
+ aggsortconvop = convertOperatorReference(fout, aggsortop);
+ if (aggsortconvop)
{
appendPQExpBuffer(details, ",\n SORTOP = %s",
- aggsortop);
+ aggsortconvop);
+ free(aggsortconvop);
}
+ if (hypothetical)
+ appendPQExpBufferStr(details, ",\n HYPOTHETICAL");
+
/*
* DROP must be fully qualified in case same name appears in pg_catalog
*/
aggsig);
appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n",
- aggsig, details->data);
+ aggfullsig ? aggfullsig : aggsig, details->data);
appendPQExpBuffer(labelq, "AGGREGATE %s", aggsig);
agginfo->aggfn.rolname,
false, "AGGREGATE", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- agginfo->aggfn.dobj.dependencies, agginfo->aggfn.dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Aggregate Comments */
/*
* Since there is no GRANT ON AGGREGATE syntax, we have to make the ACL
* command look like a function's GRANT; in particular this affects the
- * syntax for zero-argument aggregates.
+ * syntax for zero-argument aggregates and ordered-set aggregates.
*/
free(aggsig);
free(aggsig_tag);
- aggsig = format_function_signature(&agginfo->aggfn, true);
- aggsig_tag = format_function_signature(&agginfo->aggfn, false);
+ aggsig = format_function_signature(fout, &agginfo->aggfn, true);
+ aggsig_tag = format_function_signature(fout, &agginfo->aggfn, false);
dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
"FUNCTION",
agginfo->aggfn.rolname, agginfo->aggfn.proacl);
free(aggsig);
+ if (aggfullsig)
+ free(aggfullsig);
free(aggsig_tag);
PQclear(res);
labelq = createPQExpBuffer();
/* Make sure we are in proper schema */
- selectSourceSchema(prsinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, prsinfo->dobj.namespace->dobj.name);
appendPQExpBuffer(q, "CREATE TEXT SEARCH PARSER %s (\n",
fmtId(prsinfo->dobj.name));
appendPQExpBuffer(q, " START = %s,\n",
- convertTSFunction(prsinfo->prsstart));
+ convertTSFunction(fout, prsinfo->prsstart));
appendPQExpBuffer(q, " GETTOKEN = %s,\n",
- convertTSFunction(prsinfo->prstoken));
+ convertTSFunction(fout, prsinfo->prstoken));
appendPQExpBuffer(q, " END = %s,\n",
- convertTSFunction(prsinfo->prsend));
+ convertTSFunction(fout, prsinfo->prsend));
if (prsinfo->prsheadline != InvalidOid)
appendPQExpBuffer(q, " HEADLINE = %s,\n",
- convertTSFunction(prsinfo->prsheadline));
+ convertTSFunction(fout, prsinfo->prsheadline));
appendPQExpBuffer(q, " LEXTYPES = %s );\n",
- convertTSFunction(prsinfo->prslextype));
+ convertTSFunction(fout, prsinfo->prslextype));
/*
* DROP must be fully qualified in case same name appears in pg_catalog
"",
false, "TEXT SEARCH PARSER", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- prsinfo->dobj.dependencies, prsinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Parser Comments */
PQExpBuffer labelq;
PQExpBuffer query;
PGresult *res;
- int ntups;
char *nspname;
char *tmplname;
query = createPQExpBuffer();
/* Fetch name and namespace of the dictionary's template */
- selectSourceSchema("pg_catalog");
+ 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",
dictinfo->dicttemplate);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
nspname = PQgetvalue(res, 0, 0);
tmplname = PQgetvalue(res, 0, 1);
/* Make sure we are in proper schema */
- selectSourceSchema(dictinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, dictinfo->dobj.namespace->dobj.name);
appendPQExpBuffer(q, "CREATE TEXT SEARCH DICTIONARY %s (\n",
fmtId(dictinfo->dobj.name));
- appendPQExpBuffer(q, " TEMPLATE = ");
+ appendPQExpBufferStr(q, " TEMPLATE = ");
if (strcmp(nspname, dictinfo->dobj.namespace->dobj.name) != 0)
appendPQExpBuffer(q, "%s.", fmtId(nspname));
- appendPQExpBuffer(q, "%s", fmtId(tmplname));
+ appendPQExpBufferStr(q, fmtId(tmplname));
PQclear(res);
if (dictinfo->dictinitoption)
appendPQExpBuffer(q, ",\n %s", dictinfo->dictinitoption);
- appendPQExpBuffer(q, " );\n");
+ appendPQExpBufferStr(q, " );\n");
/*
* DROP must be fully qualified in case same name appears in pg_catalog
dictinfo->rolname,
false, "TEXT SEARCH DICTIONARY", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- dictinfo->dobj.dependencies, dictinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Dictionary Comments */
labelq = createPQExpBuffer();
/* Make sure we are in proper schema */
- selectSourceSchema(tmplinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tmplinfo->dobj.namespace->dobj.name);
appendPQExpBuffer(q, "CREATE TEXT SEARCH TEMPLATE %s (\n",
fmtId(tmplinfo->dobj.name));
if (tmplinfo->tmplinit != InvalidOid)
appendPQExpBuffer(q, " INIT = %s,\n",
- convertTSFunction(tmplinfo->tmplinit));
+ convertTSFunction(fout, tmplinfo->tmplinit));
appendPQExpBuffer(q, " LEXIZE = %s );\n",
- convertTSFunction(tmplinfo->tmpllexize));
+ convertTSFunction(fout, tmplinfo->tmpllexize));
/*
* DROP must be fully qualified in case same name appears in pg_catalog
"",
false, "TEXT SEARCH TEMPLATE", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- tmplinfo->dobj.dependencies, tmplinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Template Comments */
query = createPQExpBuffer();
/* Fetch name and namespace of the config's parser */
- selectSourceSchema("pg_catalog");
+ 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",
cfginfo->cfgparser);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
nspname = PQgetvalue(res, 0, 0);
prsname = PQgetvalue(res, 0, 1);
/* Make sure we are in proper schema */
- selectSourceSchema(cfginfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, cfginfo->dobj.namespace->dobj.name);
appendPQExpBuffer(q, "CREATE TEXT SEARCH CONFIGURATION %s (\n",
fmtId(cfginfo->dobj.name));
- appendPQExpBuffer(q, " PARSER = ");
+ appendPQExpBufferStr(q, " PARSER = ");
if (strcmp(nspname, cfginfo->dobj.namespace->dobj.name) != 0)
appendPQExpBuffer(q, "%s.", fmtId(nspname));
appendPQExpBuffer(q, "%s );\n", fmtId(prsname));
"ORDER BY m.mapcfg, m.maptokentype, m.mapseqno",
cfginfo->cfgparser, cfginfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
i_tokenname = PQfnumber(res, "tokenname");
{
/* starting a new token type, so start a new command */
if (i > 0)
- appendPQExpBuffer(q, ";\n");
+ appendPQExpBufferStr(q, ";\n");
appendPQExpBuffer(q, "\nALTER TEXT SEARCH CONFIGURATION %s\n",
fmtId(cfginfo->dobj.name));
/* tokenname needs quoting, dictname does NOT */
}
if (ntups > 0)
- appendPQExpBuffer(q, ";\n");
+ appendPQExpBufferStr(q, ";\n");
PQclear(res);
cfginfo->rolname,
false, "TEXT SEARCH CONFIGURATION", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- cfginfo->dobj.dependencies, cfginfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump Configuration Comments */
if (strlen(fdwinfo->fdwoptions) > 0)
appendPQExpBuffer(q, " OPTIONS (\n %s\n)", fdwinfo->fdwoptions);
- appendPQExpBuffer(q, ";\n");
+ appendPQExpBufferStr(q, ";\n");
appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n",
qfdwname);
fdwinfo->rolname,
false, "FOREIGN DATA WRAPPER", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- fdwinfo->dobj.dependencies, fdwinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Handle the ACL */
PQExpBuffer labelq;
PQExpBuffer query;
PGresult *res;
- int ntups;
char *qsrvname;
char *fdwname;
qsrvname = pg_strdup(fmtId(srvinfo->dobj.name));
/* look up the foreign-data wrapper */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query, "SELECT fdwname "
"FROM pg_foreign_data_wrapper w "
"WHERE w.oid = '%u'",
srvinfo->srvfdw);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
fdwname = PQgetvalue(res, 0, 0);
appendPQExpBuffer(q, "CREATE SERVER %s", qsrvname);
if (srvinfo->srvtype && strlen(srvinfo->srvtype) > 0)
{
- appendPQExpBuffer(q, " TYPE ");
+ appendPQExpBufferStr(q, " TYPE ");
appendStringLiteralAH(q, srvinfo->srvtype, fout);
}
if (srvinfo->srvversion && strlen(srvinfo->srvversion) > 0)
{
- appendPQExpBuffer(q, " VERSION ");
+ appendPQExpBufferStr(q, " VERSION ");
appendStringLiteralAH(q, srvinfo->srvversion, fout);
}
- appendPQExpBuffer(q, " FOREIGN DATA WRAPPER ");
- appendPQExpBuffer(q, "%s", fmtId(fdwname));
+ appendPQExpBufferStr(q, " FOREIGN DATA WRAPPER ");
+ appendPQExpBufferStr(q, fmtId(fdwname));
if (srvinfo->srvoptions && strlen(srvinfo->srvoptions) > 0)
appendPQExpBuffer(q, " OPTIONS (\n %s\n)", srvinfo->srvoptions);
- appendPQExpBuffer(q, ";\n");
+ appendPQExpBufferStr(q, ";\n");
appendPQExpBuffer(delq, "DROP SERVER %s;\n",
qsrvname);
srvinfo->rolname,
false, "SERVER", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- srvinfo->dobj.dependencies, srvinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Handle the ACL */
* OPTIONS clause. A possible alternative is to skip such mappings
* altogether, but it's not clear that that's an improvement.
*/
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
appendPQExpBuffer(query,
"SELECT usename, "
"array_to_string(ARRAY("
"SELECT quote_ident(option_name) || ' ' || "
"quote_literal(option_value) "
- "FROM pg_options_to_table(umoptions)"
+ "FROM pg_options_to_table(umoptions) "
+ "ORDER BY option_name"
"), E',\n ') AS umoptions "
"FROM pg_user_mappings "
"WHERE srvid = '%u' "
"ORDER BY usename",
catalogId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
i_usename = PQfnumber(res, "usename");
if (umoptions && strlen(umoptions) > 0)
appendPQExpBuffer(q, " OPTIONS (\n %s\n)", umoptions);
- appendPQExpBuffer(q, ";\n");
+ appendPQExpBufferStr(q, ";\n");
resetPQExpBuffer(delq);
appendPQExpBuffer(delq, "DROP USER MAPPING FOR %s", fmtId(usename));
destroyPQExpBuffer(query);
destroyPQExpBuffer(delq);
+ destroyPQExpBuffer(tag);
destroyPQExpBuffer(q);
}
case DEFACLOBJ_FUNCTION:
type = "FUNCTIONS";
break;
+ case DEFACLOBJ_TYPE:
+ type = "TYPES";
+ break;
default:
/* shouldn't get here */
- write_msg(NULL, "unknown object type (%d) in default privileges\n",
- (int) daclinfo->defaclobjtype);
- exit_nicely();
+ exit_horribly(NULL,
+ "unrecognized object type in default privileges: %d\n",
+ (int) daclinfo->defaclobjtype);
type = ""; /* keep compiler quiet */
}
daclinfo->defaclrole,
fout->remoteVersion,
q))
- {
- write_msg(NULL, "could not parse default ACL list (%s)\n",
- daclinfo->defaclacl);
- exit_nicely();
- }
+ exit_horribly(NULL, "could not parse default ACL list (%s)\n",
+ daclinfo->defaclacl);
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_NONE,
+ false, "DEFAULT ACL", SECTION_POST_DATA,
q->data, "", NULL,
- daclinfo->dobj.dependencies, daclinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
destroyPQExpBuffer(tag);
if (!buildACLCommands(name, subname, type, acls, owner,
"", fout->remoteVersion, sql))
- {
- write_msg(NULL, "could not parse ACL list (%s) for object \"%s\" (%s)\n",
- acls, name, type);
- exit_nicely();
- }
+ exit_horribly(NULL,
+ "could not parse ACL list (%s) for object \"%s\" (%s)\n",
+ acls, name, type);
if (sql->len > 0)
ArchiveEntry(fout, nilCatalogId, createDumpId(),
"SECURITY LABEL FOR %s ON %s IS ",
fmtId(labels[i].provider), target);
appendStringLiteralAH(query, labels[i].label, fout);
- appendPQExpBuffer(query, ";\n");
+ appendPQExpBufferStr(query, ";\n");
}
if (query->len > 0)
appendPQExpBuffer(query, "SECURITY LABEL FOR %s ON %s IS ",
fmtId(provider), target->data);
appendStringLiteralAH(query, label, fout);
- appendPQExpBuffer(query, ";\n");
+ appendPQExpBufferStr(query, ";\n");
}
if (query->len > 0)
{
query = createPQExpBuffer();
- appendPQExpBuffer(query,
- "SELECT label, provider, classoid, objoid, objsubid "
- "FROM pg_catalog.pg_seclabel "
- "ORDER BY classoid, objoid, objsubid");
+ appendPQExpBufferStr(query,
+ "SELECT label, provider, classoid, objoid, objsubid "
+ "FROM pg_catalog.pg_seclabel "
+ "ORDER BY classoid, objoid, objsubid");
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
/* Construct lookup table containing OIDs in numeric form */
i_label = PQfnumber(res, "label");
static void
dumpTable(Archive *fout, TableInfo *tbinfo)
{
- if (tbinfo->dobj.dump)
+ if (tbinfo->dobj.dump && !dataOnly)
{
char *namecopy;
if (tbinfo->relkind == RELKIND_SEQUENCE)
dumpSequence(fout, tbinfo);
- else if (!dataOnly)
+ else
dumpTableSchema(fout, tbinfo);
/* Handle the ACL here */
* query rather than trying to fetch them during getTableAttrs, so
* that we won't miss ACLs on system columns.
*/
- if (g_fout->remoteVersion >= 80400)
+ if (fout->remoteVersion >= 80400)
{
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
"WHERE attrelid = '%u' AND NOT attisdropped AND attacl IS NOT NULL "
"ORDER BY attnum",
tbinfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
for (i = 0; i < PQntuples(res); i++)
{
char *acltag;
attnamecopy = pg_strdup(fmtId(attname));
- acltag = pg_malloc(strlen(tbinfo->dobj.name) + strlen(attname) + 2);
- sprintf(acltag, "%s.%s", tbinfo->dobj.name, 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,
}
}
+/*
+ * Create the AS clause for a view or materialized view. The semicolon is
+ * stripped because a materialized view must add a WITH NO DATA clause.
+ *
+ * This returns a new buffer which must be freed by the caller.
+ */
+static PQExpBuffer
+createViewAsClause(Archive *fout, TableInfo *tbinfo)
+{
+ PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer result = createPQExpBuffer();
+ PGresult *res;
+ int len;
+
+ /* Fetch the view definition */
+ if (fout->remoteVersion >= 70300)
+ {
+ /* Beginning in 7.3, viewname is not unique; rely on OID */
+ appendPQExpBuffer(query,
+ "SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) AS viewdef",
+ tbinfo->dobj.catId.oid);
+ }
+ else
+ {
+ appendPQExpBufferStr(query, "SELECT definition AS viewdef "
+ "FROM pg_views WHERE viewname = ");
+ appendStringLiteralAH(query, tbinfo->dobj.name, fout);
+ }
+
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+ 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);
+ else
+ exit_horribly(NULL, "query to obtain definition of view \"%s\" returned more than one definition\n",
+ 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);
+
+ /* Strip off the trailing semicolon so that other things may follow. */
+ Assert(PQgetvalue(res, 0, 0)[len - 1] == ';');
+ appendBinaryPQExpBuffer(result, PQgetvalue(res, 0, 0), len - 1);
+
+ PQclear(res);
+ destroyPQExpBuffer(query);
+
+ return result;
+}
+
/*
* dumpTableSchema
* write the declaration (not data) of one user-defined table or view
static void
dumpTableSchema(Archive *fout, TableInfo *tbinfo)
{
- PQExpBuffer query = createPQExpBuffer();
PQExpBuffer q = createPQExpBuffer();
PQExpBuffer delq = createPQExpBuffer();
PQExpBuffer labelq = createPQExpBuffer();
- PGresult *res;
int numParents;
TableInfo **parents;
- int actual_atts; /* number of attrs in this CREATE statment */
+ int actual_atts; /* number of attrs in this CREATE statement */
const char *reltypename;
char *storage;
char *srvname;
k;
/* Make sure we are in proper schema */
- selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
if (binary_upgrade)
- binary_upgrade_set_type_oids_by_rel_oid(q,
+ binary_upgrade_set_type_oids_by_rel_oid(fout, q,
tbinfo->dobj.catId.oid);
/* Is it a table or a view? */
if (tbinfo->relkind == RELKIND_VIEW)
{
- char *viewdef;
+ PQExpBuffer result;
reltypename = "VIEW";
- /* Fetch the view definition */
- if (g_fout->remoteVersion >= 70300)
- {
- /* Beginning in 7.3, viewname is not unique; rely on OID */
- appendPQExpBuffer(query,
- "SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) AS viewdef",
- tbinfo->dobj.catId.oid);
- }
- else
- {
- appendPQExpBuffer(query, "SELECT definition AS viewdef "
- "FROM pg_views WHERE viewname = ");
- appendStringLiteralAH(query, tbinfo->dobj.name, fout);
- appendPQExpBuffer(query, ";");
- }
-
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- if (PQntuples(res) != 1)
- {
- if (PQntuples(res) < 1)
- write_msg(NULL, "query to obtain definition of view \"%s\" returned no data\n",
- tbinfo->dobj.name);
- else
- write_msg(NULL, "query to obtain definition of view \"%s\" returned more than one definition\n",
- tbinfo->dobj.name);
- exit_nicely();
- }
-
- viewdef = PQgetvalue(res, 0, 0);
-
- if (strlen(viewdef) == 0)
- {
- write_msg(NULL, "definition of view \"%s\" appears to be empty (length zero)\n",
- tbinfo->dobj.name);
- exit_nicely();
- }
-
/*
* DROP must be fully qualified in case same name appears in
* pg_catalog
fmtId(tbinfo->dobj.name));
if (binary_upgrade)
- binary_upgrade_set_pg_class_oids(q, tbinfo->dobj.catId.oid, false);
+ binary_upgrade_set_pg_class_oids(fout, q,
+ tbinfo->dobj.catId.oid, false);
appendPQExpBuffer(q, "CREATE VIEW %s", fmtId(tbinfo->dobj.name));
if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
appendPQExpBuffer(q, " WITH (%s)", tbinfo->reloptions);
- appendPQExpBuffer(q, " AS\n %s\n", viewdef);
+ result = createViewAsClause(fout, tbinfo);
+ appendPQExpBuffer(q, " AS\n%s", result->data);
+ destroyPQExpBuffer(result);
+
+ if (tbinfo->checkoption != NULL)
+ appendPQExpBuffer(q, "\n WITH %s CHECK OPTION", tbinfo->checkoption);
+ appendPQExpBufferStr(q, ";\n");
appendPQExpBuffer(labelq, "VIEW %s",
fmtId(tbinfo->dobj.name));
-
- PQclear(res);
}
else
{
- if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
- {
- int i_srvname;
- int i_ftoptions;
-
- reltypename = "FOREIGN TABLE";
-
- /* retrieve name of foreign server and generic options */
- appendPQExpBuffer(query,
- "SELECT fs.srvname, "
- "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(ftoptions)"
- "), E',\n ') AS ftoptions "
- "FROM pg_catalog.pg_foreign_table ft "
- "JOIN pg_catalog.pg_foreign_server fs "
- "ON (fs.oid = ft.ftserver) "
- "WHERE ft.ftrelid = '%u'",
- tbinfo->dobj.catId.oid);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
- if (PQntuples(res) != 1)
- {
- write_msg(NULL, ngettext("query returned %d foreign server entry for foreign table \"%s\"\n",
- "query returned %d foreign server entries for foreign table \"%s\"\n",
- PQntuples(res)),
- PQntuples(res), tbinfo->dobj.name);
- exit_nicely();
- }
- i_srvname = PQfnumber(res, "srvname");
- i_ftoptions = PQfnumber(res, "ftoptions");
- srvname = pg_strdup(PQgetvalue(res, 0, i_srvname));
- ftoptions = pg_strdup(PQgetvalue(res, 0, i_ftoptions));
- PQclear(res);
- }
- else
+ switch (tbinfo->relkind)
{
- reltypename = "TABLE";
- srvname = NULL;
- ftoptions = NULL;
+ case (RELKIND_FOREIGN_TABLE):
+ {
+ PQExpBuffer query = createPQExpBuffer();
+ PGresult *res;
+ int i_srvname;
+ int i_ftoptions;
+
+ reltypename = "FOREIGN TABLE";
+
+ /* retrieve name of foreign server and generic options */
+ appendPQExpBuffer(query,
+ "SELECT fs.srvname, "
+ "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(ftoptions) "
+ "ORDER BY option_name"
+ "), E',\n ') AS ftoptions "
+ "FROM pg_catalog.pg_foreign_table ft "
+ "JOIN pg_catalog.pg_foreign_server fs "
+ "ON (fs.oid = ft.ftserver) "
+ "WHERE ft.ftrelid = '%u'",
+ tbinfo->dobj.catId.oid);
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
+ i_srvname = PQfnumber(res, "srvname");
+ i_ftoptions = PQfnumber(res, "ftoptions");
+ srvname = pg_strdup(PQgetvalue(res, 0, i_srvname));
+ ftoptions = pg_strdup(PQgetvalue(res, 0, i_ftoptions));
+ PQclear(res);
+ destroyPQExpBuffer(query);
+ break;
+ }
+ case (RELKIND_MATVIEW):
+ reltypename = "MATERIALIZED VIEW";
+ srvname = NULL;
+ ftoptions = NULL;
+ break;
+ default:
+ reltypename = "TABLE";
+ srvname = NULL;
+ ftoptions = NULL;
}
+
numParents = tbinfo->numParents;
parents = tbinfo->parents;
fmtId(tbinfo->dobj.name));
if (binary_upgrade)
- binary_upgrade_set_pg_class_oids(q, tbinfo->dobj.catId.oid, false);
+ binary_upgrade_set_pg_class_oids(fout, q,
+ tbinfo->dobj.catId.oid, false);
appendPQExpBuffer(q, "CREATE %s%s %s",
tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ?
fmtId(tbinfo->dobj.name));
/*
- * In case of a binary upgrade, we dump the table normally and attach
- * it to the type afterward.
+ * Attach to type, if reloftype; except in case of a binary upgrade,
+ * we dump the table normally and attach it to the type afterward.
*/
if (tbinfo->reloftype && !binary_upgrade)
appendPQExpBuffer(q, " OF %s", tbinfo->reloftype);
- actual_atts = 0;
- for (j = 0; j < tbinfo->numatts; j++)
+
+ if (tbinfo->relkind != RELKIND_MATVIEW)
{
- /*
- * Normally, dump if it's one of the table's own attrs, and not
- * dropped. But for binary upgrade, dump all the columns.
- */
- if ((!tbinfo->inhAttrs[j] && !tbinfo->attisdropped[j]) ||
- binary_upgrade)
+ /* Dump the attributes */
+ actual_atts = 0;
+ for (j = 0; j < tbinfo->numatts; j++)
{
/*
- * Default value --- suppress if inherited (except in
- * binary-upgrade case, where we're not doing normal
- * inheritance) or if it's to be printed separately.
- */
- bool has_default = (tbinfo->attrdefs[j] != NULL
- && (!tbinfo->inhAttrDef[j] || binary_upgrade)
- && !tbinfo->attrdefs[j]->separate);
-
- /*
- * Not Null constraint --- suppress if inherited, except in
- * binary-upgrade case.
+ * Normally, dump if it's locally defined in this table, and
+ * not dropped. But for binary upgrade, we'll dump all the
+ * columns, and then fix up the dropped and nonlocal cases
+ * below.
*/
- bool has_notnull = (tbinfo->notnull[j]
- && (!tbinfo->inhNotNull[j] || binary_upgrade));
-
- if (tbinfo->reloftype && !has_default && !has_notnull && !binary_upgrade)
- continue;
-
- /* Format properly if not first attr */
- if (actual_atts == 0)
- appendPQExpBuffer(q, " (");
- else
- appendPQExpBuffer(q, ",");
- appendPQExpBuffer(q, "\n ");
- actual_atts++;
-
- /* Attribute name */
- appendPQExpBuffer(q, "%s ",
- fmtId(tbinfo->attnames[j]));
-
- if (tbinfo->attisdropped[j])
+ if (shouldPrintColumn(tbinfo, j))
{
/*
- * ALTER TABLE DROP COLUMN clears pg_attribute.atttypid,
- * so we will not have gotten a valid type name; insert
- * INTEGER as a stopgap. We'll clean things up later.
+ * Default value --- suppress if to be printed separately.
*/
- appendPQExpBuffer(q, "INTEGER /* dummy */");
- /* Skip all the rest, too */
- continue;
- }
+ bool has_default = (tbinfo->attrdefs[j] != NULL &&
+ !tbinfo->attrdefs[j]->separate);
- /* Attribute type */
- if (tbinfo->reloftype && !binary_upgrade)
- {
- appendPQExpBuffer(q, "WITH OPTIONS");
- }
- else if (g_fout->remoteVersion >= 70100)
- {
- appendPQExpBuffer(q, "%s",
- tbinfo->atttypnames[j]);
- }
- else
- {
- /* If no format_type, fake it */
- appendPQExpBuffer(q, "%s",
- myFormatType(tbinfo->atttypnames[j],
- tbinfo->atttypmod[j]));
- }
+ /*
+ * Not Null constraint --- suppress if inherited, except
+ * in binary-upgrade case where that won't work.
+ */
+ bool has_notnull = (tbinfo->notnull[j] &&
+ (!tbinfo->inhNotNull[j] ||
+ binary_upgrade));
+
+ /* Skip column if fully defined by reloftype */
+ if (tbinfo->reloftype &&
+ !has_default && !has_notnull && !binary_upgrade)
+ continue;
+
+ /* Format properly if not first attr */
+ if (actual_atts == 0)
+ appendPQExpBufferStr(q, " (");
+ else
+ appendPQExpBufferStr(q, ",");
+ appendPQExpBufferStr(q, "\n ");
+ actual_atts++;
- /* Add collation if not default for the type */
- if (OidIsValid(tbinfo->attcollation[j]))
- {
- CollInfo *coll;
+ /* Attribute name */
+ appendPQExpBufferStr(q, fmtId(tbinfo->attnames[j]));
+
+ if (tbinfo->attisdropped[j])
+ {
+ /*
+ * ALTER TABLE DROP COLUMN clears
+ * pg_attribute.atttypid, so we will not have gotten a
+ * valid type name; insert INTEGER as a stopgap. We'll
+ * clean things up later.
+ */
+ appendPQExpBufferStr(q, " INTEGER /* dummy */");
+ /* Skip all the rest, too */
+ continue;
+ }
+
+ /* Attribute type */
+ if (tbinfo->reloftype && !binary_upgrade)
+ {
+ appendPQExpBufferStr(q, " WITH OPTIONS");
+ }
+ else if (fout->remoteVersion >= 70100)
+ {
+ appendPQExpBuffer(q, " %s",
+ tbinfo->atttypnames[j]);
+ }
+ else
+ {
+ /* If no format_type, fake it */
+ appendPQExpBuffer(q, " %s",
+ myFormatType(tbinfo->atttypnames[j],
+ tbinfo->atttypmod[j]));
+ }
- coll = findCollationByOid(tbinfo->attcollation[j]);
- if (coll)
+ /* Add collation if not default for the type */
+ if (OidIsValid(tbinfo->attcollation[j]))
{
- /* always schema-qualify, don't try to be smart */
- appendPQExpBuffer(q, " COLLATE %s.",
+ CollInfo *coll;
+
+ 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));
- appendPQExpBuffer(q, "%s",
- fmtId(coll->dobj.name));
+ appendPQExpBufferStr(q, fmtId(coll->dobj.name));
+ }
}
- }
- if (has_default)
- appendPQExpBuffer(q, " DEFAULT %s",
- tbinfo->attrdefs[j]->adef_expr);
+ if (has_default)
+ appendPQExpBuffer(q, " DEFAULT %s",
+ tbinfo->attrdefs[j]->adef_expr);
- if (has_notnull)
- appendPQExpBuffer(q, " NOT NULL");
+ if (has_notnull)
+ appendPQExpBufferStr(q, " NOT NULL");
+ }
}
- }
- /*
- * Add non-inherited CHECK constraints, if any.
- */
- for (j = 0; j < tbinfo->ncheck; j++)
- {
- ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
+ /*
+ * Add non-inherited CHECK constraints, if any.
+ */
+ for (j = 0; j < tbinfo->ncheck; j++)
+ {
+ ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
- if (constr->separate || !constr->conislocal)
- continue;
+ if (constr->separate || !constr->conislocal)
+ continue;
- if (actual_atts == 0)
- appendPQExpBuffer(q, " (\n ");
- else
- appendPQExpBuffer(q, ",\n ");
+ if (actual_atts == 0)
+ appendPQExpBufferStr(q, " (\n ");
+ else
+ appendPQExpBufferStr(q, ",\n ");
- appendPQExpBuffer(q, "CONSTRAINT %s ",
- fmtId(constr->dobj.name));
- appendPQExpBuffer(q, "%s", constr->condef);
+ appendPQExpBuffer(q, "CONSTRAINT %s ",
+ fmtId(constr->dobj.name));
+ appendPQExpBufferStr(q, constr->condef);
- actual_atts++;
- }
+ actual_atts++;
+ }
- if (actual_atts)
- appendPQExpBuffer(q, "\n)");
- else if (!(tbinfo->reloftype && !binary_upgrade))
- {
- /*
- * We must have a parenthesized attribute list, even though empty,
- * when not using the OF TYPE syntax.
- */
- appendPQExpBuffer(q, " (\n)");
- }
+ if (actual_atts)
+ appendPQExpBufferStr(q, "\n)");
+ else if (!(tbinfo->reloftype && !binary_upgrade))
+ {
+ /*
+ * We must have a parenthesized attribute list, even though
+ * empty, when not using the OF TYPE syntax.
+ */
+ appendPQExpBufferStr(q, " (\n)");
+ }
- if (numParents > 0 && !binary_upgrade)
- {
- appendPQExpBuffer(q, "\nINHERITS (");
- for (k = 0; k < numParents; k++)
+ if (numParents > 0 && !binary_upgrade)
{
- TableInfo *parentRel = parents[k];
+ appendPQExpBufferStr(q, "\nINHERITS (");
+ for (k = 0; k < numParents; k++)
+ {
+ TableInfo *parentRel = parents[k];
- if (k > 0)
- appendPQExpBuffer(q, ", ");
- if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
- appendPQExpBuffer(q, "%s.",
+ if (k > 0)
+ appendPQExpBufferStr(q, ", ");
+ if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
+ appendPQExpBuffer(q, "%s.",
fmtId(parentRel->dobj.namespace->dobj.name));
- appendPQExpBuffer(q, "%s",
- fmtId(parentRel->dobj.name));
+ appendPQExpBufferStr(q, fmtId(parentRel->dobj.name));
+ }
+ appendPQExpBufferChar(q, ')');
}
- appendPQExpBuffer(q, ")");
- }
- if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
- appendPQExpBuffer(q, "\nSERVER %s", fmtId(srvname));
+ if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
+ appendPQExpBuffer(q, "\nSERVER %s", fmtId(srvname));
+ }
if ((tbinfo->reloptions && strlen(tbinfo->reloptions) > 0) ||
(tbinfo->toast_reloptions && strlen(tbinfo->toast_reloptions) > 0))
{
bool addcomma = false;
- appendPQExpBuffer(q, "\nWITH (");
+ appendPQExpBufferStr(q, "\nWITH (");
if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
{
addcomma = true;
- appendPQExpBuffer(q, "%s", tbinfo->reloptions);
+ appendPQExpBufferStr(q, tbinfo->reloptions);
}
if (tbinfo->toast_reloptions && strlen(tbinfo->toast_reloptions) > 0)
{
appendPQExpBuffer(q, "%s%s", addcomma ? ", " : "",
tbinfo->toast_reloptions);
}
- appendPQExpBuffer(q, ")");
+ appendPQExpBufferChar(q, ')');
}
/* Dump generic options if any */
if (ftoptions && ftoptions[0])
appendPQExpBuffer(q, "\nOPTIONS (\n %s\n)", ftoptions);
- appendPQExpBuffer(q, ";\n");
+ /*
+ * For materialized views, create the AS clause just like a view. At
+ * this point, we always mark the view as not populated.
+ */
+ if (tbinfo->relkind == RELKIND_MATVIEW)
+ {
+ PQExpBuffer result;
+
+ result = createViewAsClause(fout, tbinfo);
+ appendPQExpBuffer(q, " AS\n%s\n WITH NO DATA;\n",
+ result->data);
+ destroyPQExpBuffer(result);
+ }
+ else
+ appendPQExpBufferStr(q, ";\n");
/*
* To create binary-compatible heap files, we have to ensure the same
* attislocal correctly, plus fix up any inherited CHECK constraints.
* Analogously, we set up typed tables using ALTER TABLE / OF here.
*/
- if (binary_upgrade && tbinfo->relkind == RELKIND_RELATION)
+ if (binary_upgrade && (tbinfo->relkind == RELKIND_RELATION ||
+ tbinfo->relkind == RELKIND_FOREIGN_TABLE) )
{
for (j = 0; j < tbinfo->numatts; j++)
{
if (tbinfo->attisdropped[j])
{
- appendPQExpBuffer(q, "\n-- For binary upgrade, recreate dropped column.\n");
+ appendPQExpBufferStr(q, "\n-- For binary upgrade, recreate dropped column.\n");
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_attribute\n"
"SET attlen = %d, "
"attalign = '%c', attbyval = false\n"
tbinfo->attlen[j],
tbinfo->attalign[j]);
appendStringLiteralAH(q, tbinfo->attnames[j], fout);
- appendPQExpBuffer(q, "\n AND attrelid = ");
+ appendPQExpBufferStr(q, "\n AND attrelid = ");
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
- appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
+ appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
+
+ if (tbinfo->relkind == RELKIND_RELATION)
+ appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
+ fmtId(tbinfo->dobj.name));
+ else
+ appendPQExpBuffer(q, "ALTER FOREIGN TABLE %s ",
+ fmtId(tbinfo->dobj.name));
- appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
- fmtId(tbinfo->dobj.name));
appendPQExpBuffer(q, "DROP COLUMN %s;\n",
fmtId(tbinfo->attnames[j]));
}
else if (!tbinfo->attislocal[j])
{
- appendPQExpBuffer(q, "\n-- For binary upgrade, recreate inherited column.\n");
- appendPQExpBuffer(q, "UPDATE pg_catalog.pg_attribute\n"
+ Assert(tbinfo->relkind != RELKIND_FOREIGN_TABLE);
+ appendPQExpBufferStr(q, "\n-- For binary upgrade, recreate inherited column.\n");
+ appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_attribute\n"
"SET attislocal = false\n"
"WHERE attname = ");
appendStringLiteralAH(q, tbinfo->attnames[j], fout);
- appendPQExpBuffer(q, "\n AND attrelid = ");
+ appendPQExpBufferStr(q, "\n AND attrelid = ");
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
- appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
+ appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
}
}
if (constr->separate || constr->conislocal)
continue;
- appendPQExpBuffer(q, "\n-- For binary upgrade, set up inherited constraint.\n");
+ appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inherited constraint.\n");
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
fmtId(tbinfo->dobj.name));
appendPQExpBuffer(q, " ADD CONSTRAINT %s ",
fmtId(constr->dobj.name));
appendPQExpBuffer(q, "%s;\n", constr->condef);
- appendPQExpBuffer(q, "UPDATE pg_catalog.pg_constraint\n"
+ appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_constraint\n"
"SET conislocal = false\n"
"WHERE contype = 'c' AND conname = ");
appendStringLiteralAH(q, constr->dobj.name, fout);
- appendPQExpBuffer(q, "\n AND conrelid = ");
+ appendPQExpBufferStr(q, "\n AND conrelid = ");
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
- appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
+ appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
}
if (numParents > 0)
{
- appendPQExpBuffer(q, "\n-- For binary upgrade, set up inheritance 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];
if (tbinfo->reloftype)
{
- appendPQExpBuffer(q, "\n-- For binary upgrade, set up typed tables this way.\n");
+ 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),
tbinfo->reloftype);
}
- appendPQExpBuffer(q, "\n-- For binary upgrade, set heap's relfrozenxid\n");
+ appendPQExpBufferStr(q, "\n-- For binary upgrade, set heap's relfrozenxid\n");
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
"SET relfrozenxid = '%u'\n"
"WHERE oid = ",
tbinfo->frozenxid);
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
- appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
+ appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
if (tbinfo->toast_oid)
{
/* We preserve the toast oids, so we can use it during restore */
- appendPQExpBuffer(q, "\n-- For binary upgrade, set toast's relfrozenxid\n");
+ appendPQExpBufferStr(q, "\n-- For binary upgrade, set toast's relfrozenxid\n");
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
"SET relfrozenxid = '%u'\n"
"WHERE oid = '%u';\n",
}
}
- /* Loop dumping statistics and storage statements */
+ /*
+ * 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.
+ */
+ if (binary_upgrade && tbinfo->relkind == RELKIND_MATVIEW &&
+ tbinfo->relispopulated)
+ {
+ appendPQExpBufferStr(q, "\n-- For binary upgrade, mark materialized view as populated\n");
+ appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_class\n"
+ "SET relispopulated = 't'\n"
+ "WHERE oid = ");
+ appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+ appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
+ }
+
+ /*
+ * Dump additional per-column properties that we can't handle in the
+ * main CREATE TABLE command.
+ */
for (j = 0; j < tbinfo->numatts; j++)
{
+ /* None of this applies to dropped columns */
+ if (tbinfo->attisdropped[j])
+ continue;
+
+ /*
+ * If we didn't dump the column definition explicitly above, and
+ * it is NOT NULL and did not inherit that property from a parent,
+ * we have to mark it separately.
+ */
+ if (!shouldPrintColumn(tbinfo, j) &&
+ tbinfo->notnull[j] && !tbinfo->inhNotNull[j])
+ {
+ appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
+ fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(q, "ALTER COLUMN %s SET NOT NULL;\n",
+ fmtId(tbinfo->attnames[j]));
+ }
+
/*
* Dump per-column statistics information. We only issue an ALTER
* TABLE statement if the attstattarget entry for this column is
* non-negative (i.e. it's not the default value)
*/
- if (tbinfo->attstattarget[j] >= 0 &&
- !tbinfo->attisdropped[j])
+ if (tbinfo->attstattarget[j] >= 0)
{
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
fmtId(tbinfo->dobj.name));
* Dump per-column storage information. The statement is only
* dumped if the storage has been changed from the type's default.
*/
- if (!tbinfo->attisdropped[j] && tbinfo->attstorage[j] != tbinfo->typstorage[j])
+ if (tbinfo->attstorage[j] != tbinfo->typstorage[j])
{
switch (tbinfo->attstorage[j])
{
}
}
+ /*
+ * dump properties we only have ALTER TABLE syntax for
+ */
+ if ((tbinfo->relkind == RELKIND_RELATION || tbinfo->relkind == RELKIND_MATVIEW) &&
+ tbinfo->relreplident != REPLICA_IDENTITY_DEFAULT)
+ {
+ if (tbinfo->relreplident == REPLICA_IDENTITY_INDEX)
+ {
+ /* nothing to do, will be set when the index is dumped */
+ }
+ else if (tbinfo->relreplident == REPLICA_IDENTITY_NOTHING)
+ {
+ appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY NOTHING;\n",
+ fmtId(tbinfo->dobj.name));
+ }
+ else if (tbinfo->relreplident == REPLICA_IDENTITY_FULL)
+ {
+ appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY FULL;\n",
+ fmtId(tbinfo->dobj.name));
+ }
+ }
+
if (binary_upgrade)
binary_upgrade_extension_member(q, &tbinfo->dobj, labelq->data);
(tbinfo->relkind == RELKIND_VIEW) ? NULL : tbinfo->reltablespace,
tbinfo->rolname,
(strcmp(reltypename, "TABLE") == 0) ? tbinfo->hasoids : false,
- reltypename, SECTION_PRE_DATA,
+ reltypename,
+ tbinfo->postponed_def ? SECTION_POST_DATA : SECTION_PRE_DATA,
q->data, delq->data, NULL,
- tbinfo->dobj.dependencies, tbinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
dumpTableConstraintComment(fout, constr);
}
- destroyPQExpBuffer(query);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
destroyPQExpBuffer(labelq);
PQExpBuffer q;
PQExpBuffer delq;
- /* Only print it if "separate" mode is selected */
- if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly)
+ /* Skip if table definition not to be dumped */
+ if (!tbinfo->dobj.dump || dataOnly)
return;
- /* Don't print inherited defaults, either, except for binary upgrade */
- if (tbinfo->inhAttrDef[adnum - 1] && !binary_upgrade)
+ /* Skip if not "separate"; it was dumped in the table's definition */
+ if (!adinfo->separate)
return;
q = createPQExpBuffer();
delq = createPQExpBuffer();
- appendPQExpBuffer(q, "ALTER TABLE %s ",
+ appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
fmtId(tbinfo->dobj.name));
appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
fmtId(tbinfo->attnames[adnum - 1]),
tbinfo->rolname,
false, "DEFAULT", SECTION_PRE_DATA,
q->data, delq->data, NULL,
- adinfo->dobj.dependencies, adinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
destroyPQExpBuffer(q);
case TableOidAttributeNumber:
return "tableoid";
}
- write_msg(NULL, "invalid column number %d for table \"%s\"\n",
- attrnum, tblInfo->dobj.name);
- exit_nicely();
+ exit_horribly(NULL, "invalid column number %d for table \"%s\"\n",
+ attrnum, tblInfo->dobj.name);
return NULL; /* keep compiler quiet */
}
dumpIndex(Archive *fout, IndxInfo *indxinfo)
{
TableInfo *tbinfo = indxinfo->indextable;
+ bool is_constraint = (indxinfo->indexconstraint != 0);
PQExpBuffer q;
PQExpBuffer delq;
PQExpBuffer labelq;
/*
* If there's an associated constraint, don't dump the index per se, but
* do dump any comment for it. (This is safe because dependency ordering
- * will have ensured the constraint is emitted first.)
+ * will have ensured the constraint is emitted first.) Note that the
+ * emitted comment has to be shown as depending on the constraint, not
+ * the index, in such cases.
*/
- if (indxinfo->indexconstraint == 0)
+ if (!is_constraint)
{
if (binary_upgrade)
- binary_upgrade_set_pg_class_oids(q, indxinfo->dobj.catId.oid, true);
+ binary_upgrade_set_pg_class_oids(fout, q,
+ indxinfo->dobj.catId.oid, true);
/* Plain secondary index */
appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef);
fmtId(indxinfo->dobj.name));
}
+ /* 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));
+ appendPQExpBuffer(q, " INDEX %s;\n",
+ fmtId(indxinfo->dobj.name));
+ }
+
/*
* DROP must be fully qualified in case same name appears in
* pg_catalog
tbinfo->rolname, false,
"INDEX", SECTION_POST_DATA,
q->data, delq->data, NULL,
- indxinfo->dobj.dependencies, indxinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
}
dumpComment(fout, labelq->data,
tbinfo->dobj.namespace->dobj.name,
tbinfo->rolname,
- indxinfo->dobj.catId, 0, indxinfo->dobj.dumpId);
+ indxinfo->dobj.catId, 0,
+ is_constraint ? indxinfo->indexconstraint :
+ indxinfo->dobj.dumpId);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
indxinfo = (IndxInfo *) findObjectByDumpId(coninfo->conindex);
if (indxinfo == NULL)
- {
- write_msg(NULL, "missing index for constraint \"%s\"\n",
- coninfo->dobj.name);
- exit_nicely();
- }
+ exit_horribly(NULL, "missing index for constraint \"%s\"\n",
+ coninfo->dobj.name);
if (binary_upgrade)
- binary_upgrade_set_pg_class_oids(q, indxinfo->dobj.catId.oid, true);
+ binary_upgrade_set_pg_class_oids(fout, q,
+ indxinfo->dobj.catId.oid, true);
appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
fmtId(tbinfo->dobj.name));
fmtId(attname));
}
- appendPQExpBuffer(q, ")");
+ appendPQExpBufferChar(q, ')');
if (indxinfo->options && strlen(indxinfo->options) > 0)
appendPQExpBuffer(q, " WITH (%s)", indxinfo->options);
if (coninfo->condeferrable)
{
- appendPQExpBuffer(q, " DEFERRABLE");
+ appendPQExpBufferStr(q, " DEFERRABLE");
if (coninfo->condeferred)
- appendPQExpBuffer(q, " INITIALLY DEFERRED");
+ appendPQExpBufferStr(q, " INITIALLY DEFERRED");
}
- appendPQExpBuffer(q, ";\n");
+ appendPQExpBufferStr(q, ";\n");
}
/* If the index is clustered, we need to record that. */
tbinfo->rolname, false,
"CONSTRAINT", SECTION_POST_DATA,
q->data, delq->data, NULL,
- coninfo->dobj.dependencies, coninfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
}
else if (coninfo->contype == 'f')
tbinfo->rolname, false,
"FK CONSTRAINT", SECTION_POST_DATA,
q->data, delq->data, NULL,
- coninfo->dobj.dependencies, coninfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
}
else if (coninfo->contype == 'c' && tbinfo)
/* Ignore if not to be dumped separately */
if (coninfo->separate)
{
- /* add ONLY if we do not want it to propagate to children */
- appendPQExpBuffer(q, "ALTER TABLE %s %s\n",
- coninfo->conisonly ? "ONLY" : "", fmtId(tbinfo->dobj.name));
+ /* not ONLY since we want it to propagate to children */
+ appendPQExpBuffer(q, "ALTER TABLE %s\n",
+ fmtId(tbinfo->dobj.name));
appendPQExpBuffer(q, " ADD CONSTRAINT %s %s;\n",
fmtId(coninfo->dobj.name),
coninfo->condef);
tbinfo->rolname, false,
"CHECK CONSTRAINT", SECTION_POST_DATA,
q->data, delq->data, NULL,
- coninfo->dobj.dependencies, coninfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
}
}
tyinfo->rolname, false,
"CHECK CONSTRAINT", SECTION_POST_DATA,
q->data, delq->data, NULL,
- coninfo->dobj.dependencies, coninfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
}
}
else
{
- write_msg(NULL, "unrecognized constraint type: %c\n", coninfo->contype);
- exit_nicely();
+ exit_horribly(NULL, "unrecognized constraint type: %c\n",
+ coninfo->contype);
}
/* Dump Constraint Comments --- only works for table constraints */
* pg_database entry for the current database
*/
static Oid
-findLastBuiltinOid_V71(const char *dbname)
+findLastBuiltinOid_V71(Archive *fout, const char *dbname)
{
PGresult *res;
- int ntups;
Oid last_oid;
PQExpBuffer query = createPQExpBuffer();
resetPQExpBuffer(query);
- appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = ");
- appendStringLiteralAH(query, dbname, g_fout);
+ appendPQExpBufferStr(query, "SELECT datlastsysoid from pg_database where datname = ");
+ appendStringLiteralAH(query, dbname, fout);
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
- ntups = PQntuples(res);
- if (ntups < 1)
- {
- write_msg(NULL, "missing pg_database entry for this database\n");
- exit_nicely();
- }
- if (ntups > 1)
- {
- write_msg(NULL, "found more than one pg_database entry for this database\n");
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "datlastsysoid")));
PQclear(res);
destroyPQExpBuffer(query);
* initdb won't be changing anymore, it'll do.
*/
static Oid
-findLastBuiltinOid_V70(void)
+findLastBuiltinOid_V70(Archive *fout)
{
PGresult *res;
- int ntups;
int last_oid;
- res = PQexec(g_conn,
- "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'");
- check_sql_result(res, g_conn,
- "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'",
- PGRES_TUPLES_OK);
- ntups = PQntuples(res);
- if (ntups < 1)
- {
- write_msg(NULL, "could not find entry for pg_indexes in pg_class\n");
- exit_nicely();
- }
- if (ntups > 1)
- {
- write_msg(NULL, "found more than one entry for pg_indexes in pg_class\n");
- exit_nicely();
- }
+ res = ExecuteSqlQueryForSingleRow(fout,
+ "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'");
last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "oid")));
PQclear(res);
return last_oid;
}
+/*
+ * dumpSequence
+ * write the declaration (not data) of one user-defined sequence
+ */
static void
dumpSequence(Archive *fout, TableInfo *tbinfo)
{
PGresult *res;
char *startv,
- *last,
*incby,
*maxv = NULL,
*minv = NULL,
*cache;
char bufm[100],
bufx[100];
- bool cycled,
- called;
+ bool cycled;
PQExpBuffer query = createPQExpBuffer();
PQExpBuffer delqry = createPQExpBuffer();
PQExpBuffer labelq = createPQExpBuffer();
/* Make sure we are in proper schema */
- selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
snprintf(bufm, sizeof(bufm), INT64_FORMAT, SEQ_MINVALUE);
snprintf(bufx, sizeof(bufx), INT64_FORMAT, SEQ_MAXVALUE);
- if (g_fout->remoteVersion >= 80400)
+ if (fout->remoteVersion >= 80400)
{
appendPQExpBuffer(query,
"SELECT sequence_name, "
- "start_value, last_value, increment_by, "
+ "start_value, increment_by, "
"CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
" WHEN increment_by < 0 AND max_value = -1 THEN NULL "
" ELSE max_value "
" WHEN increment_by < 0 AND min_value = %s THEN NULL "
" ELSE min_value "
"END AS min_value, "
- "cache_value, is_cycled, is_called from %s",
+ "cache_value, is_cycled FROM %s",
bufx, bufm,
fmtId(tbinfo->dobj.name));
}
{
appendPQExpBuffer(query,
"SELECT sequence_name, "
- "0 AS start_value, last_value, increment_by, "
+ "0 AS start_value, increment_by, "
"CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
" WHEN increment_by < 0 AND max_value = -1 THEN NULL "
" ELSE max_value "
" WHEN increment_by < 0 AND min_value = %s THEN NULL "
" ELSE min_value "
"END AS min_value, "
- "cache_value, is_cycled, is_called from %s",
+ "cache_value, is_cycled FROM %s",
bufx, bufm,
fmtId(tbinfo->dobj.name));
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
if (PQntuples(res) != 1)
{
"query to get data of sequence \"%s\" returned %d rows (expected 1)\n",
PQntuples(res)),
tbinfo->dobj.name, PQntuples(res));
- exit_nicely();
+ exit_nicely(1);
}
/* Disable this check: it fails if sequence has been renamed */
{
write_msg(NULL, "query to get data of sequence \"%s\" returned name \"%s\"\n",
tbinfo->dobj.name, PQgetvalue(res, 0, 0));
- exit_nicely();
+ exit_nicely(1);
}
#endif
startv = PQgetvalue(res, 0, 1);
- last = PQgetvalue(res, 0, 2);
- incby = PQgetvalue(res, 0, 3);
+ incby = PQgetvalue(res, 0, 2);
+ if (!PQgetisnull(res, 0, 3))
+ maxv = PQgetvalue(res, 0, 3);
if (!PQgetisnull(res, 0, 4))
- maxv = PQgetvalue(res, 0, 4);
- if (!PQgetisnull(res, 0, 5))
- minv = PQgetvalue(res, 0, 5);
- cache = PQgetvalue(res, 0, 6);
- cycled = (strcmp(PQgetvalue(res, 0, 7), "t") == 0);
- called = (strcmp(PQgetvalue(res, 0, 8), "t") == 0);
+ minv = PQgetvalue(res, 0, 4);
+ cache = PQgetvalue(res, 0, 5);
+ cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0);
/*
- * The logic we use for restoring sequences is as follows:
- *
- * Add a CREATE SEQUENCE statement as part of a "schema" dump (use
- * last_val for start if called is false, else use min_val for start_val).
- * Also, if the sequence is owned by a column, add an ALTER SEQUENCE OWNED
- * BY command for it.
- *
- * Add a 'SETVAL(seq, last_val, iscalled)' as part of a "data" dump.
+ * DROP must be fully qualified in case same name appears in pg_catalog
*/
- if (!dataOnly)
- {
- /*
- * DROP must be fully qualified in case same name appears in
- * pg_catalog
- */
- appendPQExpBuffer(delqry, "DROP SEQUENCE %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(delqry, "%s;\n",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(delqry, "DROP SEQUENCE %s.",
+ fmtId(tbinfo->dobj.namespace->dobj.name));
+ appendPQExpBuffer(delqry, "%s;\n",
+ fmtId(tbinfo->dobj.name));
- resetPQExpBuffer(query);
+ resetPQExpBuffer(query);
- if (binary_upgrade)
- {
- binary_upgrade_set_pg_class_oids(query, tbinfo->dobj.catId.oid, false);
- binary_upgrade_set_type_oids_by_rel_oid(query, tbinfo->dobj.catId.oid);
- }
+ if (binary_upgrade)
+ {
+ binary_upgrade_set_pg_class_oids(fout, query,
+ tbinfo->dobj.catId.oid, false);
+ binary_upgrade_set_type_oids_by_rel_oid(fout, query,
+ tbinfo->dobj.catId.oid);
+ }
- appendPQExpBuffer(query,
- "CREATE SEQUENCE %s\n",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(query,
+ "CREATE SEQUENCE %s\n",
+ fmtId(tbinfo->dobj.name));
- if (g_fout->remoteVersion >= 80400)
- appendPQExpBuffer(query, " START WITH %s\n", startv);
- else
- {
- /*
- * Versions before 8.4 did not remember the true start value. If
- * is_called is false then the sequence has never been incremented
- * so we can use last_val. Otherwise punt and let it default.
- */
- if (!called)
- appendPQExpBuffer(query, " START WITH %s\n", last);
- }
+ if (fout->remoteVersion >= 80400)
+ appendPQExpBuffer(query, " START WITH %s\n", startv);
- appendPQExpBuffer(query, " INCREMENT BY %s\n", incby);
+ appendPQExpBuffer(query, " INCREMENT BY %s\n", incby);
- if (minv)
- appendPQExpBuffer(query, " MINVALUE %s\n", minv);
- else
- appendPQExpBuffer(query, " NO MINVALUE\n");
+ if (minv)
+ appendPQExpBuffer(query, " MINVALUE %s\n", minv);
+ else
+ appendPQExpBufferStr(query, " NO MINVALUE\n");
- if (maxv)
- appendPQExpBuffer(query, " MAXVALUE %s\n", maxv);
- else
- appendPQExpBuffer(query, " NO MAXVALUE\n");
+ if (maxv)
+ appendPQExpBuffer(query, " MAXVALUE %s\n", maxv);
+ else
+ appendPQExpBufferStr(query, " NO MAXVALUE\n");
- appendPQExpBuffer(query,
- " CACHE %s%s",
- cache, (cycled ? "\n CYCLE" : ""));
+ appendPQExpBuffer(query,
+ " CACHE %s%s",
+ cache, (cycled ? "\n CYCLE" : ""));
- appendPQExpBuffer(query, ";\n");
+ appendPQExpBufferStr(query, ";\n");
- appendPQExpBuffer(labelq, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(labelq, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
- /* binary_upgrade: no need to clear TOAST table oid */
+ /* binary_upgrade: no need to clear TOAST table oid */
- if (binary_upgrade)
- binary_upgrade_extension_member(query, &tbinfo->dobj,
- labelq->data);
+ if (binary_upgrade)
+ binary_upgrade_extension_member(query, &tbinfo->dobj,
+ labelq->data);
- 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,
- tbinfo->dobj.dependencies, tbinfo->dobj.nDeps,
- NULL, NULL);
+ 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);
- /*
- * If the sequence is owned by a table column, emit the ALTER for it
- * as a separate TOC entry immediately following the sequence's own
- * entry. It's OK to do this rather than using full sorting logic,
- * because the dependency that tells us it's owned will have forced
- * the table to be created first. We can't just include the ALTER in
- * the TOC entry because it will fail if we haven't reassigned the
- * sequence owner to match the table's owner.
- *
- * We need not schema-qualify the table reference because both
- * sequence and table must be in the same schema.
- */
- if (OidIsValid(tbinfo->owning_tab))
- {
- TableInfo *owning_tab = findTableByOid(tbinfo->owning_tab);
+ /*
+ * If the sequence is owned by a table column, emit the ALTER for it as a
+ * separate TOC entry immediately following the sequence's own entry. It's
+ * OK to do this rather than using full sorting logic, because the
+ * dependency that tells us it's owned will have forced the table to be
+ * created first. We can't just include the ALTER in the TOC entry
+ * because it will fail if we haven't reassigned the sequence owner to
+ * match the table's owner.
+ *
+ * We need not schema-qualify the table reference because both sequence
+ * and table must be in the same schema.
+ */
+ if (OidIsValid(tbinfo->owning_tab))
+ {
+ TableInfo *owning_tab = findTableByOid(tbinfo->owning_tab);
- if (owning_tab && owning_tab->dobj.dump)
- {
- resetPQExpBuffer(query);
- appendPQExpBuffer(query, "ALTER SEQUENCE %s",
- fmtId(tbinfo->dobj.name));
- appendPQExpBuffer(query, " OWNED BY %s",
- fmtId(owning_tab->dobj.name));
- appendPQExpBuffer(query, ".%s;\n",
+ if (owning_tab && owning_tab->dobj.dump)
+ {
+ resetPQExpBuffer(query);
+ appendPQExpBuffer(query, "ALTER SEQUENCE %s",
+ fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(query, " OWNED BY %s",
+ fmtId(owning_tab->dobj.name));
+ appendPQExpBuffer(query, ".%s;\n",
fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
- 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);
- }
+ 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);
}
-
- /* Dump Sequence Comments and Security Labels */
- dumpComment(fout, labelq->data,
- tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
- tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
- dumpSecLabel(fout, labelq->data,
- tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
- tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
}
- if (!schemaOnly)
- {
- resetPQExpBuffer(query);
- appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
- appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
- appendPQExpBuffer(query, ", %s, %s);\n",
- last, (called ? "true" : "false"));
-
- ArchiveEntry(fout, nilCatalogId, createDumpId(),
- tbinfo->dobj.name,
- tbinfo->dobj.namespace->dobj.name,
- NULL,
- tbinfo->rolname,
- false, "SEQUENCE SET", SECTION_PRE_DATA,
- query->data, "", NULL,
- &(tbinfo->dobj.dumpId), 1,
- NULL, NULL);
- }
+ /* Dump Sequence Comments and Security Labels */
+ dumpComment(fout, labelq->data,
+ tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
+ tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
+ dumpSecLabel(fout, labelq->data,
+ tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
+ tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
PQclear(res);
destroyPQExpBuffer(labelq);
}
+/*
+ * dumpSequenceData
+ * write the data of one user-defined sequence
+ */
+static void
+dumpSequenceData(Archive *fout, TableDataInfo *tdinfo)
+{
+ TableInfo *tbinfo = tdinfo->tdtable;
+ PGresult *res;
+ char *last;
+ 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));
+
+ 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));
+ exit_nicely(1);
+ }
+
+ last = PQgetvalue(res, 0, 0);
+ called = (strcmp(PQgetvalue(res, 0, 1), "t") == 0);
+
+ resetPQExpBuffer(query);
+ appendPQExpBufferStr(query, "SELECT pg_catalog.setval(");
+ appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
+ appendPQExpBuffer(query, ", %s, %s);\n",
+ last, (called ? "true" : "false"));
+
+ 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);
+
+ PQclear(res);
+
+ destroyPQExpBuffer(query);
+}
+
+/*
+ * dumpTrigger
+ * write the declaration of one user-defined table trigger
+ */
static void
dumpTrigger(Archive *fout, TriggerInfo *tginfo)
{
const char *p;
int findx;
+ /*
+ * we needn't check dobj.dump because TriggerInfo wouldn't have been
+ * created in the first place for non-dumpable triggers
+ */
if (dataOnly)
return;
{
if (tginfo->tgisconstraint)
{
- appendPQExpBuffer(query, "CREATE CONSTRAINT TRIGGER ");
+ appendPQExpBufferStr(query, "CREATE CONSTRAINT TRIGGER ");
appendPQExpBufferStr(query, fmtId(tginfo->tgconstrname));
}
else
{
- appendPQExpBuffer(query, "CREATE TRIGGER ");
+ appendPQExpBufferStr(query, "CREATE TRIGGER ");
appendPQExpBufferStr(query, fmtId(tginfo->dobj.name));
}
- appendPQExpBuffer(query, "\n ");
+ appendPQExpBufferStr(query, "\n ");
/* Trigger type */
if (TRIGGER_FOR_BEFORE(tginfo->tgtype))
- appendPQExpBuffer(query, "BEFORE");
+ appendPQExpBufferStr(query, "BEFORE");
else if (TRIGGER_FOR_AFTER(tginfo->tgtype))
- appendPQExpBuffer(query, "AFTER");
+ appendPQExpBufferStr(query, "AFTER");
else if (TRIGGER_FOR_INSTEAD(tginfo->tgtype))
- appendPQExpBuffer(query, "INSTEAD OF");
+ appendPQExpBufferStr(query, "INSTEAD OF");
else
{
write_msg(NULL, "unexpected tgtype value: %d\n", tginfo->tgtype);
- exit_nicely();
+ exit_nicely(1);
}
findx = 0;
if (TRIGGER_FOR_INSERT(tginfo->tgtype))
{
- appendPQExpBuffer(query, " INSERT");
+ appendPQExpBufferStr(query, " INSERT");
findx++;
}
if (TRIGGER_FOR_DELETE(tginfo->tgtype))
{
if (findx > 0)
- appendPQExpBuffer(query, " OR DELETE");
+ appendPQExpBufferStr(query, " OR DELETE");
else
- appendPQExpBuffer(query, " DELETE");
+ appendPQExpBufferStr(query, " DELETE");
findx++;
}
if (TRIGGER_FOR_UPDATE(tginfo->tgtype))
{
if (findx > 0)
- appendPQExpBuffer(query, " OR UPDATE");
+ appendPQExpBufferStr(query, " OR UPDATE");
else
- appendPQExpBuffer(query, " UPDATE");
+ appendPQExpBufferStr(query, " UPDATE");
findx++;
}
if (TRIGGER_FOR_TRUNCATE(tginfo->tgtype))
{
if (findx > 0)
- appendPQExpBuffer(query, " OR TRUNCATE");
+ appendPQExpBufferStr(query, " OR TRUNCATE");
else
- appendPQExpBuffer(query, " TRUNCATE");
+ appendPQExpBufferStr(query, " TRUNCATE");
findx++;
}
appendPQExpBuffer(query, " ON %s\n",
if (OidIsValid(tginfo->tgconstrrelid))
{
/* If we are using regclass, name is already quoted */
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
appendPQExpBuffer(query, " FROM %s\n ",
tginfo->tgconstrrelname);
else
fmtId(tginfo->tgconstrrelname));
}
if (!tginfo->tgdeferrable)
- appendPQExpBuffer(query, "NOT ");
- appendPQExpBuffer(query, "DEFERRABLE INITIALLY ");
+ appendPQExpBufferStr(query, "NOT ");
+ appendPQExpBufferStr(query, "DEFERRABLE INITIALLY ");
if (tginfo->tginitdeferred)
- appendPQExpBuffer(query, "DEFERRED\n");
+ appendPQExpBufferStr(query, "DEFERRED\n");
else
- appendPQExpBuffer(query, "IMMEDIATE\n");
+ appendPQExpBufferStr(query, "IMMEDIATE\n");
}
if (TRIGGER_FOR_ROW(tginfo->tgtype))
- appendPQExpBuffer(query, " FOR EACH ROW\n ");
+ appendPQExpBufferStr(query, " FOR EACH ROW\n ");
else
- appendPQExpBuffer(query, " FOR EACH STATEMENT\n ");
+ appendPQExpBufferStr(query, " FOR EACH STATEMENT\n ");
/* In 7.3, result of regproc is already quoted */
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
appendPQExpBuffer(query, "EXECUTE PROCEDURE %s(",
tginfo->tgfname);
else
tginfo->tgargs,
tginfo->dobj.name,
tbinfo->dobj.name);
- exit_nicely();
+ exit_nicely(1);
}
if (findx > 0)
- appendPQExpBuffer(query, ", ");
+ appendPQExpBufferStr(query, ", ");
appendStringLiteralAH(query, p, fout);
p += tlen + 1;
}
free(tgargs);
- appendPQExpBuffer(query, ");\n");
+ appendPQExpBufferStr(query, ");\n");
}
if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
{
case 'D':
case 'f':
- appendPQExpBuffer(query, "DISABLE");
+ appendPQExpBufferStr(query, "DISABLE");
break;
case 'A':
- appendPQExpBuffer(query, "ENABLE ALWAYS");
+ appendPQExpBufferStr(query, "ENABLE ALWAYS");
break;
case 'R':
- appendPQExpBuffer(query, "ENABLE REPLICA");
+ appendPQExpBufferStr(query, "ENABLE REPLICA");
break;
default:
- appendPQExpBuffer(query, "ENABLE");
+ appendPQExpBufferStr(query, "ENABLE");
break;
}
appendPQExpBuffer(query, " TRIGGER %s;\n",
tbinfo->rolname, false,
"TRIGGER", SECTION_POST_DATA,
query->data, delqry->data, NULL,
- tginfo->dobj.dependencies, tginfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
dumpComment(fout, labelq->data,
destroyPQExpBuffer(labelq);
}
+/*
+ * dumpEventTrigger
+ * write the declaration of one user-defined event trigger
+ */
+static void
+dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
+{
+ PQExpBuffer query;
+ PQExpBuffer labelq;
+
+ /* Skip if not to be dumped */
+ if (!evtinfo->dobj.dump || dataOnly)
+ return;
+
+ query = createPQExpBuffer();
+ labelq = createPQExpBuffer();
+
+ appendPQExpBufferStr(query, "CREATE EVENT TRIGGER ");
+ appendPQExpBufferStr(query, fmtId(evtinfo->dobj.name));
+ appendPQExpBufferStr(query, " ON ");
+ appendPQExpBufferStr(query, fmtId(evtinfo->evtevent));
+ appendPQExpBufferStr(query, " ");
+
+ if (strcmp("", evtinfo->evttags) != 0)
+ {
+ appendPQExpBufferStr(query, "\n WHEN TAG IN (");
+ appendPQExpBufferStr(query, evtinfo->evttags);
+ appendPQExpBufferStr(query, ") ");
+ }
+
+ appendPQExpBufferStr(query, "\n EXECUTE PROCEDURE ");
+ appendPQExpBufferStr(query, evtinfo->evtfname);
+ appendPQExpBufferStr(query, "();\n");
+
+ if (evtinfo->evtenabled != 'O')
+ {
+ appendPQExpBuffer(query, "\nALTER EVENT TRIGGER %s ",
+ fmtId(evtinfo->dobj.name));
+ switch (evtinfo->evtenabled)
+ {
+ case 'D':
+ appendPQExpBufferStr(query, "DISABLE");
+ break;
+ case 'A':
+ appendPQExpBufferStr(query, "ENABLE ALWAYS");
+ break;
+ case 'R':
+ appendPQExpBufferStr(query, "ENABLE REPLICA");
+ break;
+ default:
+ appendPQExpBufferStr(query, "ENABLE");
+ break;
+ }
+ appendPQExpBufferStr(query, ";\n");
+ }
+ appendPQExpBuffer(labelq, "EVENT TRIGGER %s ",
+ fmtId(evtinfo->dobj.name));
+
+ ArchiveEntry(fout, evtinfo->dobj.catId, evtinfo->dobj.dumpId,
+ evtinfo->dobj.name, NULL, NULL, evtinfo->evtowner, false,
+ "EVENT TRIGGER", SECTION_POST_DATA,
+ query->data, "", NULL, NULL, 0, NULL, NULL);
+
+ dumpComment(fout, labelq->data,
+ NULL, NULL,
+ evtinfo->dobj.catId, 0, evtinfo->dobj.dumpId);
+
+ destroyPQExpBuffer(query);
+ destroyPQExpBuffer(labelq);
+}
+
/*
* dumpRule
* Dump a rule
/*
* Make sure we are in proper schema.
*/
- selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+ selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
query = createPQExpBuffer();
cmd = createPQExpBuffer();
delcmd = createPQExpBuffer();
labelq = createPQExpBuffer();
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query,
"SELECT pg_catalog.pg_get_ruledef('%u'::pg_catalog.oid) AS definition",
rinfo->dobj.name);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
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);
- exit_nicely();
+ exit_nicely(1);
}
printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, 0, 0));
*/
if (rinfo->ev_enabled != 'O')
{
- appendPQExpBuffer(cmd, "ALTER TABLE %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
- appendPQExpBuffer(cmd, "%s ",
- fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(cmd, "ALTER TABLE %s ", fmtId(tbinfo->dobj.name));
switch (rinfo->ev_enabled)
{
case 'A':
}
}
+ /*
+ * Apply view's reloptions when its ON SELECT rule is separate.
+ */
+ if (rinfo->reloptions && strlen(rinfo->reloptions) > 0)
+ {
+ appendPQExpBuffer(cmd, "ALTER VIEW %s SET (%s);\n",
+ fmtId(tbinfo->dobj.name),
+ rinfo->reloptions);
+ }
+
/*
* DROP must be fully qualified in case same name appears in pg_catalog
*/
tbinfo->rolname, false,
"RULE", SECTION_POST_DATA,
cmd->data, delcmd->data, NULL,
- rinfo->dobj.dependencies, rinfo->dobj.nDeps,
+ NULL, 0,
NULL, NULL);
/* Dump rule comments */
* getExtensionMembership --- obtain extension membership data
*/
void
-getExtensionMembership(ExtensionInfo extinfo[], int numExtensions)
+getExtensionMembership(Archive *fout, ExtensionInfo extinfo[],
+ int numExtensions)
{
PQExpBuffer query;
PGresult *res;
return;
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
query = createPQExpBuffer();
/* refclassid constraint is redundant but may speed the search */
- appendPQExpBuffer(query, "SELECT "
- "classid, objid, refclassid, refobjid "
- "FROM pg_depend "
- "WHERE refclassid = 'pg_extension'::regclass "
- "AND deptype = 'e' "
- "ORDER BY 3,4");
+ appendPQExpBufferStr(query, "SELECT "
+ "classid, objid, refclassid, refobjid "
+ "FROM pg_depend "
+ "WHERE refclassid = 'pg_extension'::regclass "
+ "AND deptype = 'e' "
+ "ORDER BY 3,4");
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*/
for (i = 0; i < numExtensions; i++)
{
- char *extconfig = extinfo[i].extconfig;
- char *extcondition = extinfo[i].extcondition;
+ ExtensionInfo *curext = &(extinfo[i]);
+ char *extconfig = curext->extconfig;
+ char *extcondition = curext->extcondition;
char **extconfigarray = NULL;
char **extconditionarray = NULL;
int nconfigitems;
for (j = 0; j < nconfigitems; j++)
{
TableInfo *configtbl;
+ Oid configtbloid = atooid(extconfigarray[j]);
+ bool dumpobj = curext->dobj.dump;
+
+ configtbl = findTableByOid(configtbloid);
+ if (configtbl == NULL)
+ continue;
- configtbl = findTableByOid(atooid(extconfigarray[j]));
- if (configtbl && configtbl->dataObj == NULL)
+ /*
+ * Tables of not-to-be-dumped extensions shouldn't be dumped
+ * unless the table or its schema is explicitly included
+ */
+ if (!curext->dobj.dump)
+ {
+ /* check table explicitly requested */
+ if (table_include_oids.head != NULL &&
+ simple_oid_list_member(&table_include_oids,
+ configtbloid))
+ dumpobj = true;
+
+ /* check table's schema explicitly requested */
+ if (configtbl->dobj.namespace->dobj.dump)
+ dumpobj = true;
+ }
+
+ /* check table excluded by an exclusion switch */
+ if (table_exclude_oids.head != NULL &&
+ simple_oid_list_member(&table_exclude_oids,
+ configtbloid))
+ dumpobj = false;
+
+ /* check schema excluded by an exclusion switch */
+ if (simple_oid_list_member(&schema_exclude_oids,
+ configtbl->dobj.namespace->dobj.catId.oid))
+ dumpobj = false;
+
+ if (dumpobj)
{
/*
* Note: config tables are dumped without OIDs regardless
* conditions aren't compatible with dumping OIDs.
*/
makeTableDataInfo(configtbl, false);
- if (strlen(extconditionarray[j]) > 0)
- configtbl->dataObj->filtercond = pg_strdup(extconditionarray[j]);
+ if (configtbl->dataObj != NULL)
+ {
+ if (strlen(extconditionarray[j]) > 0)
+ configtbl->dataObj->filtercond = pg_strdup(extconditionarray[j]);
+ }
}
}
}
* getDependencies --- obtain available dependency data
*/
static void
-getDependencies(void)
+getDependencies(Archive *fout)
{
PQExpBuffer query;
PGresult *res;
*refdobj;
/* No dependency info available before 7.3 */
- if (g_fout->remoteVersion < 70300)
+ if (fout->remoteVersion < 70300)
return;
if (g_verbose)
write_msg(NULL, "reading dependency data\n");
/* Make sure we are in proper schema */
- selectSourceSchema("pg_catalog");
+ selectSourceSchema(fout, "pg_catalog");
query = createPQExpBuffer();
* PIN dependencies aren't interesting, and EXTENSION dependencies were
* already processed by getExtensionMembership.
*/
- appendPQExpBuffer(query, "SELECT "
- "classid, objid, refclassid, refobjid, deptype "
- "FROM pg_depend "
- "WHERE deptype != 'p' AND deptype != 'e' "
- "ORDER BY 1,2");
+ appendPQExpBufferStr(query, "SELECT "
+ "classid, objid, refclassid, refobjid, deptype "
+ "FROM pg_depend "
+ "WHERE deptype != 'p' AND deptype != 'e' "
+ "ORDER BY 1,2");
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
}
+/*
+ * createBoundaryObjects - create dummy DumpableObjects to represent
+ * dump section boundaries.
+ */
+static DumpableObject *
+createBoundaryObjects(void)
+{
+ DumpableObject *dobjs;
+
+ dobjs = (DumpableObject *) pg_malloc(2 * sizeof(DumpableObject));
+
+ dobjs[0].objType = DO_PRE_DATA_BOUNDARY;
+ dobjs[0].catId = nilCatalogId;
+ AssignDumpId(dobjs + 0);
+ dobjs[0].name = pg_strdup("PRE-DATA BOUNDARY");
+
+ dobjs[1].objType = DO_POST_DATA_BOUNDARY;
+ dobjs[1].catId = nilCatalogId;
+ AssignDumpId(dobjs + 1);
+ dobjs[1].name = pg_strdup("POST-DATA BOUNDARY");
+
+ return dobjs;
+}
+
+/*
+ * addBoundaryDependencies - add dependencies as needed to enforce the dump
+ * section boundaries.
+ */
+static void
+addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
+ DumpableObject *boundaryObjs)
+{
+ DumpableObject *preDataBound = boundaryObjs + 0;
+ DumpableObject *postDataBound = boundaryObjs + 1;
+ int i;
+
+ for (i = 0; i < numObjs; i++)
+ {
+ DumpableObject *dobj = dobjs[i];
+
+ /*
+ * The classification of object types here must match the SECTION_xxx
+ * values assigned during subsequent ArchiveEntry calls!
+ */
+ switch (dobj->objType)
+ {
+ case DO_NAMESPACE:
+ case DO_EXTENSION:
+ case DO_TYPE:
+ case DO_SHELL_TYPE:
+ case DO_FUNC:
+ case DO_AGG:
+ case DO_OPERATOR:
+ case DO_OPCLASS:
+ case DO_OPFAMILY:
+ case DO_COLLATION:
+ case DO_CONVERSION:
+ case DO_TABLE:
+ case DO_ATTRDEF:
+ case DO_PROCLANG:
+ case DO_CAST:
+ case DO_DUMMY_TYPE:
+ case DO_TSPARSER:
+ case DO_TSDICT:
+ case DO_TSTEMPLATE:
+ case DO_TSCONFIG:
+ case DO_FDW:
+ case DO_FOREIGN_SERVER:
+ case DO_BLOB:
+ /* Pre-data objects: must come before the pre-data boundary */
+ addObjectDependency(preDataBound, dobj->dumpId);
+ break;
+ case DO_TABLE_DATA:
+ case DO_BLOB_DATA:
+ /* Data objects: must come between the boundaries */
+ addObjectDependency(dobj, preDataBound->dumpId);
+ addObjectDependency(postDataBound, dobj->dumpId);
+ break;
+ case DO_INDEX:
+ case DO_REFRESH_MATVIEW:
+ case DO_TRIGGER:
+ case DO_EVENT_TRIGGER:
+ case DO_DEFAULT_ACL:
+ /* Post-data objects: must come after the post-data boundary */
+ addObjectDependency(dobj, postDataBound->dumpId);
+ break;
+ case DO_RULE:
+ /* Rules are post-data, but only if dumped separately */
+ if (((RuleInfo *) dobj)->separate)
+ addObjectDependency(dobj, postDataBound->dumpId);
+ break;
+ case DO_CONSTRAINT:
+ case DO_FK_CONSTRAINT:
+ /* Constraints are post-data, but only if dumped separately */
+ if (((ConstraintInfo *) dobj)->separate)
+ addObjectDependency(dobj, postDataBound->dumpId);
+ break;
+ case DO_PRE_DATA_BOUNDARY:
+ /* nothing to do */
+ break;
+ case DO_POST_DATA_BOUNDARY:
+ /* must come after the pre-data boundary */
+ addObjectDependency(dobj, preDataBound->dumpId);
+ break;
+ }
+ }
+}
+
+
+/*
+ * BuildArchiveDependencies - create dependency data for archive TOC entries
+ *
+ * The raw dependency data obtained by getDependencies() is not terribly
+ * useful in an archive dump, because in many cases there are dependency
+ * chains linking through objects that don't appear explicitly in the dump.
+ * For example, a view will depend on its _RETURN rule while the _RETURN rule
+ * will depend on other objects --- but the rule will not appear as a separate
+ * object in the dump. We need to adjust the view's dependencies to include
+ * whatever the rule depends on that is included in the dump.
+ *
+ * Just to make things more complicated, there are also "special" dependencies
+ * such as the dependency of a TABLE DATA item on its TABLE, which we must
+ * not rearrange because pg_restore knows that TABLE DATA only depends on
+ * its table. In these cases we must leave the dependencies strictly as-is
+ * even if they refer to not-to-be-dumped objects.
+ *
+ * To handle this, the convention is that "special" dependencies are created
+ * during ArchiveEntry calls, and an archive TOC item that has any such
+ * entries will not be touched here. Otherwise, we recursively search the
+ * DumpableObject data structures to build the correct dependencies for each
+ * archive TOC item.
+ */
+static void
+BuildArchiveDependencies(Archive *fout)
+{
+ ArchiveHandle *AH = (ArchiveHandle *) fout;
+ TocEntry *te;
+
+ /* Scan all TOC entries in the archive */
+ for (te = AH->toc->next; te != AH->toc; te = te->next)
+ {
+ DumpableObject *dobj;
+ DumpId *dependencies;
+ int nDeps;
+ int allocDeps;
+
+ /* No need to process entries that will not be dumped */
+ if (te->reqs == 0)
+ continue;
+ /* Ignore entries that already have "special" dependencies */
+ if (te->nDeps > 0)
+ continue;
+ /* Otherwise, look up the item's original DumpableObject, if any */
+ dobj = findObjectByDumpId(te->dumpId);
+ if (dobj == NULL)
+ continue;
+ /* No work if it has no dependencies */
+ if (dobj->nDeps <= 0)
+ continue;
+ /* Set up work array */
+ allocDeps = 64;
+ dependencies = (DumpId *) pg_malloc(allocDeps * sizeof(DumpId));
+ nDeps = 0;
+ /* Recursively find all dumpable dependencies */
+ findDumpableDependencies(AH, dobj,
+ &dependencies, &nDeps, &allocDeps);
+ /* And save 'em ... */
+ if (nDeps > 0)
+ {
+ dependencies = (DumpId *) pg_realloc(dependencies,
+ nDeps * sizeof(DumpId));
+ te->dependencies = dependencies;
+ te->nDeps = nDeps;
+ }
+ else
+ free(dependencies);
+ }
+}
+
+/* Recursive search subroutine for BuildArchiveDependencies */
+static void
+findDumpableDependencies(ArchiveHandle *AH, DumpableObject *dobj,
+ DumpId **dependencies, int *nDeps, int *allocDeps)
+{
+ int i;
+
+ /*
+ * Ignore section boundary objects: if we search through them, we'll
+ * report lots of bogus dependencies.
+ */
+ if (dobj->objType == DO_PRE_DATA_BOUNDARY ||
+ dobj->objType == DO_POST_DATA_BOUNDARY)
+ return;
+
+ for (i = 0; i < dobj->nDeps; i++)
+ {
+ DumpId depid = dobj->dependencies[i];
+
+ if (TocIDRequired(AH, depid) != 0)
+ {
+ /* Object will be dumped, so just reference it as a dependency */
+ if (*nDeps >= *allocDeps)
+ {
+ *allocDeps *= 2;
+ *dependencies = (DumpId *) pg_realloc(*dependencies,
+ *allocDeps * sizeof(DumpId));
+ }
+ (*dependencies)[*nDeps] = depid;
+ (*nDeps)++;
+ }
+ else
+ {
+ /*
+ * Object will not be dumped, so recursively consider its deps. We
+ * rely on the assumption that sortDumpableObjects already broke
+ * any dependency loops, else we might recurse infinitely.
+ */
+ DumpableObject *otherdobj = findObjectByDumpId(depid);
+
+ if (otherdobj)
+ findDumpableDependencies(AH, otherdobj,
+ dependencies, nDeps, allocDeps);
+ }
+ }
+}
+
+
/*
* selectSourceSchema - make the specified schema the active search path
* in the source database.
*
* 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(const char *schemaName)
+selectSourceSchema(Archive *fout, const char *schemaName)
{
- static char *curSchemaName = NULL;
PQExpBuffer query;
+ /* This is checked by the callers already */
+ Assert(schemaName != NULL && *schemaName != '\0');
+
/* Not relevant if fetching from pre-7.3 DB */
- if (g_fout->remoteVersion < 70300)
- return;
- /* Ignore null schema names */
- if (schemaName == NULL || *schemaName == '\0')
- return;
- /* Optimize away repeated selection of same schema */
- if (curSchemaName && strcmp(curSchemaName, schemaName) == 0)
+ if (fout->remoteVersion < 70300)
return;
query = createPQExpBuffer();
appendPQExpBuffer(query, "SET search_path = %s",
fmtId(schemaName));
if (strcmp(schemaName, "pg_catalog") != 0)
- appendPQExpBuffer(query, ", pg_catalog");
+ appendPQExpBufferStr(query, ", pg_catalog");
- do_sql_command(g_conn, query->data);
+ ExecuteSqlStatement(fout, query->data);
destroyPQExpBuffer(query);
- if (curSchemaName)
- free(curSchemaName);
- curSchemaName = pg_strdup(schemaName);
}
/*
* schema; this is why we don't try to cache the names.
*/
static char *
-getFormattedTypeName(Oid oid, OidOptions opts)
+getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts)
{
char *result;
PQExpBuffer query;
PGresult *res;
- int ntups;
if (oid == 0)
{
}
query = createPQExpBuffer();
- if (g_fout->remoteVersion >= 70300)
+ if (fout->remoteVersion >= 70300)
{
appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)",
oid);
}
- else if (g_fout->remoteVersion >= 70100)
+ else if (fout->remoteVersion >= 70100)
{
appendPQExpBuffer(query, "SELECT format_type('%u'::oid, NULL)",
oid);
oid);
}
- res = PQexec(g_conn, query->data);
- check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ res = ExecuteSqlQueryForSingleRow(fout, query->data);
- /* Expecting a single result only */
- ntups = PQntuples(res);
- if (ntups != 1)
- {
- write_msg(NULL, ngettext("query returned %d row instead of one: %s\n",
- "query returned %d rows instead of one: %s\n",
- ntups),
- ntups, query->data);
- exit_nicely();
- }
-
- if (g_fout->remoteVersion >= 70100)
+ if (fout->remoteVersion >= 70100)
{
/* already quoted */
result = pg_strdup(PQgetvalue(res, 0, 0));
{
int len = (typmod - VARHDRSZ);
- appendPQExpBuffer(buf, "character");
+ appendPQExpBufferStr(buf, "character");
if (len > 1)
appendPQExpBuffer(buf, "(%d)",
typmod - VARHDRSZ);
}
else if (strcmp(typname, "varchar") == 0)
{
- appendPQExpBuffer(buf, "character varying");
+ appendPQExpBufferStr(buf, "character varying");
if (typmod != -1)
appendPQExpBuffer(buf, "(%d)",
typmod - VARHDRSZ);
}
else if (strcmp(typname, "numeric") == 0)
{
- appendPQExpBuffer(buf, "numeric");
+ appendPQExpBufferStr(buf, "numeric");
if (typmod != -1)
{
int32 tmp_typmod;
* through with quotes. - thomas 1998-12-13
*/
else if (strcmp(typname, "char") == 0)
- appendPQExpBuffer(buf, "\"char\"");
+ appendPQExpBufferStr(buf, "\"char\"");
else
- appendPQExpBuffer(buf, "%s", fmtId(typname));
+ appendPQExpBufferStr(buf, fmtId(typname));
/* Append array qualifier for array types */
if (isarray)
- appendPQExpBuffer(buf, "[]");
+ appendPQExpBufferStr(buf, "[]");
result = pg_strdup(buf->data);
destroyPQExpBuffer(buf);
return result;
}
-/*
- * fmtQualifiedId - convert a qualified name to the proper format for
- * the source database.
- *
- * Like fmtId, use the result before calling again.
- */
-static const char *
-fmtQualifiedId(const char *schema, const char *id)
-{
- static PQExpBuffer id_return = NULL;
-
- if (id_return) /* first time through? */
- resetPQExpBuffer(id_return);
- else
- id_return = createPQExpBuffer();
-
- /* Suppress schema name if fetching from pre-7.3 DB */
- if (g_fout->remoteVersion >= 70300 && schema && *schema)
- {
- appendPQExpBuffer(id_return, "%s.",
- fmtId(schema));
- }
- appendPQExpBuffer(id_return, "%s",
- fmtId(id));
-
- return id_return->data;
-}
-
/*
* Return a column list clause for the given relation.
*
* "", not an invalid "()" column list.
*/
static const char *
-fmtCopyColumnList(const TableInfo *ti)
+fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer)
{
- static PQExpBuffer q = NULL;
int numatts = ti->numatts;
char **attnames = ti->attnames;
bool *attisdropped = ti->attisdropped;
bool needComma;
int i;
- if (q) /* first time through? */
- resetPQExpBuffer(q);
- else
- q = createPQExpBuffer();
-
- appendPQExpBuffer(q, "(");
+ appendPQExpBufferChar(buffer, '(');
needComma = false;
for (i = 0; i < numatts; i++)
{
if (attisdropped[i])
continue;
if (needComma)
- appendPQExpBuffer(q, ", ");
- appendPQExpBuffer(q, "%s", fmtId(attnames[i]));
+ appendPQExpBufferStr(buffer, ", ");
+ appendPQExpBufferStr(buffer, fmtId(attnames[i]));
needComma = true;
}
if (!needComma)
return ""; /* no undropped columns */
- appendPQExpBuffer(q, ")");
- return q->data;
+ appendPQExpBufferChar(buffer, ')');
+ return buffer->data;
}
/*
- * Convenience subroutine to execute a SQL command and check for
- * COMMAND_OK status.
+ * Execute an SQL query and verify that we got exactly one row back.
*/
-static void
-do_sql_command(PGconn *conn, const char *query)
+static PGresult *
+ExecuteSqlQueryForSingleRow(Archive *fout, char *query)
{
PGresult *res;
+ int ntups;
- res = PQexec(conn, query);
- check_sql_result(res, conn, query, PGRES_COMMAND_OK);
- PQclear(res);
-}
-
-/*
- * Convenience subroutine to verify a SQL command succeeded,
- * and exit with a useful error message if not.
- */
-static void
-check_sql_result(PGresult *res, PGconn *conn, const char *query,
- ExecStatusType expected)
-{
- const char *err;
+ res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
- if (res && PQresultStatus(res) == expected)
- return; /* A-OK */
+ /* Expecting a single result only */
+ ntups = PQntuples(res);
+ if (ntups != 1)
+ exit_horribly(NULL,
+ ngettext("query returned %d row instead of one: %s\n",
+ "query returned %d rows instead of one: %s\n",
+ ntups),
+ ntups, query);
- write_msg(NULL, "SQL command failed\n");
- if (res)
- err = PQresultErrorMessage(res);
- else
- err = PQerrorMessage(conn);
- write_msg(NULL, "Error message from server: %s", err);
- write_msg(NULL, "The command was: %s\n", query);
- exit_nicely();
+ return res;
}