Fix brown paper bag bug in bbe08b8869.

We must issue the TRUNCATE command first and update relfrozenxid
and relminmxid afterward; otherwise, TRUNCATE overwrites the
previously-set values.

Add a test case like I should have done the first time.

Per buildfarm report from TestUpgradeXversion.pm, by way of Tom
Lane.
This commit is contained in:
Robert Haas 2022-07-29 16:31:57 -04:00
parent e6e804aa27
commit 5c9ea19b79
2 changed files with 55 additions and 9 deletions

View File

@ -3141,7 +3141,7 @@ dumpDatabase(Archive *fout)
PGresult *lo_res;
PQExpBuffer loFrozenQry = createPQExpBuffer();
PQExpBuffer loOutQry = createPQExpBuffer();
PQExpBuffer loVacQry = createPQExpBuffer();
PQExpBuffer loHorizonQry = createPQExpBuffer();
int i_relfrozenxid,
i_relfilenode,
i_oid,
@ -3168,14 +3168,14 @@ dumpDatabase(Archive *fout)
i_relfilenode = PQfnumber(lo_res, "relfilenode");
i_oid = PQfnumber(lo_res, "oid");
appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, set pg_largeobject relfrozenxid and relminmxid\n");
appendPQExpBufferStr(loVacQry, "\n-- For binary upgrade, preserve pg_largeobject and index relfilenodes\n");
appendPQExpBufferStr(loHorizonQry, "\n-- For binary upgrade, set pg_largeobject relfrozenxid and relminmxid\n");
appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, preserve pg_largeobject and index relfilenodes\n");
for (int i = 0; i < PQntuples(lo_res); ++i)
{
Oid oid;
Oid relfilenode;
appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n"
appendPQExpBuffer(loHorizonQry, "UPDATE pg_catalog.pg_class\n"
"SET relfrozenxid = '%u', relminmxid = '%u'\n"
"WHERE oid = %u;\n",
atooid(PQgetvalue(lo_res, i, i_relfrozenxid)),
@ -3186,18 +3186,18 @@ dumpDatabase(Archive *fout)
relfilenode = atooid(PQgetvalue(lo_res, i, i_relfilenode));
if (oid == LargeObjectRelationId)
appendPQExpBuffer(loVacQry,
appendPQExpBuffer(loOutQry,
"SELECT pg_catalog.binary_upgrade_set_next_heap_relfilenode('%u'::pg_catalog.oid);\n",
relfilenode);
else if (oid == LargeObjectLOidPNIndexId)
appendPQExpBuffer(loVacQry,
appendPQExpBuffer(loOutQry,
"SELECT pg_catalog.binary_upgrade_set_next_index_relfilenode('%u'::pg_catalog.oid);\n",
relfilenode);
}
appendPQExpBufferStr(loVacQry,
appendPQExpBufferStr(loOutQry,
"TRUNCATE pg_catalog.pg_largeobject;\n");
appendPQExpBufferStr(loOutQry, loVacQry->data);
appendPQExpBufferStr(loOutQry, loHorizonQry->data);
ArchiveEntry(fout, nilCatalogId, createDumpId(),
ARCHIVE_OPTS(.tag = "pg_largeobject",
@ -3208,8 +3208,8 @@ dumpDatabase(Archive *fout)
PQclear(lo_res);
destroyPQExpBuffer(loFrozenQry);
destroyPQExpBuffer(loHorizonQry);
destroyPQExpBuffer(loOutQry);
destroyPQExpBuffer(loVacQry);
}
PQclear(res);

View File

@ -161,6 +161,27 @@ $newnode->command_ok(
],
'dump before running pg_upgrade');
# Also record the relfrozenxid and relminmxid horizons.
my $horizon_query = <<EOM;
SELECT
c.oid::regclass, c.relfrozenxid, c.relminmxid
FROM
pg_class c, pg_namespace n
WHERE
c.relnamespace = n.oid AND
((n.nspname !~ '^pg_temp_' AND n.nspname !~ '^pg_toast_temp_' AND
n.nspname NOT IN ('pg_catalog', 'information_schema', 'binary_upgrade',
'pg_toast'))
OR (n.nspname = 'pg_catalog' AND relname IN ('pg_largeobject')))
EOM
$horizon_query =~ s/\s+/ /g; # run it together on one line
$newnode->command_ok(
[
'psql', '-At', '-d', $oldnode->connstr('postgres'),
'-o', "$tempdir/horizon1.txt", '-c', $horizon_query,
],
'horizons before running pg_upgrade');
# After dumping, update references to the old source tree's regress.so
# to point to the new tree.
if (defined($ENV{oldinstall}))
@ -294,6 +315,14 @@ $newnode->command_ok(
],
'dump after running pg_upgrade');
# And second record of horizons as well.
$newnode->command_ok(
[
'psql', '-At', '-d', $newnode->connstr('postgres'),
'-o', "$tempdir/horizon2.txt", '-c', $horizon_query,
],
'horizons after running pg_upgrade');
# Compare the two dumps, there should be no differences.
my $compare_res = compare("$tempdir/dump1.sql", "$tempdir/dump2.sql");
is($compare_res, 0, 'old and new dumps match after pg_upgrade');
@ -311,4 +340,21 @@ if ($compare_res != 0)
print "=== EOF ===\n";
}
# Compare the horizons, there should be no differences.
$compare_res = compare("$tempdir/horizon1.txt", "$tempdir/horizon2.txt");
is($compare_res, 0, 'old and new horizons match after pg_upgrade');
# Provide more context if the horizons do not match.
if ($compare_res != 0)
{
my ($stdout, $stderr) =
run_command([ 'diff', "$tempdir/horizon1.txt", "$tempdir/horizon2.txt" ]);
print "=== diff of $tempdir/horizon1.txt and $tempdir/horizon2.txt\n";
print "=== stdout ===\n";
print $stdout;
print "=== stderr ===\n";
print $stderr;
print "=== EOF ===\n";
}
done_testing();