@@ -4291,6 +4291,55 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
42914291 free(qsubname);
42924292}
42934293
4294+ /*
4295+ * Given a "create query", append as many ALTER ... DEPENDS ON EXTENSION as
4296+ * the object needs.
4297+ */
4298+ static void
4299+ append_depends_on_extension(Archive *fout,
4300+ PQExpBuffer create,
4301+ DumpableObject *dobj,
4302+ const char *catalog,
4303+ const char *keyword,
4304+ const char *objname)
4305+ {
4306+ if (dobj->depends_on_ext)
4307+ {
4308+ char *nm;
4309+ PGresult *res;
4310+ PQExpBuffer query;
4311+ int ntups;
4312+ int i_extname;
4313+ int i;
4314+
4315+ /* dodge fmtId() non-reentrancy */
4316+ nm = pg_strdup(objname);
4317+
4318+ query = createPQExpBuffer();
4319+ appendPQExpBuffer(query,
4320+ "SELECT e.extname "
4321+ "FROM pg_catalog.pg_depend d, pg_catalog.pg_extension e "
4322+ "WHERE d.refobjid = e.oid AND classid = '%s'::pg_catalog.regclass "
4323+ "AND objid = '%u'::pg_catalog.oid AND deptype = 'x' "
4324+ "AND refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass",
4325+ catalog,
4326+ dobj->catId.oid);
4327+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
4328+ ntups = PQntuples(res);
4329+ i_extname = PQfnumber(res, "extname");
4330+ for (i = 0; i < ntups; i++)
4331+ {
4332+ appendPQExpBuffer(create, "ALTER %s %s DEPENDS ON EXTENSION %s;\n",
4333+ keyword, nm,
4334+ fmtId(PQgetvalue(res, i, i_extname)));
4335+ }
4336+
4337+ PQclear(res);
4338+ pg_free(nm);
4339+ }
4340+ }
4341+
4342+
42944343static void
42954344binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
42964345 PQExpBuffer upgrade_buffer,
@@ -12161,6 +12210,12 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
1216112210
1216212211 appendPQExpBuffer(q, "\n %s;\n", asPart->data);
1216312212
12213+ append_depends_on_extension(fout, q, &finfo->dobj,
12214+ "pg_catalog.pg_proc", keyword,
12215+ psprintf("%s.%s",
12216+ fmtId(finfo->dobj.namespace->dobj.name),
12217+ funcsig));
12218+
1216412219 if (dopt->binary_upgrade)
1216512220 binary_upgrade_extension_member(q, &finfo->dobj,
1216612221 keyword, funcsig,
@@ -15871,6 +15926,14 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
1587115926 else
1587215927 appendPQExpBufferStr(q, ";\n");
1587315928
15929+ /* Materialized views can depend on extensions */
15930+ if (tbinfo->relkind == RELKIND_MATVIEW)
15931+ append_depends_on_extension(fout, q, &tbinfo->dobj,
15932+ "pg_catalog.pg_class",
15933+ tbinfo->relkind == RELKIND_MATVIEW ?
15934+ "MATERIALIZED VIEW" : "INDEX",
15935+ qualrelname);
15936+
1587415937 /*
1587515938 * in binary upgrade mode, update the catalog with any missing values
1587615939 * that might be present.
@@ -16375,6 +16438,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1637516438 PQExpBuffer q;
1637616439 PQExpBuffer delq;
1637716440 char *qindxname;
16441+ char *qqindxname;
1637816442
1637916443 if (dopt->dataOnly)
1638016444 return;
@@ -16383,6 +16447,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1638316447 delq = createPQExpBuffer();
1638416448
1638516449 qindxname = pg_strdup(fmtId(indxinfo->dobj.name));
16450+ qqindxname = pg_strdup(fmtQualifiedDumpable(indxinfo));
1638616451
1638716452 /*
1638816453 * If there's an associated constraint, don't dump the index per se, but
@@ -16435,8 +16500,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1643516500
1643616501 for (j = 0; j < nstatcols; j++)
1643716502 {
16438- appendPQExpBuffer(q, "ALTER INDEX %s ",
16439- fmtQualifiedDumpable(indxinfo));
16503+ appendPQExpBuffer(q, "ALTER INDEX %s ", qqindxname);
1644016504
1644116505 /*
1644216506 * Note that this is a column number, so no quotes should be
@@ -16449,6 +16513,11 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1644916513 }
1645016514 }
1645116515
16516+ /* Indexes can depend on extensions */
16517+ append_depends_on_extension(fout, q, &indxinfo->dobj,
16518+ "pg_catalog.pg_class",
16519+ "INDEX", qqindxname);
16520+
1645216521 /* If the index defines identity, we need to record that. */
1645316522 if (indxinfo->indisreplident)
1645416523 {
@@ -16459,8 +16528,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1645916528 qindxname);
1646016529 }
1646116530
16462- appendPQExpBuffer(delq, "DROP INDEX %s;\n",
16463- fmtQualifiedDumpable(indxinfo));
16531+ appendPQExpBuffer(delq, "DROP INDEX %s;\n", qqindxname);
1646416532
1646516533 if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
1646616534 ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
@@ -16491,6 +16559,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1649116559 destroyPQExpBuffer(q);
1649216560 destroyPQExpBuffer(delq);
1649316561 free(qindxname);
16562+ free(qqindxname);
1649416563}
1649516564
1649616565/*
@@ -16729,6 +16798,11 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
1672916798 fmtId(indxinfo->dobj.name));
1673016799 }
1673116800
16801+ /* Indexes can depend on extensions */
16802+ append_depends_on_extension(fout, q, &indxinfo->dobj,
16803+ "pg_catalog.pg_class", "INDEX",
16804+ fmtQualifiedDumpable(indxinfo));
16805+
1673216806 appendPQExpBuffer(delq, "ALTER TABLE ONLY %s ",
1673316807 fmtQualifiedDumpable(tbinfo));
1673416808 appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
@@ -17248,6 +17322,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
1724817322 PQExpBuffer query;
1724917323 PQExpBuffer delqry;
1725017324 PQExpBuffer trigprefix;
17325+ PQExpBuffer trigidentity;
1725117326 char *qtabname;
1725217327 char *tgargs;
1725317328 size_t lentgargs;
@@ -17265,13 +17340,14 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
1726517340 query = createPQExpBuffer();
1726617341 delqry = createPQExpBuffer();
1726717342 trigprefix = createPQExpBuffer();
17343+ trigidentity = createPQExpBuffer();
1726817344
1726917345 qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
1727017346
17271- appendPQExpBuffer(delqry , "DROP TRIGGER %s ",
17272- fmtId(tginfo->dobj.name ));
17273- appendPQExpBuffer(delqry, "ON %s;\n",
17274- fmtQualifiedDumpable(tbinfo) );
17347+ appendPQExpBuffer(trigidentity , "%s ", fmtId(tginfo->dobj.name));
17348+ appendPQExpBuffer(trigidentity, "ON %s", fmtQualifiedDumpable(tbinfo ));
17349+
17350+ appendPQExpBuffer(delqry, "DROP TRIGGER %s;\n", trigidentity->data );
1727517351
1727617352 if (tginfo->tgdef)
1727717353 {
@@ -17390,6 +17466,11 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
1739017466 appendPQExpBufferStr(query, ");\n");
1739117467 }
1739217468
17469+ /* Triggers can depend on extensions */
17470+ append_depends_on_extension(fout, query, &tginfo->dobj,
17471+ "pg_catalog.pg_trigger", "TRIGGER",
17472+ trigidentity->data);
17473+
1739317474 if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
1739417475 {
1739517476 appendPQExpBuffer(query, "\nALTER TABLE %s ",
@@ -17438,6 +17519,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
1743817519 destroyPQExpBuffer(query);
1743917520 destroyPQExpBuffer(delqry);
1744017521 destroyPQExpBuffer(trigprefix);
17522+ destroyPQExpBuffer(trigidentity);
1744117523 free(qtabname);
1744217524}
1744317525
@@ -18087,6 +18169,15 @@ getDependencies(Archive *fout)
1808718169 continue;
1808818170 }
1808918171
18172+ /*
18173+ * For 'x' dependencies, mark the object for later; we still add the
18174+ * normal dependency, for possible ordering purposes. Currently
18175+ * pg_dump_sort.c knows to put extensions ahead of all object types
18176+ * that could possibly depend on them, but this is safer.
18177+ */
18178+ if (deptype == 'x')
18179+ dobj->depends_on_ext = true;
18180+
1809018181 /*
1809118182 * Ordinarily, table rowtypes have implicit dependencies on their
1809218183 * tables. However, for a composite type the implicit dependency goes
0 commit comments