Skip to content

Commit 79d3ac7

Browse files
committed
pg_dump: label PUBLICATION TABLE ArchiveEntries with an owner.
This is the same fix as commit 9eabfe300 applied to INDEX ATTACH entries, but for table-to-publication attachments. As in that case, even though the backend doesn't record "ownership" of the attachment, we still ought to label it in the dump archive with the role name that should run the ALTER PUBLICATION command. The existing behavior causes the ALTER to be done by the original role that started the restore; that will usually work fine, but there may be corner cases where it fails. The bulk of the patch is concerned with changing struct PublicationRelInfo to include a pointer to the associated PublicationInfo object, so that we can get the owner's name out of that when the time comes. While at it, I rewrote getPublicationTables() to do just one query of pg_publication_rel, not one per table. Back-patch to v10 where this code was introduced. Discussion: https://postgr.es/m/1165710.1610473242@sss.pgh.pa.us
1 parent 5b01a6f commit 79d3ac7

File tree

3 files changed

+85
-62
lines changed

3 files changed

+85
-62
lines changed

src/bin/pg_dump/common.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,15 @@ static DumpableObject **oprinfoindex;
5252
static DumpableObject **collinfoindex;
5353
static DumpableObject **nspinfoindex;
5454
static DumpableObject **extinfoindex;
55+
static DumpableObject **pubinfoindex;
5556
static int numTables;
5657
static int numTypes;
5758
static int numFuncs;
5859
static int numOperators;
5960
static int numCollations;
6061
static int numNamespaces;
6162
static int numExtensions;
63+
static int numPublications;
6264

6365
/* This is an array of object identities, not actual DumpableObjects */
6466
static ExtensionMemberId *extmembers;
@@ -93,6 +95,7 @@ getSchemaData(Archive *fout, int *numTablesPtr)
9395
CollInfo *collinfo;
9496
NamespaceInfo *nspinfo;
9597
ExtensionInfo *extinfo;
98+
PublicationInfo *pubinfo;
9699
InhInfo *inhinfo;
97100
int numAggregates;
98101
int numInherits;
@@ -247,7 +250,9 @@ getSchemaData(Archive *fout, int *numTablesPtr)
247250
getPolicies(fout, tblinfo, numTables);
248251

249252
pg_log_info("reading publications");
250-
getPublications(fout);
253+
pubinfo = getPublications(fout, &numPublications);
254+
pubinfoindex = buildIndexArray(pubinfo, numPublications,
255+
sizeof(PublicationInfo));
251256

252257
pg_log_info("reading publication membership");
253258
getPublicationTables(fout, tblinfo, numTables);
@@ -897,6 +902,17 @@ findExtensionByOid(Oid oid)
897902
return (ExtensionInfo *) findObjectByOid(oid, extinfoindex, numExtensions);
898903
}
899904

905+
/*
906+
* findPublicationByOid
907+
* finds the entry (in pubinfo) of the publication with the given oid
908+
* returns NULL if not found
909+
*/
910+
PublicationInfo *
911+
findPublicationByOid(Oid oid)
912+
{
913+
return (PublicationInfo *) findObjectByOid(oid, pubinfoindex, numPublications);
914+
}
915+
900916
/*
901917
* findIndexByOid
902918
* find the entry of the index with the given oid

src/bin/pg_dump/pg_dump.c

Lines changed: 64 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3855,8 +3855,8 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
38553855
* getPublications
38563856
* get information about publications
38573857
*/
3858-
void
3859-
getPublications(Archive *fout)
3858+
PublicationInfo *
3859+
getPublications(Archive *fout, int *numPublications)
38603860
{
38613861
DumpOptions *dopt = fout->dopt;
38623862
PQExpBuffer query;
@@ -3876,7 +3876,10 @@ getPublications(Archive *fout)
38763876
ntups;
38773877

38783878
if (dopt->no_publications || fout->remoteVersion < 100000)
3879-
return;
3879+
{
3880+
*numPublications = 0;
3881+
return NULL;
3882+
}
38803883

38813884
query = createPQExpBuffer();
38823885

@@ -3954,6 +3957,9 @@ getPublications(Archive *fout)
39543957
PQclear(res);
39553958

39563959
destroyPQExpBuffer(query);
3960+
3961+
*numPublications = ntups;
3962+
return pubinfo;
39573963
}
39583964

39593965
/*
@@ -4062,7 +4068,8 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
40624068
DumpOptions *dopt = fout->dopt;
40634069
int i_tableoid;
40644070
int i_oid;
4065-
int i_pubname;
4071+
int i_prpubid;
4072+
int i_prrelid;
40664073
int i,
40674074
j,
40684075
ntups;
@@ -4072,15 +4079,39 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
40724079

40734080
query = createPQExpBuffer();
40744081

4075-
for (i = 0; i < numTables; i++)
4082+
/* Collect all publication membership info. */
4083+
appendPQExpBufferStr(query,
4084+
"SELECT tableoid, oid, prpubid, prrelid "
4085+
"FROM pg_catalog.pg_publication_rel");
4086+
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
4087+
4088+
ntups = PQntuples(res);
4089+
4090+
i_tableoid = PQfnumber(res, "tableoid");
4091+
i_oid = PQfnumber(res, "oid");
4092+
i_prpubid = PQfnumber(res, "prpubid");
4093+
i_prrelid = PQfnumber(res, "prrelid");
4094+
4095+
/* this allocation may be more than we need */
4096+
pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo));
4097+
j = 0;
4098+
4099+
for (i = 0; i < ntups; i++)
40764100
{
4077-
TableInfo *tbinfo = &tblinfo[i];
4101+
Oid prpubid = atooid(PQgetvalue(res, i, i_prpubid));
4102+
Oid prrelid = atooid(PQgetvalue(res, i, i_prrelid));
4103+
PublicationInfo *pubinfo;
4104+
TableInfo *tbinfo;
40784105

40794106
/*
4080-
* Only regular and partitioned tables can be added to publications.
4107+
* Ignore any entries for which we aren't interested in either the
4108+
* publication or the rel.
40814109
*/
4082-
if (tbinfo->relkind != RELKIND_RELATION &&
4083-
tbinfo->relkind != RELKIND_PARTITIONED_TABLE)
4110+
pubinfo = findPublicationByOid(prpubid);
4111+
if (pubinfo == NULL)
4112+
continue;
4113+
tbinfo = findTableByOid(prrelid);
4114+
if (tbinfo == NULL)
40844115
continue;
40854116

40864117
/*
@@ -4090,55 +4121,24 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
40904121
if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
40914122
continue;
40924123

4093-
pg_log_info("reading publication membership for table \"%s.%s\"",
4094-
tbinfo->dobj.namespace->dobj.name,
4095-
tbinfo->dobj.name);
4096-
4097-
resetPQExpBuffer(query);
4098-
4099-
/* Get the publication membership for the table. */
4100-
appendPQExpBuffer(query,
4101-
"SELECT pr.tableoid, pr.oid, p.pubname "
4102-
"FROM pg_publication_rel pr, pg_publication p "
4103-
"WHERE pr.prrelid = '%u'"
4104-
" AND p.oid = pr.prpubid",
4105-
tbinfo->dobj.catId.oid);
4106-
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
4107-
4108-
ntups = PQntuples(res);
4109-
4110-
if (ntups == 0)
4111-
{
4112-
/*
4113-
* Table is not member of any publications. Clean up and return.
4114-
*/
4115-
PQclear(res);
4116-
continue;
4117-
}
4118-
4119-
i_tableoid = PQfnumber(res, "tableoid");
4120-
i_oid = PQfnumber(res, "oid");
4121-
i_pubname = PQfnumber(res, "pubname");
4124+
/* OK, make a DumpableObject for this relationship */
4125+
pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
4126+
pubrinfo[j].dobj.catId.tableoid =
4127+
atooid(PQgetvalue(res, i, i_tableoid));
4128+
pubrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
4129+
AssignDumpId(&pubrinfo[j].dobj);
4130+
pubrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
4131+
pubrinfo[j].dobj.name = tbinfo->dobj.name;
4132+
pubrinfo[j].publication = pubinfo;
4133+
pubrinfo[j].pubtable = tbinfo;
41224134

4123-
pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo));
4135+
/* Decide whether we want to dump it */
4136+
selectDumpablePublicationTable(&(pubrinfo[j].dobj), fout);
41244137

