Skip to content

Commit f977e6d

Browse files
committed
Add pg_dump support for ALTER obj DEPENDS ON EXTENSION
pg_dump is oblivious to this kind of dependency, so they're lost on dump/restores (and pg_upgrade). Have pg_dump emit ALTER lines so that they're preserved. Add some pg_dump tests for the whole thing, also. Reviewed-by: Tom Lane (offlist) Reviewed-by: Ibrar Ahmed Reviewed-by: Ahsan Hadi (who also reviewed commit 899a04f) Discussion: https://postgr.es/m/20200217225333.GA30974@alvherre.pgsql
1 parent 3c8864f commit f977e6d

File tree

4 files changed

+133
-8
lines changed

4 files changed

+133
-8
lines changed

src/bin/pg_dump/common.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ AssignDumpId(DumpableObject *dobj)
551551
dobj->namespace = NULL; /* may be set later */
552552
dobj->dump = DUMP_COMPONENT_ALL; /* default assumption */
553553
dobj->ext_member = false; /* default assumption */
554+
dobj->depends_on_ext = false; /* default assumption */
554555
dobj->dependencies = NULL;
555556
dobj->nDeps = 0;
556557
dobj->allocDeps = 0;

src/bin/pg_dump/pg_dump.c

Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4285,6 +4285,55 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
42854285
free(qsubname);
42864286
}
42874287

4288+
/*
4289+
* Given a "create query", append as many ALTER ... DEPENDS ON EXTENSION as
4290+
* the object needs.
4291+
*/
4292+
static void
4293+
append_depends_on_extension(Archive *fout,
4294+
PQExpBuffer create,
4295+
DumpableObject *dobj,
4296+
const char *catalog,
4297+
const char *keyword,
4298+
const char *objname)
4299+
{
4300+
if (dobj->depends_on_ext)
4301+
{
4302+
char *nm;
4303+
PGresult *res;
4304+
PQExpBuffer query;
4305+
int ntups;
4306+
int i_extname;
4307+
int i;
4308+
4309+
/* dodge fmtId() non-reentrancy */
4310+
nm = pg_strdup(objname);
4311+
4312+
query = createPQExpBuffer();
4313+
appendPQExpBuffer(query,
4314+
"SELECT e.extname "
4315+
"FROM pg_catalog.pg_depend d, pg_catalog.pg_extension e "
4316+
"WHERE d.refobjid = e.oid AND classid = '%s'::pg_catalog.regclass "
4317+
"AND objid = '%u'::pg_catalog.oid AND deptype = 'x' "
4318+
"AND refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass",
4319+
catalog,
4320+
dobj->catId.oid);
4321+
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
4322+
ntups = PQntuples(res);
4323+
i_extname = PQfnumber(res, "extname");
4324+
for (i = 0; i < ntups; i++)
4325+
{
4326+
appendPQExpBuffer(create, "ALTER %s %s DEPENDS ON EXTENSION %s;\n",
4327+
keyword, nm,
4328+
fmtId(PQgetvalue(res, i, i_extname)));
4329+
}
4330+
4331+
PQclear(res);
4332+
pg_free(nm);
4333+
}
4334+
}
4335+
4336+
42884337
static void
42894338
binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
42904339
PQExpBuffer upgrade_buffer,
@@ -12148,6 +12197,12 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
1214812197

1214912198
appendPQExpBuffer(q, "\n %s;\n", asPart->data);
1215012199

12200+
append_depends_on_extension(fout, q, &finfo->dobj,
12201+
"pg_catalog.pg_proc", keyword,
12202+
psprintf("%s.%s",
12203+
fmtId(finfo->dobj.namespace->dobj.name),
12204+
funcsig));
12205+
1215112206
if (dopt->binary_upgrade)
1215212207
binary_upgrade_extension_member(q, &finfo->dobj,
1215312208
keyword, funcsig,
@@ -15860,6 +15915,14 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
1586015915
else
1586115916
appendPQExpBufferStr(q, ";\n");
1586215917

15918+
/* Materialized views can depend on extensions */
15919+
if (tbinfo->relkind == RELKIND_MATVIEW)
15920+
append_depends_on_extension(fout, q, &tbinfo->dobj,
15921+
"pg_catalog.pg_class",
15922+
tbinfo->relkind == RELKIND_MATVIEW ?
15923+
"MATERIALIZED VIEW" : "INDEX",
15924+
qualrelname);
15925+
1586315926
/*
1586415927
* in binary upgrade mode, update the catalog with any missing values
1586515928
* that might be present.
@@ -16364,6 +16427,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1636416427
PQExpBuffer q;
1636516428
PQExpBuffer delq;
1636616429
char *qindxname;
16430+
char *qqindxname;
1636716431

1636816432
if (dopt->dataOnly)
1636916433
return;
@@ -16372,6 +16436,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1637216436
delq = createPQExpBuffer();
1637316437

1637416438
qindxname = pg_strdup(fmtId(indxinfo->dobj.name));
16439+
qqindxname = pg_strdup(fmtQualifiedDumpable(indxinfo));
1637516440

1637616441
/*
1637716442
* If there's an associated constraint, don't dump the index per se, but
@@ -16424,8 +16489,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1642416489

1642516490
for (j = 0; j < nstatcols; j++)
1642616491
{
16427-
appendPQExpBuffer(q, "ALTER INDEX %s ",
16428-
fmtQualifiedDumpable(indxinfo));
16492+
appendPQExpBuffer(q, "ALTER INDEX %s ", qqindxname);
1642916493

1643016494
/*
1643116495
* Note that this is a column number, so no quotes should be
@@ -16438,6 +16502,11 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1643816502
}
1643916503
}
1644016504

16505+
/* Indexes can depend on extensions */
16506+
append_depends_on_extension(fout, q, &indxinfo->dobj,
16507+
"pg_catalog.pg_class",
16508+
"INDEX", qqindxname);
16509+
1644116510
/* If the index defines identity, we need to record that. */
1644216511
if (indxinfo->indisreplident)
1644316512
{
@@ -16448,8 +16517,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1644816517
qindxname);
1644916518
}
1645016519

16451-
appendPQExpBuffer(delq, "DROP INDEX %s;\n",
16452-
fmtQualifiedDumpable(indxinfo));
16520+
appendPQExpBuffer(delq, "DROP INDEX %s;\n", qqindxname);
1645316521

1645416522
if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
1645516523
ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
@@ -16480,6 +16548,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
1648016548
destroyPQExpBuffer(q);
1648116549
destroyPQExpBuffer(delq);
1648216550
free(qindxname);
16551+
free(qqindxname);
1648316552
}
1648416553

1648516554
/*
@@ -16705,6 +16774,11 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
1670516774
fmtId(indxinfo->dobj.name));
1670616775
}
1670716776

16777+
/* Indexes can depend on extensions */
16778+
append_depends_on_extension(fout, q, &indxinfo->dobj,
16779+
"pg_catalog.pg_class", "INDEX",
16780+
fmtQualifiedDumpable(indxinfo));
16781+
1670816782
appendPQExpBuffer(delq, "ALTER TABLE ONLY %s ",
1670916783
fmtQualifiedDumpable(tbinfo));
1671016784
appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
@@ -17224,6 +17298,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
1722417298
PQExpBuffer query;
1722517299
PQExpBuffer delqry;
1722617300
PQExpBuffer trigprefix;
17301+
PQExpBuffer trigidentity;
1722717302
char *qtabname;
1722817303
char *tgargs;
1722917304
size_t lentgargs;
@@ -17241,13 +17316,14 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
1724117316
query = createPQExpBuffer();
1724217317
delqry = createPQExpBuffer();
1724317318
trigprefix = createPQExpBuffer();
17319+
trigidentity = createPQExpBuffer();
1724417320

1724517321
qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
1724617322

17247-
appendPQExpBuffer(delqry, "DROP TRIGGER %s ",
17248-
fmtId(tginfo->dobj.name));
17249-
appendPQExpBuffer(delqry, "ON %s;\n",
17250-
fmtQualifiedDumpable(tbinfo));
17323+
appendPQExpBuffer(trigidentity, "%s ", fmtId(tginfo->dobj.name));
17324+
appendPQExpBuffer(trigidentity, "ON %s", fmtQualifiedDumpable(tbinfo));
17325+
17326+
appendPQExpBuffer(delqry, "DROP TRIGGER %s;\n", trigidentity->data);
1725117327

