PostgreSQL 10.12 (upcoming) commit log

Ensure maxlen is at leat 1 in dict_int

commit   : 46ce37b67a5144458adb0789eb4e9169a61881fd    
author   : Tomas Vondra <>    
date     : Tue, 3 Dec 2019 16:55:51 +0100    
committer: Tomas Vondra <>    
date     : Tue, 3 Dec 2019 16:55:51 +0100    

Click here for diff

The dict_int text search dictionary template accepts maxlen parameter,  
which is then used to cap the length of input strings. The value was  
not properly checked, and the code simply does  
    txt[d->maxlen] = '\0';  
to insert a terminator, leading to segfaults with negative values.  
This commit simply rejects values less than 1. The issue was there since  
dct_int was introduced in 9.3, so backpatch all the way back to 9.4  
which is the oldest supported version.  
Reported-by: cili  
Backpatch-through: 9.4  

M contrib/dict_int/dict_int.c
M contrib/dict_int/expected/dict_int.out
M contrib/dict_int/sql/dict_int.sql

Fix misbehavior with expression indexes on ON COMMIT DELETE ROWS tables.

commit   : 25c7183c06271b44ad2f13fc6ffe435544bee970    
author   : Tom Lane <>    
date     : Sun, 1 Dec 2019 13:09:27 -0500    
committer: Tom Lane <>    
date     : Sun, 1 Dec 2019 13:09:27 -0500    

Click here for diff

We implement ON COMMIT DELETE ROWS by truncating tables marked that  
way, which requires also truncating/rebuilding their indexes.  But  
RelationTruncateIndexes asks the relcache for up-to-date copies of any  
index expressions, which may cause execution of eval_const_expressions  
on them, which can result in actual execution of subexpressions.  
This is a bad thing to have happening during ON COMMIT.  Manuel Rigger  
reported that use of a SQL function resulted in crashes due to  
expectations that ActiveSnapshot would be set, which it isn't.  
The most obvious fix perhaps would be to push a snapshot during  
PreCommit_on_commit_actions, but I think that would just open the door  
to more problems: CommitTransaction explicitly expects that no  
user-defined code can be running at this point.  
Fortunately, since we know that no tuples exist to be indexed, there  
seems no need to use the real index expressions or predicates during  
RelationTruncateIndexes.  We can set up dummy index expressions  
instead (we do need something that will expose the right data type,  
as there are places that build index tupdescs based on this), and  
just ignore predicates and exclusion constraints.  
In a green field it'd likely be better to reimplement ON COMMIT DELETE  
ROWS using the same "init fork" infrastructure used for unlogged  
relations.  That seems impractical without catalog changes though,  
and even without that it'd be too big a change to back-patch.  
So for now do it like this.  
Per private report from Manuel Rigger.  This has been broken forever,  
so back-patch to all supported branches.  

M src/backend/catalog/heap.c
M src/backend/catalog/index.c
M src/backend/utils/cache/relcache.c
M src/include/catalog/index.h
M src/include/utils/relcache.h
M src/test/regress/expected/temp.out
M src/test/regress/sql/temp.sql

Fix off-by-one error in PGTYPEStimestamp_fmt_asc

commit   : f71b22f537b987f6f4b04f889bbd955c548d7d72    
author   : Tomas Vondra <>    
date     : Sat, 30 Nov 2019 14:51:27 +0100    
committer: Tomas Vondra <>    
date     : Sat, 30 Nov 2019 14:51:27 +0100    

Click here for diff

When using %b or %B patterns to format a date, the code was simply using  
tm_mon as an index into array of month names. But that is wrong, because  
tm_mon is 1-based, while array indexes are 0-based. The result is we  
either use name of the next month, or a segfault (for December).  
Fix by subtracting 1 from tm_mon for both patterns, and add a regression  
test triggering the issue. Backpatch to all supported versions (the bug  
is there far longer, since at least 2003).  
Reported-by: Paul Spencer  
Backpatch-through: 9.4  

M src/interfaces/ecpg/pgtypeslib/timestamp.c
M src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.c
M src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stderr
M src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stdout
M src/interfaces/ecpg/test/pgtypeslib/dt_test.pgc

Fix typo in comment.

commit   : e429b03cc63b5879b87be6dd96c49c7868febeb1    
author   : Etsuro Fujita <>    
date     : Wed, 27 Nov 2019 16:00:49 +0900    
committer: Etsuro Fujita <>    
date     : Wed, 27 Nov 2019 16:00:49 +0900    

