From: Peter Eisentraut Date: Tue, 20 Jun 2017 16:25:07 +0000 (-0400) Subject: Tweak publication fetching in psql X-Git-Tag: REL_10_BETA2~110 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a2141c42f9ebc51b4501a4fafea9dd3fb7eda23d;p=postgresql Tweak publication fetching in psql Viewing a table with \d in psql also shows the publications at table is in. If a publication is concurrently dropped, this shows an error, because the view pg_publication_tables internally uses pg_get_publication_tables(), which uses a catalog snapshot. This can be particularly annoying if a for-all-tables publication is concurrently dropped. To avoid that, write the query in psql differently. Expose the function pg_relation_is_publishable() to SQL and write the query using that. That still has a risk of being affected by concurrent catalog changes, but in this case it would be a table drop that causes problems, and then the psql \d command wouldn't be interesting anymore anyway. Reported-by: Tom Lane --- diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index 17105f4f2c..17b2e8d649 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -105,6 +105,30 @@ is_publishable_class(Oid relid, Form_pg_class reltuple) relid >= FirstNormalObjectId; } + +/* + * SQL-callable variant of the above + * + * This returns null when the relation does not exist. This is intended to be + * used for example in psql to avoid gratuitous errors when there are + * concurrent catalog changes. + */ +Datum +pg_relation_is_publishable(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + HeapTuple tuple; + bool result; + + tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!tuple) + PG_RETURN_NULL(); + result = is_publishable_class(relid, (Form_pg_class) GETSTRUCT(tuple)); + ReleaseSysCache(tuple); + PG_RETURN_BOOL(result); +} + + /* * Insert new publication / relation mapping. */ diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index ea0e8af2ec..0e19e94841 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -2536,12 +2536,16 @@ describeOneTableDetails(const char *schemaname, if (pset.sversion >= 100000) { printfPQExpBuffer(&buf, - "SELECT pub.pubname\n" - " FROM pg_catalog.pg_publication pub,\n" - " pg_catalog.pg_get_publication_tables(pub.pubname)\n" - "WHERE relid = '%s'\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 ALL\n" + "SELECT pubname\n" + "FROM pg_catalog.pg_publication p\n" + "WHERE p.puballtables AND pg_relation_is_publishable('%s')\n" "ORDER BY 1;", - oid); + oid, oid); result = PSQLexec(buf.data); if (!result) diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 93992edc36..f4d2770e7e 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201706201 +#define CATALOG_VERSION_NO 201706202 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 73ce026d89..f22cc4f472 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -5436,6 +5436,8 @@ DESCR("get progress for all replication origins"); /* publications */ DATA(insert OID = 6119 ( pg_get_publication_tables PGNSP PGUID 12 1 1000 0 0 f f f f t t s s 1 0 26 "25" "{25,26}" "{i,o}" "{pubname,relid}" _null_ _null_ pg_get_publication_tables _null_ _null_ _null_ )); DESCR("get OIDs of tables in a publication"); +DATA(insert OID = 6121 ( pg_relation_is_publishable PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 16 "2205" _null_ _null_ _null_ _null_ _null_ pg_relation_is_publishable _null_ _null_ _null_ )); +DESCR("returns whether a relation can be part of a publication"); /* rls */ DATA(insert OID = 3298 ( row_security_active PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 16 "26" _null_ _null_ _null_ _null_ _null_ row_security_active _null_ _null_ _null_ ));