diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 647baa3cf6..ec4a8fb9cc 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -6969,139 +6969,135 @@ apply_scanjoin_target_to_paths(PlannerInfo *root, rel->nparts = 0; rel->part_rels = NULL; rel->boundinfo = NULL; - - /* Now fix things up if scan/join target contains SRFs */ - if (root->parse->hasTargetSRFs) - adjust_paths_for_srfs(root, rel, - scanjoin_targets, - scanjoin_targets_contain_srfs); - - return; } - - /* - * Adjust each input path. If the tlist exprs are the same, we can just - * inject the sortgroupref information into the existing pathtarget. - * Otherwise, replace each path with a projection path that generates the - * SRF-free scan/join target. This can't change the ordering of paths - * within rel->pathlist, so we just modify the list in place. - */ - foreach(lc, rel->pathlist) + else { - Path *subpath = (Path *) lfirst(lc); - Path *newpath; - - Assert(subpath->param_info == NULL); - - if (tlist_same_exprs) - subpath->pathtarget->sortgrouprefs = - scanjoin_target->sortgrouprefs; - else + /* + * Adjust each input path. If the tlist exprs are the same, we can + * just inject the sortgroupref information into the existing + * pathtarget. Otherwise, replace each path with a projection path + * that generates the SRF-free scan/join target. This can't change the + * ordering of paths within rel->pathlist, so we just modify the list + * in place. + */ + foreach(lc, rel->pathlist) { - newpath = (Path *) create_projection_path(root, rel, subpath, - scanjoin_target); - lfirst(lc) = newpath; - } - } + Path *subpath = (Path *) lfirst(lc); + Path *newpath; - /* Same for partial paths. */ - foreach(lc, rel->partial_pathlist) - { - Path *subpath = (Path *) lfirst(lc); - Path *newpath; + Assert(subpath->param_info == NULL); - /* Shouldn't have any parameterized paths anymore */ - Assert(subpath->param_info == NULL); + if (tlist_same_exprs) + subpath->pathtarget->sortgrouprefs = + scanjoin_target->sortgrouprefs; + else + { + newpath = (Path *) create_projection_path(root, rel, subpath, + scanjoin_target); + lfirst(lc) = newpath; + } + } - if (tlist_same_exprs) - subpath->pathtarget->sortgrouprefs = - scanjoin_target->sortgrouprefs; - else + /* Same for partial paths. */ + foreach(lc, rel->partial_pathlist) { - newpath = (Path *) create_projection_path(root, - rel, - subpath, - scanjoin_target); - lfirst(lc) = newpath; - } - } + Path *subpath = (Path *) lfirst(lc); + Path *newpath; - /* Now fix things up if scan/join target contains SRFs */ - if (root->parse->hasTargetSRFs) - adjust_paths_for_srfs(root, rel, - scanjoin_targets, - scanjoin_targets_contain_srfs); + /* Shouldn't have any parameterized paths anymore */ + Assert(subpath->param_info == NULL); - /* - * If the relation is partitioned, recursively apply the same changes to - * all partitions and generate new Append paths. Since Append is not - * projection-capable, that might save a separate Result node, and it also - * is important for partitionwise aggregate. - */ - if (rel->part_scheme && rel->part_rels) - { - int partition_idx; - List *live_children = NIL; + if (tlist_same_exprs) + subpath->pathtarget->sortgrouprefs = + scanjoin_target->sortgrouprefs; + else + { + newpath = (Path *) create_projection_path(root, + rel, + subpath, + scanjoin_target); + lfirst(lc) = newpath; + } + } - /* Adjust each partition. */ - for (partition_idx = 0; partition_idx < rel->nparts; partition_idx++) + /* + * If the relation is partitioned, recursively apply the same changes + * to all partitions and generate new Append paths. Since Append is + * not projection-capable, that might save a separate Result node, and + * it also is important for partitionwise aggregate. + */ + if (rel->part_scheme && rel->part_rels) { - RelOptInfo *child_rel = rel->part_rels[partition_idx]; - ListCell *lc; - AppendRelInfo **appinfos; - int nappinfos; - List *child_scanjoin_targets = NIL; - - /* Translate scan/join targets for this child. */ - appinfos = find_appinfos_by_relids(root, child_rel->relids, - &nappinfos); - foreach(lc, scanjoin_targets) + int part_idx; + List *live_children = NIL; + + /* Adjust each partition. */ + for (part_idx = 0; part_idx < rel->nparts; part_idx++) { - PathTarget *target = lfirst_node(PathTarget, lc); - - target = copy_pathtarget(target); - target->exprs = (List *) - adjust_appendrel_attrs(root, - (Node *) target->exprs, - nappinfos, appinfos); - child_scanjoin_targets = lappend(child_scanjoin_targets, - target); + RelOptInfo *child_rel = rel->part_rels[part_idx]; + ListCell *lc; + AppendRelInfo **appinfos; + int nappinfos; + List *child_scanjoin_targets = NIL; + + /* Translate scan/join targets for this child. */ + appinfos = find_appinfos_by_relids(root, child_rel->relids, + &nappinfos); + foreach(lc, scanjoin_targets) + { + PathTarget *target = lfirst_node(PathTarget, lc); + + target = copy_pathtarget(target); + target->exprs = (List *) + adjust_appendrel_attrs(root, + (Node *) target->exprs, + nappinfos, appinfos); + child_scanjoin_targets = lappend(child_scanjoin_targets, + target); + } + pfree(appinfos); + + /* Recursion does the real work. */ + apply_scanjoin_target_to_paths(root, child_rel, + child_scanjoin_targets, + scanjoin_targets_contain_srfs, + scanjoin_target_parallel_safe, + tlist_same_exprs); + + /* Save non-dummy children for Append paths. */ + if (!IS_DUMMY_REL(child_rel)) + live_children = lappend(live_children, child_rel); } - pfree(appinfos); - - /* Recursion does the real work. */ - apply_scanjoin_target_to_paths(root, child_rel, - child_scanjoin_targets, - scanjoin_targets_contain_srfs, - scanjoin_target_parallel_safe, - tlist_same_exprs); - - /* Save non-dummy children for Append paths. */ - if (!IS_DUMMY_REL(child_rel)) - live_children = lappend(live_children, child_rel); + + /* Build new paths for this relation by appending child paths. */ + if (live_children != NIL) + add_paths_to_append_rel(root, rel, live_children); } - /* Build new paths for this relation by appending child paths. */ - if (live_children != NIL) - add_paths_to_append_rel(root, rel, live_children); - } + /* + * Consider generating Gather or Gather Merge paths. We must only do + * this if the relation is parallel safe, and we don't do it for child + * rels to avoid creating multiple Gather nodes within the same plan. + * We must do this after all paths have been generated and before + * set_cheapest, since one of the generated paths may turn out to be + * the cheapest one. + */ + if (rel->consider_parallel && !IS_OTHER_REL(rel)) + generate_gather_paths(root, rel, false); - /* - * Consider generating Gather or Gather Merge paths. We must only do this - * if the relation is parallel safe, and we don't do it for child rels to - * avoid creating multiple Gather nodes within the same plan. We must do - * this after all paths have been generated and before set_cheapest, since - * one of the generated paths may turn out to be the cheapest one. - */ - if (rel->consider_parallel && !IS_OTHER_REL(rel)) - generate_gather_paths(root, rel, false); + /* + * Reassess which paths are the cheapest, now that we've potentially + * added new Gather (or Gather Merge) and/or Append (or MergeAppend) + * paths to this relation. + */ + set_cheapest(rel); + } - /* - * Reassess which paths are the cheapest, now that we've potentially added - * new Gather (or Gather Merge) and/or Append (or MergeAppend) paths to - * this relation. - */ - set_cheapest(rel); + /* Now fix things up if scan/join target contains SRFs */ + if (root->parse->hasTargetSRFs) + adjust_paths_for_srfs(root, rel, + scanjoin_targets, + scanjoin_targets_contain_srfs); } /*