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>
This commit is contained in:
parent
20d7d68b09
commit
a2141c42f9
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -53,6 +53,6 @@
|
|||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 201706201
|
||||
#define CATALOG_VERSION_NO 201706202
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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_ ));
|
||||
|
|
Loading…
Reference in New Issue