* pg_dump is a utility for dumping out a postgres database
* into a script file.
*
- * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2008, 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
* by PostgreSQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.475 2007/11/08 10:37:54 petere Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.495 2008/07/16 16:55:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
-/*
- * Although this is not a backend module, we must include postgres.h anyway
- * so that we can include a bunch of backend include files. pg_dump has
- * never pretended to be very independent of the backend anyhow ...
- */
-#include "postgres.h"
+#include "postgres_fe.h"
#include <unistd.h>
-
#include <ctype.h>
#ifdef ENABLE_NLS
#include <locale.h>
int optreset;
#endif
-#include "access/htup.h"
+#include "access/attnum.h"
+#include "access/sysattr.h"
#include "catalog/pg_class.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
-#include "commands/sequence.h"
#include "libpq/libpq-fs.h"
#include "pg_backup_archiver.h"
* The string lists record the patterns given by command-line switches,
* which we then convert to lists of OIDs of matching objects.
*/
-static SimpleStringList schema_include_patterns = { NULL, NULL };
-static SimpleOidList schema_include_oids = { NULL, NULL };
-static SimpleStringList schema_exclude_patterns = { NULL, NULL };
-static SimpleOidList schema_exclude_oids = { NULL, NULL };
+static SimpleStringList schema_include_patterns = {NULL, NULL};
+static SimpleOidList schema_include_oids = {NULL, NULL};
+static SimpleStringList schema_exclude_patterns = {NULL, NULL};
+static SimpleOidList schema_exclude_oids = {NULL, NULL};
-static SimpleStringList table_include_patterns = { NULL, NULL };
-static SimpleOidList table_include_oids = { NULL, NULL };
-static SimpleStringList table_exclude_patterns = { NULL, NULL };
-static SimpleOidList table_exclude_oids = { NULL, NULL };
+static SimpleStringList table_include_patterns = {NULL, NULL};
+static SimpleOidList table_include_oids = {NULL, NULL};
+static SimpleStringList table_exclude_patterns = {NULL, NULL};
+static SimpleOidList table_exclude_oids = {NULL, NULL};
/* default, if no "inclusion" switches appear, is to dump everything */
static bool include_everything = true;
static void help(const char *progname);
static void expand_schema_name_patterns(SimpleStringList *patterns,
- SimpleOidList *oids);
+ SimpleOidList *oids);
static void expand_table_name_patterns(SimpleStringList *patterns,
- SimpleOidList *oids);
+ SimpleOidList *oids);
static NamespaceInfo *findNamespace(Oid nsoid, Oid objoid);
static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
+static void guessConstraintInheritance(TableInfo *tblinfo, int numTables);
static void dumpComment(Archive *fout, const char *target,
const char *namespace, const char *owner,
CatalogId catalogId, int subid, DumpId dumpId);
int i;
bool force_password = false;
int compressLevel = -1;
- bool ignore_version = false;
int plainText = 0;
int outputClean = 0;
int outputCreate = 0;
bool outputBlobs = false;
int outputNoOwner = 0;
- static int use_setsessauth = 0;
- static int disable_triggers = 0;
char *outputSuperuser = NULL;
-
+ int my_version;
+ int optindex;
RestoreOptions *ropt;
+ static int disable_triggers = 0;
+ static int outputNoTablespaces = 0;
+ static int use_setsessauth = 0;
+
static struct option long_options[] = {
{"data-only", no_argument, NULL, 'a'},
{"blobs", no_argument, NULL, 'b'},
*/
{"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
{"disable-triggers", no_argument, &disable_triggers, 1},
+ {"no-tablespaces", no_argument, &outputNoTablespaces, 1},
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
{NULL, 0, NULL, 0}
};
- int optindex;
set_pglocale_pgservice(argv[0], "pg_dump");
}
}
- while ((c = getopt_long(argc, argv, "abcCdDE:f:F:h:in:N:oOp:RsS:t:T:uU:vWxX:Z:",
+ while ((c = getopt_long(argc, argv, "abcCdDE:f:F:h:in:N:oOp:RsS:t:T:U:vWxX:Z:",
long_options, &optindex)) != -1)
{
switch (c)
pghost = optarg;
break;
- case 'i': /* ignore database version mismatch */
- ignore_version = true;
+ case 'i':
+ /* ignored, deprecated option */
break;
case 'n': /* include schema(s) */
simple_string_list_append(&table_exclude_patterns, optarg);
break;
- case 'u':
- force_password = true;
- username = simple_prompt("User name: ", 100, true);
- break;
-
case 'U':
username = optarg;
break;
disable_dollar_quoting = 1;
else if (strcmp(optarg, "disable-triggers") == 0)
disable_triggers = 1;
+ else if (strcmp(optarg, "no-tablespaces") == 0)
+ outputNoTablespaces = 1;
else if (strcmp(optarg, "use-set-session-authorization") == 0)
use_setsessauth = 1;
else
else if (pg_strcasecmp(format, "f") == 0 || pg_strcasecmp(format, "file") == 0)
{
/*
- * Dump files into the current directory; for demonstration only, not
- * documented.
+ * Dump files into the current directory; for demonstration only, not
+ * documented.
*/
g_fout = CreateArchive(filename, archFiles, compressLevel, archModeWrite);
}
/* Let the archiver know how noisy to be */
g_fout->verbose = g_verbose;
- g_fout->minRemoteVersion = 70000; /* we can handle back to 7.0 */
- g_fout->maxRemoteVersion = parse_version(PG_VERSION);
- if (g_fout->maxRemoteVersion < 0)
+ 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, force_password, ignore_version);
+ username, force_password);
/* Set the client encoding if requested */
if (dumpencoding)
do_sql_command(g_conn, "SET DATESTYLE = ISO");
/*
+ * 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 >= 70400)
+ do_sql_command(g_conn, "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 (g_fout->remoteVersion >= 80300)
+ do_sql_command(g_conn, "SET synchronize_seqscans TO off");
+
+ /*
+ * Disable timeouts if supported.
+ */
+ if (g_fout->remoteVersion >= 70300)
+ do_sql_command(g_conn, "SET statement_timeout = 0");
+
+ /*
* Start serializable transaction to dump consistent data.
*/
do_sql_command(g_conn, "BEGIN");
else
username_subquery = "SELECT usename FROM pg_user WHERE usesysid =";
- /*
- * 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 >= 70400)
- do_sql_command(g_conn, "SET extra_float_digits TO 2");
-
/* Find the last built-in OID, if needed */
if (g_fout->remoteVersion < 70300)
{
*/
tblinfo = getSchemaData(&numTables);
+ if (g_fout->remoteVersion < 80400)
+ guessConstraintInheritance(tblinfo, numTables);
+
if (!schemaOnly)
getTableData(tblinfo, numTables, oids);
ropt->superuser = outputSuperuser;
ropt->create = outputCreate;
ropt->noOwner = outputNoOwner;
+ ropt->noTablespace = outputNoTablespaces;
ropt->disable_triggers = disable_triggers;
ropt->use_setsessauth = use_setsessauth;
ropt->dataOnly = dataOnly;
printf(_("\nGeneral options:\n"));
printf(_(" -f, --file=FILENAME output file name\n"));
printf(_(" -F, --format=c|t|p output file format (custom, tar, plain text)\n"));
- printf(_(" -i, --ignore-version proceed even when server version mismatches\n"
- " pg_dump version\n"));
printf(_(" -v, --verbose verbose mode\n"));
printf(_(" -Z, --compress=0-9 compression level for compressed formats\n"));
printf(_(" --help show this help, then exit\n"));
printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
printf(_(" --disable-triggers disable triggers during data-only restore\n"));
+ printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
printf(_(" --use-set-session-authorization\n"
" use SESSION AUTHORIZATION commands instead of\n"
- " ALTER OWNER commands to set ownership\n"));
+ " ALTER OWNER commands to set ownership\n"));
printf(_("\nConnection options:\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\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"
+ "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
"\nWHERE c.relkind in ('%c', '%c', '%c')\n",
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
processSQLNamePattern(g_conn, query, cell->val, true, false,
nsinfo->dobj.dump = false;
else
nsinfo->dobj.dump = true;
+
/*
* In any case, a namespace can be excluded by an exclusion switch
*/
selectDumpableTable(TableInfo *tbinfo)
{
/*
- * If specific tables are being dumped, dump just those tables;
- * else, dump according to the parent namespace's dump flag.
+ * If specific tables are being dumped, dump just those tables; else, dump
+ * according to the parent namespace's dump flag.
*/
if (table_include_oids.head != NULL)
tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids,
tbinfo->dobj.catId.oid);
else
tbinfo->dobj.dump = tbinfo->dobj.namespace->dobj.dump;
+
/*
* In any case, a table can be excluded by an exclusion switch
*/
* was too tight. Finally, the following was implemented:
*
* If throttle is non-zero, then
- * See how long since the last sleep.
+ * See how long since the last sleep.
* Work out how long to sleep (based on ratio).
- * If sleep is more than 100ms, then
- * sleep
+ * If sleep is more than 100ms, then
+ * sleep
* reset timer
* EndIf
* EndIf
/*
+ * guessConstraintInheritance:
+ * In pre-8.4 databases, we can't tell for certain which constraints
+ * are inherited. We assume a CHECK constraint is inherited if its name
+ * matches the name of any constraint in the parent. Originally this code
+ * tried to compare the expression texts, but that can fail for various
+ * reasons --- for example, if the parent and child tables are in different
+ * schemas, reverse-listing of function calls may produce different text
+ * (schema-qualified or not) depending on search path.
+ *
+ * In 8.4 and up we can rely on the conislocal field to decide which
+ * constraints must be dumped; much safer.
+ *
+ * This function assumes all conislocal flags were initialized to TRUE.
+ * It clears the flag on anything that seems to be inherited.
+ */
+static void
+guessConstraintInheritance(TableInfo *tblinfo, int numTables)
+{
+ int i,
+ j,
+ k;
+
+ for (i = 0; i < numTables; i++)
+ {
+ TableInfo *tbinfo = &(tblinfo[i]);
+ int numParents;
+ TableInfo **parents;
+ TableInfo *parent;
+
+ /* Sequences and views never have parents */
+ if (tbinfo->relkind == RELKIND_SEQUENCE ||
+ tbinfo->relkind == RELKIND_VIEW)
+ continue;
+
+ /* Don't bother computing anything for non-target tables, either */
+ if (!tbinfo->dobj.dump)
+ continue;
+
+ numParents = tbinfo->numParents;
+ parents = tbinfo->parents;
+
+ if (numParents == 0)
+ continue; /* nothing to see here, move along */
+
+ /* scan for inherited CHECK constraints */
+ for (j = 0; j < tbinfo->ncheck; j++)
+ {
+ ConstraintInfo *constr;
+
+ constr = &(tbinfo->checkexprs[j]);
+
+ for (k = 0; k < numParents; k++)
+ {
+ int l;
+
+ parent = parents[k];
+ for (l = 0; l < parent->ncheck; l++)
+ {
+ ConstraintInfo *pconstr = &(parent->checkexprs[l]);
+
+ if (strcmp(pconstr->dobj.name, constr->dobj.name) == 0)
+ {
+ constr->conislocal = false;
+ break;
+ }
+ }
+ if (!constr->conislocal)
+ break;
+ }
+ }
+ }
+}
+
+
+/*
* dumpDatabase:
* dump the database definition
*/
if (comment && strlen(comment))
{
resetPQExpBuffer(dbQry);
+ /* Generates warning when loaded into a differently-named database.*/
appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
appendStringLiteralAH(dbQry, comment, AH);
appendPQExpBuffer(dbQry, ";\n");
*
* Note: as of 8.3 we can reliably detect whether a type is an
* auto-generated array type by checking the element type's typarray.
- * (Before that the test is capable of generating false positives.)
- * We still check for name beginning with '_', though, so as to avoid
- * the cost of the subselect probe for all standard types. This would
- * have to be revisited if the backend ever allows renaming of array types.
+ * (Before that the test is capable of generating false positives.) We
+ * still check for name beginning with '_', though, so as to avoid the
+ * cost of the subselect probe for all standard types. This would have to
+ * be revisited if the backend ever allows renaming of array types.
*/
/* Make sure we are in proper schema */
constrinfo[j].contype = contype;
constrinfo[j].condef = NULL;
constrinfo[j].conindex = indxinfo[j].dobj.dumpId;
- constrinfo[j].coninherited = false;
+ constrinfo[j].conislocal = true;
constrinfo[j].separate = true;
indxinfo[j].indexconstraint = constrinfo[j].dobj.dumpId;
constrinfo[j].contype = 'f';
constrinfo[j].condef = strdup(PQgetvalue(res, j, i_condef));
constrinfo[j].conindex = 0;
- constrinfo[j].coninherited = false;
+ constrinfo[j].conislocal = true;
constrinfo[j].separate = true;
}
constrinfo[i].contype = 'c';
constrinfo[i].condef = strdup(PQgetvalue(res, i, i_consrc));
constrinfo[i].conindex = 0;
- constrinfo[i].coninherited = false;
+ constrinfo[i].conislocal = true;
constrinfo[i].separate = false;
/*
tbinfo->dobj.name);
resetPQExpBuffer(q);
- if (g_fout->remoteVersion >= 70400)
+ if (g_fout->remoteVersion >= 80400)
{
appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
- "pg_catalog.pg_get_constraintdef(oid) AS consrc "
+ "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
+ "conislocal "
+ "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)
+ {
+ appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
+ "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
+ "true as conislocal "
"FROM pg_catalog.pg_constraint "
"WHERE conrelid = '%u'::pg_catalog.oid "
" AND contype = 'c' "
{
/* no pg_get_constraintdef, must use consrc */
appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
- "'CHECK (' || consrc || ')' AS consrc "
+ "'CHECK (' || consrc || ')' AS consrc, "
+ "true as conislocal "
"FROM pg_catalog.pg_constraint "
"WHERE conrelid = '%u'::pg_catalog.oid "
" AND contype = 'c' "
/* 7.2 did not have OIDs in pg_relcheck */
appendPQExpBuffer(q, "SELECT tableoid, 0 as oid, "
"rcname AS conname, "
- "'CHECK (' || rcsrc || ')' AS consrc "
+ "'CHECK (' || rcsrc || ')' AS consrc, "
+ "true as conislocal "
"FROM pg_relcheck "
"WHERE rcrelid = '%u'::oid "
"ORDER BY rcname",
{
appendPQExpBuffer(q, "SELECT tableoid, oid, "
"rcname AS conname, "
- "'CHECK (' || rcsrc || ')' AS consrc "
+ "'CHECK (' || rcsrc || ')' AS consrc, "
+ "true as conislocal "
"FROM pg_relcheck "
"WHERE rcrelid = '%u'::oid "
"ORDER BY rcname",
appendPQExpBuffer(q, "SELECT "
"(SELECT oid FROM pg_class WHERE relname = 'pg_relcheck') AS tableoid, "
"oid, rcname AS conname, "
- "'CHECK (' || rcsrc || ')' AS consrc "
+ "'CHECK (' || rcsrc || ')' AS consrc, "
+ "true as conislocal "
"FROM pg_relcheck "
"WHERE rcrelid = '%u'::oid "
"ORDER BY rcname",
constrs[j].contype = 'c';
constrs[j].condef = strdup(PQgetvalue(res, j, 3));
constrs[j].conindex = 0;
- constrs[j].coninherited = false;
+ constrs[j].conislocal = (PQgetvalue(res, j, 4)[0] == 't');
constrs[j].separate = false;
constrs[j].dobj.dump = tbinfo->dobj.dump;
/*
* If the constraint is inherited, this will be detected
- * later. We also detect later if the constraint must be
- * split out from the table definition.
+ * later (in pre-8.4 databases). We also detect later if the
+ * constraint must be split out from the table definition.
*/
}
PQclear(res);
AssignDumpId(&prsinfo[i].dobj);
prsinfo[i].dobj.name = 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.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));
AssignDumpId(&dictinfo[i].dobj);
dictinfo[i].dobj.name = 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.catId.oid);
dictinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
dictinfo[i].dicttemplate = atooid(PQgetvalue(res, i, i_dicttemplate));
if (PQgetisnull(res, i, i_dictinitoption))
AssignDumpId(&tmplinfo[i].dobj);
tmplinfo[i].dobj.name = 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.catId.oid);
tmplinfo[i].tmplinit = atooid(PQgetvalue(res, i, i_tmplinit));
tmplinfo[i].tmpllexize = atooid(PQgetvalue(res, i, i_tmpllexize));
AssignDumpId(&cfginfo[i].dobj);
cfginfo[i].dobj.name = 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.catId.oid);
cfginfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));
PQExpBuffer delq = createPQExpBuffer();
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
- int num, i;
- char *label;
+ int num,
+ i;
+ char *label;
/* Set proper schema search path so regproc references list correctly */
selectSourceSchema(tinfo->dobj.namespace->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 functions are generic and do not get dropped.
+ * CASCADE shouldn't be required here as for normal types since the I/O
+ * functions are generic and do not get dropped.
*/
appendPQExpBuffer(delq, "DROP TYPE %s.",
fmtId(tinfo->dobj.namespace->dobj.name));
{
label = PQgetvalue(res, i, 0);
if (i > 0)
- appendPQExpBuffer(q, ",\n");
- appendPQExpBuffer(q, " ");
+ appendPQExpBuffer(q, ",\n");
+ appendPQExpBuffer(q, " ");
appendStringLiteralAH(q, label, fout);
}
appendPQExpBuffer(q, "\n);\n");
{
switch (argmodes[j][0])
{
- case 'i':
+ case PROARGMODE_IN:
argmode = "";
break;
- case 'o':
+ case PROARGMODE_OUT:
argmode = "OUT ";
break;
- case 'b':
+ case PROARGMODE_INOUT:
argmode = "INOUT ";
break;
+ case PROARGMODE_VARIADIC:
+ argmode = "VARIADIC ";
+ break;
default:
write_msg(NULL, "WARNING: bogus value in proargmodes array\n");
argmode = "";
lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
/*
- * See backend/commands/define.c for details of how the 'AS' clause is
- * used.
+ * See backend/commands/functioncmds.c for details of how the 'AS' clause
+ * is used. In 8.4 and up, an unused probin is NULL (here ""); previous
+ * versions would set it to "-". There are no known cases in which prosrc
+ * is unused, so the tests below for "-" are probably useless.
*/
- if (strcmp(probin, "-") != 0)
+ if (probin[0] != '\0' && strcmp(probin, "-") != 0)
{
appendPQExpBuffer(asPart, "AS ");
appendStringLiteralAH(asPart, probin, fout);
rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque);
appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcsig);
- appendPQExpBuffer(q, "RETURNS %s%s\n %s\n LANGUAGE %s",
+ appendPQExpBuffer(q, "RETURNS %s%s",
(proretset[0] == 't') ? "SETOF " : "",
- rettypename,
- asPart->data,
- fmtId(lanname));
-
+ rettypename);
free(rettypename);
+ appendPQExpBuffer(q, "\n LANGUAGE %s", fmtId(lanname));
if (provolatile[0] != PROVOLATILE_VOLATILE)
{
if (provolatile[0] == PROVOLATILE_IMMUTABLE)
/*
* COST and ROWS are emitted only if present and not default, so as not to
- * break backwards-compatibility of the dump without need. Keep this code
+ * break backwards-compatibility of the dump without need. Keep this code
* in sync with the defaults in functioncmds.c.
*/
if (strcmp(procost, "0") != 0)
appendPQExpBuffer(q, "\n SET %s TO ", fmtId(configitem));
/*
- * Some GUC variable names are 'LIST' type and hence must not be quoted.
+ * Some GUC variable names are 'LIST' type and hence must not be
+ * quoted.
*/
if (pg_strcasecmp(configitem, "DateStyle") == 0
|| pg_strcasecmp(configitem, "search_path") == 0)
appendStringLiteralAH(q, pos, fout);
}
- appendPQExpBuffer(q, ";\n");
+ appendPQExpBuffer(q, "\n %s;\n", asPart->data);
ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
funcsig_tag,
"nspname AS opcfamilynsp, "
"(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
"FROM pg_catalog.pg_opclass c "
- "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
- "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
+ "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
+ "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
"WHERE c.oid = '%u'::pg_catalog.oid",
opcinfo->dobj.catId.oid);
}
"opcdefault, "
"NULL AS opcfamily, "
"NULL AS opcfamilynsp, "
- "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
+ "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
"FROM pg_catalog.pg_opclass "
"WHERE oid = '%u'::pg_catalog.oid",
opcinfo->dobj.catId.oid);
*/
resetPQExpBuffer(query);
- if (g_fout->remoteVersion >= 80300)
+ if (g_fout->remoteVersion >= 80400)
+ {
+ /*
+ * Print only those opfamily members that are tied to the opclass by
+ * pg_depend entries.
+ *
+ * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
+ * an older server's table in which it is used. Would it be better
+ * to silently ignore it?
+ */
+ appendPQExpBuffer(query, "SELECT amopstrategy, false as amopreqcheck, "
+ "amopopr::pg_catalog.regoperator "
+ "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
+ "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+ "AND refobjid = '%u'::pg_catalog.oid "
+ "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
+ "AND objid = ao.oid "
+ "ORDER BY amopstrategy",
+ opcinfo->dobj.catId.oid);
+ }
+ else if (g_fout->remoteVersion >= 80300)
{
/*
- * Print only those opfamily members that are tied to the opclass
- * by pg_depend entries.
+ * Print only those opfamily members that are tied to the opclass by
+ * pg_depend entries.
*/
appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
"amopopr::pg_catalog.regoperator "
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
- "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+ "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
- "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
+ "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
"AND objid = ao.oid "
"ORDER BY amopstrategy",
opcinfo->dobj.catId.oid);
if (g_fout->remoteVersion >= 80300)
{
/*
- * Print only those opfamily members that are tied to the opclass
- * by pg_depend entries.
+ * Print only those opfamily members that are tied to the opclass by
+ * pg_depend entries.
*/
appendPQExpBuffer(query, "SELECT amprocnum, "
"amproc::pg_catalog.regprocedure "
- "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
- "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+ "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
+ "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
- "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
+ "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
"AND objid = ap.oid "
"ORDER BY amprocnum",
opcinfo->dobj.catId.oid);
* or functions, or (2) it contains an opclass with a different name or
* owner. Otherwise it's sufficient to let it be created during creation
* of the contained opclass, and not dumping it improves portability of
- * the dump. Since we have to fetch the loose operators/funcs anyway,
- * do that first.
+ * the dump. Since we have to fetch the loose operators/funcs anyway, do
+ * that first.
*/
query = createPQExpBuffer();
selectSourceSchema(opfinfo->dobj.namespace->dobj.name);
/*
- * Fetch only those opfamily members that are tied directly to the opfamily
- * by pg_depend entries.
+ * Fetch only those opfamily members that are tied directly to the
+ * opfamily by pg_depend entries.
*/
- appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
+ if (g_fout->remoteVersion >= 80400)
+ {
+ /*
+ * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
+ * an older server's table in which it is used. Would it be better
+ * to silently ignore it?
+ */
+ appendPQExpBuffer(query, "SELECT amopstrategy, false as amopreqcheck, "
+ "amopopr::pg_catalog.regoperator "
+ "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
+ "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+ "AND refobjid = '%u'::pg_catalog.oid "
+ "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
+ "AND objid = ao.oid "
+ "ORDER BY amopstrategy",
+ opfinfo->dobj.catId.oid);
+ }
+ else
+ {
+ appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
"amopopr::pg_catalog.regoperator "
"FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
- "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+ "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
- "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
+ "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
"AND objid = ao.oid "
"ORDER BY amopstrategy",
opfinfo->dobj.catId.oid);
+ }
res_ops = PQexec(g_conn, query->data);
check_sql_result(res_ops, g_conn, query->data, PGRES_TUPLES_OK);
"amproclefttype::pg_catalog.regtype, "
"amprocrighttype::pg_catalog.regtype "
"FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
- "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+ "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
"AND refobjid = '%u'::pg_catalog.oid "
- "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
+ "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
"AND objid = ap.oid "
"ORDER BY amprocnum",
opfinfo->dobj.catId.oid);
appendPQExpBuffer(query, "SELECT 1 "
"FROM pg_catalog.pg_opclass c, pg_catalog.pg_opfamily f, pg_catalog.pg_depend "
"WHERE f.oid = '%u'::pg_catalog.oid "
- "AND refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+ "AND refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
"AND refobjid = f.oid "
- "AND classid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+ "AND classid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
"AND objid = c.oid "
"AND (opcname != opfname OR opcnamespace != opfnamespace OR opcowner != opfowner) "
"LIMIT 1",
resetPQExpBuffer(query);
appendPQExpBuffer(query, "SELECT "
- "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opfmethod) AS amname "
+ "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opfmethod) AS amname "
"FROM pg_catalog.pg_opfamily "
"WHERE oid = '%u'::pg_catalog.oid",
opfinfo->dobj.catId.oid);
* write out a single text search parser
*/
static void
-dumpTSParser(Archive *fout, TSParserInfo * prsinfo)
+dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
{
PQExpBuffer q;
PQExpBuffer delq;
* write out a single text search dictionary
*/
static void
-dumpTSDictionary(Archive *fout, TSDictInfo * dictinfo)
+dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
{
PQExpBuffer q;
PQExpBuffer delq;
* write out a single text search template
*/
static void
-dumpTSTemplate(Archive *fout, TSTemplateInfo * tmplinfo)
+dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
{
PQExpBuffer q;
PQExpBuffer delq;
* write out a single text search configuration
*/
static void
-dumpTSConfig(Archive *fout, TSConfigInfo * cfginfo)
+dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
{
PQExpBuffer q;
PQExpBuffer delq;
for (i = 0; i < ntups; i++)
{
- char *tokenname = PQgetvalue(res, i, i_tokenname);
- char *dictname = PQgetvalue(res, i, i_dictname);
+ char *tokenname = PQgetvalue(res, i, i_tokenname);
+ char *dictname = PQgetvalue(res, i, i_dictname);
if (i == 0 ||
- strcmp(tokenname, PQgetvalue(res, i-1, i_tokenname)) != 0)
+ strcmp(tokenname, PQgetvalue(res, i - 1, i_tokenname)) != 0)
{
/* starting a new token type, so start a new command */
if (i > 0)
cfginfo->dobj.namespace->dobj.name,
NULL,
cfginfo->rolname,
- false, "TEXT SEARCH CONFIGURATION", q->data, delq->data, NULL,
+ false, "TEXT SEARCH CONFIGURATION", q->data, delq->data, NULL,
cfginfo->dobj.dependencies, cfginfo->dobj.nDeps,
NULL, NULL);
{
ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
- if (constr->coninherited || constr->separate)
+ if (constr->separate || !constr->conislocal)
continue;
if (actual_atts > 0)
{
ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
- if (constr->coninherited || constr->separate)
+ if (constr->separate || !constr->conislocal)
continue;
dumpTableConstraintComment(fout, constr);
dumpSequence(Archive *fout, TableInfo *tbinfo)
{
PGresult *res;
- char *last,
+ char *startv,
+ *last,
*incby,
*maxv = NULL,
*minv = NULL,
snprintf(bufm, sizeof(bufm), INT64_FORMAT, SEQ_MINVALUE);
snprintf(bufx, sizeof(bufx), INT64_FORMAT, SEQ_MAXVALUE);
- appendPQExpBuffer(query,
- "SELECT sequence_name, last_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 "
- "END AS max_value, "
- "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
- " 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",
- bufx, bufm,
- fmtId(tbinfo->dobj.name));
+ if (g_fout->remoteVersion >= 80400)
+ {
+ appendPQExpBuffer(query,
+ "SELECT sequence_name, "
+ "start_value, last_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 "
+ "END AS max_value, "
+ "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
+ " 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",
+ bufx, bufm,
+ fmtId(tbinfo->dobj.name));
+ }
+ else
+ {
+ appendPQExpBuffer(query,
+ "SELECT sequence_name, "
+ "0 as start_value, last_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 "
+ "END AS max_value, "
+ "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
+ " 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",
+ bufx, bufm,
+ fmtId(tbinfo->dobj.name));
+ }
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
}
#endif
- last = PQgetvalue(res, 0, 1);
- incby = PQgetvalue(res, 0, 2);
- if (!PQgetisnull(res, 0, 3))
- maxv = PQgetvalue(res, 0, 3);
+ startv = PQgetvalue(res, 0, 1);
+ last = PQgetvalue(res, 0, 2);
+ incby = PQgetvalue(res, 0, 3);
if (!PQgetisnull(res, 0, 4))
- minv = PQgetvalue(res, 0, 4);
- cache = PQgetvalue(res, 0, 5);
- cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0);
- called = (strcmp(PQgetvalue(res, 0, 7), "t") == 0);
+ 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);
/*
* 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.
+ * 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.
*/
"CREATE SEQUENCE %s\n",
fmtId(tbinfo->dobj.name));
- if (!called)
- appendPQExpBuffer(query, " START WITH %s\n", last);
+ 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);
+ }
appendPQExpBuffer(query, " INCREMENT BY %s\n", incby);
else
appendPQExpBuffer(query, " UPDATE");
}
+ if (TRIGGER_FOR_TRUNCATE(tginfo->tgtype))
+ {
+ if (findx > 0)
+ appendPQExpBuffer(query, " OR TRUNCATE");
+ else
+ appendPQExpBuffer(query, " TRUNCATE");
+ }
appendPQExpBuffer(query, " ON %s\n",
fmtId(tbinfo->dobj.name));
printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, 0, 0));
/*
- * Add the command to alter the rules replication firing semantics
- * if it differs from the default.
+ * Add the command to alter the rules replication firing semantics if it
+ * differs from the default.
*/
if (rinfo->ev_enabled != 'O')
{
appendPQExpBuffer(cmd, "ALTER TABLE %s.",
- fmtId(tbinfo->dobj.namespace->dobj.name));
+ fmtId(tbinfo->dobj.namespace->dobj.name));
appendPQExpBuffer(cmd, "%s ",
- fmtId(tbinfo->dobj.name));
+ fmtId(tbinfo->dobj.name));
switch (rinfo->ev_enabled)
{
case 'A':
appendPQExpBuffer(cmd, "ENABLE ALWAYS RULE %s;\n",
- fmtId(rinfo->dobj.name));
+ fmtId(rinfo->dobj.name));
break;
case 'R':
appendPQExpBuffer(cmd, "ENABLE REPLICA RULE %s;\n",
- fmtId(rinfo->dobj.name));
+ fmtId(rinfo->dobj.name));
break;
case 'D':
appendPQExpBuffer(cmd, "DISABLE RULE %s;\n",
- fmtId(rinfo->dobj.name));
+ fmtId(rinfo->dobj.name));
break;
}
}