]> granicus.if.org Git - postgresql/commitdiff
Fix pg_dump to assign domain array type OIDs during pg_upgrade.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 30 Sep 2017 21:05:07 +0000 (17:05 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 30 Sep 2017 21:05:07 +0000 (17:05 -0400)
During a binary upgrade, all type OIDs are supposed to be assigned by
pg_dump based on their values in the old cluster.  But now that domains
have arrays, there's nothing to base the arrays' type OIDs on, if we're
upgrading from a pre-v11 cluster.  Make pg_dump search for an unused type
OID to use for this purpose.  Per buildfarm.

Discussion: https://postgr.es/m/E1dyLlE-0002gT-H5@gemulon.postgresql.org

src/bin/pg_dump/pg_dump.c

index 75f08cd7924a450c2ba6f58ed0558673337b3bc3..e34c83acd2a6c42f2257d83203d91a61b04874ce 100644 (file)
@@ -253,7 +253,9 @@ static void dumpDatabase(Archive *AH);
 static void dumpEncoding(Archive *AH);
 static void dumpStdStrings(Archive *AH);
 static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
-                                                                                PQExpBuffer upgrade_buffer, Oid pg_type_oid);
+                                                                                PQExpBuffer upgrade_buffer,
+                                                                                Oid pg_type_oid,
+                                                                                bool force_array_type);
 static bool binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
                                                                                PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
 static void binary_upgrade_set_pg_class_oids(Archive *fout,
@@ -3949,10 +3951,11 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
 static void
 binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
                                                                                 PQExpBuffer upgrade_buffer,
-                                                                                Oid pg_type_oid)
+                                                                                Oid pg_type_oid,
+                                                                                bool force_array_type)
 {
        PQExpBuffer upgrade_query = createPQExpBuffer();
-       PGresult   *upgrade_res;
+       PGresult   *res;
        Oid                     pg_type_array_oid;
 
        appendPQExpBufferStr(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type oid\n");
@@ -3964,12 +3967,43 @@ binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
        appendPQExpBuffer(upgrade_query,
                                          "SELECT typarray "
                                          "FROM pg_catalog.pg_type "
-                                         "WHERE pg_type.oid = '%u'::pg_catalog.oid;",
+                                         "WHERE oid = '%u'::pg_catalog.oid;",
                                          pg_type_oid);
 
-       upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
+       res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
+
+       pg_type_array_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typarray")));
 
-       pg_type_array_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "typarray")));
+       PQclear(res);
+
+       if (!OidIsValid(pg_type_array_oid) && force_array_type)
+       {
+               /*
+                * If the old version didn't assign an array type, but the new version
+                * does, we must select an unused type OID to assign.  This currently
+                * only happens for domains, when upgrading pre-v11 to v11 and up.
+                *
+                * Note: local state here is kind of ugly, but we must have some,
+                * since we mustn't choose the same unused OID more than once.
+                */
+               static Oid      next_possible_free_oid = FirstNormalObjectId;
+               bool            is_dup;
+
+               do
+               {
+                       ++next_possible_free_oid;
+                       printfPQExpBuffer(upgrade_query,
+                                                         "SELECT EXISTS(SELECT 1 "
+                                                         "FROM pg_catalog.pg_type "
+                                                         "WHERE oid = '%u'::pg_catalog.oid);",
+                                                         next_possible_free_oid);
+                       res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
+                       is_dup = (PQgetvalue(res, 0, 0)[0] == 't');
+                       PQclear(res);
+               } while (is_dup);
+
+               pg_type_array_oid = next_possible_free_oid;
+       }
 
        if (OidIsValid(pg_type_array_oid))
        {
@@ -3980,7 +4014,6 @@ binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
                                                  pg_type_array_oid);
        }
 
-       PQclear(upgrade_res);
        destroyPQExpBuffer(upgrade_query);
 }
 
@@ -4008,7 +4041,7 @@ binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
        pg_type_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "crel")));
 
        binary_upgrade_set_type_oids_by_type_oid(fout, upgrade_buffer,
-                                                                                        pg_type_oid);
+                                                                                        pg_type_oid, false);
 
        if (!PQgetisnull(upgrade_res, 0, PQfnumber(upgrade_res, "trel")))
        {
@@ -9840,7 +9873,8 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
 
        if (dopt->binary_upgrade)
                binary_upgrade_set_type_oids_by_type_oid(fout, q,
-                                                                                                tyinfo->dobj.catId.oid);
+                                                                                                tyinfo->dobj.catId.oid,
+                                                                                                false);
 
        appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (",
                                          qtypname);
@@ -9976,8 +10010,9 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
                                          qtypname);
 
        if (dopt->binary_upgrade)
-               binary_upgrade_set_type_oids_by_type_oid(fout,
-                                                                                                q, tyinfo->dobj.catId.oid);
+               binary_upgrade_set_type_oids_by_type_oid(fout, q,
+                                                                                                tyinfo->dobj.catId.oid,
+                                                                                                false);
 
        appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (",
                                          qtypname);
@@ -10091,8 +10126,9 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo)
                                          qtypname);
 
        if (dopt->binary_upgrade)
-               binary_upgrade_set_type_oids_by_type_oid(fout,
-                                                                                                q, tyinfo->dobj.catId.oid);
+               binary_upgrade_set_type_oids_by_type_oid(fout, q,
+                                                                                                tyinfo->dobj.catId.oid,
+                                                                                                false);
 
        appendPQExpBuffer(q, "CREATE TYPE %s;\n",
                                          qtypname);
@@ -10296,10 +10332,14 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
        appendPQExpBuffer(delq, "%s CASCADE;\n",
                                          qtypname);
 
-       /* We might already have a shell type, but setting pg_type_oid is harmless */
+       /*
+        * We might already have a shell type, but setting pg_type_oid is
+        * harmless, and in any case we'd better set the array type OID.
+        */
        if (dopt->binary_upgrade)
                binary_upgrade_set_type_oids_by_type_oid(fout, q,
-                                                                                                tyinfo->dobj.catId.oid);
+                                                                                                tyinfo->dobj.catId.oid,
+                                                                                                false);
 
        appendPQExpBuffer(q,
                                          "CREATE TYPE %s (\n"
@@ -10490,7 +10530,8 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
 
        if (dopt->binary_upgrade)
                binary_upgrade_set_type_oids_by_type_oid(fout, q,
-                                                                                                tyinfo->dobj.catId.oid);
+                                                                                                tyinfo->dobj.catId.oid,
+                                                                                                true); /* force array type */
 
        qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
 
@@ -10692,7 +10733,8 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
        if (dopt->binary_upgrade)
        {
                binary_upgrade_set_type_oids_by_type_oid(fout, q,
-                                                                                                tyinfo->dobj.catId.oid);
+                                                                                                tyinfo->dobj.catId.oid,
+                                                                                                false);
                binary_upgrade_set_pg_class_oids(fout, q, tyinfo->typrelid, false);
        }
 
@@ -10967,7 +11009,8 @@ dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
 
        if (dopt->binary_upgrade)
                binary_upgrade_set_type_oids_by_type_oid(fout, q,
-                                                                                                stinfo->baseType->dobj.catId.oid);
+                                                                                                stinfo->baseType->dobj.catId.oid,
+                                                                                                false);
 
        appendPQExpBuffer(q, "CREATE TYPE %s;\n",
                                          fmtId(stinfo->dobj.name));