From 20068bdda00716da712fb3f1e554401e81924e19 Mon Sep 17 00:00:00 2001
From: "yizhi.fzh" <yizhi.fzh@alibaba-inc.com>
Date: Sun, 17 Dec 2023 21:41:34 +0800
Subject: [PATCH v2 1/1] Use MemoryContext instead of ExprContext for
 nodeMergejoin.c

MergeJoin needs to store the values in MergeJoinClause for a longer
lifespan, in the past it uses a dedicate ExprContext, however a
MemoryContext should be OK. This patch does this.
---
 src/backend/executor/nodeMergejoin.c | 29 +++++++++++++++++-----------
 src/include/nodes/execnodes.h        |  5 +++--
 2 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 3cdab77dfc..4d45305482 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -294,7 +294,7 @@ MJExamineQuals(List *mergeclauses,
 static MJEvalResult
 MJEvalOuterValues(MergeJoinState *mergestate)
 {
-	ExprContext *econtext = mergestate->mj_OuterEContext;
+	ExprContext *econtext = mergestate->js.ps.ps_ExprContext;
 	MJEvalResult result = MJEVAL_MATCHABLE;
 	int			i;
 	MemoryContext oldContext;
@@ -303,9 +303,9 @@ MJEvalOuterValues(MergeJoinState *mergestate)
 	if (TupIsNull(mergestate->mj_OuterTupleSlot))
 		return MJEVAL_ENDOFJOIN;
 
-	ResetExprContext(econtext);
+	MemoryContextReset(mergestate->mj_outerTuple_memory);
 
-	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+	oldContext = MemoryContextSwitchTo(mergestate->mj_outerTuple_memory);
 
 	econtext->ecxt_outertuple = mergestate->mj_OuterTupleSlot;
 
@@ -341,7 +341,7 @@ MJEvalOuterValues(MergeJoinState *mergestate)
 static MJEvalResult
 MJEvalInnerValues(MergeJoinState *mergestate, TupleTableSlot *innerslot)
 {
-	ExprContext *econtext = mergestate->mj_InnerEContext;
+	ExprContext *econtext = mergestate->js.ps.ps_ExprContext;
 	MJEvalResult result = MJEVAL_MATCHABLE;
 	int			i;
 	MemoryContext oldContext;
@@ -350,9 +350,9 @@ MJEvalInnerValues(MergeJoinState *mergestate, TupleTableSlot *innerslot)
 	if (TupIsNull(innerslot))
 		return MJEVAL_ENDOFJOIN;
 
-	ResetExprContext(econtext);
+	MemoryContextReset(mergestate->mj_innerTuple_memory);
 
-	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+	oldContext = MemoryContextSwitchTo(mergestate->mj_innerTuple_memory);
 
 	econtext->ecxt_innertuple = innerslot;
 
@@ -1447,6 +1447,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
 	TupleDesc	outerDesc,
 				innerDesc;
 	const TupleTableSlotOps *innerOps;
+	ExprContext *econtext;
 
 	/* check for unsupported flags */
 	Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
@@ -1471,13 +1472,19 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
 	 */
 	ExecAssignExprContext(estate, &mergestate->js.ps);
 
+	econtext = mergestate->js.ps.ps_ExprContext;
+
 	/*
-	 * we need two additional econtexts in which we can compute the join
-	 * expressions from the left and right input tuples.  The node's regular
-	 * econtext won't do because it gets reset too often.
+	 * we need two additional contexts in which we can compute the join
+	 * expressions from the left and right input tuples.  The econtext's
+	 * regular ecxt_per_tuple_memory won't do because it gets reset too often.
 	 */
-	mergestate->mj_OuterEContext = CreateExprContext(estate);
-	mergestate->mj_InnerEContext = CreateExprContext(estate);
+	mergestate->mj_outerTuple_memory = AllocSetContextCreate(econtext->ecxt_per_query_memory,
+															 "OuterTupleCtx",
+															 ALLOCSET_SMALL_SIZES);
+	mergestate->mj_innerTuple_memory = AllocSetContextCreate(econtext->ecxt_per_query_memory,
+															 "InnerTupleCtx",
+															 ALLOCSET_SMALL_SIZES);
 
 	/*
 	 * initialize child nodes
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 5d7f17dee0..e8af959c01 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -2064,8 +2064,9 @@ typedef struct MergeJoinState
 	TupleTableSlot *mj_MarkedTupleSlot;
 	TupleTableSlot *mj_NullOuterTupleSlot;
 	TupleTableSlot *mj_NullInnerTupleSlot;
-	ExprContext *mj_OuterEContext;
-	ExprContext *mj_InnerEContext;
+
+	MemoryContext mj_outerTuple_memory;
+	MemoryContext mj_innerTuple_memory;
 } MergeJoinState;
 
 /* ----------------
-- 
2.34.1

