From 27c7875d95cf629e3f344ba91d1f8a1a936ed043 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Sat, 21 May 2011 08:18:00 -0400 Subject: [PATCH] In binary-upgrade mode, dump dropped attributes of composite types. Noah Misch --- src/bin/pg_dump/pg_dump.c | 100 +++++++++++++++++++++++------- src/test/regress/expected/alter_table.out | 6 ++ src/test/regress/sql/alter_table.sql | 7 +++ 3 files changed, 91 insertions(+), 22 deletions(-) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index c5eaa189b9..6faa88527f 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -7937,6 +7937,7 @@ static void dumpCompositeType(Archive *fout, TypeInfo *tyinfo) { PQExpBuffer q = createPQExpBuffer(); + PQExpBuffer dropped = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); PQExpBuffer labelq = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer(); @@ -7944,9 +7945,13 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) int ntups; int i_attname; int i_atttypdefn; + int i_attlen; + int i_attalign; + int i_attisdropped; int i_attcollation; int i_typrelid; int i; + int actual_atts; /* Set proper schema search path so type references list correctly */ selectSourceSchema(tyinfo->dobj.namespace->dobj.name); @@ -7958,33 +7963,37 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) * attcollation is new in 9.1. Since we only want to dump COLLATE * clauses for attributes whose collation is different from their * type's default, we use a CASE here to suppress uninteresting - * attcollations cheaply. + * attcollations cheaply. atttypid will be 0 for dropped columns; + * collation does not matter for those. */ appendPQExpBuffer(query, "SELECT a.attname, " "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, " + "a.attlen, a.attalign, a.attisdropped, " "CASE WHEN a.attcollation <> at.typcollation " "THEN a.attcollation ELSE 0 END AS attcollation, " "ct.typrelid " - "FROM pg_catalog.pg_type ct, pg_catalog.pg_attribute a, " - "pg_catalog.pg_type at " + "FROM pg_catalog.pg_type ct " + "JOIN pg_catalog.pg_attribute a ON a.attrelid = ct.typrelid " + "LEFT JOIN pg_catalog.pg_type at ON at.oid = a.atttypid " "WHERE ct.oid = '%u'::pg_catalog.oid " - "AND a.attrelid = ct.typrelid " - "AND a.atttypid = at.oid " - "AND NOT a.attisdropped " "ORDER BY a.attnum ", tyinfo->dobj.catId.oid); } else { - /* We assume here that remoteVersion must be at least 70300 */ + /* + * We assume here that remoteVersion must be at least 70300. Since + * ALTER TYPE could not drop columns until 9.1, attisdropped should + * always be false. + */ appendPQExpBuffer(query, "SELECT a.attname, " "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, " + "a.attlen, a.attalign, a.attisdropped, " "0 AS attcollation, " "ct.typrelid " "FROM pg_catalog.pg_type ct, pg_catalog.pg_attribute a " "WHERE ct.oid = '%u'::pg_catalog.oid " "AND a.attrelid = ct.typrelid " - "AND NOT a.attisdropped " "ORDER BY a.attnum ", tyinfo->dobj.catId.oid); } @@ -7996,6 +8005,9 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) i_attname = PQfnumber(res, "attname"); i_atttypdefn = PQfnumber(res, "atttypdefn"); + i_attlen = PQfnumber(res, "attlen"); + i_attalign = PQfnumber(res, "attalign"); + i_attisdropped = PQfnumber(res, "attisdropped"); i_attcollation = PQfnumber(res, "attcollation"); i_typrelid = PQfnumber(res, "typrelid"); @@ -8010,38 +8022,81 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) appendPQExpBuffer(q, "CREATE TYPE %s AS (", fmtId(tyinfo->dobj.name)); + actual_atts = 0; for (i = 0; i < ntups; i++) { char *attname; char *atttypdefn; + char *attlen; + char *attalign; + bool attisdropped; Oid attcollation; attname = PQgetvalue(res, i, i_attname); atttypdefn = PQgetvalue(res, i, i_atttypdefn); + attlen = PQgetvalue(res, i, i_attlen); + attalign = PQgetvalue(res, i, i_attalign); + attisdropped = (PQgetvalue(res, i, i_attisdropped)[0] == 't'); attcollation = atooid(PQgetvalue(res, i, i_attcollation)); - appendPQExpBuffer(q, "\n\t%s %s", fmtId(attname), atttypdefn); + if (attisdropped && !binary_upgrade) + continue; + + /* Format properly if not first attr */ + if (actual_atts++ > 0) + appendPQExpBuffer(q, ","); + appendPQExpBuffer(q, "\n\t"); - /* Add collation if not default for the column type */ - if (OidIsValid(attcollation)) + if (!attisdropped) { - CollInfo *coll; + appendPQExpBuffer(q, "%s %s", fmtId(attname), atttypdefn); - coll = findCollationByOid(attcollation); - if (coll) + /* Add collation if not default for the column type */ + if (OidIsValid(attcollation)) { - /* 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)); + CollInfo *coll; + + coll = findCollationByOid(attcollation); + 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)); + } } } - - if (i < ntups - 1) - appendPQExpBuffer(q, ","); + else + { + /* + * This is a dropped attribute and we're in binary_upgrade mode. + * Insert a placeholder for it in the CREATE TYPE command, and + * set length and alignment with direct UPDATE to the catalogs + * afterwards. See similar code in dumpTableSchema(). + */ + appendPQExpBuffer(q, "%s INTEGER /* dummy */", fmtId(attname)); + + /* stash separately for insertion after the CREATE TYPE */ + appendPQExpBuffer(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"); + + appendPQExpBuffer(dropped, "ALTER TYPE %s ", + fmtId(tyinfo->dobj.name)); + appendPQExpBuffer(dropped, "DROP ATTRIBUTE %s;\n", + fmtId(attname)); + } } appendPQExpBuffer(q, "\n);\n"); + appendPQExpBufferStr(q, dropped->data); /* * DROP must be fully qualified in case same name appears in pg_catalog @@ -8077,6 +8132,7 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo) PQclear(res); destroyPQExpBuffer(q); + destroyPQExpBuffer(dropped); destroyPQExpBuffer(delq); destroyPQExpBuffer(labelq); destroyPQExpBuffer(query); diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index a6fb36e2d9..26e7bfd8c2 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -1955,6 +1955,12 @@ Table "public.test_tbl2_subclass" Inherits: test_tbl2 DROP TABLE test_tbl2_subclass; +-- This test isn't that interesting on its own, but the purpose is to leave +-- behind a table to test pg_upgrade with. The table has a composite type +-- column in it, and the composite type has a dropped attribute. +CREATE TYPE test_type3 AS (a int); +CREATE TABLE test_tbl3 (c) AS SELECT '(1)'::test_type3; +ALTER TYPE test_type3 DROP ATTRIBUTE a, ADD ATTRIBUTE b int; CREATE TYPE test_type_empty AS (); DROP TYPE test_type_empty; -- diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index 4b2afe8bc9..0ed16fb7cf 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -1371,6 +1371,13 @@ ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE; DROP TABLE test_tbl2_subclass; +-- This test isn't that interesting on its own, but the purpose is to leave +-- behind a table to test pg_upgrade with. The table has a composite type +-- column in it, and the composite type has a dropped attribute. +CREATE TYPE test_type3 AS (a int); +CREATE TABLE test_tbl3 (c) AS SELECT '(1)'::test_type3; +ALTER TYPE test_type3 DROP ATTRIBUTE a, ADD ATTRIBUTE b int; + CREATE TYPE test_type_empty AS (); DROP TYPE test_type_empty; -- 2.11.0