Skip to content

Commit 8e396a7

Browse files
committed
pg_dump: label PUBLICATION TABLE ArchiveEntries with an owner.
This is the same fix as commit 9eabfe3 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/[email protected]
1 parent ebfe2db commit 8e396a7

File tree

3 files changed

+85
-62
lines changed

3 files changed

+85
-62
lines changed

src/bin/pg_dump/common.c

+17-1
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);
@@ -937,6 +942,17 @@ findExtensionByOid(Oid oid)
937942
return (ExtensionInfo *) findObjectByOid(oid, extinfoindex, numExtensions);
938943
}
939944

945+
/*
946+
* findPublicationByOid
947+
* finds the entry (in pubinfo) of the publication with the given oid
948+
* returns NULL if not found
949+
*/
950+
PublicationInfo *
951+
findPublicationByOid(Oid oid)
952+
{
953+
return (PublicationInfo *) findObjectByOid(oid, pubinfoindex, numPublications);
954+
}
955+
940956
/*
941957
* findIndexByOid
942958
* find the entry of the index with the given oid

src/bin/pg_dump/pg_dump.c

+64-59
Original file line numberDiff line numberDiff line change
@@ -3865,8 +3865,8 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
38653865
* getPublications
38663866
* get information about publications
38673867
*/
3868-
void
3869-
getPublications(Archive *fout)
3868+
PublicationInfo *
3869+
getPublications(Archive *fout, int *numPublications)
38703870
{
38713871
DumpOptions *dopt = fout->dopt;
38723872
PQExpBuffer query;
@@ -3886,7 +3886,10 @@ getPublications(Archive *fout)
38863886
ntups;
38873887

38883888
if (dopt->no_publications || fout->remoteVersion < 100000)
3889-
return;
3889+
{
3890+
*numPublications = 0;
3891+
return NULL;
3892+
}
38903893

38913894
query = createPQExpBuffer();
38923895

@@ -3964,6 +3967,9 @@ getPublications(Archive *fout)
39643967
PQclear(res);
39653968

39663969
destroyPQExpBuffer(query);
3970+
3971+
*numPublications = ntups;
3972+
return pubinfo;
39673973
}
39683974

39693975
/*
@@ -4072,7 +4078,8 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
40724078
DumpOptions *dopt = fout->dopt;
40734079
int i_tableoid;
40744080
int i_oid;
4075-
int i_pubname;
4081+
int i_prpubid;
4082+
int i_prrelid;
40764083
int i,
40774084
j,
40784085
ntups;
@@ -4082,15 +4089,39 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
40824089

40834090
query = createPQExpBuffer();
40844091

4085-
for (i = 0; i < numTables; i++)
4092+
/* Collect all publication membership info. */
4093+
appendPQExpBufferStr(query,
4094+
"SELECT tableoid, oid, prpubid, prrelid "
4095+
"FROM pg_catalog.pg_publication_rel");
4096+
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
4097+
4098+
ntups = PQntuples(res);
4099+
4100+
i_tableoid = PQfnumber(res, "tableoid");
4101+
i_oid = PQfnumber(res, "oid");
4102+
i_prpubid = PQfnumber(res, "prpubid");
4103+
i_prrelid = PQfnumber(res, "prrelid");
4104+
4105+
/* this allocation may be more than we need */
4106+
pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo));
4107+
j = 0;
4108+
4109+
for (i = 0; i < ntups; i++)
40864110
{
4087-
TableInfo *tbinfo = &tblinfo[i];
4111+
Oid prpubid = atooid(PQgetvalue(res, i, i_prpubid));
4112+
Oid prrelid = atooid(PQgetvalue(res, i, i_prrelid));
4113+
PublicationInfo *pubinfo;
4114+
TableInfo *tbinfo;
40884115

40894116
/*
4090-
* Only regular and partitioned tables can be added to publications.
4117+
* Ignore any entries for which we aren't interested in either the
4118+
* publication or the rel.
40914119
*/
4092-
if (tbinfo->relkind != RELKIND_RELATION &&
4093-
tbinfo->relkind != RELKIND_PARTITIONED_TABLE)
4120+
pubinfo = findPublicationByOid(prpubid);
4121+
if (pubinfo == NULL)
4122+
continue;
4123+
tbinfo = findTableByOid(prrelid);
4124+
if (tbinfo == NULL)
40944125
continue;
40954126

40964127
/*
@@ -4100,55 +4131,24 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
41004131
if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
41014132
continue;
41024133

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

4133-
pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo));
4145+
/* Decide whether we want to dump it */
4146+
selectDumpablePublicationTable(&(pubrinfo[j].dobj), fout);
41344147

4135-
for (j = 0; j < ntups; j++)
4136-
{
4137-
pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
4138-
pubrinfo[j].dobj.catId.tableoid =
4139-
atooid(PQgetvalue(res, j, i_tableoid));
4140-
pubrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
4141-
AssignDumpId(&pubrinfo[j].dobj);
4142-
pubrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
4143-
pubrinfo[j].dobj.name = tbinfo->dobj.name;
4144-
pubrinfo[j].pubname = pg_strdup(PQgetvalue(res, j, i_pubname));
4145-
pubrinfo[j].pubtable = tbinfo;
4146-
4147-
/* Decide whether we want to dump it */
4148-
selectDumpablePublicationTable(&(pubrinfo[j].dobj), fout);
4149-
}
4150-
PQclear(res);
4148+
j++;
41514149
}
4150+
4151+
PQclear(res);
41524152
destroyPQExpBuffer(query);
41534153
}
41544154