Click here for diff

M src/backend/optimizer/util/relnode.c

Don't shut down Gather[Merge] early under Limit.

commit   : f7ae68aacd9d9cd18a62575b927491d56e57a555    
author   : Amit Kapila <>    
date     : Mon, 18 Nov 2019 14:17:41 +0530    
committer: Amit Kapila <>    
date     : Mon, 18 Nov 2019 14:17:41 +0530    

Click here for diff

Revert part of commit 19df1702f5.  
Early shutdown was added by that commit so that we could collect  
statistics from workers, but unfortunately, it interacted badly with  
rescans.  The problem is that we ended up destroying the parallel context  
which is required for rescans.  This leads to rescans of a Limit node over  
a Gather node to produce unpredictable results as it tries to access  
destroyed parallel context.  By reverting the early shutdown code, we  
might lose statistics in some cases of Limit over Gather [Merge], but that  
will require further study to fix.  
Reported-by: Jerry Sievers  
Diagnosed-by: Thomas Munro  
Author: Amit Kapila, testcase by Vignesh C  
Backpatch-through: 9.6  

M src/backend/executor/nodeLimit.c
M src/test/regress/expected/select_parallel.out
M src/test/regress/sql/select_parallel.sql

Avoid assertion failure with LISTEN in a serializable transaction.

commit   : bd743b6006191796d08d4a1836e539626f01f50d    
author   : Tom Lane <>    
date     : Sun, 24 Nov 2019 15:57:31 -0500    
committer: Tom Lane <>    
date     : Sun, 24 Nov 2019 15:57:31 -0500    

Click here for diff

If LISTEN is the only action in a serializable-mode transaction,  
and the session was not previously listening, and the notify queue  
is not empty, predicate.c reported an assertion failure.  That  
happened because we'd acquire the transaction's initial snapshot  
during PreCommit_Notify, which was called *after* predicate.c  
expects any such snapshot to have been established.  
To fix, just swap the order of the PreCommit_Notify and  
PreCommit_CheckForSerializationFailure calls during CommitTransaction.  
This will imply holding the notify-insertion lock slightly longer,  
but the difference could only be meaningful in serializable mode,  
which is an expensive option anyway.  
It appears that this is just an assertion failure, with no  
consequences in non-assert builds.  A snapshot used only to scan  
the notify queue could not have been involved in any serialization  
conflicts, so there would be nothing for  
PreCommit_CheckForSerializationFailure to do except assign it a  
prepareSeqNo and set the SXACT_FLAG_PREPARED flag.  And given no  
conflicts, neither of those omissions affect the behavior of  
ReleasePredicateLocks.  This admittedly once-over-lightly analysis  
is backed up by the lack of field reports of trouble.  
Per report from Mark Dilger.  The bug is old, so back-patch to all  
supported branches; but the new test case only goes back to 9.6,  
for lack of adequate isolationtester infrastructure before that.  

M src/backend/access/transam/xact.c
M src/test/isolation/expected/async-notify.out
M src/test/isolation/specs/async-notify.spec

doc: Fix whitespace in syntax.

commit   : c08ac67f47a3e3e8ca7889178f1f12fe993ca7d2    
author   : Thomas Munro <>    
date     : Mon, 25 Nov 2019 09:20:28 +1300    
committer: Thomas Munro <>    
date     : Mon, 25 Nov 2019 09:20:28 +1300    

Click here for diff

Back-patch to 10.  
Author: Andreas Karlsson  

M doc/src/sgml/ref/insert.sgml

Stabilize NOTIFY behavior by transmitting notifies before ReadyForQuery.

commit   : dbe15524becb0d1366e9421aabdf85f538001942    
author   : Tom Lane <>    
date     : Sun, 24 Nov 2019 14:42:59 -0500    
committer: Tom Lane <>    
date     : Sun, 24 Nov 2019 14:42:59 -0500    

Click here for diff

