typedef struct pgpa_planner_state
{
+ MemoryContext mcxt;
bool generate_advice_feedback;
bool generate_advice_string;
pgpa_trove *trove;
* some purpose. That could be (1) recording that we will need to generate
* an advice string, (2) storing a trove of supplied advice, or (3)
* facilitating debugging cross-checks when asserts are enabled.
+ *
+ * Currently, the active memory context should be one that will last for
+ * the entire duration of query planning, but if GEQO is in use, it's
+ * possible that some of our callbacks may be invoked later with
+ * CurrentMemoryContext set to some shorter-lived context. So, record the
+ * context that should be used for allocations that need to live as long
+ * as the pgpa_planner_state itself.
*/
if (needs_pps)
{
pps = palloc0_object(pgpa_planner_state);
+ pps->mcxt = CurrentMemoryContext;
pps->generate_advice_feedback = generate_advice_feedback;
pps->generate_advice_string = generate_advice_string;
pps->trove = trove;
/* If not a duplicate, append to the list. */
if (!found)
{
- pgpa_sj_unique_rel *ur = palloc_object(pgpa_sj_unique_rel);
+ pgpa_sj_unique_rel *ur;
+ MemoryContext oldcontext;
+ oldcontext = MemoryContextSwitchTo(pps->mcxt);
+ ur = palloc_object(pgpa_sj_unique_rel);
ur->plan_name = root->plan_name;
- ur->relids = uniquerel->relids;
+ ur->relids = bms_copy(uniquerel->relids);
pps->sj_unique_rels = lappend(pps->sj_unique_rels, ur);
+ MemoryContextSwitchTo(oldcontext);
}
}
}