Commit 53fa850c authored by Tom Lane's avatar Tom Lane

Fix up pg_dump's --binary-upgrade option so that it behaves properly with

inherited columns and check constraints.  Per my recent trouble report.
parent 7cc514ac
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.539 2009/06/11 14:49:07 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.540 2009/07/02 21:34:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -233,7 +233,7 @@ main(int argc, char **argv) ...@@ -233,7 +233,7 @@ main(int argc, char **argv)
static int outputNoTablespaces = 0; static int outputNoTablespaces = 0;
static int use_setsessauth = 0; static int use_setsessauth = 0;
struct option long_options[] = { static struct option long_options[] = {
{"data-only", no_argument, NULL, 'a'}, {"data-only", no_argument, NULL, 'a'},
{"blobs", no_argument, NULL, 'b'}, {"blobs", no_argument, NULL, 'b'},
{"clean", no_argument, NULL, 'c'}, {"clean", no_argument, NULL, 'c'},
...@@ -1733,7 +1733,7 @@ dumpDatabase(Archive *AH) ...@@ -1733,7 +1733,7 @@ dumpDatabase(Archive *AH)
if (binary_upgrade) if (binary_upgrade)
{ {
appendPQExpBuffer(creaQry, "\n-- For binary upgrade, set datfrozenxid.\n"); appendPQExpBuffer(creaQry, "\n-- For binary upgrade, set datfrozenxid.\n");
appendPQExpBuffer(creaQry, "UPDATE pg_database\n" appendPQExpBuffer(creaQry, "UPDATE pg_catalog.pg_database\n"
"SET datfrozenxid = '%u'\n" "SET datfrozenxid = '%u'\n"
"WHERE datname = ", "WHERE datname = ",
frozenxid); frozenxid);
...@@ -4712,8 +4712,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables) ...@@ -4712,8 +4712,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, " appendPQExpBuffer(q, "SELECT a.attnum, a.attname, "
"a.atttypmod, -1 AS attstattarget, a.attstorage, " "a.atttypmod, -1 AS attstattarget, a.attstorage, "
"t.typstorage, a.attnotnull, a.atthasdef, " "t.typstorage, a.attnotnull, a.atthasdef, "
"false AS attisdropped, 0 AS attlen, " "false AS attisdropped, a.attlen, "
"' ' AS attalign, false AS attislocal, " "a.attalign, false AS attislocal, "
"format_type(t.oid,a.atttypmod) AS atttypname " "format_type(t.oid,a.atttypmod) AS atttypname "
"FROM pg_attribute a LEFT JOIN pg_type t " "FROM pg_attribute a LEFT JOIN pg_type t "
"ON a.atttypid = t.oid " "ON a.atttypid = t.oid "
...@@ -4729,7 +4729,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables) ...@@ -4729,7 +4729,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"-1 AS attstattarget, attstorage, " "-1 AS attstattarget, attstorage, "
"attstorage AS typstorage, " "attstorage AS typstorage, "
"attnotnull, atthasdef, false AS attisdropped, " "attnotnull, atthasdef, false AS attisdropped, "
"0 AS attlen, ' ' AS attalign, " "attlen, attalign, "
"false AS attislocal, " "false AS attislocal, "
"(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname " "(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname "
"FROM pg_attribute a " "FROM pg_attribute a "
...@@ -4806,20 +4806,6 @@ getTableAttrs(TableInfo *tblinfo, int numTables) ...@@ -4806,20 +4806,6 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
PQclear(res); PQclear(res);
/*
* ALTER TABLE DROP COLUMN clears pg_attribute.atttypid, so we set the
* column data type to 'TEXT; we will later drop the column.
*/
if (binary_upgrade)
{
for (j = 0; j < ntups; j++)
{
if (tbinfo->attisdropped[j])
tbinfo->atttypnames[j] = strdup("TEXT");
}
}
/* /*
* Get info about column defaults * Get info about column defaults
*/ */
...@@ -9783,19 +9769,35 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -9783,19 +9769,35 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
actual_atts = 0; actual_atts = 0;
for (j = 0; j < tbinfo->numatts; j++) for (j = 0; j < tbinfo->numatts; j++)
{ {
/* Is this one of the table's own attrs, and not dropped ? */ /*
if (!tbinfo->inhAttrs[j] && * Normally, dump if it's one of the table's own attrs, and not
(!tbinfo->attisdropped[j] || binary_upgrade)) * dropped. But for binary upgrade, dump all the columns.
*/
if ((!tbinfo->inhAttrs[j] && !tbinfo->attisdropped[j]) ||
binary_upgrade)
{ {
/* Format properly if not first attr */ /* Format properly if not first attr */
if (actual_atts > 0) if (actual_atts > 0)
appendPQExpBuffer(q, ","); appendPQExpBuffer(q, ",");
appendPQExpBuffer(q, "\n "); appendPQExpBuffer(q, "\n ");
actual_atts++;
/* Attribute name */ /* Attribute name */
appendPQExpBuffer(q, "%s ", appendPQExpBuffer(q, "%s ",
fmtId(tbinfo->attnames[j])); 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.
*/
appendPQExpBuffer(q, "INTEGER /* dummy */");
/* Skip all the rest, too */
continue;
}
/* Attribute type */ /* Attribute type */
if (g_fout->remoteVersion >= 70100) if (g_fout->remoteVersion >= 70100)
{ {
...@@ -9811,22 +9813,23 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -9811,22 +9813,23 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
} }
/* /*
* Default value --- suppress if inherited or to be printed * Default value --- suppress if inherited (except in
* separately. * binary-upgrade case, where we're not doing normal
* inheritance) or if it's to be printed separately.
*/ */
if (tbinfo->attrdefs[j] != NULL && if (tbinfo->attrdefs[j] != NULL &&
!tbinfo->inhAttrDef[j] && (!tbinfo->inhAttrDef[j] || binary_upgrade) &&
!tbinfo->attrdefs[j]->separate) !tbinfo->attrdefs[j]->separate)
appendPQExpBuffer(q, " DEFAULT %s", appendPQExpBuffer(q, " DEFAULT %s",
tbinfo->attrdefs[j]->adef_expr); tbinfo->attrdefs[j]->adef_expr);
/* /*
* Not Null constraint --- suppress if inherited * Not Null constraint --- suppress if inherited, except
* in binary-upgrade case.
*/ */
if (tbinfo->notnull[j] && !tbinfo->inhNotNull[j]) if (tbinfo->notnull[j] &&
(!tbinfo->inhNotNull[j] || binary_upgrade))
appendPQExpBuffer(q, " NOT NULL"); appendPQExpBuffer(q, " NOT NULL");
actual_atts++;
} }
} }
...@@ -9852,7 +9855,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -9852,7 +9855,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
appendPQExpBuffer(q, "\n)"); appendPQExpBuffer(q, "\n)");
if (numParents > 0) if (numParents > 0 && !binary_upgrade)
{ {
appendPQExpBuffer(q, "\nINHERITS ("); appendPQExpBuffer(q, "\nINHERITS (");
for (k = 0; k < numParents; k++) for (k = 0; k < numParents; k++)
...@@ -9892,8 +9895,16 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -9892,8 +9895,16 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
appendPQExpBuffer(q, ";\n"); appendPQExpBuffer(q, ";\n");
/* /*
* For binary-compatible heap files, we create dropped columns above * To create binary-compatible heap files, we have to ensure the
* and drop them here. * same physical column order, including dropped columns, as in the
* original. Therefore, we create dropped columns above and drop
* them here, also updating their attlen/attalign values so that
* the dropped column can be skipped properly. (We do not bother
* with restoring the original attbyval setting.) Also, inheritance
* relationships are set up by doing ALTER INHERIT rather than using
* an INHERITS clause --- the latter would possibly mess up the
* column order. That also means we have to take care about setting
* attislocal correctly, plus fix up any inherited CHECK constraints.
*/ */
if (binary_upgrade) if (binary_upgrade)
{ {
...@@ -9901,50 +9912,82 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -9901,50 +9912,82 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
{ {
if (tbinfo->attisdropped[j]) if (tbinfo->attisdropped[j])
{ {
appendPQExpBuffer(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"
"WHERE attname = ",
tbinfo->attlen[j],
tbinfo->attalign[j]);
appendStringLiteralAH(q, tbinfo->attnames[j], fout);
appendPQExpBuffer(q, "\n AND attrelid = ");
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ", appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
fmtId(tbinfo->dobj.name)); fmtId(tbinfo->dobj.name));
appendPQExpBuffer(q, "DROP COLUMN %s;\n", appendPQExpBuffer(q, "DROP COLUMN %s;\n",
fmtId(tbinfo->attnames[j])); 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"
"SET attislocal = false\n"
"WHERE attname = ");
appendStringLiteralAH(q, tbinfo->attnames[j], fout);
appendPQExpBuffer(q, "\n AND attrelid = ");
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
}
}
/* for (k = 0; k < tbinfo->ncheck; k++)
* ALTER TABLE DROP COLUMN clears pg_attribute.atttypid, {
* so we have to set pg_attribute.attlen and ConstraintInfo *constr = &(tbinfo->checkexprs[k]);
* pg_attribute.attalign values because that is what is
* used to skip over dropped columns in the heap tuples. if (constr->separate || constr->conislocal)
* We have atttypmod, but it seems impossible to know the continue;
* correct data type that will yield pg_attribute values
* that match the old installation. See comment in appendPQExpBuffer(q, "\n-- For binary upgrade, set up inherited constraint.\n");
* backend/catalog/heap.c::RemoveAttributeById() appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
*/ fmtId(tbinfo->dobj.name));
appendPQExpBuffer(q, "\n-- For binary upgrade, recreate dropped column's length and alignment.\n"); appendPQExpBuffer(q, " ADD CONSTRAINT %s ",
appendPQExpBuffer(q, "UPDATE pg_attribute\n" fmtId(constr->dobj.name));
"SET attlen = %d, " appendPQExpBuffer(q, "%s;\n", constr->condef);
"attalign = '%c'\n" appendPQExpBuffer(q, "UPDATE pg_catalog.pg_constraint\n"
"WHERE attname = '%s'\n" "SET conislocal = false\n"
" AND attrelid = \n" "WHERE contype = 'c' AND conname = ");
" (\n" appendStringLiteralAH(q, constr->dobj.name, fout);
" SELECT oid\n" appendPQExpBuffer(q, "\n AND conrelid = ");
" FROM pg_class\n" appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
" WHERE relnamespace = " appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
"(SELECT oid FROM pg_namespace "
"WHERE nspname = CURRENT_SCHEMA)\n"
" AND relname = ",
tbinfo->attlen[j],
tbinfo->attalign[j],
tbinfo->attnames[j]);
appendStringLiteralAH(q, tbinfo->dobj.name, fout);
appendPQExpBuffer(q, "\n );\n");
} }
if (numParents > 0)
{
appendPQExpBuffer(q, "\n-- For binary upgrade, set up inheritance this way.\n");
for (k = 0; k < numParents; k++)
{
TableInfo *parentRel = parents[k];
appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT ",
fmtId(tbinfo->dobj.name));
if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
appendPQExpBuffer(q, "%s.",
fmtId(parentRel->dobj.namespace->dobj.name));
appendPQExpBuffer(q, "%s;\n",
fmtId(parentRel->dobj.name));
} }
}
appendPQExpBuffer(q, "\n-- For binary upgrade, set relfrozenxid.\n"); appendPQExpBuffer(q, "\n-- For binary upgrade, set relfrozenxid.\n");
appendPQExpBuffer(q, "UPDATE pg_class\n" appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
"SET relfrozenxid = '%u'\n" "SET relfrozenxid = '%u'\n"
"WHERE relname = ", "WHERE oid = ",
tbinfo->frozenxid); tbinfo->frozenxid);
appendStringLiteralAH(q, tbinfo->dobj.name, fout); appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
appendPQExpBuffer(q, "\n AND relnamespace = " appendPQExpBuffer(q, "::pg_catalog.regclass;\n");
"(SELECT oid FROM pg_namespace "
"WHERE nspname = CURRENT_SCHEMA);\n");
} }
/* Loop dumping statistics and storage statements */ /* Loop dumping statistics and storage statements */
...@@ -10051,8 +10094,8 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo) ...@@ -10051,8 +10094,8 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly) if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly)
return; return;
/* Don't print inherited defaults, either */ /* Don't print inherited defaults, either, except for binary upgrade */
if (tbinfo->inhAttrDef[adnum - 1]) if (tbinfo->inhAttrDef[adnum - 1] && !binary_upgrade)
return; return;
q = createPQExpBuffer(); q = createPQExpBuffer();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment