aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorAmit Kapila <akapila@postgresql.org>2022-05-19 08:20:55 +0530
committerAmit Kapila <akapila@postgresql.org>2022-05-19 08:20:55 +0530
commit0ff20288e1cb3282efb43401896a939916fceb4d (patch)
treec92b34d13bd072e0c06127b3a8640a25ea4dc917 /src/backend
parent62221ef187b0098c8f331f804b7c63859e5ee6ff (diff)
downloadpostgresql-0ff20288e1cb3282efb43401896a939916fceb4d.tar.gz
postgresql-0ff20288e1cb3282efb43401896a939916fceb4d.zip
Extend pg_publication_tables to display column list and row filter.
Commit 923def9a53 and 52e4f0cd47 allowed to specify column lists and row filters for publication tables. This commit extends the pg_publication_tables view and pg_get_publication_tables function to display that information. This information will be useful to users and we also need this for the later commit that prohibits combining multiple publications with different column lists for the same table. Author: Hou Zhijie Reviewed By: Amit Kapila, Alvaro Herrera, Shi Yu, Takamichi Osumi Discussion: https://postgr.es/m/202204251548.mudq7jbqnh7r@alvherre.pgsql
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/pg_publication.c54
-rw-r--r--src/backend/catalog/system_views.sql10
-rw-r--r--src/backend/replication/logical/tablesync.c14
3 files changed, 65 insertions, 13 deletions
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index e2c8bcb2797..8c7fca62de3 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -1077,11 +1077,12 @@ get_publication_name(Oid pubid, bool missing_ok)
}
/*
- * Returns Oids of tables in a publication.
+ * Returns information of tables in a publication.
*/
Datum
pg_get_publication_tables(PG_FUNCTION_ARGS)
{
+#define NUM_PUBLICATOIN_TABLES_ELEM 3
FuncCallContext *funcctx;
char *pubname = text_to_cstring(PG_GETARG_TEXT_PP(0));
Publication *publication;
@@ -1090,6 +1091,7 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
/* stuff done only on the first call of the function */
if (SRF_IS_FIRSTCALL())
{
+ TupleDesc tupdesc;
MemoryContext oldcontext;
/* create a function context for cross-call persistence */
@@ -1136,6 +1138,16 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
tables = filter_partitions(tables);
}
+ /* Construct a tuple descriptor for the result rows. */
+ tupdesc = CreateTemplateTupleDesc(NUM_PUBLICATOIN_TABLES_ELEM);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relid",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "attrs",
+ INT2VECTOROID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "qual",
+ PG_NODE_TREEOID, -1, 0);
+
+ funcctx->tuple_desc = BlessTupleDesc(tupdesc);
funcctx->user_fctx = (void *) tables;
MemoryContextSwitchTo(oldcontext);
@@ -1147,9 +1159,47 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
if (funcctx->call_cntr < list_length(tables))
{
+ HeapTuple pubtuple = NULL;
+ HeapTuple rettuple;
Oid relid = list_nth_oid(tables, funcctx->call_cntr);
+ Datum values[NUM_PUBLICATOIN_TABLES_ELEM];
+ bool nulls[NUM_PUBLICATOIN_TABLES_ELEM];
+
+ /*
+ * Form tuple with appropriate data.
+ */
+ MemSet(nulls, 0, sizeof(nulls));
+ MemSet(values, 0, sizeof(values));
+
+ publication = GetPublicationByName(pubname, false);
+
+ values[0] = ObjectIdGetDatum(relid);
+
+ pubtuple = SearchSysCacheCopy2(PUBLICATIONRELMAP,
+ ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(publication->oid));
+
+ if (HeapTupleIsValid(pubtuple))
+ {
+ /* Lookup the column list attribute. */
+ values[1] = SysCacheGetAttr(PUBLICATIONRELMAP, pubtuple,
+ Anum_pg_publication_rel_prattrs,
+ &(nulls[1]));
+
+ /* Null indicates no filter. */
+ values[2] = SysCacheGetAttr(PUBLICATIONRELMAP, pubtuple,
+ Anum_pg_publication_rel_prqual,
+ &(nulls[2]));
+ }
+ else
+ {
+ nulls[1] = true;
+ nulls[2] = true;
+ }
+
+ rettuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
- SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(relid));
+ SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(rettuple));
}
SRF_RETURN_DONE(funcctx);
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 0fc614e32c0..fedaed533b9 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -368,7 +368,15 @@ CREATE VIEW pg_publication_tables AS
SELECT
P.pubname AS pubname,
N.nspname AS schemaname,
- C.relname AS tablename
+ C.relname AS tablename,
+ ( SELECT array_agg(a.attname ORDER BY a.attnum)
+ FROM unnest(CASE WHEN GPT.attrs IS NOT NULL THEN GPT.attrs
+ ELSE (SELECT array_agg(g) FROM generate_series(1, C.relnatts) g)
+ END) k
+ JOIN pg_attribute a
+ ON (a.attrelid = GPT.relid AND a.attnum = k)
+ ) AS attnames,
+ pg_get_expr(GPT.qual, GPT.relid) AS rowfilter
FROM pg_publication P,
LATERAL pg_get_publication_tables(P.pubname) GPT,
pg_class C JOIN pg_namespace N ON (N.oid = C.relnamespace)
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index b03e0f5aac2..994c7a09d92 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -795,15 +795,12 @@ fetch_remote_table_info(char *nspname, char *relname,
resetStringInfo(&cmd);
appendStringInfo(&cmd,
"SELECT DISTINCT unnest"
- " FROM pg_publication p"
- " LEFT OUTER JOIN pg_publication_rel pr"
- " ON (p.oid = pr.prpubid AND pr.prrelid = %u)"
- " LEFT OUTER JOIN unnest(pr.prattrs) ON TRUE,"
+ " FROM pg_publication p,"
" LATERAL pg_get_publication_tables(p.pubname) gpt"
+ " LEFT OUTER JOIN unnest(gpt.attrs) ON TRUE"
" WHERE gpt.relid = %u"
" AND p.pubname IN ( %s )",
lrel->remoteid,
- lrel->remoteid,
pub_names.data);
pubres = walrcv_exec(LogRepWorkerWalRcvConn, cmd.data,
@@ -965,15 +962,12 @@ fetch_remote_table_info(char *nspname, char *relname,
/* Check for row filters. */
resetStringInfo(&cmd);
appendStringInfo(&cmd,
- "SELECT DISTINCT pg_get_expr(pr.prqual, pr.prrelid)"
- " FROM pg_publication p"
- " LEFT OUTER JOIN pg_publication_rel pr"
- " ON (p.oid = pr.prpubid AND pr.prrelid = %u),"
+ "SELECT DISTINCT pg_get_expr(gpt.qual, gpt.relid)"
+ " FROM pg_publication p,"
" LATERAL pg_get_publication_tables(p.pubname) gpt"
" WHERE gpt.relid = %u"
" AND p.pubname IN ( %s )",
lrel->remoteid,
- lrel->remoteid,
pub_names.data);
res = walrcv_exec(LogRepWorkerWalRcvConn, cmd.data, 1, qualRow);