=== Applying patches on top of PostgreSQL commit ID c6abf24ebfecf0ef4f7d21750e198959b8b61586 === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Tue Aug 19 19:22:19 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 src/backend/optimizer/plan/createplan.c 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/backend/optimizer/plan/createplan.c CONFLICT (content): Merge conflict in src/backend/optimizer/plan/createplan.c 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 patching file contrib/pg_overexplain/pg_overexplain.c patching file contrib/pg_overexplain/sql/pg_overexplain.sql patching file src/backend/optimizer/plan/createplan.c Hunk #2 succeeded at 173 (offset -3 lines). Hunk #3 succeeded at 1241 (offset -13 lines). Hunk #4 succeeded at 1425 (offset -13 lines). Hunk #5 succeeded at 1469 (offset -13 lines). Hunk #6 succeeded at 1639 (offset -13 lines). Hunk #7 succeeded at 1664 (offset -13 lines). Hunk #8 succeeded at 1692 (offset -13 lines). Hunk #9 succeeded at 1747 (offset -13 lines). Hunk #10 FAILED at 1961. Hunk #11 succeeded at 1782 (offset -214 lines). Hunk #12 succeeded at 1811 (offset -214 lines). Hunk #13 succeeded at 1937 (offset -214 lines). Hunk #14 succeeded at 2038 (offset -214 lines). Hunk #15 succeeded at 2064 (offset -214 lines). Hunk #16 succeeded at 2103 (offset -214 lines). Hunk #17 succeeded at 2139 with fuzz 2 (offset -206 lines). Hunk #18 succeeded at 2183 (offset -206 lines). Hunk #19 succeeded at 2380 (offset -206 lines). Hunk #20 succeeded at 2439 (offset -206 lines). Hunk #21 succeeded at 2543 (offset -206 lines). Hunk #22 succeeded at 2583 (offset -206 lines). Hunk #23 succeeded at 2619 (offset -206 lines). Hunk #24 succeeded at 2642 (offset -206 lines). Hunk #25 succeeded at 2683 (offset -206 lines). Hunk #26 succeeded at 2737 (offset -206 lines). Hunk #27 succeeded at 2783 (offset -206 lines). Hunk #28 succeeded at 2829 (offset -206 lines). Hunk #29 succeeded at 3030 (offset -206 lines). Hunk #30 succeeded at 3145 (offset -206 lines). Hunk #31 succeeded at 3465 (offset -206 lines). Hunk #32 succeeded at 3530 (offset -206 lines). Hunk #33 succeeded at 3589 (offset -206 lines). Hunk #34 succeeded at 3632 (offset -206 lines). Hunk #35 succeeded at 3675 (offset -206 lines). Hunk #36 succeeded at 3719 (offset -206 lines). Hunk #37 succeeded at 3813 (offset -206 lines). Hunk #38 succeeded at 3852 (offset -206 lines). Hunk #39 succeeded at 3890 (offset -206 lines). Hunk #40 succeeded at 3950 (offset -206 lines). Hunk #41 succeeded at 4010 (offset -206 lines). Hunk #42 succeeded at 4155 (offset -206 lines). Hunk #43 succeeded at 4333 (offset -206 lines). Hunk #44 succeeded at 4687 (offset -206 lines). Hunk #45 succeeded at 4860 (offset -206 lines). Hunk #46 succeeded at 5354 (offset -206 lines). Hunk #47 succeeded at 5363 (offset -206 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 3523 (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 6791cbeb416,c2f7b1ecf31..00000000000 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@@ -1752,6 -1766,207 +1753,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 @@@ -2126,19 -2341,11 +2331,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; }