Skip to content

Commit e60e681

Browse files
author
Commitfest Bot
committed
[CF 5666] v2 - Logical replication worker Segmentation fault
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5666 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/OS3PR01MB57185F018C8F64689B44672B94B52@OS3PR01MB5718.jpnprd01.prod.outlook.com Author(s): Zhijie Hou
2 parents 15f0cb2 + 16a0ff6 commit e60e681

File tree

4 files changed

+71
-6
lines changed

4 files changed

+71
-6
lines changed

src/backend/executor/execIndexing.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,8 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
214214
ii = BuildIndexInfo(indexDesc);
215215

216216
/*
217-
* If the indexes are to be used for speculative insertion or conflict
218-
* detection in logical replication, add extra information required by
219-
* unique index entries.
217+
* If the indexes are to be used for speculative insertion, add extra
218+
* information required by unique index entries.
220219
*/
221220
if (speculative && ii->ii_Unique && !indexDesc->rd_index->indisexclusion)
222221
BuildSpeculativeIndexInfo(indexDesc, ii);

src/backend/executor/execReplication.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,30 @@ RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode,
431431
return found;
432432
}
433433

434+
/*
435+
* Build additional index information necessary for conflict detection.
436+
*/
437+
static void
438+
BuildConflictIndexInfo(ResultRelInfo *resultRelInfo, Oid conflictindex)
439+
{
440+
for (int i = 0; i < resultRelInfo->ri_NumIndices; i++)
441+
{
442+
Relation indexRelation = resultRelInfo->ri_IndexRelationDescs[i];
443+
IndexInfo *indexRelationInfo = resultRelInfo->ri_IndexRelationInfo[i];
444+
445+
if (conflictindex != RelationGetRelid(indexRelation))
446+
continue;
447+
448+
/*
449+
* This Assert will fail if BuildSpeculativeIndexInfo() is called
450+
* twice for the given index.
451+
*/
452+
Assert(indexRelationInfo->ii_UniqueOps == NULL);
453+
454+
BuildSpeculativeIndexInfo(indexRelation, indexRelationInfo);
455+
}
456+
}
457+
434458
/*
435459
* Find the tuple that violates the passed unique index (conflictindex).
436460
*
@@ -452,6 +476,13 @@ FindConflictTuple(ResultRelInfo *resultRelInfo, EState *estate,
452476

453477
*conflictslot = NULL;
454478

479+
/*
480+
* Build additional information required to detect constraints violations.
481+
* Refer to check_exclusion_or_unique_constraint() for details on how this
482+
* information is used.
483+
*/
484+
BuildConflictIndexInfo(resultRelInfo, conflictindex);
485+
455486
retry:
456487
if (ExecCheckIndexConstraints(resultRelInfo, slot, estate,
457488
&conflictTid, &slot->tts_tid,

src/backend/replication/logical/worker.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2457,7 +2457,7 @@ apply_handle_insert(StringInfo s)
24572457
{
24582458
ResultRelInfo *relinfo = edata->targetRelInfo;
24592459

2460-
ExecOpenIndices(relinfo, true);
2460+
ExecOpenIndices(relinfo, false);
24612461
apply_handle_insert_internal(edata, relinfo, remoteslot);
24622462
ExecCloseIndices(relinfo);
24632463
}
@@ -2680,7 +2680,7 @@ apply_handle_update_internal(ApplyExecutionData *edata,
26802680
MemoryContext oldctx;
26812681

26822682
EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1, NIL);
2683-
ExecOpenIndices(relinfo, true);
2683+
ExecOpenIndices(relinfo, false);
26842684

26852685
found = FindReplTupleInLocalRel(edata, localrel,
26862686
&relmapentry->remoterel,

src/test/subscription/t/035_conflicts.pl

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,23 @@
2525
$node_publisher->safe_psql('postgres',
2626
"CREATE TABLE conf_tab (a int PRIMARY KEY, b int UNIQUE, c int UNIQUE);");
2727

28+
$node_publisher->safe_psql('postgres',
29+
"CREATE TABLE conf_tab_2 (a int PRIMARY KEY, b int UNIQUE, c int UNIQUE);");
30+
2831
# Create same table on subscriber
2932
$node_subscriber->safe_psql('postgres',
3033
"CREATE TABLE conf_tab (a int PRIMARY key, b int UNIQUE, c int UNIQUE);");
3134

35+
$node_subscriber->safe_psql(
36+
'postgres', qq[
37+
CREATE TABLE conf_tab_2 (a int PRIMARY KEY, b int, c int, unique(a,b)) PARTITION BY RANGE (a);
38+
CREATE TABLE conf_tab_2_p1 PARTITION OF conf_tab_2 FOR VALUES FROM (MINVALUE) TO (100);
39+
]);
40+
3241
# Setup logical replication
3342
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
3443
$node_publisher->safe_psql('postgres',
35-
"CREATE PUBLICATION pub_tab FOR TABLE conf_tab");
44+
"CREATE PUBLICATION pub_tab FOR TABLE conf_tab, conf_tab_2");
3645

3746
# Create the subscription
3847
my $appname = 'sub_tab';
@@ -110,4 +119,30 @@
110119

111120
pass('multiple_unique_conflicts detected during update');
112121

122+
# Truncate table to get rid of the error
123+
$node_subscriber->safe_psql('postgres', "TRUNCATE conf_tab;");
124+
125+
126+
##################################################
127+
# Test multiple_unique_conflicts due to INSERT on a leaf partition
128+
##################################################
129+
130+
# Insert data in the subscriber table
131+
$node_subscriber->safe_psql('postgres',
132+
"INSERT INTO conf_tab_2 VALUES (55,2,3);");
133+
134+
# Insert data in the publisher table
135+
$node_publisher->safe_psql('postgres',
136+
"INSERT INTO conf_tab_2 VALUES (55,2,3);");
137+
138+
$node_subscriber->wait_for_log(
139+
qr/conflict detected on relation \"public.conf_tab_2_p1\": conflict=multiple_unique_conflicts.*
140+
.*Key already exists in unique index \"conf_tab_2_p1_pkey\".*
141+
.*Key \(a\)=\(55\); existing local tuple \(55, 2, 3\); remote tuple \(55, 2, 3\).*
142+
.*Key already exists in unique index \"conf_tab_2_p1_a_b_key\".*
143+
.*Key \(a, b\)=\(55, 2\); existing local tuple \(55, 2, 3\); remote tuple \(55, 2, 3\)./,
144+
$log_offset);
145+
146+
pass('multiple_unique_conflicts detected on a leaf partition during insert');
147+
113148
done_testing();

0 commit comments

Comments
 (0)