diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index afc7fd7..13ba7dd 100644 *** a/src/bin/pg_dump/pg_dump.c --- b/src/bin/pg_dump/pg_dump.c *************** *** 7937,7942 **** static void --- 7937,7943 ---- dumpCompositeType(Archive *fout, TypeInfo *tyinfo) { PQExpBuffer q = createPQExpBuffer(); + PQExpBuffer dropped = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); PQExpBuffer labelq = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer(); *************** *** 7944,7952 **** dumpCompositeType(Archive *fout, TypeInfo *tyinfo) --- 7945,7957 ---- 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,7990 **** 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. */ appendPQExpBuffer(query, "SELECT a.attname, " "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, " "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 " "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 */ appendPQExpBuffer(query, "SELECT a.attname, " "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, " "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); } --- 7963,7999 ---- * 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. 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 " ! "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 " "ORDER BY a.attnum ", tyinfo->dobj.catId.oid); } else { ! /* ! * 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 " "ORDER BY a.attnum ", tyinfo->dobj.catId.oid); } *************** *** 7996,8001 **** dumpCompositeType(Archive *fout, TypeInfo *tyinfo) --- 8005,8013 ---- 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,8047 **** dumpCompositeType(Archive *fout, TypeInfo *tyinfo) appendPQExpBuffer(q, "CREATE TYPE %s AS (", fmtId(tyinfo->dobj.name)); for (i = 0; i < ntups; i++) { char *attname; char *atttypdefn; Oid attcollation; attname = PQgetvalue(res, i, i_attname); atttypdefn = PQgetvalue(res, i, i_atttypdefn); attcollation = atooid(PQgetvalue(res, i, i_attcollation)); ! appendPQExpBuffer(q, "\n\t%s %s", fmtId(attname), atttypdefn); ! /* Add collation if not default for the column type */ ! if (OidIsValid(attcollation)) { ! 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, ","); } appendPQExpBuffer(q, "\n);\n"); /* * DROP must be fully qualified in case same name appears in pg_catalog --- 8022,8096 ---- 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)); ! if (attisdropped && !binary_upgrade) ! continue; ! /* Format properly if not first attr */ ! if (actual_atts++ > 0) ! appendPQExpBuffer(q, ","); ! appendPQExpBuffer(q, "\n\t"); ! ! if (!attisdropped) { ! appendPQExpBuffer(q, "%s %s", fmtId(attname), atttypdefn); ! /* Add collation if not default for the column type */ ! if (OidIsValid(attcollation)) { ! 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)); ! } } } ! else /* binary_upgrade - see under 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,8082 **** dumpCompositeType(Archive *fout, TypeInfo *tyinfo) --- 8126,8132 ---- PQclear(res); destroyPQExpBuffer(q); + destroyPQExpBuffer(dropped); destroyPQExpBuffer(delq); destroyPQExpBuffer(labelq); destroyPQExpBuffer(query); diff --git a/src/test/regress/exindex a6fb36e..dd814af 100644 *** a/src/test/regress/expected/alter_table.out --- b/src/test/regress/expected/alter_table.out *************** *** 1955,1960 **** Table "public.test_tbl2_subclass" --- 1955,1963 ---- Inherits: test_tbl2 DROP TABLE test_tbl2_subclass; + 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.sqindex 4b2afe8..6cede13 100644 *** a/src/test/regress/sql/alter_table.sql --- b/src/test/regress/sql/alter_table.sql *************** *** 1371,1376 **** ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE; --- 1371,1380 ---- DROP TABLE test_tbl2_subclass; + 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;