Skip to content

Commit bb12a7f

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/1165710.1610473242@sss.pgh.pa.us
1 parent c442b32 commit bb12a7f

File tree

3 files changed

+87
-63
lines changed

3 files changed

+87
-63
lines changed

src/bin/pg_dump/common.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,15 @@ static DumpableObject **oprinfoindex;
5454
static DumpableObject **collinfoindex;
5555
static DumpableObject **nspinfoindex;
5656
static DumpableObject **extinfoindex;
57+
static DumpableObject **pubinfoindex;
5758
static int numTables;
5859
static int numTypes;
5960
static int numFuncs;
6061
static int numOperators;
6162
static int numCollations;
6263
static int numNamespaces;
6364
static int numExtensions;
65+
static int numPublications;
6466

6567
/* This is an array of object identities, not actual DumpableObjects */
6668
static ExtensionMemberId *extmembers;
@@ -95,6 +97,7 @@ getSchemaData(Archive *fout, int *numTablesPtr)
9597
CollInfo *collinfo;
9698
NamespaceInfo *nspinfo;
9799
ExtensionInfo *extinfo;
100+
PublicationInfo *pubinfo;
98101
InhInfo *inhinfo;
99102
int numAggregates;
100103
int numInherits;
@@ -286,7 +289,9 @@ getSchemaData(Archive *fout, int *numTablesPtr)
286289

287290
if (g_verbose)
288291
write_msg(NULL, "reading publications\n");
289-
getPublications(fout);
292+
pubinfo = getPublications(fout, &numPublications);
293+
pubinfoindex = buildIndexArray(pubinfo, numPublications,
294+
sizeof(PublicationInfo));
290295

291296
if (g_verbose)
292297
write_msg(NULL, "reading publication membership\n");
@@ -935,6 +940,17 @@ findExtensionByOid(Oid oid)
935940
return (ExtensionInfo *) findObjectByOid(oid, extinfoindex, numExtensions);
936941
}
937942

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

src/bin/pg_dump/pg_dump.c

Lines changed: 66 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3742,8 +3742,8 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
37423742
* getPublications
37433743
* get information about publications
37443744
*/
3745-
void
3746-
getPublications(Archive *fout)
3745+
PublicationInfo *
3746+
getPublications(Archive *fout, int *numPublications)
37473747
{
37483748
DumpOptions *dopt = fout->dopt;
37493749
PQExpBuffer query;
@@ -3762,7 +3762,10 @@ getPublications(Archive *fout)
37623762
ntups;
37633763

37643764
if (dopt->no_publications || fout->remoteVersion < 100000)
3765-
return;
3765+
{
3766+
*numPublications = 0;
3767+
return NULL;
3768+
}
37663769

37673770
query = createPQExpBuffer();
37683771

@@ -3830,6 +3833,9 @@ getPublications(Archive *fout)
38303833
PQclear(res);
38313834

38323835
destroyPQExpBuffer(query);
3836+
3837+
*numPublications = ntups;
3838+
return pubinfo;
38333839
}
38343840

38353841
/*
@@ -3935,7 +3941,8 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
39353941
DumpOptions *dopt = fout->dopt;
39363942
int i_tableoid;
39373943
int i_oid;
3938-
int i_pubname;
3944+
int i_prpubid;
3945+
int i_prrelid;
39393946
int i,
39403947
j,
39413948
ntups;
@@ -3945,12 +3952,39 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
39453952

39463953
query = createPQExpBuffer();
39473954

3948-
for (i = 0; i < numTables; i++)
3955+
/* Collect all publication membership info. */
3956+
appendPQExpBufferStr(query,
3957+
"SELECT tableoid, oid, prpubid, prrelid "
3958+
"FROM pg_catalog.pg_publication_rel");
3959+
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
3960+
3961+
ntups = PQntuples(res);
3962+
3963+
i_tableoid = PQfnumber(res, "tableoid");
3964+
i_oid = PQfnumber(res, "oid");
3965+
i_prpubid = PQfnumber(res, "prpubid");
3966+
i_prrelid = PQfnumber(res, "prrelid");
3967+
3968+
/* this allocation may be more than we need */
3969+
pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo));
3970+
j = 0;
3971+
3972+
for (i = 0; i < ntups; i++)
39493973
{
3950-
TableInfo *tbinfo = &tblinfo[i];
3974+
Oid prpubid = atooid(PQgetvalue(res, i, i_prpubid));
3975+
Oid prrelid = atooid(PQgetvalue(res, i, i_prrelid));
3976+
PublicationInfo *pubinfo;
3977+
TableInfo *tbinfo;
39513978

3952-
/* Only plain tables can be aded to publications. */
3953-
if (tbinfo->relkind != RELKIND_RELATION)
3979+
/*
3980+
* Ignore any entries for which we aren't interested in either the
3981+
* publication or the rel.
3982+
*/
3983+
pubinfo = findPublicationByOid(prpubid);
3984+
if (pubinfo == NULL)
3985+
continue;
3986+
tbinfo = findTableByOid(prrelid);
3987+
if (tbinfo == NULL)
39543988
continue;
39553989

39563990
/*
@@ -3960,56 +3994,24 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
39603994
if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
39613995
continue;
39623996

3963-
if (g_verbose)
3964-
write_msg(NULL, "reading publication membership for table \"%s.%s\"\n",
3965-
tbinfo->dobj.namespace->dobj.name,
3966-
tbinfo->dobj.name);
3967-
3968-
resetPQExpBuffer(query);
3969-
3970-
/* Get the publication membership for the table. */
3971-
appendPQExpBuffer(query,
3972-
"SELECT pr.tableoid, pr.oid, p.pubname "
3973-
"FROM pg_publication_rel pr, pg_publication p "
3974-
"WHERE pr.prrelid = '%u'"
3975-
" AND p.oid = pr.prpubid",
3976-
tbinfo->dobj.catId.oid);
3977-
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
3978-
3979-
ntups = PQntuples(res);
3980-
3981-
if (ntups == 0)
3982-
{
3983-
/*
3984-
* Table is not member of any publications. Clean up and return.
3985-
*/
3986-
PQclear(res);
3987-
continue;
3988-
}
3989-
3990-
i_tableoid = PQfnumber(res, "tableoid");
3991-
i_oid = PQfnumber(res, "oid");
3992-
i_pubname = PQfnumber(res, "pubname");
3997+
/* OK, make a DumpableObject for this relationship */
3998+
pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
3999+
pubrinfo[j].dobj.catId.tableoid =
4000+
atooid(PQgetvalue(res, i, i_tableoid));
4001+
pubrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
4002+
AssignDumpId(&pubrinfo[j].dobj);
4003+
pubrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
4004+
pubrinfo[j].dobj.name = tbinfo->dobj.name;
4005+
pubrinfo[j].publication = pubinfo;
4006+
pubrinfo[j].pubtable = tbinfo;
39934007

3994-
pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo));
4008+
/* Decide whether we want to dump it */
4009+
selectDumpablePublicationTable(&(pubrinfo[j].dobj), fout);
39954010

3996-
for (j = 0; j < ntups; j++)
3997-
{
3998-
pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
3999-
pubrinfo[j].dobj.catId.tableoid =
4000-
atooid(PQgetvalue(res, j, i_tableoid));
4001-
pubrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
4002-
AssignDumpId(&pubrinfo[j].dobj);
4003-
pubrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
4004-
pubrinfo[j].dobj.name = tbinfo->dobj.name;
4005-
pubrinfo[j].pubname = pg_strdup(PQgetvalue(res, j, i_pubname));
4006-
pubrinfo[j].pubtable = tbinfo;
4007-
4008-
/* Decide whether we want to dump it */
4009-
selectDumpablePublicationTable(&(pubrinfo[j].dobj), fout);
4010-
}
4011-
PQclear(res);
4011+
j++;
40124012
}
4013+
4014+
PQclear(res);
40134015
destroyPQExpBuffer(query);
40144016
}
40154017

@@ -4020,31 +4022,35 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
40204022
static void
40214023
dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo)
40224024
{
4025+
PublicationInfo *pubinfo = pubrinfo->publication;
40234026
TableInfo *tbinfo = pubrinfo->pubtable;
40244027
PQExpBuffer query;
40254028
char *tag;
40264029

40274030
if (!(pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
40284031
return;
40294032

4030-
tag = psprintf("%s %s", pubrinfo->pubname, tbinfo->dobj.name);
4033+
tag = psprintf("%s %s", pubinfo->dobj.name, tbinfo->dobj.name);
40314034

40324035
query = createPQExpBuffer();
40334036

40344037
appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
4035-
fmtId(pubrinfo->pubname));
4038+
fmtId(pubinfo->dobj.name));
40364039
appendPQExpBuffer(query, " %s;\n",
40374040
fmtQualifiedDumpable(tbinfo));
40384041

40394042
/*
4040-
* There is no point in creating drop query as drop query as the drop is
4041-
* done by table drop.
4043+
* There is no point in creating a drop query as the drop is done by table
4044+
* drop. (If you think to change this, see also _printTocEntry().)
4045+
* Although this object doesn't really have ownership as such, set the
4046+
* owner field anyway to ensure that the command is run by the correct
4047+
* role at restore time.
40424048
*/
40434049
ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
40444050
tag,
40454051
tbinfo->dobj.namespace->dobj.name,
40464052
NULL,
4047-
"", false,
4053+
pubinfo->rolname, false,
40484054
"PUBLICATION TABLE", SECTION_POST_DATA,
40494055
query->data, "", NULL,
40504056
NULL, 0,

src/bin/pg_dump/pg_dump.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,8 +611,8 @@ typedef struct _PublicationInfo
611611
typedef struct _PublicationRelInfo
612612
{
613613
DumpableObject dobj;
614+
PublicationInfo *publication;
614615
TableInfo *pubtable;
615-
char *pubname;
616616
} PublicationRelInfo;
617617

618618
/*
@@ -671,6 +671,7 @@ extern OprInfo *findOprByOid(Oid oid);
671671
extern CollInfo *findCollationByOid(Oid oid);
672672
extern NamespaceInfo *findNamespaceByOid(Oid oid);
673673
extern ExtensionInfo *findExtensionByOid(Oid oid);
674+
extern PublicationInfo *findPublicationByOid(Oid oid);
674675

675676
extern void setExtensionMembership(ExtensionMemberId *extmems, int nextmems);
676677
extern ExtensionInfo *findOwningExtension(CatalogId catalogId);
@@ -724,7 +725,8 @@ extern void processExtensionTables(Archive *fout, ExtensionInfo extinfo[],
724725
int numExtensions);
725726
extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
726727
extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);
727-
extern void getPublications(Archive *fout);
728+
extern PublicationInfo *getPublications(Archive *fout,
729+
int *numPublications);
728730
extern void getPublicationTables(Archive *fout, TableInfo tblinfo[],
729731
int numTables);
730732
extern void getSubscriptions(Archive *fout);

0 commit comments

Comments
 (0)