aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/pg_dump/pg_dump.c100
-rw-r--r--src/test/regress/expected/alter_table.out6
-rw-r--r--src/test/regress/sql/alter_table.sql7
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 c5eaa189b94..6faa88527f3 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 a6fb36e2d97..26e7bfd8c2f 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 4b2afe8bc93..0ed16fb7cf9 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;