This is an automated email from the ASF dual-hosted git repository.

reshke pushed a commit to branch REL_2_STABLE
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 61472e2b5e427bf532a1af5d83b89bf4083fc0f5
Author: Tom Lane <[email protected]>
AuthorDate: Wed Nov 2 12:29:39 2022 -0400

    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/[email protected]
---
 src/backend/replication/logical/worker.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/backend/replication/logical/worker.c 
b/src/backend/replication/logical/worker.c
index 7190dd94ebf..cb8f76d902a 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -1706,6 +1706,15 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
        Assert(partrelinfo != NULL);
        partrel = partrelinfo->ri_RelationDesc;
 
+       /*
+        * Check for supported relkind.  We need this since partitions might be 
of
+        * unsupported relkinds; and the set of partitions can change, so 
checking
+        * at CREATE/ALTER SUBSCRIPTION would be insufficient.
+        */
+       CheckSubscriptionRelkind(partrel->rd_rel->relkind,
+                                                        
get_namespace_name(RelationGetNamespace(partrel)),
+                                                        
RelationGetRelationName(partrel));
+
        /*
         * To perform any of the operations below, the tuple must match the
         * partition's rowtype. Convert if needed or just copy, using a 
dedicated
@@ -1759,6 +1768,7 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
                        {
                                TupleTableSlot *localslot;
                                ResultRelInfo *partrelinfo_new;
+                               Relation        partrel_new;
                                bool            found;
 
                                /* Get the matching local tuple from the 
partition. */
@@ -1842,7 +1852,6 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
                                                slot_getallattrs(remoteslot);
                                        }
 
-
                                        /* Find the new partition. */
                                        oldctx = 
MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
                                        partrelinfo_new = 
ExecFindPartition(mtstate, relinfo,
@@ -1850,6 +1859,12 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
                                                                                
                                estate);
                                        MemoryContextSwitchTo(oldctx);
                                        Assert(partrelinfo_new != partrelinfo);
+                                       partrel_new = 
partrelinfo_new->ri_RelationDesc;
+
+                                       /* Check that new partition also has 
supported relkind. */
+                                       
CheckSubscriptionRelkind(partrel_new->rd_rel->relkind,
+                                                                               
         get_namespace_name(RelationGetNamespace(partrel_new)),
+                                                                               
         RelationGetRelationName(partrel_new));
 
                                        /* DELETE old tuple found in the old 
partition. */
                                        apply_handle_delete_internal(edata, 
partrelinfo,
@@ -1862,10 +1877,9 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
                                         * partition rowtype.
                                         */
                                        oldctx = 
MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
-                                       partrel = 
partrelinfo_new->ri_RelationDesc;
                                        remoteslot_part = 
partrelinfo_new->ri_PartitionTupleSlot;
                                        if (remoteslot_part == NULL)
-                                               remoteslot_part = 
table_slot_create(partrel,
+                                               remoteslot_part = 
table_slot_create(partrel_new,
                                                                                
                                        &estate->es_tupleTable);
                                        map = 
partrelinfo_new->ri_RootToPartitionMap;
                                        if (map != NULL)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to