1725217328
if (tginfo->tgdef)
1725317329
{
@@ -17366,6 +17442,11 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
1736617442
appendPQExpBufferStr(query, ");\n");
1736717443
}
1736817444

17445+
/* Triggers can depend on extensions */
17446+
append_depends_on_extension(fout, query, &tginfo->dobj,
17447+
"pg_catalog.pg_trigger", "TRIGGER",
17448+
trigidentity->data);
17449+
1736917450
if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
1737017451
{
1737117452
appendPQExpBuffer(query, "\nALTER TABLE %s ",
@@ -17414,6 +17495,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
1741417495
destroyPQExpBuffer(query);
1741517496
destroyPQExpBuffer(delqry);
1741617497
destroyPQExpBuffer(trigprefix);
17498+
destroyPQExpBuffer(trigidentity);
1741717499
free(qtabname);
1741817500
}
1741917501

@@ -18063,6 +18145,15 @@ getDependencies(Archive *fout)
1806318145
continue;
1806418146
}
1806518147

18148+
/*
18149+
* For 'x' dependencies, mark the object for later; we still add the
18150+
* normal dependency, for possible ordering purposes. Currently
18151+
* pg_dump_sort.c knows to put extensions ahead of all object types
18152+
* that could possibly depend on them, but this is safer.
18153+
*/
18154+
if (deptype == 'x')
18155+
dobj->depends_on_ext = true;
18156+
1806618157
/*
1806718158
* Ordinarily, table rowtypes have implicit dependencies on their
1806818159
* tables. However, for a composite type the implicit dependency goes

src/bin/pg_dump/pg_dump.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ typedef struct _dumpableObject
136136
DumpComponents dump; /* bitmask of components to dump */
137137
DumpComponents dump_contains; /* as above, but for contained objects */
138138
bool ext_member; /* true if object is member of extension */
139+
bool depends_on_ext; /* true if object depends on an extension */
139140
DumpId *dependencies; /* dumpIds of objects this one depends on */
140141
int nDeps; /* number of valid dependencies */
141142
int allocDeps; /* allocated size of dependencies[] */

src/test/modules/test_pg_dump/t/001_base.pl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,38 @@
523523
like => { binary_upgrade => 1, },
524524
},
525525
526+
'ALTER INDEX pkey DEPENDS ON extension' => {
527+
create_order => 11,
528+
create_sql =>
529+
'CREATE TABLE regress_pg_dump_schema.extdependtab (col1 integer primary key, col2 int);
530+
CREATE INDEX ON regress_pg_dump_schema.extdependtab (col2);
531+
ALTER INDEX regress_pg_dump_schema.extdependtab_col2_idx DEPENDS ON EXTENSION test_pg_dump;
532+
ALTER INDEX regress_pg_dump_schema.extdependtab_pkey DEPENDS ON EXTENSION test_pg_dump;',
533+
regexp => qr/^
534+
\QALTER INDEX regress_pg_dump_schema.extdependtab_pkey DEPENDS ON EXTENSION test_pg_dump;\E\n
535+
/xms,
536+
like => {%pgdump_runs},
537+
unlike => {
538+
data_only => 1,
539+
pg_dumpall_globals => 1,
540+
section_data => 1,
541+
section_pre_data => 1,
542+
},
543+
},
544+
545+
'ALTER INDEX idx DEPENDS ON extension' => {
546+
regexp => qr/^
547+
\QALTER INDEX regress_pg_dump_schema.extdependtab_col2_idx DEPENDS ON EXTENSION test_pg_dump;\E\n
548+
/xms,
549+
like => {%pgdump_runs},
550+
unlike => {
551+
data_only => 1,
552+
pg_dumpall_globals => 1,
553+
section_data => 1,
554+
section_pre_data => 1,
555+
},
556+
},
557+
526558
# Objects not included in extension, part of schema created by extension
527559
'CREATE TABLE regress_pg_dump_schema.external_tab' => {
528560
create_order => 4,

0 commit comments

Comments
 (0)