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)
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