Skip to content

Commit 7615afa

Browse files
committed
Fix pg_dump's handling of dependencies for custom opclasses.
Since pg_dump doesn't treat the member operators and functions of operator classes/families (that is, the pg_amop and pg_amproc entries, not the underlying operators/functions) as separate dumpable objects, it missed their dependency information. I think this was safe when the code was designed, because the default object sorting rule emits operators and functions before opclasses, and there were no dependency types that could mess that up. However, the introduction of range types in 9.2 broke it: now a type can have a dependency on an opclass, allowing dependency rules to push the opclass before the type and hence before custom operators. Lacking any information showing that it shouldn't do so, pg_dump emitted the objects in the wrong order. Fix by teaching getDependencies() to translate pg_depend entries for pg_amop/amproc rows to look like dependencies for their parent opfamily. I added a regression test for this in HEAD/v12, but not further back; life is too short to fight with 002_pg_dump.pl. Per bug #15934 from Tom Gottfried. Back-patch to all supported branches. Discussion: https://postgr.es/m/15934-58b8c8ab7a09ea15@postgresql.org
1 parent 35fc44b commit 7615afa

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17162,14 +17162,45 @@ getDependencies(Archive *fout)
1716217162
query = createPQExpBuffer();
1716317163

1716417164
/*
17165+
* Messy query to collect the dependency data we need. Note that we
17166+
* ignore the sub-object column, so that dependencies of or on a column
17167+
* look the same as dependencies of or on a whole table.
17168+
*
1716517169
* PIN dependencies aren't interesting, and EXTENSION dependencies were
1716617170
* already processed by getExtensionMembership.
1716717171
*/
1716817172
appendPQExpBufferStr(query, "SELECT "
1716917173
"classid, objid, refclassid, refobjid, deptype "
1717017174
"FROM pg_depend "
17171-
"WHERE deptype != 'p' AND deptype != 'e' "
17172-
"ORDER BY 1,2");
17175+
"WHERE deptype != 'p' AND deptype != 'e'\n");
17176+
17177+
/*
17178+
* Since we don't treat pg_amop entries as separate DumpableObjects, we
17179+
* have to translate their dependencies into dependencies of their parent
17180+
* opfamily. Ignore internal dependencies though, as those will point to
17181+
* their parent opclass, which we needn't consider here (and if we did,
17182+
* it'd just result in circular dependencies). Also, "loose" opfamily
17183+
* entries will have dependencies on their parent opfamily, which we
17184+
* should drop since they'd likewise become useless self-dependencies.
17185+
* (But be sure to keep deps on *other* opfamilies; see amopsortfamily.)
17186+
*/
17187+
appendPQExpBufferStr(query, "UNION ALL\n"
17188+
"SELECT 'pg_opfamily'::regclass AS classid, amopfamily AS objid, refclassid, refobjid, deptype "
17189+
"FROM pg_depend d, pg_amop o "
17190+
"WHERE deptype NOT IN ('p', 'e', 'i') AND "
17191+
"classid = 'pg_amop'::regclass AND objid = o.oid "
17192+
"AND NOT (refclassid = 'pg_opfamily'::regclass AND amopfamily = refobjid)\n");
17193+
17194+
/* Likewise for pg_amproc entries */
17195+
appendPQExpBufferStr(query, "UNION ALL\n"
17196+
"SELECT 'pg_opfamily'::regclass AS classid, amprocfamily AS objid, refclassid, refobjid, deptype "
17197+
"FROM pg_depend d, pg_amproc p "
17198+
"WHERE deptype NOT IN ('p', 'e', 'i') AND "
17199+
"classid = 'pg_amproc'::regclass AND objid = p.oid "
17200+
"AND NOT (refclassid = 'pg_opfamily'::regclass AND amprocfamily = refobjid)\n");
17201+
17202+
/* Sort the output for efficiency below */
17203+
appendPQExpBufferStr(query, "ORDER BY 1,2");
1717317204

1717417205
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
1717517206

0 commit comments

Comments
 (0)