summaryrefslogtreecommitdiff
path: root/src/bin/psql/describe.c
diff options
context:
space:
mode:
authorAmit Kapila2021-10-27 02:14:52 +0000
committerAmit Kapila2021-10-27 02:14:52 +0000
commit5a2832465fd8984d089e8c44c094e6900d987fcd (patch)
tree68a10449d24643fcdac2b5363accfa7af2196128 /src/bin/psql/describe.c
parentf0b051e322d530a340e62f2ae16d99acdbcb3d05 (diff)
Allow publishing the tables of schema.
A new option "FOR ALL TABLES IN SCHEMA" in Create/Alter Publication allows one or more schemas to be specified, whose tables are selected by the publisher for sending the data to the subscriber. The new syntax allows specifying both the tables and schemas. For example: CREATE PUBLICATION pub1 FOR TABLE t1,t2,t3, ALL TABLES IN SCHEMA s1,s2; OR ALTER PUBLICATION pub1 ADD TABLE t1,t2,t3, ALL TABLES IN SCHEMA s1,s2; A new system table "pg_publication_namespace" has been added, to maintain the schemas that the user wants to publish through the publication. Modified the output plugin (pgoutput) to publish the changes if the relation is part of schema publication. Updates pg_dump to identify and dump schema publications. Updates the \d family of commands to display schema publications and \dRp+ variant will now display associated schemas if any. Author: Vignesh C, Hou Zhijie, Amit Kapila Syntax-Suggested-by: Tom Lane, Alvaro Herrera Reviewed-by: Greg Nancarrow, Masahiko Sawada, Hou Zhijie, Amit Kapila, Haiying Tang, Ajin Cherian, Rahila Syed, Bharath Rupireddy, Mark Dilger Tested-by: Haiying Tang Discussion: https://www.postgresql.org/message-id/CALDaNm0OANxuJ6RXqwZsM1MSY4s19nuH3734j4a72etDwvBETQ@mail.gmail.com
Diffstat (limited to 'src/bin/psql/describe.c')
-rw-r--r--src/bin/psql/describe.c198
1 files changed, 159 insertions, 39 deletions
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index ea4ca5c05c2..006661412ea 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3146,17 +3146,40 @@ describeOneTableDetails(const char *schemaname,
/* print any publications */
if (pset.sversion >= 100000)
{
- printfPQExpBuffer(&buf,
- "SELECT pubname\n"
- "FROM pg_catalog.pg_publication p\n"
- "JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
- "WHERE pr.prrelid = '%s'\n"
- "UNION ALL\n"
- "SELECT pubname\n"
- "FROM pg_catalog.pg_publication p\n"
- "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
- "ORDER BY 1;",
- oid, oid);
+ if (pset.sversion >= 150000)
+ {
+ printfPQExpBuffer(&buf,
+ "SELECT pubname\n"
+ "FROM pg_catalog.pg_publication p\n"
+ " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
+ " JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.pnnspid\n"
+ "WHERE pc.oid ='%s' and pg_catalog.pg_relation_is_publishable('%s')\n"
+ "UNION\n"
+ "SELECT pubname\n"
+ "FROM pg_catalog.pg_publication p\n"
+ " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
+ "WHERE pr.prrelid = '%s'\n"
+ "UNION\n"
+ "SELECT pubname\n"
+ "FROM pg_catalog.pg_publication p\n"
+ "WHERE puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
+ "ORDER BY 1;",
+ oid, oid, oid, oid);
+ }
+ else
+ {
+ printfPQExpBuffer(&buf,
+ "SELECT pubname\n"
+ "FROM pg_catalog.pg_publication p\n"
+ "JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
+ "WHERE pr.prrelid = '%s'\n"
+ "UNION ALL\n"
+ "SELECT pubname\n"
+ "FROM pg_catalog.pg_publication p\n"
+ "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
+ "ORDER BY 1;",
+ oid, oid);
+ }
result = PSQLexec(buf.data);
if (!result)
@@ -5020,6 +5043,8 @@ listSchemas(const char *pattern, bool verbose, bool showSystem)
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
+ int pub_schema_tuples = 0;
+ char **footers = NULL;
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf,
@@ -5052,17 +5077,80 @@ listSchemas(const char *pattern, bool verbose, bool showSystem)
appendPQExpBufferStr(&buf, "ORDER BY 1;");
res = PSQLexec(buf.data);
- termPQExpBuffer(&buf);
if (!res)
+ {
+ termPQExpBuffer(&buf);
return false;
+ }
myopt.nullPrint = NULL;
myopt.title = _("List of schemas");
myopt.translate_header = true;
+ if (pattern && pset.sversion >= 150000)
+ {
+ PGresult *result;
+ int i;
+
+ printfPQExpBuffer(&buf,
+ "SELECT pubname \n"
+ "FROM pg_catalog.pg_publication p\n"
+ " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
+ " JOIN pg_catalog.pg_namespace n ON n.oid = pn.pnnspid \n"
+ "WHERE n.nspname = '%s'\n"
+ "ORDER BY 1",
+ pattern);
+ result = PSQLexec(buf.data);
+ if (!result)
+ {
+ termPQExpBuffer(&buf);
+ return false;
+ }
+ else
+ pub_schema_tuples = PQntuples(result);
+
+ if (pub_schema_tuples > 0)
+ {
+ /*
+ * Allocate memory for footers. Size of footers will be 1 (for
+ * storing "Publications:" string) + publication schema mapping
+ * count + 1 (for storing NULL).
+ */
+ footers = (char **) pg_malloc((1 + pub_schema_tuples + 1) * sizeof(char *));
+ footers[0] = pg_strdup(_("Publications:"));
+
+ /* Might be an empty set - that's ok */
+ for (i = 0; i < pub_schema_tuples; i++)
+ {
+ printfPQExpBuffer(&buf, " \"%s\"",
+ PQgetvalue(result, i, 0));
+
+ footers[i + 1] = pg_strdup(buf.data);
+ }
+
+ footers[i + 1] = NULL;
+ myopt.footers = footers;
+ }
+
+ PQclear(result);
+ }
+
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+ termPQExpBuffer(&buf);
PQclear(res);
+
+ /* Free the memory allocated for the footer */
+ if (footers)
+ {
+ char **footer = NULL;
+
+ for (footer = footers; *footer; footer++)
+ pg_free(*footer);
+
+ pg_free(footers);
+ }
+
return true;
}
@@ -6210,6 +6298,41 @@ listPublications(const char *pattern)
}
/*
+ * Add footer to publication description.
+ */
+static bool
+addFooterToPublicationDesc(PQExpBuffer buf, char *footermsg,
+ bool singlecol, printTableContent *cont)
+{
+ PGresult *res;
+ int count = 0;
+ int i = 0;
+
+ res = PSQLexec(buf->data);
+ if (!res)
+ return false;
+ else
+ count = PQntuples(res);
+
+ if (count > 0)
+ printTableAddFooter(cont, _(footermsg));
+
+ for (i = 0; i < count; i++)
+ {
+ if (!singlecol)
+ printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
+ PQgetvalue(res, i, 1));
+ else
+ printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
+
+ printTableAddFooter(cont, buf->data);
+ }
+
+ PQclear(res);
+ return true;
+}
+
+/*
* \dRp+
* Describes publications including the contents.
*
@@ -6224,6 +6347,9 @@ describePublications(const char *pattern)
bool has_pubtruncate;
bool has_pubviaroot;
+ PQExpBufferData title;
+ printTableContent cont;
+
if (pset.sversion < 100000)
{
char sverbuf[32];
@@ -6286,15 +6412,10 @@ describePublications(const char *pattern)
const char align = 'l';
int ncols = 5;
int nrows = 1;
- int tables = 0;
- PGresult *tabres;
char *pubid = PQgetvalue(res, i, 0);
char *pubname = PQgetvalue(res, i, 1);
bool puballtables = strcmp(PQgetvalue(res, i, 3), "t") == 0;
- int j;
- PQExpBufferData title;
printTableOpt myopt = pset.popt.topt;
- printTableContent cont;
if (has_pubtruncate)
ncols++;
@@ -6327,6 +6448,7 @@ describePublications(const char *pattern)
if (!puballtables)
{
+ /* Get the tables for the specified publication */
printfPQExpBuffer(&buf,
"SELECT n.nspname, c.relname\n"
"FROM pg_catalog.pg_class c,\n"
@@ -6336,31 +6458,22 @@ describePublications(const char *pattern)
" AND c.oid = pr.prrelid\n"
" AND pr.prpubid = '%s'\n"
"ORDER BY 1,2", pubid);
+ if (!addFooterToPublicationDesc(&buf, "Tables:", false, &cont))
+ goto error_return;
- tabres = PSQLexec(buf.data);
- if (!tabres)
- {
- printTableCleanup(&cont);
- PQclear(res);
- termPQExpBuffer(&buf);
- termPQExpBuffer(&title);
- return false;
- }
- else
- tables = PQntuples(tabres);
-
- if (tables > 0)
- printTableAddFooter(&cont, _("Tables:"));
-
- for (j = 0; j < tables; j++)
+ if (pset.sversion >= 150000)
{
- printfPQExpBuffer(&buf, " \"%s.%s\"",
- PQgetvalue(tabres, j, 0),
- PQgetvalue(tabres, j, 1));
-
- printTableAddFooter(&cont, buf.data);
+ /* Get the schemas for the specified publication */
+ printfPQExpBuffer(&buf,
+ "SELECT n.nspname\n"
+ "FROM pg_catalog.pg_namespace n\n"
+ " JOIN pg_catalog.pg_publication_namespace pn ON n.oid = pn.pnnspid\n"
+ "WHERE pn.pnpubid = '%s'\n"
+ "ORDER BY 1", pubid);
+ if (!addFooterToPublicationDesc(&buf, "Tables from schemas:",
+ true, &cont))
+ goto error_return;
}
- PQclear(tabres);
}
printTable(&cont, pset.queryFout, false, pset.logfile);
@@ -6373,6 +6486,13 @@ describePublications(const char *pattern)
PQclear(res);
return true;
+
+error_return:
+ printTableCleanup(&cont);
+ PQclear(res);
+ termPQExpBuffer(&buf);
+ termPQExpBuffer(&title);
+ return false;
}
/*