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

Commit 2f1f189

Browse files
committed
Fix construction of updated-columns bitmap in logical replication.
Commit b9c130a failed to apply the publisher-to-subscriber column mapping while checking which columns were updated. Perhaps less significantly, it didn't exclude dropped columns either. This could result in an incorrect updated-columns bitmap and thus wrong decisions about whether to fire column-specific triggers on the subscriber while applying updates. In HEAD (since commit 9de77b545), it could also result in accesses off the end of the colstatus array, as detected by buildfarm member skink. Fix the logic, and adjust 003_constraints.pl so that the problem is exposed in unpatched code. In HEAD, also add some assertions to check that we don't access off the ends of these newly variable-sized arrays. Back-patch to v10, as b9c130a was. Discussion: https://postgr.es/m/CAH2-Wz=79hKQ4++c5A060RYbjTHgiYTHz=fw6mptCtgghH2gJA@mail.gmail.com
1 parent f5dff45 commit 2f1f189

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

src/backend/replication/logical/worker.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -765,9 +765,16 @@ apply_handle_update(StringInfo s)
765765
target_rte = list_nth(estate->es_range_table, 0);
766766
for (int i = 0; i < remoteslot->tts_tupleDescriptor->natts; i++)
767767
{
768-
if (newtup.changed[i])
769-
target_rte->updatedCols = bms_add_member(target_rte->updatedCols,
770-
i + 1 - FirstLowInvalidHeapAttributeNumber);
768+
Form_pg_attribute att = TupleDescAttr(remoteslot->tts_tupleDescriptor, i);
769+
int remoteattnum = rel->attrmap->attnums[i];
770+
771+
if (!att->attisdropped && remoteattnum >= 0)
772+
{
773+
if (newtup.changed[remoteattnum])
774+
target_rte->updatedCols =
775+
bms_add_member(target_rte->updatedCols,
776+
i + 1 - FirstLowInvalidHeapAttributeNumber);
777+
}
771778
}
772779

773780
fill_extraUpdatedCols(target_rte, RelationGetDescr(rel->localrel));

src/test/subscription/t/003_constraints.pl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@
1919
$node_publisher->safe_psql('postgres',
2020
"CREATE TABLE tab_fk (bid int PRIMARY KEY);");
2121
$node_publisher->safe_psql('postgres',
22-
"CREATE TABLE tab_fk_ref (id int PRIMARY KEY, bid int REFERENCES tab_fk (bid));"
22+
"CREATE TABLE tab_fk_ref (id int PRIMARY KEY, junk text, bid int REFERENCES tab_fk (bid));"
2323
);
2424

25-
# Setup structure on subscriber
25+
# Setup structure on subscriber; column order intentionally different
2626
$node_subscriber->safe_psql('postgres',
2727
"CREATE TABLE tab_fk (bid int PRIMARY KEY);");
2828
$node_subscriber->safe_psql('postgres',
29-
"CREATE TABLE tab_fk_ref (id int PRIMARY KEY, bid int REFERENCES tab_fk (bid));"
29+
"CREATE TABLE tab_fk_ref (id int PRIMARY KEY, bid int REFERENCES tab_fk (bid), junk text);"
3030
);
3131

3232
# Setup logical replication
@@ -42,8 +42,10 @@
4242

4343
$node_publisher->safe_psql('postgres',
4444
"INSERT INTO tab_fk (bid) VALUES (1);");
45+
# "junk" value is meant to be large enough to force out-of-line storage
4546
$node_publisher->safe_psql('postgres',
46-
"INSERT INTO tab_fk_ref (id, bid) VALUES (1, 1);");
47+
"INSERT INTO tab_fk_ref (id, bid, junk) VALUES (1, 1, repeat(pi()::text,20000));"
48+
);
4749

4850
$node_publisher->wait_for_catchup('tap_sub');
4951

@@ -128,7 +130,7 @@ BEGIN
128130
$result = $node_subscriber->safe_psql('postgres',
129131
"SELECT count(*), min(id), max(id) FROM tab_fk_ref;");
130132
is($result, qq(2|1|2),
131-
'check column trigger applied on even for other column');
133+
'check column trigger applied even on update for other column');
132134

133135
$node_subscriber->stop('fast');
134136
$node_publisher->stop('fast');

0 commit comments

Comments
 (0)