This patch ensures that, if any notify messages were received during  
a just-finished transaction, they get sent to the frontend just before  
not just after the ReadyForQuery message.  With libpq and other client  
libraries that act similarly, this guarantees that the client will see  
the notify messages as available as soon as it thinks the transaction  
is done.  
This probably makes no difference in practice, since in realistic  
use-cases the application would have to cope with asynchronous  
arrival of notify events anyhow.  However, it makes it a lot easier  
to build cross-session-notify test cases with stable behavior.  
I'm a bit surprised now that we've not seen any buildfarm instability  
with the test cases added by commit b10f40bf0.  Tests that I intend  
to add in an upcoming bug fix are definitely unstable without this.  
Back-patch to 9.6, which is as far back as we can do NOTIFY testing  
with the isolationtester infrastructure.  

M src/backend/commands/async.c
M src/backend/tcop/postgres.c

Improve test coverage for LISTEN/NOTIFY.

commit   : 34f66c0ed800f50ffa75d57c7769f07d0adb5e29    
author   : Tom Lane <>    
date     : Sat, 23 Nov 2019 17:30:01 -0500    
committer: Tom Lane <>    
date     : Sat, 23 Nov 2019 17:30:01 -0500    

Click here for diff

Back-patch commit b10f40bf0 into older branches.  This adds reporting  
of NOTIFY messages to isolationtester.c, and extends the async-notify  
test to include direct tests of basic NOTIFY functionality.  
This provides useful infrastructure for testing a bug fix I'm about  
to back-patch, and there seems no good reason not to have better tests  
of LISTEN/NOTIFY in the back branches.  The commit's survived long  
enough in HEAD to make it unlikely that it will cause problems.  
Back-patch as far as 9.6.  isolationtester.c changed too much in 9.6  
to make it sane to try to fix older branches this way, and I don't  
really want to back-patch those changes too.  

M src/test/isolation/expected/async-notify.out
M src/test/isolation/isolationtester.c
M src/test/isolation/specs/async-notify.spec

Add test coverage for "unchanged toast column" replication code path.

commit   : 8b46acf7c423128439423f6677e9d85e286e1806    
author   : Tom Lane <>    
date     : Fri, 22 Nov 2019 12:52:26 -0500    
committer: Tom Lane <>    
date     : Fri, 22 Nov 2019 12:52:26 -0500    

Click here for diff

It seems pretty unacceptable to have no regression test coverage  
for this aspect of the logical replication protocol, especially  
given the bugs we've found in related code.  

M src/test/subscription/t/

Fix bogus tuple-slot management in logical replication UPDATE handling.

commit   : 5d3fcb53a6a81a75457a3afef6aff91629705f2b    
author   : Tom Lane <>    
date     : Fri, 22 Nov 2019 11:31:19 -0500    
committer: Tom Lane <>    
date     : Fri, 22 Nov 2019 11:31:19 -0500    

Click here for diff

slot_modify_cstrings seriously abused the TupleTableSlot API by relying  
on a slot's underlying data to stay valid across ExecClearTuple.  Since  
this abuse was also quite undocumented, it's little surprise that the  
case got broken during the v12 slot rewrites.  As reported in bug #16129  
from Ondřej Jirman, this could lead to crashes or data corruption when  
a logical replication subscriber processes a row update.  Problems would  
only arise if the subscriber's table contained columns of pass-by-ref  
types that were not being copied from the publisher.  
Fix by explicitly copying the datum/isnull arrays from the source slot  
that the old row was in already.  This ends up being about the same  
thing that happened pre-v12, but hopefully in a less opaque and  
fragile way.  
We might've caught the problem sooner if there were any test cases  
dealing with updates involving non-replicated or dropped columns.  
Now there are.  
Back-patch to v10 where this code came in.  Even though the failure  
does not manifest before v12, IMO this code is too fragile to leave  
as-is.  In any case we certainly want the additional test coverage.  
Patch by me; thanks to Tomas Vondra for initial investigation.  

M src/backend/replication/logical/worker.c
M src/test/subscription/t/

Defend against self-referential views in relation_is_updatable().

commit   : b9f3d7a5317bbafb0cef1921c2e777bb327fdaee    
author   : Tom Lane <>    
date     : Thu, 21 Nov 2019 16:21:44 -0500    
committer: Tom Lane <>    
date     : Thu, 21 Nov 2019 16:21:44 -0500    

Click here for diff

