From 7c89d0e697f573a33938523d9cabe8f21f2771a4 Mon Sep 17 00:00:00 2001
From: "Zizhuan Liu(X-MAN)" <44973863@qq.com>
Date: Sun, 16 Aug 2026 23:02:14 +0800
Subject: [PATCH v2] proper-handling-examine_variable-RelabelType

---
 src/backend/utils/adt/selfuncs.c | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 2b4e6acf..682c8059 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -5655,6 +5655,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 	Relids		varnos;
 	Relids		basevarnos;
 	RelOptInfo *onerel;
+	Node	   *save_node; 
 
 	/* Make sure we don't return dangling pointers in vardata */
 	MemSet(vardata, 0, sizeof(VariableStatData));
@@ -5672,12 +5673,23 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 	basenode = strip_all_phvs_deep(root, node);
 
 	/*
-	 * Look inside any binary-compatible relabeling.  We need to handle nested
-	 * RelabelType nodes here, because the prior stripping of PlaceHolderVars
-	 * may have brought separate RelabelTypes into adjacency.
+	 * eval_const_expressions() should already have stripped adjacent
+	 * RelabelTypes. However, stripping PlaceHolderVars above may have
+	 * brought previously separated RelabelTypes into adjacency, whether
+	 * at the top level or within a deeper subtree. Therefore, run
+	 * eval_const_expressions() again to normalize the expression.
+	 *
+	 * If the leading RelabelType and its underlying argument have the same
+	 * type, typmod, and collation, and the underlying argument is a base Var,
+	 * applyRelabelType() will reduce the RelabelType chain to that base Var.
+	 * Thus, the resulting expression is equivalent to a plain base Var.
+	 *
+	 * Keep the stripped result in save_node rather than modifying the
+	 * original node. The result is used to compare against indexprs and
+	 * extended-statistics expressions, which are also processed by
+	 * eval_const_expressions() and compared using equal().
 	 */
-	while (IsA(basenode, RelabelType))
-		basenode = (Node *) ((RelabelType *) basenode)->arg;
+	save_node = basenode = eval_const_expressions(root, basenode);
 
 	/* Fast path for a simple Var */
 	if (IsA(basenode, Var) &&
@@ -5798,9 +5810,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 					if (indexpr_item == NULL)
 						elog(ERROR, "too few entries in indexprs list");
 					indexkey = (Node *) lfirst(indexpr_item);
-					if (indexkey && IsA(indexkey, RelabelType))
-						indexkey = (Node *) ((RelabelType *) indexkey)->arg;
-					if (equal(node, indexkey))
+					if (equal(save_node, indexkey))
 					{
 						/*
 						 * Found a match ... is it a unique index? Tests here
@@ -5924,12 +5934,8 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
 
 				Assert(expr);
 
-				/* strip RelabelType before comparing it */
-				if (expr && IsA(expr, RelabelType))
-					expr = (Node *) ((RelabelType *) expr)->arg;
-
 				/* found a match, see if we can extract pg_statistic row */
-				if (equal(node, expr))
+				if (equal(save_node, expr))
 				{
 					/*
 					 * XXX Not sure if we should cache the tuple somewhere.
-- 
2.43.0

