From 012a966983d2316245ce847d2889db0ec2bec43f Mon Sep 17 00:00:00 2001
From: test <test>
Date: Tue, 9 Jun 2026 00:17:33 +0200
Subject: [PATCH v2 5/6] free mergejoin keys

---
 src/backend/optimizer/path/joinpath.c | 18 ++++++++++-
 src/backend/optimizer/util/pathnode.c | 44 ++++++++++++++++++++++++---
 2 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index 713283a73aa..9396ce4c145 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -379,6 +379,8 @@ add_paths_to_joinrel(PlannerInfo *root,
 	if (set_join_pathlist_hook)
 		set_join_pathlist_hook(root, joinrel, outerrel, innerrel,
 							   save_jointype, &extra);
+
+	list_free(extra.mergeclause_list);
 }
 
 /*
@@ -1519,7 +1521,7 @@ sort_inner_and_outer(PlannerInfo *root,
 							  list_delete_nth_cell(list_copy(all_pathkeys),
 												   foreach_current_index(l)));
 		else
-			outerkeys = all_pathkeys;	/* no work at first one... */
+			outerkeys = list_copy(all_pathkeys);	/* no work at first one... */
 
 		/* Sort the mergeclauses into the corresponding ordering */
 		cur_mergeclauses =
@@ -1573,7 +1575,15 @@ sort_inner_and_outer(PlannerInfo *root,
 									   innerkeys,
 									   jointype,
 									   extra);
+
+		list_free(cur_mergeclauses);
+		list_free(innerkeys);
+
+		if ((outerkeys != merge_pathkeys) && (innerkeys != merge_pathkeys))
+			list_free(outerkeys);
 	}
+
+	list_free(all_pathkeys);
 }
 
 /*
@@ -1634,7 +1644,10 @@ generate_mergejoin_paths(PlannerInfo *root,
 	}
 	if (useallclauses &&
 		list_length(mergeclauses) != list_length(extra->mergeclause_list))
+	{
+		list_free(mergeclauses);
 		return;
+	}
 
 	/* Compute the required ordering of the inner path */
 	innersortkeys = make_inner_pathkeys_for_merge(root,
@@ -1805,6 +1818,9 @@ generate_mergejoin_paths(PlannerInfo *root,
 		if (useallclauses)
 			break;
 	}
+
+	list_free(innersortkeys);
+	list_free(mergeclauses);
 }
 
 /*
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 73518c8f870..911f0de8c82 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -624,6 +624,14 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
 			parent_rel->pathlist = foreach_delete_current(parent_rel->pathlist,
 														  p1);
 
+			if (IsA(old_path, MergePath))
+			{
+				MergePath  *mjpath = (MergePath *) old_path;
+				list_free(mjpath->path_mergeclauses);
+				list_free(mjpath->innersortkeys);
+				list_free(mjpath->outersortkeys);
+				list_free(mjpath->jpath.path.pathkeys);
+			}
 			/*
 			 * Delete the data pointed-to by the deleted cell, if possible
 			 */
@@ -659,6 +667,15 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
 	}
 	else
 	{
+		if (IsA(new_path, MergePath))
+		{
+			MergePath  *mjpath = (MergePath *) new_path;
+			list_free(mjpath->path_mergeclauses);
+			list_free(mjpath->innersortkeys);
+			list_free(mjpath->outersortkeys);
+			list_free(mjpath->jpath.path.pathkeys);
+		}
+
 		/* Reject and recycle the new path */
 		if (!IsA(new_path, IndexPath))
 			pfree(new_path);
@@ -863,6 +880,16 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
 		{
 			parent_rel->partial_pathlist =
 				foreach_delete_current(parent_rel->partial_pathlist, p1);
+
+			if (IsA(old_path, MergePath))
+			{
+				MergePath  *mjpath = (MergePath *) old_path;
+				list_free(mjpath->path_mergeclauses);
+				list_free(mjpath->innersortkeys);
+				list_free(mjpath->outersortkeys);
+				list_free(mjpath->jpath.path.pathkeys);
+			}
+
 			pfree(old_path);
 		}
 		else
@@ -895,6 +922,15 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
 	else
 	{
 		/* Reject and recycle the new path */
+		if (IsA(new_path, MergePath))
+		{
+			MergePath  *mjpath = (MergePath *) new_path;
+			list_free(mjpath->path_mergeclauses);
+			list_free(mjpath->innersortkeys);
+			list_free(mjpath->outersortkeys);
+			list_free(mjpath->jpath.path.pathkeys);
+		}
+
 		pfree(new_path);
 	}
 }
@@ -2483,15 +2519,15 @@ create_mergejoin_path(PlannerInfo *root,
 		outer_path->parallel_safe && inner_path->parallel_safe;
 	/* This is a foolish way to estimate parallel_workers, but for now... */
 	pathnode->jpath.path.parallel_workers = outer_path->parallel_workers;
-	pathnode->jpath.path.pathkeys = pathkeys;
+	pathnode->jpath.path.pathkeys = list_copy(pathkeys);
 	pathnode->jpath.jointype = jointype;
 	pathnode->jpath.inner_unique = extra->inner_unique;
 	pathnode->jpath.outerjoinpath = outer_path;
 	pathnode->jpath.innerjoinpath = inner_path;
 	pathnode->jpath.joinrestrictinfo = restrict_clauses;
-	pathnode->path_mergeclauses = mergeclauses;
-	pathnode->outersortkeys = outersortkeys;
-	pathnode->innersortkeys = innersortkeys;
+	pathnode->path_mergeclauses = list_copy(mergeclauses);
+	pathnode->outersortkeys = list_copy(outersortkeys);
+	pathnode->innersortkeys = list_copy(innersortkeys);
 	pathnode->outer_presorted_keys = outer_presorted_keys;
 	/* pathnode->skip_mark_restore will be set by final_cost_mergejoin */
 	/* pathnode->materialize_inner will be set by final_cost_mergejoin */
-- 
2.54.0

