Skip to content

Commit 34295b8

Browse files
alvherrekaigaiAmit Langote
committed
Fix per-tuple memory leak in partition tuple routing
Some operations were being done in a longer-lived memory context, causing intra-query leaks. It's not noticeable unless you're doing a large COPY, but if you are, it eats enough memory to cause a problem. Co-authored-by: Kohei KaiGai <kaigai@heterodb.com> Co-authored-by: Amit Langote <Langote_Amit_f8@lab.ntt.co.jp> Co-authored-by: Álvaro Herrera <alvherre@alvh.no-ip.org> Discussion: https://postgr.es/m/CAOP8fzYtVFWZADq4c=KoTAqgDrHWfng+AnEPEZccyxqxPVbbWQ@mail.gmail.com
1 parent e9bbfe6 commit 34295b8

File tree

1 file changed

+38
-14
lines changed

1 file changed

+38
-14
lines changed

src/backend/executor/execPartition.c

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,15 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
193193
Datum values[PARTITION_MAX_KEYS];
194194
bool isnull[PARTITION_MAX_KEYS];
195195
Relation rel;
196-
PartitionDispatch parent;
196+
PartitionDispatch dispatch;
197197
ExprContext *ecxt = GetPerTupleExprContext(estate);
198198
TupleTableSlot *ecxt_scantuple_old = ecxt->ecxt_scantuple;
199+
TupleTableSlot *myslot = NULL;
200+
MemoryContext oldcxt;
201+
HeapTuple tuple;
202+
203+
/* use per-tuple context here to avoid leaking memory */
204+
oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
199205

200206
/*
201207
* First check the root table's partition constraint, if any. No point in
@@ -205,26 +211,24 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
205211
ExecPartitionCheck(resultRelInfo, slot, estate, true);
206212

207213
/* start with the root partitioned table */
208-
parent = pd[0];
214+
tuple = ExecFetchSlotTuple(slot);
215+
dispatch = pd[0];
209216
while (true)
210217
{
211218
PartitionDesc partdesc;
212-
TupleTableSlot *myslot = parent->tupslot;
213-
TupleConversionMap *map = parent->tupmap;
219+
TupleConversionMap *map = dispatch->tupmap;
214220
int cur_index = -1;
215221

216-
rel = parent->reldesc;
222+
rel = dispatch->reldesc;
217223
partdesc = RelationGetPartitionDesc(rel);
218224

219225
/*
220-
* Convert the tuple to this parent's layout so that we can do certain
221-
* things we do below.
226+
* Convert the tuple to this parent's layout, if different from the
227+
* current relation.
222228
*/
229+
myslot = dispatch->tupslot;
223230
if (myslot != NULL && map != NULL)
224231
{
225-
HeapTuple tuple = ExecFetchSlotTuple(slot);
226-
227-
ExecClearTuple(myslot);
228232
tuple = do_convert_tuple(tuple, map);
229233
ExecStoreTuple(tuple, myslot, InvalidBuffer, true);
230234
slot = myslot;
@@ -239,7 +243,7 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
239243
* So update ecxt_scantuple accordingly.
240244
*/
241245
ecxt->ecxt_scantuple = slot;
242-
FormPartitionKeyDatum(parent, slot, estate, values, isnull);
246+
FormPartitionKeyDatum(dispatch, slot, estate, values, isnull);
243247

244248
/*
245249
* Nothing for get_partition_for_tuple() to do if there are no
@@ -263,15 +267,33 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
263267
result = -1;
264268
break;
265269
}
266-
else if (parent->indexes[cur_index] >= 0)
270+
else if (dispatch->indexes[cur_index] >= 0)
267271
{
268-
result = parent->indexes[cur_index];
272+
result = dispatch->indexes[cur_index];
273+
/* success! */
269274
break;
270275
}
271276
else
272-
parent = pd[-parent->indexes[cur_index]];
277+
{
278+
/* move down one level */
279+
dispatch = pd[-dispatch->indexes[cur_index]];
280+
281+
/*
282+
* Release the dedicated slot, if it was used. Create a copy of
283+
* the tuple first, for the next iteration.
284+
*/
285+
if (slot == myslot)
286+
{
287+
tuple = ExecCopySlotTuple(myslot);
288+
ExecClearTuple(myslot);
289+
}
290+
}
273291
}
274292

293+
/* Release the tuple in the lowest parent's dedicated slot. */
294+
if (slot == myslot)
295+
ExecClearTuple(myslot);
296+
275297
/* A partition was not found. */
276298
if (result < 0)
277299
{
@@ -287,7 +309,9 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
287309
val_desc ? errdetail("Partition key of the failing row contains %s.", val_desc) : 0));
288310
}
289311

312+
MemoryContextSwitchTo(oldcxt);
290313
ecxt->ecxt_scantuple = ecxt_scantuple_old;
314+
291315
return result;
292316
}
293317

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy