diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index be5f108f0a..b64171d275 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -229,7 +229,8 @@ old_9_3_check_for_line_data_type_usage(ClusterInfo *cluster) * mid-upgrade. Worse, if there's a matview with such a column, the * DDL reload will silently change it to "text" which won't match the * on-disk storage (which is like "cstring"). So we *must* reject that. - * Also check composite types, in case they are used for table columns. + * Also check composite types and domains on the "unknwown" type (even + * combinations of both), in case they are used for table columns. * We needn't check indexes, because "unknown" has no opclasses. */ void @@ -256,17 +257,40 @@ old_9_6_check_for_unknown_data_type_usage(ClusterInfo *cluster) DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; PGconn *conn = connectToServer(cluster, active_db->db_name); + /* + * The pg_catalog.unknown type may be wrapped in a domain or composite + * type, or both (9.3 did not allow domains on composite types, but + * there may be multi-level composite type). To detect these cases + * we need a recursive CTE. + */ res = executeQueryOrDie(conn, + "WITH RECURSIVE oids AS ( " + /* the pg_catalog.unknown type itself */ + " SELECT 'pg_catalog.unknown'::pg_catalog.regtype AS oid " + " UNION ALL " + " SELECT * FROM ( " + /* domains on the type */ + " WITH x AS (SELECT oid FROM oids) " + " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typbasetype = x.oid AND typtype = 'd' " + " UNION " + /* composite types containing the type */ + " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_class c, pg_catalog.pg_attribute a, x " + " WHERE t.typtype = 'c' AND " + " t.oid = c.reltype AND " + " c.oid = a.attrelid AND " + " NOT a.attisdropped AND " + " a.atttypid = x.oid " + " ) foo " + ") " "SELECT n.nspname, c.relname, a.attname " "FROM pg_catalog.pg_class c, " " pg_catalog.pg_namespace n, " " pg_catalog.pg_attribute a " "WHERE c.oid = a.attrelid AND " " NOT a.attisdropped AND " - " a.atttypid = 'pg_catalog.unknown'::pg_catalog.regtype AND " + " a.atttypid IN (SELECT oid FROM oids) AND " " c.relkind IN (" CppAsString2(RELKIND_RELATION) ", " - CppAsString2(RELKIND_COMPOSITE_TYPE) ", " CppAsString2(RELKIND_MATVIEW) ") AND " " c.relnamespace = n.oid AND " /* exclude possible orphaned temp tables */