OSDN Git Service

In binary-upgrade mode, dump dropped attributes of composite types.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sat, 21 May 2011 12:18:00 +0000 (08:18 -0400)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sat, 21 May 2011 12:24:34 +0000 (08:24 -0400)
Noah Misch

src/bin/pg_dump/pg_dump.c
src/test/regress/expected/alter_table.out
src/test/regress/sql/alter_table.sql

index c5eaa18..6faa885 100644 (file)
@@ -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);
index a6fb36e..26e7bfd 100644 (file)
@@ -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;
 --
index 4b2afe8..0ed16fb 100644 (file)
@@ -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;