While a self-referential view doesn't actually work, it's possible  
to create one, and it turns out that this breaks some of the  
information_schema views.  Those views call relation_is_updatable(),  
which neglected to consider the hazards of being recursive.  In  
older PG versions you get a "stack depth limit exceeded" error,  
but since v10 it'd recurse to the point of stack overrun and crash,  
because commit a4c35ea1c took out the expression_returns_set() call  
that was incidentally checking the stack depth.  
Since this function is only used by information_schema views, it  
seems like it'd be better to return "not updatable" than suffer  
an error.  Hence, add tracking of what views we're examining,  
in just the same way that the nearby fireRIRrules() code detects  
self-referential views.  I added a check_stack_depth() call too,  
just to be defensive.  
Per private report from Manuel Rigger.  Back-patch to all  
supported versions.  

M src/backend/rewrite/rewriteHandler.c
M src/backend/utils/adt/misc.c
M src/include/rewrite/rewriteHandler.h

Provide statistics for hypothetical BRIN indexes

commit   : f4095026cf174f9993920b8fce227db9c128bd5c    
author   : Michael Paquier <>    
date     : Thu, 21 Nov 2019 10:23:49 +0900    
committer: Michael Paquier <>    
date     : Thu, 21 Nov 2019 10:23:49 +0900    

Click here for diff

Trying to use hypothetical indexes with BRIN currently fails when trying  
to access a relation that does not exist when looking for the  
statistics.  With the current API, it is not possible to easily pass  
a value for pages_per_range down to the hypothetical index, so this  
makes use of the default value of BRIN_DEFAULT_PAGES_PER_RANGE, which  
should be fine enough in most cases.  
Being able to refine or enforce the hypothetical costs in more  
optimistic ways would require more refactoring by filling in the  
statistics when building IndexOptInfo in plancat.c.  This would involve  
ABI breakages around the costing routines, something not fit for stable  
This is broken since 7e534ad, so backpatch down to v10.  
Author: Julien Rouhaud, Heikki Linnakangas  
Reviewed-by: Álvaro Herrera, Tom Lane, Michael Paquier  
Backpatch-through: 10  

M src/backend/utils/adt/selfuncs.c

Remove incorrect markup

commit   : a45feb1a4fd48dad5d969d1ff010861a18b4a6b9    
author   : Magnus Hagander <>    
date     : Wed, 20 Nov 2019 17:03:07 +0100    
committer: Magnus Hagander <>    
date     : Wed, 20 Nov 2019 17:03:07 +0100    

Click here for diff

Author: Daniel Gustafsson <>  

M doc/src/sgml/libpq.sgml


commit   : b6f57c2d7bfc2c0ddfc33158b2c42ebd0c715959    
author   : Alexander Korotkov <>    
date     : Tue, 19 Nov 2019 23:11:24 +0300    
committer: Alexander Korotkov <>    
date     : Tue, 19 Nov 2019 23:11:24 +0300    

Click here for diff

We find GIN concurrency bugs from time to time.  One of the problems here is  
that concurrency of GIN isn't well-documented in README.  So, it might be even  
hard to distinguish design bugs from implementation bugs.  
This commit revised concurrency section in GIN README providing more details.  
Some examples are illustrated in ASCII art.  
Also, this commit add the explanation of how is tuple layout in internal GIN  
B-tree page different in comparison with nbtree.  
Author: Alexander Korotkov  
Reviewed-by: Peter Geoghegan  
Backpatch-through: 9.4  

M src/backend/access/gin/README

Fix traversing to the deleted GIN page via downlink

commit   : ab64b474d9bec8486b42e550526a121f0d81b681    
author   : Alexander Korotkov <>    
date     : Tue, 19 Nov 2019 23:08:14 +0300    
committer: Alexander Korotkov <>    
date     : Tue, 19 Nov 2019 23:08:14 +0300    

Click here for diff

Current GIN code appears to don't handle traversing to the deleted page via  
downlink.  This commit fixes that by stepping right from the delete page like  
we do in nbtree.  
This commit also fixes setting 'deleted' flag to the GIN pages.  Now other page  
flags are not erased once page is deleted.  That helps to keep our assertions  
true if we arrive deleted page via downlink.  
Author: Alexander Korotkov  
Reviewed-by: Peter Geoghegan  
Backpatch-through: 9.4  

M src/backend/access/gin/ginbtree.c
M src/backend/access/gin/gindatapage.c
M src/backend/access/gin/ginvacuum.c
M src/backend/access/gin/ginxlog.c

Fix deadlock between ginDeletePage() and ginStepRight()

commit   : 21ad61ab31786128ae780feca8fcf766bbb6a579    
author   : Alexander Korotkov <>    
date     : Tue, 19 Nov 2019 23:07:36 +0300    
committer: Alexander Korotkov <>    
date     : Tue, 19 Nov 2019 23:07:36 +0300    

Click here for diff

When ginDeletePage() is about to delete page it locks its left sibling to revise  
the rightlink.  So, it locks pages in right to left manner.  Int he same time  
ginStepRight() locks pages in left to right manner, and that could cause a  
This commit makes ginScanToDelete() keep exclusive lock on left siblings of  
currently investigated path.  That elimites need to relock left sibling in  
ginDeletePage().  Thus, deadlock with ginStepRight() can't happen anymore.  
Reported-by: Chen Huajun  
Author: Alexander Korotkov  
Reviewed-by: Peter Geoghegan  
Backpatch-through: 10  

M src/backend/access/gin/README
M src/backend/access/gin/ginvacuum.c

Doc: clarify use of RECURSIVE in WITH.

commit   : f1155901fa598f3476a489152fbfe37a5833613c    
author   : Tom Lane <>    
date     : Tue, 19 Nov 2019 14:43:37 -0500    
committer: Tom Lane <>    
date     : Tue, 19 Nov 2019 14:43:37 -0500    

Click here for diff

Apparently some people misinterpreted the syntax as being that  
RECURSIVE is a prefix of individual WITH queries.  It's a modifier  
for the WITH clause as a whole, so state that more clearly.  

M doc/src/sgml/ref/select.sgml

Doc: clarify behavior of ALTER DEFAULT PRIVILEGES ... IN SCHEMA.

commit   : d30e0ed55c6bba632f491fa8db2c2bbde33330c3    
author   : Tom Lane <>    
date     : Tue, 19 Nov 2019 14:21:41 -0500    
committer: Tom Lane <>    
date     : Tue, 19 Nov 2019 14:21:41 -0500    

Click here for diff

The existing text stated that "Default privileges that are specified  
per-schema are added to whatever the global default privileges are for  
the particular object type".  However, that bare-bones observation is  
not quite clear enough, as demonstrated by the complaint in bug #16124.  
Flesh it out by stating explicitly that you can't revoke built-in  
default privileges this way, and by providing an example to drive  
the point home.  
Back-patch to all supported branches, since it's been like this  
from the beginning.  

M doc/src/sgml/ref/alter_default_privileges.sgml

Further fix dumping of views that contain just VALUES(...).

commit   : a1b2cf0950ea464a1d95529ed4aaf727c13e463a    
author   : Tom Lane <>    
date     : Sat, 16 Nov 2019 20:00:19 -0500    
committer: Tom Lane <>    
date     : Sat, 16 Nov 2019 20:00:19 -0500    

Click here for diff

It turns out that commit e9f1c01b7 missed a case: we must print a  
VALUES clause in long format if get_query_def is given a resultDesc  
that would require the query's output column name(s) to be different  
from what the bare VALUES clause would produce.  
This applies in case an ALTER ... RENAME COLUMN has been done to  
a view that formerly could be printed in simple format, as shown  
in the added regression test case.  It also explains bug #16119  
from Dmitry Telpt, because it turns out that (unlike CREATE VIEW)  
CREATE MATERIALIZED VIEW fails to apply any column aliases it's  
given to the stored ON SELECT rule.  So to get them to be printed,  
we have to account for the resultDesc renaming.  It might be worth  
changing the matview code so that it creates the ON SELECT rule  
with the correct aliases; but we'd still need these messy checks in  
get_simple_values_rte to handle the case of a subsequent column  
rename, so any such change would be just neatnik-ism not a bug fix.  
Like the previous patch, back-patch to all supported branches.  

M src/backend/utils/adt/ruleutils.c
M src/test/regress/expected/rules.out
M src/test/regress/sql/rules.sql

Skip system attributes when applying mvdistinct stats

commit   : 0b0f281cc0fe383162b170889e79502e21e6b35a    
author   : Tomas Vondra <>    
date     : Sat, 16 Nov 2019 01:17:15 +0100    
committer: Tomas Vondra <>    
date     : Sat, 16 Nov 2019 01:17:15 +0100    

Click here for diff

