10000 Fix pg_dump so pg_upgrade'ing an extension with simple opfamilies works. · prmdeveloper/postgres@5daf101 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5daf101

Browse files
committed
Fix pg_dump so pg_upgrade'ing an extension with simple opfamilies works.
As reported by Michael Feld, pg_upgrade'ing an installation having extensions with operator families that contain just a single operator class failed to reproduce the extension membership of those operator families. This caused no immediate ill effects, but would create problems when later trying to do a plain dump and restore, because the seemingly-not-part-of- the-extension operator families would appear separately in the pg_dump output, and then would conflict with the families created by loading the extension. This has been broken ever since extensions were introduced, and many of the standard contrib extensions are affected, so it's a bit astonishing nobody complained before. The cause of the problem is a perhaps-ill-considered decision to omit such operator families from pg_dump's output on the grounds that the CREATE OPERATOR CLASS commands could recreate them, and having explicit CREATE OPERATOR FAMILY commands would impede loading the dump script into pre-8.3 servers. Whatever the merits of that decision when 8.3 was being written, it looks like a poor tradeoff now. We can fix the pg_upgrade problem simply by removing that code, so that the operator families are dumped explicitly (and then will be properly made to be part of their extensions). Although this fixes the behavior of future pg_upgrade runs, it does nothing to clean up existing installations that may have improperly-linked operator families. Given the small number of complaints to date, maybe we don't need to worry about providing an automated solution for that; anyone who needs to clean it up can do so with manual "ALTER EXTENSION ADD OPERATOR FAMILY" commands, or even just ignore the duplicate-opfamily errors they get during a pg_restore. In any case we need this fix. Back-patch to all supported branches. Discussion: <20228.1460575691@sss.pgh.pa.us>
1 parent 112e5d2 commit 5daf101

File tree

1 file changed

+1
-46
lines changed
  • src/bin/pg_dump

1 file changed

+1
-46
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10860,9 +10860,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
1086010860
appendPQExpBuffer(q, "FOR TYPE %s USING %s",
1086110861
opcintype,
1086210862
fmtId(amname));
10863-
if (strlen(opcfamilyname) > 0 &&
10864-
(strcmp(opcfamilyname, opcinfo->dobj.name) != 0 ||
10865-
strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0))
10863+
if (strlen(opcfamilyname) > 0)
1086610864
{
1086710865
appendPQExpBufferStr(q, " FAMILY ");
1086810866
if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
@@ -11145,15 +11143,6 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
1114511143
if (!opfinfo->dobj.dump || dataOnly)
1114611144
return;
1114711145

11148-
/*
11149-
* We want to dump the opfamily only if (1) it contains "loose" operators
11150-
* or functions, or (2) it contains an opclass with a different name or
11151-
* owner. Otherwise it's sufficient to let it be created during creation
11152-
* of the contained opclass, and not dumping it improves portability of
11153-
* the dump. Since we have to fetch the loose operators/funcs anyway, do
11154-
* that first.
11155-
*/
11156-
1115711146
query = createPQExpBuffer();
1115811147
q = createPQExpBuffer();
1115911148
delq = createPQExpBuffer();
@@ -11236,40 +11225,6 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
1123611225

1123711226
res_procs = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
1123811227

11239-
if (PQntuples(res_ops) == 0 && PQntuples(res_procs) == 0)
11240-
{
11241-
/* No loose members, so check contained opclasses */
11242-
resetPQExpBuffer(query);
11243-
11244-
appendPQExpBuffer(query, "SELECT 1 "
11245-
"FROM pg_catalog.pg_opclass c, pg_catalog.pg_opfamily f, pg_catalog.pg_depend "
11246-
"WHERE f.oid = '%u'::pg_catalog.oid "
11247-
"AND refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
11248-
"AND refobjid = f.oid "
11249-
"AND classid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
11250-
"AND objid = c.oid "
11251-
"AND (opcname != opfname OR opcnamespace != opfnamespace OR opcowner != opfowner) "
11252-
"LIMIT 1",
11253-
opfinfo->dobj.catId.oid);
11254-
11255-
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
11256-
11257-
if (PQntuples(res) == 0)
11258-
{
11259-
/* no need to dump it, so bail out */
11260-
PQclear(res);
11261-
PQclear(res_ops);
11262-
PQclear(res_procs);
11263-
destroyPQExpBuffer(query);
11264-
destroyPQExpBuffer(q);
11265-
destroyPQExpBuffer(delq);
11266-
destroyPQExpBuffer(labelq);
11267-
return;
11268-
}
11269-
11270-
PQclear(res);
11271-
}
11272-
1127311228
/* Get additional fields from the pg_opfamily row */
1127411229
resetPQExpBuffer(query);
1127511230

0 commit comments

Comments
 (0)
0