@@ -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,24 +211,23 @@ 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
- TupleTableSlot * myslot = parent -> tupslot ;
212
- TupleConversionMap * map = parent -> tupmap ;
218
+ TupleTableSlot * myslot = dispatch -> tupslot ;
219
+ TupleConversionMap * map = dispatch -> tupmap ;
213
220
int cur_index = -1 ;
214
221
215
- rel = parent -> reldesc ;
222
+ rel = dispatch -> reldesc ;
216
223
217
224
/*
218
- * Convert the tuple to this parent's layout so that we can do certain
219
- * things we do below .
225
+ * Convert the tuple to this parent's layout, if different from the
226
+ * current relation .
220
227
*/
228
+ myslot = dispatch -> tupslot ;
221
229
if (myslot != NULL && map != NULL )
222
230
{
223
- HeapTuple tuple = ExecFetchSlotTuple (slot );
224
-
225
- ExecClearTuple (myslot );
226
231
tuple = do_convert_tuple (tuple , map );
227
232
ExecStoreTuple (tuple , myslot , InvalidBuffer , true);
228
233
slot = myslot ;
@@ -237,19 +242,19 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
237
242
* So update ecxt_scantuple accordingly.
238
243
*/
239
244
ecxt -> ecxt_scantuple = slot ;
240
- FormPartitionKeyDatum (parent , slot , estate , values , isnull );
245
+ FormPartitionKeyDatum (dispatch , slot , estate , values , isnull );
241
246
242
247
/*
243
248
* Nothing for get_partition_for_tuple() to do if there are no
244
249
* partitions to begin with.
245
250
*/
246
- if (parent -> partdesc -> nparts == 0 )
251
+ if (dispatch -> partdesc -> nparts == 0 )
247
252
{
248
253
result = -1 ;
249
254
break ;
250
255
}
251
256
252
- cur_index = get_partition_for_tuple (parent , values , isnull );
257
+ cur_index = get_partition_for_tuple (dispatch , values , isnull );
253
258
254
259
/*
255
260
* cur_index < 0 means we failed to find a partition of this parent.
@@ -261,15 +266,33 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
261
266
result = -1 ;
262
267
break ;
263
268
}
264
- else if (parent -> indexes [cur_index ] >= 0 )
269
+ else if (dispatch -> indexes [cur_index ] >= 0 )
265
270
{
266
- result = parent -> indexes [cur_index ];
271
+ result = dispatch -> indexes [cur_index ];
272
+ /* success! */
267
273
break ;
268
274
}
269
275
else
270
- parent = pd [- parent -> indexes [cur_index ]];
276
+ {
277
+ /* move down one level */
278
+ dispatch = pd [- dispatch -> indexes [cur_index ]];
279
+
280
+ /*
281
+ * Release the dedicated slot, if it was used. Create a copy of
282
+ * the tuple first, for the next iteration.
283
+ */
284
+ if (slot == myslot )
285
+ {
286
+ tuple = ExecCopySlotTuple (myslot );
287
+ ExecClearTuple (myslot );
288
+ }
289
+ }
271
290
}
272
291
292
+ /* Release the tuple in the lowest parent's dedicated slot. */
293
+ if (slot == myslot )
294
+ ExecClearTuple (myslot );
295
+
273
296
/* A partition was not found. */
274
297
if (result < 0 )
275
298
{
@@ -285,7 +308,9 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
285
308
val_desc ? errdetail ("Partition key of the failing row contains %s." , val_desc ) : 0 ));
286
309
}
287
310
311
+ MemoryContextSwitchTo (oldcxt );
288
312
ecxt -> ecxt_scantuple = ecxt_scantuple_old ;
313
+
289
314
return result ;
290
315
}
291
316
0 commit comments