Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)