@@ -4159,29 +4159,34 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
41594159
static void
41604160
dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo)
41614161
{
4162+
PublicationInfo *pubinfo = pubrinfo->publication;
41624163
TableInfo *tbinfo = pubrinfo->pubtable;
41634164
PQExpBuffer query;
41644165
char *tag;
41654166

41664167
if (!(pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
41674168
return;
41684169

4169-
tag = psprintf("%s %s", pubrinfo->pubname, tbinfo->dobj.name);
4170+
tag = psprintf("%s %s", pubinfo->dobj.name, tbinfo->dobj.name);
41704171

41714172
query = createPQExpBuffer();
41724173

41734174
appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
4174-
fmtId(pubrinfo->pubname));
4175+
fmtId(pubinfo->dobj.name));
41754176
appendPQExpBuffer(query, " %s;\n",
41764177
fmtQualifiedDumpable(tbinfo));
41774178

41784179
/*
4179-
* There is no point in creating drop query as the drop is done by table
4180-
* drop.
4180+
* There is no point in creating a drop query as the drop is done by table
4181+
* drop. (If you think to change this, see also _printTocEntry().)
4182+
* Although this object doesn't really have ownership as such, set the
4183+
* owner field anyway to ensure that the command is run by the correct
4184+
* role at restore time.
41814185
*/
41824186
ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
41834187
ARCHIVE_OPTS(.tag = tag,
41844188
.namespace = tbinfo->dobj.namespace->dobj.name,
4189+
.owner = pubinfo->rolname,
41854190
.description = "PUBLICATION TABLE",
41864191
.section = SECTION_POST_DATA,
41874192
.createStmt = query->data));

src/bin/pg_dump/pg_dump.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -623,8 +623,8 @@ typedef struct _PublicationInfo
623623
typedef struct _PublicationRelInfo
624624
{
625625
DumpableObject dobj;
626+
PublicationInfo *publication;
626627
TableInfo *pubtable;
627-
char *pubname;
628628
} PublicationRelInfo;
629629

630630
/*
@@ -675,6 +675,7 @@ extern OprInfo *findOprByOid(Oid oid);
675675
extern CollInfo *findCollationByOid(Oid oid);
676676
extern NamespaceInfo *findNamespaceByOid(Oid oid);
677677
extern ExtensionInfo *findExtensionByOid(Oid oid);
678+
extern PublicationInfo *findPublicationByOid(Oid oid);
678679

679680
extern void setExtensionMembership(ExtensionMemberId *extmems, int nextmems);
680681
extern ExtensionInfo *findOwningExtension(CatalogId catalogId);
@@ -727,7 +728,8 @@ extern void processExtensionTables(Archive *fout, ExtensionInfo extinfo[],
727728
int numExtensions);
728729
extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
729730
extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);
730-
extern void getPublications(Archive *fout);
731+
extern PublicationInfo *getPublications(Archive *fout,
732+
int *numPublications);
731733
extern void getPublicationTables(Archive *fout, TableInfo tblinfo[],
732734
int numTables);
733735
extern void getSubscriptions(Archive *fout);

0 commit comments

Comments
 (0)