When estimating number of distinct groups, we failed to ignore system  
attributes when matching the group expressions to mvdistinct stats,  
causing failures like  
  ERROR: negative bitmapset member not allowed  
Fix that by simply skipping anything that is not a regular attribute.  
Backpatch to PostgreSQL 10, where the extended stats were introduced.  
Bug: #16111  
Reported-by: Tuomas Leikola  
Author: Tomas Vondra  
Backpatch-through: 10  

M src/backend/utils/adt/selfuncs.c
M src/test/regress/expected/stats_ext.out
M src/test/regress/sql/stats_ext.sql

Avoid downcasing/truncation of RADIUS authentication parameters.

commit   : 4be69e2ea14d4f00c77a1185e68b7f9235aeb95f    
author   : Tom Lane <>    
date     : Wed, 13 Nov 2019 13:41:04 -0500    
committer: Tom Lane <>    
date     : Wed, 13 Nov 2019 13:41:04 -0500    

Click here for diff

Commit 6b76f1bb5 changed all the RADIUS auth parameters to be lists  
rather than single values.  But its use of SplitIdentifierString  
to parse the list format was not very carefully thought through,  
because that function thinks it's parsing SQL identifiers, which  
means it will (a) downcase the strings and (b) truncate them to  
be shorter than NAMEDATALEN.  While downcasing should be harmless  
for the server names and ports, it's just wrong for the shared  
secrets, and probably for the NAS Identifier strings as well.  
The truncation aspect is at least potentially a problem too,  
though typical values for these parameters would fit in 63 bytes.  
Fortunately, we now have a function SplitGUCList that is exactly  
the same except for not doing the two unwanted things, so fixing  
this is a trivial matter of calling that function instead.  
While here, improve the documentation to show how to double-quote  
the parameter values.  I failed to resist the temptation to do  
some copy-editing as well.  
Report and patch from Marcos David (bug #16106); doc changes by me.  
Back-patch to v10 where the aforesaid commit came in, since this is  
arguably a regression from our previous behavior with RADIUS auth.  

M doc/src/sgml/client-auth.sgml
M src/backend/libpq/hba.c

Include TableFunc references when computing expression dependencies.

commit   : e25c4b3b2f678dd4fad142e494a44a59a7748904    
author   : Tom Lane <>    
date     : Wed, 13 Nov 2019 12:11:50 -0500    
committer: Tom Lane <>    
date     : Wed, 13 Nov 2019 12:11:50 -0500    

Click here for diff

The TableFunc node (i.e., XMLTABLE) includes type and collation OIDs  
that might not be referenced anywhere else in the expression tree,  
so they need to be accounted for when extracting dependencies.  
Fortunately, the practical effects of this are limited, since  
(a) it's somewhat unlikely that people would be extracting  
columns of non-builtin types from an XML document, and (b)  
in many scenarios, the query would contain other references  
to such types, or functions depending on them.  However, it's  
not hard to construct examples wherein the existing code lets  
one drop a type used in XMLTABLE and thereby break a view.  
This is evidently an original oversight in the XMLTABLE patch,  
so back-patch to v10 where that came in.  

M src/backend/catalog/dependency.c

Handle arrays and ranges in pg_upgrade's test for non-upgradable types.

commit   : c443e3c439273217d1e9a6e1a933ece302aa4ba1    
author   : Tom Lane <>    
date     : Wed, 13 Nov 2019 11:35:37 -0500    
committer: Tom Lane <>    
date     : Wed, 13 Nov 2019 11:35:37 -0500    

Click here for diff

pg_upgrade needs to check whether certain non-upgradable data types  
appear anywhere on-disk in the source cluster.  It knew that it has  
to check for these types being contained inside domains and composite  
types; but it somehow overlooked that they could be contained in  
arrays and ranges, too.  Extend the existing recursive-containment  
query to handle those cases.  
We probably should have noticed this oversight while working on  
commit 0ccfc2822 and follow-ups, but we failed to :-(.  The whole  
thing's possibly a bit overdesigned, since we don't really expect  
that any of these types will appear on disk; but if we're going to  
the effort of doing a recursive search then it's silly not to cover  
all the possibilities.  
While at it, refactor so that we have only one copy of the search  
logic, not three-and-counting.  Also, to keep the branches looking  
more alike, back-patch the output wording change of commit 1634d3615.  
Back-patch to all supported branches.  

M src/bin/pg_upgrade/version.c