Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1c60e40

Browse files
committed
Fix negative bitmapset member not allowed error in logical replication
This happens when we add a replica identity column on a subscriber that does not yet exist on the publisher, according to the mapping maintained by the subscriber. Code that checks whether the target relation on the subscriber is updatable would check the replica identity attribute bitmap with a column number -1, which would result in an error. To fix, skip such columns in the bitmap lookup and consider the relation not updatable. The result is consistent with the rule that the replica identity columns on the subscriber must be a subset of those on the publisher, since if the column doesn't exist on the publisher, the column set on the subscriber can't be a subset. Reported-by: Tim Clarke <tim.clarke@minerva.info> Analyzed-by: Jehan-Guillaume de Rorthais <jgdr@dalibo.com> Discussion: https://www.postgresql.org/message-id/flat/a9139c29-7ddd-973b-aa7f-71fed9c38d75%40minerva.info
1 parent 943b447 commit 1c60e40

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

src/backend/replication/logical/relation.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,8 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode)
340340

341341
attnum = AttrNumberGetAttrOffset(attnum);
342342

343-
if (!bms_is_member(entry->attrmap[attnum], remoterel->attkeys))
343+
if (entry->attrmap[attnum] < 0 ||
344+
!bms_is_member(entry->attrmap[attnum], remoterel->attkeys))
344345
{
345346
entry->updatable = false;
346347
break;

src/test/subscription/t/008_diff_schema.pl

+35-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use warnings;
44
use PostgresNode;
55
use TestLib;
6-
use Test::More tests => 4;
6+
use Test::More tests => 5;
77

88
# Create publisher node
99
my $node_publisher = get_new_node('publisher');
@@ -29,7 +29,7 @@
2929
# Setup logical replication
3030
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
3131
$node_publisher->safe_psql('postgres',
32-
"CREATE PUBLICATION tap_pub FOR TABLE test_tab");
32+
"CREATE PUBLICATION tap_pub FOR ALL TABLES");
3333

3434
$node_subscriber->safe_psql('postgres',
3535
"CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr' PUBLICATION tap_pub"
@@ -88,5 +88,38 @@
8888
is($result, qq(3|3|3|3),
8989
'check extra columns contain local defaults after apply');
9090

91+
92+
# Check a bug about adding a replica identity column on the subscriber
93+
# that was not yet mapped to a column on the publisher. This would
94+
# result in errors on the subscriber and replication thus not
95+
# progressing.
96+
# (https://www.postgresql.org/message-id/flat/a9139c29-7ddd-973b-aa7f-71fed9c38d75%40minerva.info)
97+
98+
$node_publisher->safe_psql('postgres',
99+
"CREATE TABLE test_tab2 (a int)");
100+
101+
$node_subscriber->safe_psql('postgres',
102+
"CREATE TABLE test_tab2 (a int)");
103+
104+
$node_subscriber->safe_psql('postgres',
105+
"ALTER SUBSCRIPTION tap_sub REFRESH PUBLICATION");
106+
107+
# Add replica identity column. (The serial is not necessary, but it's
108+
# a convenient way to get a default on the new column so that rows
109+
# from the publisher that don't have the column yet can be inserted.)
110+
$node_subscriber->safe_psql('postgres',
111+
"ALTER TABLE test_tab2 ADD COLUMN b serial PRIMARY KEY");
112+
113+
$node_publisher->safe_psql('postgres',
114+
"INSERT INTO test_tab2 VALUES (1)");
115+
116+
$node_publisher->wait_for_catchup('tap_sub');
117+
118+
is($node_subscriber->safe_psql('postgres',
119+
"SELECT count(*), min(a), max(a) FROM test_tab2"),
120+
qq(1|1|1),
121+
'check replicated inserts on subscriber');
122+
123+
91124
$node_subscriber->stop;
92125
$node_publisher->stop;

0 commit comments

Comments
 (0)