]> granicus.if.org Git - postgresql/commitdiff
Tweak publication fetching in psql
authorPeter Eisentraut <peter_e@gmx.net>
Tue, 20 Jun 2017 16:25:07 +0000 (12:25 -0400)
committerPeter Eisentraut <peter_e@gmx.net>
Tue, 20 Jun 2017 16:35:02 +0000 (12:35 -0400)
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
src/bin/psql/describe.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h

index 17105f4f2cbc32bec0ce092d31e9bf2dfc9ed69b..17b2e8d6497c45567a2dfe980851e750e0f10b5d 100644 (file)
@@ -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.
  */
index ea0e8af2ecdbfec6fdaefc971c1ade14b18a75b6..0e19e94841c5d34074ef4f7a6d2650682d4b0f5b 100644 (file)
@@ -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)
index 93992edc36059f578bdce2d5c85a528bbc67cde4..f4d2770e7e8ce854fabb01c389a9b69e31d168c0 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201706201
+#define CATALOG_VERSION_NO     201706202
 
 #endif
index 73ce026d89350281d0adab67cf65e461ad3b6f05..f22cc4f4726f74769060d405c39c384a6d984b58 100644 (file)
@@ -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_ ));