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

Commit be541ef

Browse files
committed
Defend against unsupported partition relkind in logical replication worker.
Since partitions can be foreign tables not only plain tables, but logical replication only supports plain tables, we'd better check the relkind of a partition after we find it. (There was some discussion of checking this when adding a partitioned table to a subscription; but that would be inadequate since the troublesome partition could be added later.) Without this, the situation leads to a segfault or assertion failure. In passing, add a separate variable for the target Relation of a cross-partition UPDATE; reusing partrel seemed mighty confusing and error-prone. Shi Yu and Tom Lane, per report from Ilya Gladyshev. Back-patch to v13 where logical replication into partitioned tables became a thing. Discussion: https://postgr.es/m/6b93e3748ba43298694f376ca8797279d7945e29.camel@gmail.com
1 parent 26ee7fb commit be541ef

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

src/backend/replication/logical/worker.c

+17-3
Original file line numberDiff line numberDiff line change
@@ -2176,6 +2176,15 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
21762176
Assert(partrelinfo != NULL);
21772177
partrel = partrelinfo->ri_RelationDesc;
21782178

2179+
/*
2180+
* Check for supported relkind. We need this since partitions might be of
2181+
* unsupported relkinds; and the set of partitions can change, so checking
2182+
* at CREATE/ALTER SUBSCRIPTION would be insufficient.
2183+
*/
2184+
CheckSubscriptionRelkind(partrel->rd_rel->relkind,
2185+
get_namespace_name(RelationGetNamespace(partrel)),
2186+
RelationGetRelationName(partrel));
2187+
21792188
/*
21802189
* To perform any of the operations below, the tuple must match the
21812190
* partition's rowtype. Convert if needed or just copy, using a dedicated
@@ -2229,6 +2238,7 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
22292238
{
22302239
TupleTableSlot *localslot;
22312240
ResultRelInfo *partrelinfo_new;
2241+
Relation partrel_new;
22322242
bool found;
22332243

22342244
/* Get the matching local tuple from the partition. */
@@ -2314,14 +2324,19 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
23142324
slot_getallattrs(remoteslot);
23152325
}
23162326

2317-
23182327
/* Find the new partition. */
23192328
oldctx = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
23202329
partrelinfo_new = ExecFindPartition(mtstate, relinfo,
23212330
proute, remoteslot,
23222331
estate);
23232332
MemoryContextSwitchTo(oldctx);
23242333
Assert(partrelinfo_new != partrelinfo);
2334+
partrel_new = partrelinfo_new->ri_RelationDesc;
2335+
2336+
/* Check that new partition also has supported relkind. */
2337+
CheckSubscriptionRelkind(partrel_new->rd_rel->relkind,
2338+
get_namespace_name(RelationGetNamespace(partrel_new)),
2339+
RelationGetRelationName(partrel_new));
23252340

23262341
/* DELETE old tuple found in the old partition. */
23272342
apply_handle_delete_internal(edata, partrelinfo,
@@ -2334,10 +2349,9 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
23342349
* partition rowtype.
23352350
*/
23362351
oldctx = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
2337-
partrel = partrelinfo_new->ri_RelationDesc;
23382352
remoteslot_part = partrelinfo_new->ri_PartitionTupleSlot;
23392353
if (remoteslot_part == NULL)
2340-
remoteslot_part = table_slot_create(partrel,
2354+
remoteslot_part = table_slot_create(partrel_new,
23412355
&estate->es_tupleTable);
23422356
map = partrelinfo_new->ri_RootToPartitionMap;
23432357
if (map != NULL)

0 commit comments

Comments
 (0)