Skip to content

Commit a301663

Browse files
committed
refactoring, improve memory management inside PartitionFilter
1 parent e3da7a9 commit a301663

File tree

6 files changed

+51
-16
lines changed

6 files changed

+51
-16
lines changed

range.sql

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,6 @@ BEGIN
184184
p_start_value := p_start_value + p_interval;
185185
END LOOP;
186186

187-
/* Create triggers */
188-
-- PERFORM create_hash_update_trigger(relation, attribute, partitions_count);
189187
/* Notify backend about changes */
190188
PERFORM @extschema@.on_create_partitions(p_relation::regclass::oid);
191189

src/hooks.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pathman_join_pathlist_hook(PlannerInfo *root,
4848
ListCell *lc;
4949
double paramsel;
5050
WalkerContext context;
51+
bool context_initialized;
5152
bool innerrel_rinfo_contains_part_attr;
5253

5354
if (set_join_pathlist_next)
@@ -83,15 +84,16 @@ pathman_join_pathlist_hook(PlannerInfo *root,
8384
otherclauses = NIL;
8485
}
8586

87+
context_initialized = false;
8688
paramsel = 1.0;
8789
foreach (lc, joinclauses)
8890
{
89-
WrapperNode *wrap;
91+
WrapperNode *wrap;
9092

91-
context.prel = inner_prel;
92-
context.econtext = NULL;
93-
context.hasLeast = false;
94-
context.hasGreatest = false;
93+
/* We aim to persist cached context->ranges */
94+
InitWalkerContextCustomNode(&context, inner_prel,
95+
NULL, CurrentMemoryContext,
96+
&context_initialized);
9597

9698
wrap = walk_expr_tree((Expr *) lfirst(lc), &context);
9799
paramsel *= wrap->paramsel;
@@ -223,7 +225,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTb
223225
ranges = list_make1_irange(make_irange(0, prel->children_count - 1, false));
224226

225227
/* Make wrappers over restrictions and collect final rangeset */
226-
InitWalkerContext(&context, prel, NULL);
228+
InitWalkerContext(&context, prel, NULL, CurrentMemoryContext);
227229
wrappers = NIL;
228230
foreach(lc, rel->baserestrictinfo)
229231
{

src/nodes_common.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,8 @@ rescan_append_common(CustomScanState *node)
504504
ranges = list_make1_irange(make_irange(0, prel->children_count - 1, false));
505505

506506
InitWalkerContextCustomNode(&scan_state->wcxt, scan_state->prel,
507-
econtext, &scan_state->wcxt_cached);
507+
econtext, CurrentMemoryContext,
508+
&scan_state->wcxt_cached);
508509

509510
foreach (lc, scan_state->custom_exprs)
510511
{

src/partition_filter.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "partition_filter.h"
22
#include "utils.h"
33
#include "utils/guc.h"
4+
#include "utils/memutils.h"
45
#include "nodes/nodeFuncs.h"
56

67

@@ -139,6 +140,8 @@ partition_filter_exec(CustomScanState *node)
139140

140141
if (!TupIsNull(slot))
141142
{
143+
MemoryContext old_cxt;
144+
142145
List *ranges;
143146
int nparts;
144147
Oid *parts;
@@ -160,11 +163,16 @@ partition_filter_exec(CustomScanState *node)
160163
CopyToTempConst(constbyval, attbyval);
161164

162165
InitWalkerContextCustomNode(&state->wcxt, state->prel,
163-
econtext, &state->wcxt_cached);
166+
econtext, CurrentMemoryContext,
167+
&state->wcxt_cached);
168+
169+
/* Switch to per-tuple context */
170+
old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
164171

165172
ranges = walk_expr_tree((Expr *) &state->temp_const, &state->wcxt)->rangeset;
166173
parts = get_partition_oids(ranges, &nparts, state->prel);
167174

175+
168176
if (nparts > 1)
169177
elog(ERROR, "PartitionFilter selected more than one partition");
170178
else if (nparts == 0)
@@ -173,11 +181,16 @@ partition_filter_exec(CustomScanState *node)
173181
state->temp_const.constvalue,
174182
state->temp_const.consttype);
175183

184+
/* Now we have to refresh state->wcxt->ranges manually */
176185
refresh_walker_context_ranges(&state->wcxt);
177186
}
178187
else
179188
selected_partid = parts[0];
180189

190+
/* Switch back and clean up per-tuple context */
191+
MemoryContextSwitchTo(old_cxt);
192+
ResetExprContext(econtext);
193+
181194
/* Replace main table with suitable partition */
182195
estate->es_result_relation_info = getResultRelInfo(selected_partid,
183196
state);

src/pathman.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@ typedef struct
276276
/* Main partitioning structure */
277277
const PartRelationInfo *prel;
278278

279+
/* Long-living context for cached values */
280+
MemoryContext persistent_mcxt;
281+
279282
/* Cached values */
280283
const RangeEntry *ranges; /* cached RangeEntry array (copy) */
281284
size_t nranges; /* number of RangeEntries */
@@ -291,33 +294,40 @@ typedef struct
291294
/*
292295
* Usual initialization procedure for WalkerContext
293296
*/
294-
#define InitWalkerContext(context, prel_info, ecxt) \
297+
#define InitWalkerContext(context, prel_info, ecxt, mcxt) \
295298
do { \
296299
(context)->prel = (prel_info); \
297300
(context)->econtext = (ecxt); \
298301
(context)->ranges = NULL; \
302+
(context)->nranges = 0; \
299303
(context)->hasLeast = false; \
300304
(context)->hasGreatest = false; \
305+
(context)->persistent_mcxt = (mcxt); \
301306
} while (0)
302307

303308
/*
304309
* We'd like to persist RangeEntry (ranges) array
305310
* in case of range partitioning, so 'wcxt' is stored
306311
* inside of Custom Node
307312
*/
308-
#define InitWalkerContextCustomNode(context, prel_info, ecxt, isCached) \
313+
#define InitWalkerContextCustomNode(context, prel_info, ecxt, mcxt, isCached) \
309314
do { \
310315
if (!*isCached) \
311316
{ \
312317
(context)->prel = prel_info; \
313318
(context)->econtext = ecxt; \
314319
(context)->ranges = NULL; \
320+
(context)->nranges = 0; \
321+
(context)->persistent_mcxt = (mcxt); \
315322
*isCached = true; \
316323
} \
317324
(context)->hasLeast = false; \
318325
(context)->hasGreatest = false; \
319326
} while (0)
320327

328+
/* Check that WalkerContext contains ExprContext (plan execution stage) */
329+
#define WcxtHasExprContext(wcxt) ( (wcxt)->econtext )
330+
321331
void select_range_partitions(const Datum value,
322332
const bool byVal,
323333
FmgrInfo *cmp_func,

src/pg_pathman.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,6 @@ static Path *get_cheapest_parameterized_child_path(PlannerInfo *root, RelOptInfo
100100
#define check_gt(flinfo, arg1, arg2) \
101101
((int) FunctionCall2(cmp_func, arg1, arg2) > 0)
102102

103-
#define WcxtHasExprContext(wcxt) ( (wcxt)->econtext )
104-
105103
/* We can transform Param into Const provided that 'econtext' is available */
106104
#define IsConstValue(wcxt, node) \
107105
( IsA((node), Const) || (WcxtHasExprContext(wcxt) ? IsA((node), Param) : false) )
@@ -331,7 +329,7 @@ handle_modification_query(Query *parse)
331329
return;
332330

333331
/* Parse syntax tree and extract partition ranges */
334-
InitWalkerContext(&context, prel, NULL);
332+
InitWalkerContext(&context, prel, NULL, CurrentMemoryContext);
335333
wrap = walk_expr_tree(expr, &context);
336334
finish_least_greatest(wrap, &context);
337335
clear_walker_context(&context);
@@ -663,12 +661,22 @@ wrapper_make_expression(WrapperNode *wrap, int index, bool *alwaysTrue)
663661
void
664662
refresh_walker_context_ranges(WalkerContext *context)
665663
{
666-
RangeRelation *rangerel;
664+
RangeRelation *rangerel;
665+
MemoryContext old_mcxt;
667666

668667
rangerel = get_pathman_range_relation(context->prel->key.relid, NULL);
669668

669+
/* Clear old cached data */
670+
clear_walker_context(context);
671+
672+
/* Switch to long-living context which should store data */
673+
old_mcxt = MemoryContextSwitchTo(context->persistent_mcxt);
674+
670675
context->ranges = dsm_array_get_pointer(&rangerel->ranges, true);
671676
context->nranges = rangerel->ranges.elem_count;
677+
678+
/* Switch back */
679+
MemoryContextSwitchTo(old_mcxt);
672680
}
673681

674682
/*
@@ -799,6 +807,7 @@ select_range_partitions(const Datum value,
799807
}
800808
else
801809
{
810+
Assert(ranges);
802811
Assert(cmp_func);
803812

804813
/* Corner cases */
@@ -978,6 +987,7 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
978987
case PT_RANGE:
979988
if (get_pathman_range_relation(context->prel->key.relid, NULL))
980989
{
990+
/* Refresh 'ranges' cache if necessary */
981991
if (!context->ranges)
982992
refresh_walker_context_ranges(context);
983993

@@ -1129,6 +1139,7 @@ handle_const(const Const *c, WalkerContext *context)
11291139

11301140
tce = lookup_type_cache(c->consttype, TYPECACHE_CMP_PROC_FINFO);
11311141

1142+
/* Refresh 'ranges' cache if necessary */
11321143
if (!context->ranges)
11331144
refresh_walker_context_ranges(context);
11341145

0 commit comments

Comments
 (0)