From 0f57a9d6c01548c746338023ff576cbd4499041c Mon Sep 17 00:00:00 2001
From: test <test>
Date: Tue, 9 Jun 2026 00:19:24 +0200
Subject: [PATCH v2 6/6] free hashjoin keys

---
 src/backend/optimizer/path/joinpath.c |  5 +++++
 src/backend/optimizer/util/pathnode.c | 22 +++++++++++++++++++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index 9396ce4c145..d6475985c04 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -2278,7 +2278,10 @@ hash_inner_and_outer(PlannerInfo *root,
 		 */
 		if (PATH_PARAM_BY_REL(cheapest_total_outer, innerrel) ||
 			PATH_PARAM_BY_REL(cheapest_total_inner, outerrel))
+		{
+			list_free(hashclauses);
 			return;
+		}
 
 		/*
 		 * Consider the cheapest startup outer together with the cheapest
@@ -2400,6 +2403,8 @@ hash_inner_and_outer(PlannerInfo *root,
 										  false /* parallel_hash */ );
 		}
 	}
+
+	list_free(hashclauses);
 }
 
 /*
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 911f0de8c82..1d5cd429516 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -632,6 +632,11 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
 				list_free(mjpath->outersortkeys);
 				list_free(mjpath->jpath.path.pathkeys);
 			}
+			else if (IsA(old_path, HashPath))
+			{
+				HashPath  *hjpath = (HashPath *) old_path;
+				list_free(hjpath->path_hashclauses);
+			}
 			/*
 			 * Delete the data pointed-to by the deleted cell, if possible
 			 */
@@ -675,6 +680,11 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
 			list_free(mjpath->outersortkeys);
 			list_free(mjpath->jpath.path.pathkeys);
 		}
+		else if (IsA(new_path, HashPath))
+		{
+			HashPath  *hjpath = (HashPath *) new_path;
+			list_free(hjpath->path_hashclauses);
+		}
 
 		/* Reject and recycle the new path */
 		if (!IsA(new_path, IndexPath))
@@ -889,6 +899,11 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
 				list_free(mjpath->outersortkeys);
 				list_free(mjpath->jpath.path.pathkeys);
 			}
+			else if (IsA(old_path, HashPath))
+			{
+				HashPath  *hjpath = (HashPath *) old_path;
+				list_free(hjpath->path_hashclauses);
+			}
 
 			pfree(old_path);
 		}
@@ -930,6 +945,11 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
 			list_free(mjpath->outersortkeys);
 			list_free(mjpath->jpath.path.pathkeys);
 		}
+		else if (IsA(new_path, HashPath))
+		{
+			HashPath  *hjpath = (HashPath *) new_path;
+			list_free(hjpath->path_hashclauses);
+		}
 
 		pfree(new_path);
 	}
@@ -2603,7 +2623,7 @@ create_hashjoin_path(PlannerInfo *root,
 	pathnode->jpath.outerjoinpath = outer_path;
 	pathnode->jpath.innerjoinpath = inner_path;
 	pathnode->jpath.joinrestrictinfo = restrict_clauses;
-	pathnode->path_hashclauses = hashclauses;
+	pathnode->path_hashclauses = list_copy(hashclauses);
 	/* final_cost_hashjoin will fill in pathnode->num_batches */
 
 	final_cost_hashjoin(root, pathnode, workspace, extra);
-- 
2.54.0

