query = createPQExpBuffer();
/*
+ * Messy query to collect the dependency data we need. Note that we
+ * ignore the sub-object column, so that dependencies of or on a column
+ * look the same as dependencies of or on a whole table.
+ *
* PIN dependencies aren't interesting, and EXTENSION dependencies were
* already processed by getExtensionMembership.
*/
appendPQExpBufferStr(query, "SELECT "
"classid, objid, refclassid, refobjid, deptype "
"FROM pg_depend "
- "WHERE deptype != 'p' AND deptype != 'e' "
- "ORDER BY 1,2");
+ "WHERE deptype != 'p' AND deptype != 'e'\n");
+
+ /*
+ * Since we don't treat pg_amop entries as separate DumpableObjects, we
+ * have to translate their dependencies into dependencies of their parent
+ * opfamily. Ignore internal dependencies though, as those will point to
+ * their parent opclass, which we needn't consider here (and if we did,
+ * it'd just result in circular dependencies). Also, "loose" opfamily
+ * entries will have dependencies on their parent opfamily, which we
+ * should drop since they'd likewise become useless self-dependencies.
+ * (But be sure to keep deps on *other* opfamilies; see amopsortfamily.)
+ */
+ appendPQExpBufferStr(query, "UNION ALL\n"
+ "SELECT 'pg_opfamily'::regclass AS classid, amopfamily AS objid, refclassid, refobjid, deptype "
+ "FROM pg_depend d, pg_amop o "
+ "WHERE deptype NOT IN ('p', 'e', 'i') AND "
+ "classid = 'pg_amop'::regclass AND objid = o.oid "
+ "AND NOT (refclassid = 'pg_opfamily'::regclass AND amopfamily = refobjid)\n");
+
+ /* Likewise for pg_amproc entries */
+ appendPQExpBufferStr(query, "UNION ALL\n"
+ "SELECT 'pg_opfamily'::regclass AS classid, amprocfamily AS objid, refclassid, refobjid, deptype "
+ "FROM pg_depend d, pg_amproc p "
+ "WHERE deptype NOT IN ('p', 'e', 'i') AND "
+ "classid = 'pg_amproc'::regclass AND objid = p.oid "
+ "AND NOT (refclassid = 'pg_opfamily'::regclass AND amprocfamily = refobjid)\n");
+
+ /* Sort the output for efficiency below */
+ appendPQExpBufferStr(query, "ORDER BY 1,2");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
unlike => { exclude_dump_test_schema => 1, },
},
+ # verify that a custom operator/opclass/range type is dumped in right order
+ 'CREATE OPERATOR CLASS dump_test.op_class_custom' => {
+ create_order => 74,
+ create_sql => 'CREATE OPERATOR dump_test.~~ (
+ PROCEDURE = int4eq,
+ LEFTARG = int,
+ RIGHTARG = int);
+ CREATE OPERATOR CLASS dump_test.op_class_custom
+ FOR TYPE int USING btree AS
+ OPERATOR 3 dump_test.~~;
+ CREATE TYPE dump_test.range_type_custom AS RANGE (
+ subtype = int,
+ subtype_opclass = dump_test.op_class_custom);',
+ regexp => qr/^
+ \QCREATE OPERATOR dump_test.~~ (\E\n.+
+ \QCREATE OPERATOR FAMILY dump_test.op_class_custom USING btree;\E\n.+
+ \QCREATE OPERATOR CLASS dump_test.op_class_custom\E\n\s+
+ \QFOR TYPE integer USING btree FAMILY dump_test.op_class_custom AS\E\n\s+
+ \QOPERATOR 3 dump_test.~~(integer,integer);\E\n.+
+ \QCREATE TYPE dump_test.range_type_custom AS RANGE (\E\n\s+
+ \Qsubtype = integer,\E\n\s+
+ \Qsubtype_opclass = dump_test.op_class_custom\E\n
+ \Q);\E
+ /xms,
+ like =>
+ { %full_runs, %dump_test_schema_runs, section_pre_data => 1, },
+ unlike => { exclude_dump_test_schema => 1, },
+ },
+
'CREATE OPERATOR CLASS dump_test.op_class_empty' => {
create_order => 89,
create_sql => 'CREATE OPERATOR CLASS dump_test.op_class_empty