@@ -193,9 +193,15 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
193
193
Datum values [PARTITION_MAX_KEYS ];
194
194
bool isnull [PARTITION_MAX_KEYS ];
195
195
Relation rel ;
196
- PartitionDispatch parent ;
196
+ PartitionDispatch dispatch ;
197
197
ExprContext * ecxt = GetPerTupleExprContext (estate );
198
198
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 ));
199
205
200
206
/*
201
207
* First check the root table's partition constraint, if any. No point in
@@ -205,26 +211,24 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
205
211
ExecPartitionCheck (resultRelInfo , slot , estate , true);
206
212
207
213
/* start with the root partitioned table */
208
- parent = pd [0 ];
214
+ tuple = ExecFetchSlotTuple (slot );
215
+ dispatch = pd [0 ];
209
216
while (true)
210
217
{
211
218
PartitionDesc partdesc ;
212
- TupleTableSlot * myslot = parent -> tupslot ;
213
- TupleConversionMap * map = parent -> tupmap ;
219
+ TupleConversionMap * map = dispatch -> tupmap ;
214
220
int cur_index = -1 ;
215
221
216
- rel = parent -> reldesc ;
222
+ rel = dispatch -> reldesc ;
217
223
partdesc = RelationGetPartitionDesc (rel );
218
224
219
225
/*
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 .
222
228
*/
229
+ myslot = dispatch -> tupslot ;
223
230
if (myslot != NULL && map != NULL )
224
231
{
225
- HeapTuple tuple = ExecFetchSlotTuple (slot );
226
-
227
- ExecClearTuple (myslot );
228
232
tuple = do_convert_tuple (tuple , map );
229
233
ExecStoreTuple (tuple , myslot , InvalidBuffer , true);
230
234
slot = myslot ;
@@ -239,7 +243,7 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
239
243
* So update ecxt_scantuple accordingly.
240
244
*/
241
245
ecxt -> ecxt_scantuple = slot ;
242
- FormPartitionKeyDatum (parent , slot , estate , values , isnull );
246
+ FormPartitionKeyDatum (dispatch , slot , estate , values , isnull );
243
247
244
248
/*
245
249
* Nothing for get_partition_for_tuple() to do if there are no
@@ -263,15 +267,33 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
263
267
result = -1 ;
264
268
break ;
265
269
}
266
- else if (parent -> indexes [cur_index ] >= 0 )
270
+ else if (dispatch -> indexes [cur_index ] >= 0 )
267
271
{
268
- result = parent -> indexes [cur_index ];
272
+ result = dispatch -> indexes [cur_index ];
273
+ /* success! */
269
274
break ;
270
275
}
271
276
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
+ }
273
291
}
274
292
293
+ /* Release the tuple in the lowest parent's dedicated slot. */
294
+ if (slot == myslot )
295
+ ExecClearTuple (myslot );
296
+
275
297
/* A partition was not found. */
276
298
if (result < 0 )
277
299
{
@@ -287,7 +309,9 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
287
309
val_desc ? errdetail ("Partition key of the failing row contains %s." , val_desc ) : 0 ));
288
310
}
289
311
312
+ MemoryContextSwitchTo (oldcxt );
290
313
ecxt -> ecxt_scantuple = ecxt_scantuple_old ;
314
+
291
315
return result ;
292
316
}
293
317
0 commit comments