Fix pg_dump to assign domain array type OIDs during pg_upgrade.

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
This commit is contained in:
Tom Lane 2017-09-30 17:05:07 -04:00
parent c12d570fa1
commit 2632bcce5e
1 changed files with 61 additions and 18 deletions

View File

@ -253,7 +253,9 @@ static void dumpDatabase(Archive *AH);
static void dumpEncoding(Archive *AH); static void dumpEncoding(Archive *AH);
static void dumpStdStrings(Archive *AH); static void dumpStdStrings(Archive *AH);
static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout, 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, static bool binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
PQExpBuffer upgrade_buffer, Oid pg_rel_oid); PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
static void binary_upgrade_set_pg_class_oids(Archive *fout, static void binary_upgrade_set_pg_class_oids(Archive *fout,
@ -3949,10 +3951,11 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
static void static void
binary_upgrade_set_type_oids_by_type_oid(Archive *fout, binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
PQExpBuffer upgrade_buffer, PQExpBuffer upgrade_buffer,
Oid pg_type_oid) Oid pg_type_oid,
bool force_array_type)
{ {
PQExpBuffer upgrade_query = createPQExpBuffer(); PQExpBuffer upgrade_query = createPQExpBuffer();
PGresult *upgrade_res; PGresult *res;
Oid pg_type_array_oid; Oid pg_type_array_oid;
appendPQExpBufferStr(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type oid\n"); 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, appendPQExpBuffer(upgrade_query,
"SELECT typarray " "SELECT typarray "
"FROM pg_catalog.pg_type " "FROM pg_catalog.pg_type "
"WHERE pg_type.oid = '%u'::pg_catalog.oid;", "WHERE oid = '%u'::pg_catalog.oid;",
pg_type_oid); pg_type_oid);
upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data); res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
pg_type_array_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "typarray"))); pg_type_array_oid = atooid(PQgetvalue(res, 0, PQfnumber(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)) if (OidIsValid(pg_type_array_oid))
{ {
@ -3980,7 +4014,6 @@ binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
pg_type_array_oid); pg_type_array_oid);
} }
PQclear(upgrade_res);
destroyPQExpBuffer(upgrade_query); 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"))); pg_type_oid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "crel")));
binary_upgrade_set_type_oids_by_type_oid(fout, upgrade_buffer, 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"))) if (!PQgetisnull(upgrade_res, 0, PQfnumber(upgrade_res, "trel")))
{ {
@ -9840,7 +9873,8 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
if (dopt->binary_upgrade) if (dopt->binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(fout, q, 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 (", appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (",
qtypname); qtypname);
@ -9976,8 +10010,9 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
qtypname); qtypname);
if (dopt->binary_upgrade) if (dopt->binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(fout, binary_upgrade_set_type_oids_by_type_oid(fout, q,
q, tyinfo->dobj.catId.oid); tyinfo->dobj.catId.oid,
false);
appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (", appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (",
qtypname); qtypname);
@ -10091,8 +10126,9 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo)
qtypname); qtypname);
if (dopt->binary_upgrade) if (dopt->binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(fout, binary_upgrade_set_type_oids_by_type_oid(fout, q,
q, tyinfo->dobj.catId.oid); tyinfo->dobj.catId.oid,
false);
appendPQExpBuffer(q, "CREATE TYPE %s;\n", appendPQExpBuffer(q, "CREATE TYPE %s;\n",
qtypname); qtypname);
@ -10296,10 +10332,14 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
appendPQExpBuffer(delq, "%s CASCADE;\n", appendPQExpBuffer(delq, "%s CASCADE;\n",
qtypname); 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) if (dopt->binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(fout, q, binary_upgrade_set_type_oids_by_type_oid(fout, q,
tyinfo->dobj.catId.oid); tyinfo->dobj.catId.oid,
false);
appendPQExpBuffer(q, appendPQExpBuffer(q,
"CREATE TYPE %s (\n" "CREATE TYPE %s (\n"
@ -10490,7 +10530,8 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
if (dopt->binary_upgrade) if (dopt->binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(fout, q, 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)); qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
@ -10692,7 +10733,8 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
if (dopt->binary_upgrade) if (dopt->binary_upgrade)
{ {
binary_upgrade_set_type_oids_by_type_oid(fout, q, 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); binary_upgrade_set_pg_class_oids(fout, q, tyinfo->typrelid, false);
} }
@ -10967,7 +11009,8 @@ dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
if (dopt->binary_upgrade) if (dopt->binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(fout, q, 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", appendPQExpBuffer(q, "CREATE TYPE %s;\n",
fmtId(stinfo->dobj.name)); fmtId(stinfo->dobj.name));