4125-
for (j = 0; j < ntups; j++)
4126-
{
4127-
pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
4128-
pubrinfo[j].dobj.catId.tableoid =
4129-
atooid(PQgetvalue(res, j, i_tableoid));
4130-
pubrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
4131-
AssignDumpId(&pubrinfo[j].dobj);
4132-
pubrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
4133-
pubrinfo[j].dobj.name = tbinfo->dobj.name;
4134-
pubrinfo[j].pubname = pg_strdup(PQgetvalue(res, j, i_pubname));
4135-
pubrinfo[j].pubtable = tbinfo;
4136-
4137-
/* Decide whether we want to dump it */
4138-
selectDumpablePublicationTable(&(pubrinfo[j].dobj), fout);
4139-
}
4140-
PQclear(res);
4138+
j++;
41414139
}
4140+
4141+
PQclear(res);
41424142
destroyPQExpBuffer(query);
41434143
}
41444144

@@ -4149,29 +4149,34 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
41494149
static void
41504150
dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo)
41514151
{
4152+
PublicationInfo *pubinfo = pubrinfo->publication;
41524153
TableInfo *tbinfo = pubrinfo->pubtable;
41534154
PQExpBuffer query;
41544155
char *tag;
41554156

41564157
if (!(pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
41574158
return;
41584159

4159-
tag = psprintf("%s %s", pubrinfo->pubname, tbinfo->dobj.name);
4160+
tag = psprintf("%s %s", pubinfo->dobj.name, tbinfo->dobj.name);
41604161

41614162
query = createPQExpBuffer();
41624163

41634164
appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
4164-
fmtId(pubrinfo->pubname));
4165+
fmtId(pubinfo->dobj.name));
41654166
appendPQExpBuffer(query, " %s;\n",
41664167
fmtQualifiedDumpable(tbinfo));
41674168

41684169
/*
4169-
* There is no point in creating drop query as the drop is done by table
4170-
* drop.
4170+
* There is no point in creating a drop query as the drop is done by table
4171+
* drop. (If you think to change this, see also _printTocEntry().)
4172+
* Although this object doesn't really have ownership as such, set the
4173+
* owner field anyway to ensure that the command is run by the correct
4174+
* role at restore time.
41714175
*/
41724176
ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
41734177
ARCHIVE_OPTS(.tag = tag,
41744178
.namespace = tbinfo->dobj.namespace->dobj.name,
4179+
.owner = pubinfo->rolname,
41754180
.description = "PUBLICATION TABLE",
41764181
.section = SECTION_POST_DATA,
41774182
.createStmt = query->data));

src/bin/pg_dump/pg_dump.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,8 +612,8 @@ typedef struct _PublicationInfo
612612
typedef struct _PublicationRelInfo
613613
{
614614
DumpableObject dobj;
615+
PublicationInfo *publication;
615616
TableInfo *pubtable;
616-
char *pubname;
617617
} PublicationRelInfo;
618618

619619
/*
@@ -662,6 +662,7 @@ extern OprInfo *findOprByOid(Oid oid);
662662
extern CollInfo *findCollationByOid(Oid oid);
663663
extern NamespaceInfo *findNamespaceByOid(Oid oid);
664664
extern ExtensionInfo *findExtensionByOid(Oid oid);
665+
extern PublicationInfo *findPublicationByOid(Oid oid);
665666

666667
extern void setExtensionMembership(ExtensionMemberId *extmems, int nextmems);
667668
extern ExtensionInfo *findOwningExtension(CatalogId catalogId);
@@ -714,7 +715,8 @@ extern void processExtensionTables(Archive *fout, ExtensionInfo extinfo[],
714715
int numExtensions);
715716
extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
716717
extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);
717-
extern void getPublications(Archive *fout);
718+
extern PublicationInfo *getPublications(Archive *fout,
719+
int *numPublications);
718720
extern void getPublicationTables(Archive *fout, TableInfo tblinfo[],
719721
int numTables);
720722
extern void getSubscriptions(Archive *fout);

0 commit comments

Comments
 (0)