pgoutput-map-tupdesc-leak.patch
application/octet-stream
Filename: pgoutput-map-tupdesc-leak.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/replication/pgoutput/pgoutput.c | 34 | 9 |
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index f68348dcf4..c66e0a20a8 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -444,15 +444,7 @@ maybe_send_schema(LogicalDecodingContext *ctx,
if (relentry->publish_as_relid != RelationGetRelid(relation))
{
Relation ancestor = RelationIdGetRelation(relentry->publish_as_relid);
- TupleDesc indesc = RelationGetDescr(relation);
- TupleDesc outdesc = RelationGetDescr(ancestor);
- MemoryContext oldctx;
-
- /* Map must live as long as the session does. */
- oldctx = MemoryContextSwitchTo(CacheMemoryContext);
- relentry->map = convert_tuples_by_name(CreateTupleDescCopy(indesc),
- CreateTupleDescCopy(outdesc));
- MemoryContextSwitchTo(oldctx);
+
send_relation_and_attrs(ancestor, xid, ctx);
RelationClose(ancestor);
}
@@ -1108,6 +1100,39 @@ get_rel_sync_entry(PGOutputData *data, Oid relid)
list_free(pubids);
entry->publish_as_relid = publish_as_relid;
+
+ /*
+ * While at it, also set the map to convert leaf partition tuples into
+ * the format of the table to publish the tuples as of.
+ */
+ if (publish_as_relid != relid)
+ {
+ Relation relation = RelationIdGetRelation(relid);
+ Relation ancestor = RelationIdGetRelation(publish_as_relid);
+ TupleDesc indesc = RelationGetDescr(relation);
+ TupleDesc outdesc = RelationGetDescr(ancestor);
+ MemoryContext oldctx;
+
+ /* Map, if any, must live as long as the session does. */
+ oldctx = MemoryContextSwitchTo(CacheMemoryContext);
+
+ /*
+ * TupleDescs must be copied before putting into the map, because
+ * they may not live as long as we want the map to live.
+ */
+ indesc = CreateTupleDescCopy(indesc);
+ outdesc = CreateTupleDescCopy(outdesc);
+ entry->map = convert_tuples_by_name(indesc, outdesc);
+ if (entry->map == NULL)
+ {
+ FreeTupleDesc(indesc);
+ FreeTupleDesc(outdesc);
+ }
+
+ MemoryContextSwitchTo(oldctx);
+ RelationClose(relation);
+ RelationClose(ancestor);
+ }
entry->replicate_valid = true;
}