diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c index b5cab0c..e5883a2 100644 --- a/src/backend/optimizer/geqo/geqo_eval.c +++ b/src/backend/optimizer/geqo/geqo_eval.c @@ -267,6 +267,9 @@ merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, bool force) /* Create GatherPaths for any useful partial paths for rel */ generate_gather_paths(root, joinrel); + /* Create "append" paths for partitioned joins. */ + generate_partition_wise_join_paths(root, joinrel); + /* Find and save the cheapest paths for this joinrel */ set_cheapest(joinrel); diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 64c4f6e..df7d452 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -31,6 +31,7 @@ #include "parser/parsetree.h" #include "foreign/fdwapi.h" #include "utils/lsyscache.h" +#include "utils/memutils.h" #include "utils/selfuncs.h" @@ -3731,16 +3732,33 @@ reparameterize_path_by_child(PlannerInfo *root, Path *path, /* If we already have a PPI for this parameterization, just return it */ new_ppi = find_param_path_info(new_path->parent, required_outer); - /* If not build a new one and link it to the list of PPIs. */ + /* + * If not build a new one and link it to the list of PPIs. When called + * during GEQO join planning, we are in a short-lived memory context. We + * must make sure that the new PPI and its contents attached to a baserel + * survives the GEQO cycle, else the baserel is trashed for future GEQO + * cycles. On the other hand, when we are adding new PPI to a joinrel + * during GEQO, we don't want that to clutter the main planning context. + * Upshot is that the best solution is to explicitly allocate new PPI in + * the same context the given RelOptInfo is in. + */ if (!new_ppi) { + MemoryContext oldcontext; + RelOptInfo *rel = path->parent; + + /* No, so choose correct context to make the dummy path in */ + oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(rel)); + new_ppi = makeNode(ParamPathInfo); - new_ppi->ppi_req_outer = required_outer; + new_ppi->ppi_req_outer = bms_copy(required_outer); new_ppi->ppi_rows = old_ppi->ppi_rows; new_ppi->ppi_clauses = (List *) adjust_appendrel_attrs_multilevel(root, (Node *) old_ppi->ppi_clauses, child_rel); - new_path->parent->ppilist = lappend(new_path->parent->ppilist, new_ppi); + new_path->parent->ppilist = lappend(rel->ppilist, new_ppi); + + MemoryContextSwitchTo(oldcontext); } else bms_free(required_outer);