Skip to content

Commit b08dee2

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 085b6b6 commit b08dee2

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
@@ -549,6 +549,7 @@ AssignDumpId(DumpableObject *dobj)
549549
dobj->namespace = NULL; /* may be set later */
550550
dobj->dump = DUMP_COMPONENT_ALL; /* default assumption */
551551
dobj->ext_member = false; /* default assumption */
552+
dobj->depends_on_ext = false; /* default assumption */
552553
dobj->dependencies = NULL;
553554
dobj->nDeps = 0;
554555
dobj->allocDeps = 0;

src/bin/pg_dump/pg_dump.c

Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
42944343
static void
42954344
binary_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

src/bin/pg_dump/pg_dump.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ typedef struct _dumpableObject
132132
DumpComponents dump; /* bitmask of components to dump */
133133
DumpComponents dump_contains; /* as above, but for contained objects */
134134
bool ext_member; /* true if object is member of extension */
135+
bool depends_on_ext; /* true if object depends on an extension */
135136
DumpId *dependencies; /* dumpIds of objects this one depends on */
136137
int nDeps; /* number of valid dependencies */
137138
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy