=== Applying patches on top of PostgreSQL commit ID 5092aae431e3e1a20324ea3a42a181c63f703d0d === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Sat Oct 4 06:35:21 UTC 2025 On branch cf/5965 nothing to commit, working tree clean === using 'git am' to apply patch ./v0-0001-Introduce-a-create-plan-hook.patch === Applying: Introduce a create plan hook. Using index info to reconstruct a base tree... M contrib/pg_overexplain/expected/pg_overexplain.out M contrib/pg_overexplain/pg_overexplain.c M src/backend/optimizer/plan/createplan.c M src/include/nodes/plannodes.h M src/tools/pgindent/typedefs.list Falling back to patching base and 3-way merge... Auto-merging src/tools/pgindent/typedefs.list Auto-merging src/include/nodes/plannodes.h Auto-merging src/backend/optimizer/plan/createplan.c CONFLICT (content): Merge conflict in src/backend/optimizer/plan/createplan.c Auto-merging contrib/pg_overexplain/pg_overexplain.c Auto-merging contrib/pg_overexplain/expected/pg_overexplain.out error: Failed to merge in the changes. hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 Introduce a create plan hook. When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". Unstaged changes after reset: M contrib/pg_overexplain/expected/pg_overexplain.out M contrib/pg_overexplain/pg_overexplain.c M contrib/pg_overexplain/sql/pg_overexplain.sql M src/backend/optimizer/plan/createplan.c M src/include/nodes/plannodes.h M src/include/optimizer/planmain.h M src/tools/pgindent/typedefs.list === using patch(1) to apply patch ./v0-0001-Introduce-a-create-plan-hook.patch === patching file contrib/pg_overexplain/expected/pg_overexplain.out Hunk #1 succeeded at 489 with fuzz 2 (offset 2 lines). patching file contrib/pg_overexplain/pg_overexplain.c Hunk #8 succeeded at 363 (offset 12 lines). Hunk #9 succeeded at 801 (offset 12 lines). patching file contrib/pg_overexplain/sql/pg_overexplain.sql patching file src/backend/optimizer/plan/createplan.c Hunk #2 succeeded at 174 (offset -2 lines). Hunk #3 succeeded at 1245 with fuzz 2 (offset -9 lines). Hunk #4 succeeded at 1429 (offset -9 lines). Hunk #5 succeeded at 1473 (offset -9 lines). Hunk #6 succeeded at 1643 with fuzz 2 (offset -9 lines). Hunk #7 succeeded at 1668 (offset -9 lines). Hunk #8 succeeded at 1696 (offset -9 lines). Hunk #9 succeeded at 1751 (offset -9 lines). Hunk #10 FAILED at 1961. Hunk #11 succeeded at 1786 (offset -210 lines). Hunk #12 succeeded at 1815 (offset -210 lines). Hunk #13 succeeded at 1940 with fuzz 2 (offset -211 lines). Hunk #14 succeeded at 2041 (offset -211 lines). Hunk #15 succeeded at 2067 (offset -211 lines). Hunk #16 succeeded at 2106 (offset -211 lines). Hunk #17 succeeded at 2142 with fuzz 2 (offset -203 lines). Hunk #18 succeeded at 2186 (offset -203 lines). Hunk #19 succeeded at 2383 (offset -203 lines). Hunk #20 succeeded at 2444 with fuzz 2 (offset -201 lines). Hunk #21 succeeded at 2548 (offset -201 lines). Hunk #22 succeeded at 2588 (offset -201 lines). Hunk #23 succeeded at 2624 (offset -201 lines). Hunk #24 succeeded at 2647 (offset -201 lines). Hunk #25 succeeded at 2688 (offset -201 lines). Hunk #26 succeeded at 2742 (offset -201 lines). Hunk #27 succeeded at 2788 (offset -201 lines). Hunk #28 succeeded at 2834 (offset -201 lines). Hunk #29 succeeded at 3035 (offset -201 lines). Hunk #30 succeeded at 3150 (offset -201 lines). Hunk #31 succeeded at 3470 (offset -201 lines). Hunk #32 succeeded at 3535 (offset -201 lines). Hunk #33 succeeded at 3594 (offset -201 lines). Hunk #34 succeeded at 3637 (offset -201 lines). Hunk #35 succeeded at 3680 (offset -201 lines). Hunk #36 succeeded at 3724 (offset -201 lines). Hunk #37 succeeded at 3818 (offset -201 lines). Hunk #38 succeeded at 3857 (offset -201 lines). Hunk #39 succeeded at 3896 with fuzz 2 (offset -200 lines). Hunk #40 succeeded at 3956 (offset -200 lines). Hunk #41 succeeded at 4016 (offset -200 lines). Hunk #42 succeeded at 4161 (offset -200 lines). Hunk #43 succeeded at 4339 (offset -200 lines). Hunk #44 succeeded at 4693 (offset -200 lines). Hunk #45 succeeded at 4866 (offset -200 lines). Hunk #46 succeeded at 5360 (offset -200 lines). Hunk #47 succeeded at 5369 (offset -200 lines). 1 out of 47 hunks FAILED -- saving rejects to file src/backend/optimizer/plan/createplan.c.rej patching file src/include/nodes/plannodes.h patching file src/include/optimizer/planmain.h patching file src/tools/pgindent/typedefs.list Hunk #1 succeeded at 3527 (offset 2 lines). Unstaged changes after reset: M contrib/pg_overexplain/expected/pg_overexplain.out M contrib/pg_overexplain/pg_overexplain.c M contrib/pg_overexplain/sql/pg_overexplain.sql M src/backend/optimizer/plan/createplan.c M src/include/nodes/plannodes.h M src/include/optimizer/planmain.h M src/tools/pgindent/typedefs.list Removing src/backend/optimizer/plan/createplan.c.rej === using 'git apply' to apply patch ./v0-0001-Introduce-a-create-plan-hook.patch === Applied patch to 'contrib/pg_overexplain/expected/pg_overexplain.out' cleanly. Applied patch to 'contrib/pg_overexplain/pg_overexplain.c' cleanly. Applied patch to 'contrib/pg_overexplain/sql/pg_overexplain.sql' cleanly. Applied patch to 'src/backend/optimizer/plan/createplan.c' with conflicts. Applied patch to 'src/include/nodes/plannodes.h' cleanly. Applied patch to 'src/include/optimizer/planmain.h' cleanly. Applied patch to 'src/tools/pgindent/typedefs.list' cleanly. U src/backend/optimizer/plan/createplan.c diff --cc src/backend/optimizer/plan/createplan.c index c9dba7ff346,c2f7b1ecf31..00000000000 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@@ -1239,12 -1249,12 +1240,12 @@@ create_append_plan(PlannerInfo *root, A /* Generate a Result plan with constant-FALSE gating qual */ Plan *plan; - plan = (Plan *) make_result(tlist, - (Node *) list_make1(makeBoolConst(false, - false)), - NULL); + plan = (Plan *) make_one_row_result(tlist, + (Node *) list_make1(makeBoolConst(false, + false)), + best_path->path.parent); - copy_generic_path_info(plan, (Path *) best_path); + copy_generic_path_info(root, plan, (Path *) best_path); return plan; } @@@ -1640,9 -1650,9 +1641,9 @@@ create_group_result_plan(PlannerInfo *r /* best_path->quals is just bare clauses */ quals = order_qual_clauses(root, best_path->quals); - plan = make_result(tlist, (Node *) quals, NULL); + plan = make_one_row_result(tlist, (Node *) quals, best_path->path.parent); - copy_generic_path_info(&plan->plan, (Path *) best_path); + copy_generic_path_info(root, &plan->plan, (Path *) best_path); return plan; } @@@ -1756,6 -1766,207 +1757,210 @@@ create_memoize_plan(PlannerInfo *root, } /* ++<<<<<<< ours ++======= + * create_unique_plan + * Create a Unique plan for 'best_path' and (recursively) plans + * for its subpaths. + * + * Returns a Plan node. + */ + static Plan * + create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags) + { + Plan *plan; + Plan *subplan; + List *in_operators; + List *uniq_exprs; + List *newtlist; + int nextresno; + bool newitems; + int numGroupCols; + AttrNumber *groupColIdx; + Oid *groupCollations; + int groupColPos; + ListCell *l; + + /* Unique doesn't project, so tlist requirements pass through */ + subplan = create_plan_recurse(root, best_path->subpath, flags); + + /* Done if we don't need to do any actual unique-ifying */ + if (best_path->umethod == UNIQUE_PATH_NOOP) + return subplan; + + /* + * As constructed, the subplan has a "flat" tlist containing just the Vars + * needed here and at upper levels. The values we are supposed to + * unique-ify may be expressions in these variables. We have to add any + * such expressions to the subplan's tlist. + * + * The subplan may have a "physical" tlist if it is a simple scan plan. If + * we're going to sort, this should be reduced to the regular tlist, so + * that we don't sort more data than we need to. For hashing, the tlist + * should be left as-is if we don't need to add any expressions; but if we + * do have to add expressions, then a projection step will be needed at + * runtime anyway, so we may as well remove unneeded items. Therefore + * newtlist starts from build_path_tlist() not just a copy of the + * subplan's tlist; and we don't install it into the subplan unless we are + * sorting or stuff has to be added. + */ + in_operators = best_path->in_operators; + uniq_exprs = best_path->uniq_exprs; + + /* initialize modified subplan tlist as just the "required" vars */ + newtlist = build_path_tlist(root, &best_path->path); + nextresno = list_length(newtlist) + 1; + newitems = false; + + foreach(l, uniq_exprs) + { + Expr *uniqexpr = lfirst(l); + TargetEntry *tle; + + tle = tlist_member(uniqexpr, newtlist); + if (!tle) + { + tle = makeTargetEntry((Expr *) uniqexpr, + nextresno, + NULL, + false); + newtlist = lappend(newtlist, tle); + nextresno++; + newitems = true; + } + } + + /* Use change_plan_targetlist in case we need to insert a Result node */ + if (newitems || best_path->umethod == UNIQUE_PATH_SORT) + subplan = change_plan_targetlist(subplan, newtlist, + best_path->path.parallel_safe); + + /* + * Build control information showing which subplan output columns are to + * be examined by the grouping step. Unfortunately we can't merge this + * with the previous loop, since we didn't then know which version of the + * subplan tlist we'd end up using. + */ + newtlist = subplan->targetlist; + numGroupCols = list_length(uniq_exprs); + groupColIdx = (AttrNumber *) palloc(numGroupCols * sizeof(AttrNumber)); + groupCollations = (Oid *) palloc(numGroupCols * sizeof(Oid)); + + groupColPos = 0; + foreach(l, uniq_exprs) + { + Expr *uniqexpr = lfirst(l); + TargetEntry *tle; + + tle = tlist_member(uniqexpr, newtlist); + if (!tle) /* shouldn't happen */ + elog(ERROR, "failed to find unique expression in subplan tlist"); + groupColIdx[groupColPos] = tle->resno; + groupCollations[groupColPos] = exprCollation((Node *) tle->expr); + groupColPos++; + } + + if (best_path->umethod == UNIQUE_PATH_HASH) + { + Oid *groupOperators; + + /* + * Get the hashable equality operators for the Agg node to use. + * Normally these are the same as the IN clause operators, but if + * those are cross-type operators then the equality operators are the + * ones for the IN clause operators' RHS datatype. + */ + groupOperators = (Oid *) palloc(numGroupCols * sizeof(Oid)); + groupColPos = 0; + foreach(l, in_operators) + { + Oid in_oper = lfirst_oid(l); + Oid eq_oper; + + if (!get_compatible_hash_operators(in_oper, NULL, &eq_oper)) + elog(ERROR, "could not find compatible hash operator for operator %u", + in_oper); + groupOperators[groupColPos++] = eq_oper; + } + + /* + * Since the Agg node is going to project anyway, we can give it the + * minimum output tlist, without any stuff we might have added to the + * subplan tlist. + */ + plan = (Plan *) make_agg(build_path_tlist(root, &best_path->path), + NIL, + AGG_HASHED, + AGGSPLIT_SIMPLE, + numGroupCols, + groupColIdx, + groupOperators, + groupCollations, + NIL, + NIL, + best_path->path.rows, + 0, + subplan); + } + else + { + List *sortList = NIL; + Sort *sort; + + /* Create an ORDER BY list to sort the input compatibly */ + groupColPos = 0; + foreach(l, in_operators) + { + Oid in_oper = lfirst_oid(l); + Oid sortop; + Oid eqop; + TargetEntry *tle; + SortGroupClause *sortcl; + + sortop = get_ordering_op_for_equality_op(in_oper, false); + if (!OidIsValid(sortop)) /* shouldn't happen */ + elog(ERROR, "could not find ordering operator for equality operator %u", + in_oper); + + /* + * The Unique node will need equality operators. Normally these + * are the same as the IN clause operators, but if those are + * cross-type operators then the equality operators are the ones + * for the IN clause operators' RHS datatype. + */ + eqop = get_equality_op_for_ordering_op(sortop, NULL); + if (!OidIsValid(eqop)) /* shouldn't happen */ + elog(ERROR, "could not find equality operator for ordering operator %u", + sortop); + + tle = get_tle_by_resno(subplan->targetlist, + groupColIdx[groupColPos]); + Assert(tle != NULL); + + sortcl = makeNode(SortGroupClause); + sortcl->tleSortGroupRef = assignSortGroupRef(tle, + subplan->targetlist); + sortcl->eqop = eqop; + sortcl->sortop = sortop; + sortcl->reverse_sort = false; + sortcl->nulls_first = false; + sortcl->hashable = false; /* no need to make this accurate */ + sortList = lappend(sortList, sortcl); + groupColPos++; + } + sort = make_sort_from_sortclauses(sortList, subplan); + label_sort_with_costsize(root, sort, -1.0); + plan = (Plan *) make_unique_from_sortclauses((Plan *) sort, sortList); + } + + /* Copy cost data from Path to Plan */ + copy_generic_path_info(root, plan, &best_path->path); + + return plan; + } + + /* ++>>>>>>> theirs * create_gather_plan * * Create a Gather plan for 'best_path' and (recursively) plans @@@ -1937,9 -2148,10 +2142,9 @@@ create_projection_plan(PlannerInfo *roo } else { - /* We need a Result node */ - plan = (Plan *) make_result(tlist, NULL, subplan); + plan = (Plan *) make_gating_result(tlist, NULL, subplan); - copy_generic_path_info(plan, (Path *) best_path); + copy_generic_path_info(root, plan, (Path *) best_path); } return plan; @@@ -2129,19 -2341,11 +2334,19 @@@ create_unique_plan(PlannerInfo *root, U subplan = create_plan_recurse(root, best_path->subpath, flags | CP_LABEL_TLIST); + /* + * make_unique_from_pathkeys calls find_ec_member_matching_expr, which + * will ignore any child EC members that don't belong to the given relids. + * Thus, if this unique path is based on a child relation, we must pass + * its relids. + */ plan = make_unique_from_pathkeys(subplan, best_path->path.pathkeys, - best_path->numkeys); + best_path->numkeys, + IS_OTHER_REL(best_path->path.parent) ? + best_path->path.parent->relids : NULL); - copy_generic_path_info(&plan->plan, (Path *) best_path); + copy_generic_path_info(root, &plan->plan, (Path *) best_path); return plan; } @@@ -2439,11 -2643,9 +2644,11 @@@ create_minmaxagg_plan(PlannerInfo *root /* Generate the output plan --- basically just a Result */ tlist = build_path_tlist(root, &best_path->path); - plan = make_result(tlist, (Node *) best_path->quals, NULL); + plan = make_one_row_result(tlist, (Node *) best_path->quals, + best_path->path.parent); + plan->result_type = RESULT_TYPE_MINMAX; - copy_generic_path_info(&plan->plan, (Path *) best_path); + copy_generic_path_info(root, &plan->plan, (Path *) best_path); /* * During setrefs.c, we'll need to replace references to the Agg nodes @@@ -3892,10 -4094,9 +4097,10 @@@ create_resultscan_plan(PlannerInfo *roo replace_nestloop_params(root, (Node *) scan_clauses); } - scan_plan = make_result(tlist, (Node *) scan_clauses, NULL); + scan_plan = make_one_row_result(tlist, (Node *) scan_clauses, + best_path->parent); - copy_generic_path_info(&scan_plan->plan, best_path); + copy_generic_path_info(root, &scan_plan->plan, best_path); return scan_plan; }