Fix relation descriptor leak.
authorAmit Kapila <akapila@postgresql.org>
Tue, 12 Jan 2021 02:49:39 +0000 (08:19 +0530)
committerAmit Kapila <akapila@postgresql.org>
Tue, 12 Jan 2021 02:49:39 +0000 (08:19 +0530)
We missed closing the relation descriptor while sending changes via the
root of partitioned relations during logical replication.

Author: Amit Langote and Mark Zhao
Reviewed-by: Amit Kapila and Ashutosh Bapat
Backpatch-through: 13, where it was introduced
Discussion: https://postgr.es/m/tencent_41FEA657C206F19AB4F406BE9252A0F69C06@qq.com
Discussion: https://postgr.es/m/tencent_6E296D2F7D70AFC90D83353B69187C3AA507@qq.com

src/backend/replication/pgoutput/pgoutput.c

index 81dbed33d511c08fb633d7c341416d0bb43ca1a6..2f01137b426cd6cc9c152d327944abe883cecd83 100644 (file)
@@ -502,6 +502,7 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
        MemoryContext old;
        RelationSyncEntry *relentry;
        TransactionId xid = InvalidTransactionId;
+       Relation        ancestor = NULL;
 
        if (!is_publishable_relation(relation))
                return;
@@ -552,7 +553,8 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
                                if (relentry->publish_as_relid != RelationGetRelid(relation))
                                {
                                        Assert(relation->rd_rel->relispartition);
-                                       relation = RelationIdGetRelation(relentry->publish_as_relid);
+                                       ancestor = RelationIdGetRelation(relentry->publish_as_relid);
+                                       relation = ancestor;
                                        /* Convert tuple if needed. */
                                        if (relentry->map)
                                                tuple = execute_attr_map_tuple(tuple, relentry->map);
@@ -574,7 +576,8 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
                                if (relentry->publish_as_relid != RelationGetRelid(relation))
                                {
                                        Assert(relation->rd_rel->relispartition);
-                                       relation = RelationIdGetRelation(relentry->publish_as_relid);
+                                       ancestor = RelationIdGetRelation(relentry->publish_as_relid);
+                                       relation = ancestor;
                                        /* Convert tuples if needed. */
                                        if (relentry->map)
                                        {
@@ -598,7 +601,8 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
                                if (relentry->publish_as_relid != RelationGetRelid(relation))
                                {
                                        Assert(relation->rd_rel->relispartition);
-                                       relation = RelationIdGetRelation(relentry->publish_as_relid);
+                                       ancestor = RelationIdGetRelation(relentry->publish_as_relid);
+                                       relation = ancestor;
                                        /* Convert tuple if needed. */
                                        if (relentry->map)
                                                oldtuple = execute_attr_map_tuple(oldtuple, relentry->map);
@@ -616,6 +620,12 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
                        Assert(false);
        }
 
+       if (RelationIsValid(ancestor))
+       {
+               RelationClose(ancestor);
+               ancestor = NULL;
+       }
+
        /* Cleanup */
        MemoryContextSwitchTo(old);
        MemoryContextReset(data->context);