@@ -3946,6 +3946,55 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
3946
3946
free(qsubname);
3947
3947
}
3948
3948
3949
+ /*
3950
+ * Given a "create query", append as many ALTER ... DEPENDS ON EXTENSION as
3951
+ * the object needs.
3952
+ */
3953
+ static void
3954
+ append_depends_on_extension(Archive *fout,
3955
+ PQExpBuffer create,
3956
+ DumpableObject *dobj,
3957
+ const char *catalog,
3958
+ const char *keyword,
3959
+ const char *objname)
3960
+ {
3961
+ if (dobj->depends_on_ext)
3962
+ {
3963
+ char *nm;
3964
+ PGresult *res;
3965
+ PQExpBufferquery;
3966
+ intntups;
3967
+ inti_extname;
3968
+ inti;
3969
+
3970
+ /* dodge fmtId() non-reentrancy */
3971
+ nm = pg_strdup(objname);
3972
+
3973
+ query = createPQExpBuffer();
3974
+ appendPQExpBuffer(query,
3975
+ "SELECT e.extname "
3976
+ "FROM pg_catalog.pg_depend d, pg_catalog.pg_extension e "
3977
+ "WHERE d.refobjid = e.oid AND classid = '%s'::pg_catalog.regclass "
3978
+ "AND objid = '%u'::pg_catalog.oid AND deptype = 'x' "
3979
+ "AND refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass",
3980
+ catalog,
3981
+ dobj->catId.oid);
3982
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
3983
+ ntups = PQntuples(res);
3984
+ i_extname = PQfnumber(res, "extname");
3985
+ for (i = 0; i < ntups; i++)
3986
+ {
3987
+ appendPQExpBuffer(create, "ALTER %s %s DEPENDS ON EXTENSION %s;\n",
3988
+ keyword, nm,
3989
+ fmtId(PQgetvalue(res, i, i_extname)));
3990
+ }
3991
+
3992
+ PQclear(res);
3993
+ pg_free(nm);
3994
+ }
3995
+ }
3996
+
3997
+
3949
3998
static void
3950
3999
binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
3951
4000
PQExpBuffer upgrade_buffer,
@@ -11556,6 +11605,12 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
11556
11605
11557
11606
appendPQExpBuffer(q, "\n %s;\n", asPart->data);
11558
11607
11608
+ append_depends_on_extension(fout, q, &finfo->dobj,
11609
+ "pg_catalog.pg_proc", "FUNCTION",
11610
+ psprintf("%s.%s",
11611
+ fmtId(finfo->dobj.namespace->dobj.name),
11612
+ funcsig));
11613
+
11559
11614
if (dopt->binary_upgrade)
11560
11615
binary_upgrade_extension_member(q, &finfo->dobj,
11561
11616
"FUNCTION", funcsig,
@@ -15184,6 +15239,14 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
15184
15239
else
15185
15240
appendPQExpBufferStr(q, ";\n");
15186
15241
15242
+ /* Materialized views can depend on extensions */
15243
+ if (tbinfo->relkind == RELKIND_MATVIEW)
15244
+ append_depends_on_extension(fout, q, &tbinfo->dobj,
15245
+ "pg_catalog.pg_class",
15246
+ tbinfo->relkind == RELKIND_MATVIEW ?
15247
+ "MATERIALIZED VIEW" : "INDEX",
15248
+ qualrelname);
15249
+
15187
15250
/*
15188
15251
* To create binary-compatible heap files, we have to ensure the same
15189
15252
* physical column order, including dropped columns, as in the
@@ -15661,6 +15724,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
15661
15724
PQExpBuffer q;
15662
15725
PQExpBuffer delq;
15663
15726
char *qindxname;
15727
+ char *qqindxname;
15664
15728
15665
15729
if (dopt->dataOnly)
15666
15730
return;
@@ -15669,6 +15733,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
15669
15733
delq = createPQExpBuffer();
15670
15734
15671
15735
qindxname = pg_strdup(fmtId(indxinfo->dobj.name));
15736
+ qqindxname = pg_strdup(fmtQualifiedDumpable(indxinfo));
15672
15737
15673
15738
/*
15674
15739
* If there's an associated constraint, don't dump the index per se, but
@@ -15702,6 +15767,11 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
15702
15767
qindxname);
15703
15768
}
15704
15769
15770
+ /* Indexes can depend on extensions */
15771
+ append_depends_on_extension(fout, q, &indxinfo->dobj,
15772
+ "pg_catalog.pg_class",
15773
+ "INDEX", qqindxname);
15774
+
15705
15775
/* If the index defines identity, we need to record that. */
15706
15776
if (indxinfo->indisreplident)
15707
15777
{
@@ -15712,8 +15782,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
15712
15782
qindxname);
15713
15783
}
15714
15784
15715
- appendPQExpBuffer(delq, "DROP INDEX %s;\n",
15716
- fmtQualifiedDumpable(indxinfo));
15785
+ appendPQExpBuffer(delq, "DROP INDEX %s;\n", qqindxname);
15717
15786
15718
15787
if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
15719
15788
ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
@@ -15739,6 +15808,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
15739
15808
destroyPQExpBuffer(q);
15740
15809
destroyPQExpBuffer(delq);
15741
15810
free(qindxname);
15811
+ free(qqindxname);
15742
15812
}
15743
15813
15744
15814
/*
@@ -15918,6 +15988,11 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
15918
15988
fmtId(indxinfo->dobj.name));
15919
15989
}
15920
15990
15991
+ /* Indexes can depend on extensions */
15992
+ append_depends_on_extension(fout, q, &indxinfo->dobj,
15993
+ "pg_catalog.pg_class", "INDEX",
15994
+ fmtQualifiedDumpable(indxinfo));
15995
+
15921
15996
appendPQExpBuffer(delq, "ALTER TABLE ONLY %s ",
15922
15997
fmtQualifiedDumpable(tbinfo));
15923
15998
appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
@@ -16435,6 +16510,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
16435
16510
PQExpBuffer query;
16436
16511
PQExpBuffer delqry;
16437
16512
PQExpBuffer trigprefix;
16513
+ PQExpBuffer trigidentity;
16438
16514
char *qtabname;
16439
16515
char *tgargs;
16440
16516
size_tlentgargs;
@@ -16452,13 +16528,14 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
16452
16528
query = createPQExpBuffer();
16453
16529
delqry = createPQExpBuffer();
16454
16530
trigprefix = createPQExpBuffer();
16531
+ trigidentity = createPQExpBuffer();
16455
16532
16456
16533
qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
16457
16534
16458
- appendPQExpBuffer(delqry , "DROP TRIGGER %s ",
16459
- fmtId(tginfo->dobj.name ));
16460
- appendPQExpBuffer(delqry, "ON %s;\n",
16461
- fmtQualifiedDumpable(tbinfo) );
16535
+ appendPQExpBuffer(trigidentity , "%s ", fmtId(tginfo->dobj.name));
16536
+ appendPQExpBuffer(trigidentity, "ON %s", fmtQualifiedDumpable(tbinfo ));
16537
+
16538
+ appendPQExpBuffer(delqry, "DROP TRIGGER %s;\n", trigidentity->data );
16462
16539
16463
16540
if (tginfo->tgdef)
16464
16541
{
@@ -16577,6 +16654,11 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
16577
16654
appendPQExpBufferStr(query, ");\n");
16578
16655
}
16579
16656
16657
+ /* Triggers can depend on extensions */
16658
+ append_depends_on_extension(fout, query, &tginfo->dobj,
16659
+ "pg_catalog.pg_trigger", "TRIGGER",
16660
+ trigidentity->data);
16661
+
16580
16662
if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
16581
16663
{
16582
16664
appendPQExpBuffer(query, "\nALTER TABLE %s ",
@@ -16626,6 +16708,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
16626
16708
destroyPQExpBuffer(query);
16627
16709
destroyPQExpBuffer(delqry);
16628
16710
destroyPQExpBuffer(trigprefix);
16711
+ destroyPQExpBuffer(trigidentity);
16629
16712
free(qtabname);
16630
16713
}
16631
16714
@@ -17282,6 +17365,15 @@ getDependencies(Archive *fout)
17282
17365
continue;
17283
17366
}
17284
17367
17368
+ /*
17369
+ * For 'x' dependencies, mark the object for later; we still add the
17370
+ * normal dependency, for possible ordering purposes. Currently
17371
+ * pg_dump_sort.c knows to put extensions ahead of all object types
17372
+ * that could possibly depend on them, but this is safer.
17373
+ */
17374
+ if (deptype == 'x')
17375
+ dobj->depends_on_ext = true;
17376
+
17285
17377
/*
17286
17378
* Ordinarily, table rowtypes have implicit dependencies on their
17287
17379
* tables. However, for a composite type the implicit dependency goes