]> granicus.if.org Git - postgresql/commitdiff
Fix filtering of unsupported relations in logical replication
authorPeter Eisentraut <peter_e@gmx.net>
Sat, 24 Feb 2018 03:13:21 +0000 (22:13 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Sat, 24 Feb 2018 03:13:21 +0000 (22:13 -0500)
In the pgoutput plugin, skip changes for relations that are not
publishable, per is_publishable_class().  This concerns in particular
materialized views and information_schema tables.  While those relations
cannot be part of a publication, per existing checks, they will be
considered by a FOR ALL TABLES publication.  A subscription would not
actually apply changes for those relations, again per existing checks,
but trying to match incoming changes to local tables on the subscriber
would lead to errors if no matching local table exists.  Skipping those
changes on the publisher avoids sending useless changes and eliminates
the error.

Bug: #15044
Reported-by: Chad Trabant <chad@iris.washington.edu>
Reviewed-by: Petr Jelinek <petr.jelinek@2ndquadrant.com>
src/backend/catalog/pg_publication.c
src/backend/replication/pgoutput/pgoutput.c
src/include/catalog/pg_publication.h
src/test/subscription/t/009_matviews.pl [new file with mode: 0644]

index b4a5f48b4ecf1e6a44a45faed404bb15881864cb..ba18258ebb7ee989f281b55aeb3daad360560234 100644 (file)
@@ -105,6 +105,15 @@ is_publishable_class(Oid relid, Form_pg_class reltuple)
                relid >= FirstNormalObjectId;
 }
 
+/*
+ * Another variant of this, taking a Relation.
+ */
+bool
+is_publishable_relation(Relation rel)
+{
+       return is_publishable_class(RelationGetRelid(rel), rel->rd_rel);
+}
+
 
 /*
  * SQL-callable variant of the above
index 40a1ef3c1d7af6e9a2635863c2e7e4942902df7d..d538f25ede6c038be69dcd98f0d4a8409fd10a54 100644 (file)
@@ -262,6 +262,9 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
        MemoryContext old;
        RelationSyncEntry *relentry;
 
+       if (!is_publishable_relation(relation))
+               return;
+
        relentry = get_rel_sync_entry(data, RelationGetRelid(relation));
 
        /* First check the table filter */
index 7bdc634cf3f9b5bd76efe4f03a734ee6c522fdbe..37e77b8be7efcd433528f23291fc3b31eaa5deef 100644 (file)
@@ -93,6 +93,7 @@ extern List *GetPublicationRelations(Oid pubid);
 extern List *GetAllTablesPublications(void);
 extern List *GetAllTablesPublicationRelations(void);
 
+extern bool is_publishable_relation(Relation rel);
 extern ObjectAddress publication_add_relation(Oid pubid, Relation targetrel,
                                                 bool if_not_exists);
 
diff --git a/src/test/subscription/t/009_matviews.pl b/src/test/subscription/t/009_matviews.pl
new file mode 100644 (file)
index 0000000..c55c62c
--- /dev/null
@@ -0,0 +1,45 @@
+# Test materialized views behavior
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More tests => 1;
+
+my $node_publisher = get_new_node('publisher');
+$node_publisher->init(allows_streaming => 'logical');
+$node_publisher->start;
+
+my $node_subscriber = get_new_node('subscriber');
+$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->start;
+
+my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+my $appname           = 'replication_test';
+
+$node_publisher->safe_psql('postgres',
+       "CREATE PUBLICATION mypub FOR ALL TABLES;");
+$node_subscriber->safe_psql('postgres',
+"CREATE SUBSCRIPTION mysub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION mypub;"
+);
+
+$node_publisher->safe_psql('postgres', q{CREATE TABLE test1 (a int PRIMARY KEY, b text)});
+$node_publisher->safe_psql('postgres', q{INSERT INTO test1 (a, b) VALUES (1, 'one'), (2, 'two');});
+
+$node_subscriber->safe_psql('postgres', q{CREATE TABLE test1 (a int PRIMARY KEY, b text);});
+
+$node_publisher->wait_for_catchup($appname);
+
+# Materialized views are not supported by logical replication, but
+# logical decoding does produce change information for them, so we
+# need to make sure they are properly ignored. (bug #15044)
+
+# create a MV with some data
+$node_publisher->safe_psql('postgres', q{CREATE MATERIALIZED VIEW testmv1 AS SELECT * FROM test1;});
+$node_publisher->wait_for_catchup($appname);
+# There is no equivalent relation on the subscriber, but MV data is
+# not replicated, so this does not hang.
+
+pass "materialized view data not replicated";
+
+$node_subscriber->stop;
+$node_publisher->stop;