postgres.git / summary / log / commit / refs

commit    a2141c42f9ebc51b4501a4fafea9dd3fb7eda23d
Author:   Peter Eisentraut <peter_e@gmx.net>
Date:     Tue Jun 20 16:25:07 2017 +0000

    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 <tgl@sss.pgh.pa.us>


src/backend/catalog/pg_publication.c | 24 ++++++++++++++++++++++++ src/bin/psql/describe.c | 14 +++++++++----- src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_proc.h | 2 ++ 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index 17105f4f2cb..17b2e8d6497 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 ea0e8af2ecd..0e19e94841c 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 93992edc360..f4d2770e7e8 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 73ce026d893..f22cc4f4726 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_ )); [parent: 20d7d68b098d]