diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c index 857ceb9ce8..c74488774a 100644 --- a/src/bin/pg_dump/common.c +++ b/src/bin/pg_dump/common.c @@ -54,6 +54,7 @@ static DumpableObject **oprinfoindex; static DumpableObject **collinfoindex; static DumpableObject **nspinfoindex; static DumpableObject **extinfoindex; +static DumpableObject **pubinfoindex; static int numTables; static int numTypes; static int numFuncs; @@ -61,6 +62,7 @@ static int numOperators; static int numCollations; static int numNamespaces; static int numExtensions; +static int numPublications; /* This is an array of object identities, not actual DumpableObjects */ static ExtensionMemberId *extmembers; @@ -95,6 +97,7 @@ getSchemaData(Archive *fout, int *numTablesPtr) CollInfo *collinfo; NamespaceInfo *nspinfo; ExtensionInfo *extinfo; + PublicationInfo *pubinfo; InhInfo *inhinfo; int numAggregates; int numInherits; @@ -249,7 +252,9 @@ getSchemaData(Archive *fout, int *numTablesPtr) getPolicies(fout, tblinfo, numTables); pg_log_info("reading publications"); - getPublications(fout); + pubinfo = getPublications(fout, &numPublications); + pubinfoindex = buildIndexArray(pubinfo, numPublications, + sizeof(PublicationInfo)); pg_log_info("reading publication membership"); getPublicationTables(fout, tblinfo, numTables); @@ -899,6 +904,17 @@ findExtensionByOid(Oid oid) return (ExtensionInfo *) findObjectByOid(oid, extinfoindex, numExtensions); } +/* + * findPublicationByOid + * finds the entry (in pubinfo) of the publication with the given oid + * returns NULL if not found + */ +PublicationInfo * +findPublicationByOid(Oid oid) +{ + return (PublicationInfo *) findObjectByOid(oid, pubinfoindex, numPublications); +} + /* * findIndexByOid * find the entry of the index with the given oid diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 4bfda642a8..7cc956a92c 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -3785,8 +3785,8 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo) * getPublications * get information about publications */ -void -getPublications(Archive *fout) +PublicationInfo * +getPublications(Archive *fout, int *numPublications) { DumpOptions *dopt = fout->dopt; PQExpBuffer query; @@ -3805,7 +3805,10 @@ getPublications(Archive *fout) ntups; if (dopt->no_publications || fout->remoteVersion < 100000) - return; + { + *numPublications = 0; + return NULL; + } query = createPQExpBuffer(); @@ -3873,6 +3876,9 @@ getPublications(Archive *fout) PQclear(res); destroyPQExpBuffer(query); + + *numPublications = ntups; + return pubinfo; } /* @@ -3976,7 +3982,8 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables) DumpOptions *dopt = fout->dopt; int i_tableoid; int i_oid; - int i_pubname; + int i_prpubid; + int i_prrelid; int i, j, ntups; @@ -3986,12 +3993,39 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables) query = createPQExpBuffer(); - for (i = 0; i < numTables; i++) - { - TableInfo *tbinfo = &tblinfo[i]; + /* Collect all publication membership info. */ + appendPQExpBufferStr(query, + "SELECT tableoid, oid, prpubid, prrelid " + "FROM pg_catalog.pg_publication_rel"); + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); - /* Only plain tables can be aded to publications. */ - if (tbinfo->relkind != RELKIND_RELATION) + ntups = PQntuples(res); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_prpubid = PQfnumber(res, "prpubid"); + i_prrelid = PQfnumber(res, "prrelid"); + + /* this allocation may be more than we need */ + pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo)); + j = 0; + + for (i = 0; i < ntups; i++) + { + Oid prpubid = atooid(PQgetvalue(res, i, i_prpubid)); + Oid prrelid = atooid(PQgetvalue(res, i, i_prrelid)); + PublicationInfo *pubinfo; + TableInfo *tbinfo; + + /* + * Ignore any entries for which we aren't interested in either the + * publication or the rel. + */ + pubinfo = findPublicationByOid(prpubid); + if (pubinfo == NULL) + continue; + tbinfo = findTableByOid(prrelid); + if (tbinfo == NULL) continue; /* @@ -4001,55 +4035,24 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables) if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) continue; - pg_log_info("reading publication membership for table \"%s.%s\"", - tbinfo->dobj.namespace->dobj.name, - tbinfo->dobj.name); + /* OK, make a DumpableObject for this relationship */ + pubrinfo[j].dobj.objType = DO_PUBLICATION_REL; + pubrinfo[j].dobj.catId.tableoid = + atooid(PQgetvalue(res, i, i_tableoid)); + pubrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&pubrinfo[j].dobj); + pubrinfo[j].dobj.namespace = tbinfo->dobj.namespace; + pubrinfo[j].dobj.name = tbinfo->dobj.name; + pubrinfo[j].publication = pubinfo; + pubrinfo[j].pubtable = tbinfo; - resetPQExpBuffer(query); + /* Decide whether we want to dump it */ + selectDumpablePublicationTable(&(pubrinfo[j].dobj), fout); - /* Get the publication membership for the table. */ - appendPQExpBuffer(query, - "SELECT pr.tableoid, pr.oid, p.pubname " - "FROM pg_publication_rel pr, pg_publication p " - "WHERE pr.prrelid = '%u'" - " AND p.oid = pr.prpubid", - tbinfo->dobj.catId.oid); - res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); - - ntups = PQntuples(res); - - if (ntups == 0) - { - /* - * Table is not member of any publications. Clean up and return. - */ - PQclear(res); - continue; - } - - i_tableoid = PQfnumber(res, "tableoid"); - i_oid = PQfnumber(res, "oid"); - i_pubname = PQfnumber(res, "pubname"); - - pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo)); - - for (j = 0; j < ntups; j++) - { - pubrinfo[j].dobj.objType = DO_PUBLICATION_REL; - pubrinfo[j].dobj.catId.tableoid = - atooid(PQgetvalue(res, j, i_tableoid)); - pubrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid)); - AssignDumpId(&pubrinfo[j].dobj); - pubrinfo[j].dobj.namespace = tbinfo->dobj.namespace; - pubrinfo[j].dobj.name = tbinfo->dobj.name; - pubrinfo[j].pubname = pg_strdup(PQgetvalue(res, j, i_pubname)); - pubrinfo[j].pubtable = tbinfo; - - /* Decide whether we want to dump it */ - selectDumpablePublicationTable(&(pubrinfo[j].dobj), fout); - } - PQclear(res); + j++; } + + PQclear(res); destroyPQExpBuffer(query); } @@ -4060,6 +4063,7 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables) static void dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo) { + PublicationInfo *pubinfo = pubrinfo->publication; TableInfo *tbinfo = pubrinfo->pubtable; PQExpBuffer query; char *tag; @@ -4067,22 +4071,26 @@ dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo) if (!(pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) return; - tag = psprintf("%s %s", pubrinfo->pubname, tbinfo->dobj.name); + tag = psprintf("%s %s", pubinfo->dobj.name, tbinfo->dobj.name); query = createPQExpBuffer(); appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY", - fmtId(pubrinfo->pubname)); + fmtId(pubinfo->dobj.name)); appendPQExpBuffer(query, " %s;\n", fmtQualifiedDumpable(tbinfo)); /* - * There is no point in creating drop query as the drop is done by table - * drop. + * There is no point in creating a drop query as the drop is done by table + * drop. (If you think to change this, see also _printTocEntry().) + * Although this object doesn't really have ownership as such, set the + * owner field anyway to ensure that the command is run by the correct + * role at restore time. */ ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = tag, .namespace = tbinfo->dobj.namespace->dobj.name, + .owner = pubinfo->rolname, .description = "PUBLICATION TABLE", .section = SECTION_POST_DATA, .createStmt = query->data)); diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index b126f8bda0..830fc6a0ef 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -613,8 +613,8 @@ typedef struct _PublicationInfo typedef struct _PublicationRelInfo { DumpableObject dobj; + PublicationInfo *publication; TableInfo *pubtable; - char *pubname; } PublicationRelInfo; /* @@ -672,6 +672,7 @@ extern OprInfo *findOprByOid(Oid oid); extern CollInfo *findCollationByOid(Oid oid); extern NamespaceInfo *findNamespaceByOid(Oid oid); extern ExtensionInfo *findExtensionByOid(Oid oid); +extern PublicationInfo *findPublicationByOid(Oid oid); extern void setExtensionMembership(ExtensionMemberId *extmems, int nextmems); extern ExtensionInfo *findOwningExtension(CatalogId catalogId); @@ -724,7 +725,8 @@ extern void processExtensionTables(Archive *fout, ExtensionInfo extinfo[], int numExtensions); extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers); extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables); -extern void getPublications(Archive *fout); +extern PublicationInfo *getPublications(Archive *fout, + int *numPublications); extern void getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables); extern void getSubscriptions(Archive *fout);