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