This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git

commit 8e79827c98ee7d11acee46cde67d6380ed68162b
Author: morrySnow <[email protected]>
AuthorDate: Wed Sep 16 23:39:51 2026 +0800

    branch-4.1: [fix](variable) Track user variables in SQL cache during 
binding #67787 (#68069)
    
    ### What problem does this PR solve?
    
    Related PR: #67787
    
    Problem Summary:
    
    Backport the user-variable SQL cache dependency fix to branch-4.1. User
    variables are now recorded while binding `UnboundVariable`, before
    function binding unwraps them to their real expressions. This prevents
    expressions such as `ABS(@v)` from reusing a stale cached result after
    the variable changes.
    
    The obsolete late `VariableToLiteral` / `ReplaceVariableByLiteral` path
    is removed, and the generated-column variable check is performed on the
    parsed expression so variables nested inside functions remain rejected.
    The unit test is adapted to the Java `Optional` API used by branch-4.1.
    
    ### Release note
    
    None
    
    ### Check List (For Author)
    
    - Test
        - [x] Unit Test
        - [x] Regression test coverage included
    - Behavior changed:
        - [x] No.
    - Does this need documentation?
        - [x] No.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 .../doris/nereids/jobs/executor/Analyzer.java      | 12 ---
 .../nereids/rules/analysis/ExpressionAnalyzer.java |  7 +-
 .../nereids/rules/analysis/VariableToLiteral.java  | 40 ----------
 .../rules/expression/ExpressionRuleType.java       |  1 -
 .../expression/rules/ReplaceVariableByLiteral.java | 53 -------------
 .../expressions/functions/ExpressionTrait.java     | 29 +-------
 .../trees/plans/commands/info/CreateTableInfo.java |  8 +-
 .../apache/doris/nereids/util/ExpressionUtils.java |  9 +--
 .../rules/analysis/UserVariableAnalysisTest.java   | 29 ++++++++
 .../expressions/functions/ExpressionTraitTest.java | 86 ----------------------
 .../fault_tolerance_nereids.groovy                 | 12 ++-
 .../cache/parse_sql_from_sql_cache.groovy          | 23 ++++++
 12 files changed, 76 insertions(+), 233 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java
index 358e9faeb06..1f83b242cf8 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java
@@ -50,7 +50,6 @@ import 
org.apache.doris.nereids.rules.analysis.ProjectWithDistinctToAggregate;
 import org.apache.doris.nereids.rules.analysis.QualifyToFilter;
 import org.apache.doris.nereids.rules.analysis.ReplaceExpressionByChildOutput;
 import org.apache.doris.nereids.rules.analysis.SubqueryToApply;
-import org.apache.doris.nereids.rules.analysis.VariableToLiteral;
 import org.apache.doris.nereids.rules.rewrite.AdjustNullable;
 import org.apache.doris.nereids.rules.rewrite.MergeFilters;
 import org.apache.doris.nereids.rules.rewrite.SemiJoinCommute;
@@ -167,17 +166,6 @@ public class Analyzer extends AbstractBatchJobExecutor {
                     // LogicalProject for normalize. This rule depends on 
FillUpMissingSlots to fill up slots.
                     new NormalizeRepeat()
             ),
-            // consider sql with user defined var @t_zone
-            // set @t_zone='GMT';
-            // SELECT
-            //     DATE_FORMAT(convert_tz(dt, time_zone, @t_zone),'%Y-%m-%d') 
day
-            // FROM
-            //     t
-            // GROUP BY
-            //     1;
-            // @t_zone must be replaced as 'GMT' before 
EliminateGroupByConstant and NormalizeAggregate rule.
-            // So need run VariableToLiteral rule before the two rules.
-            topDown(new VariableToLiteral()),
             // run CheckSearchUsage before CheckAnalysis to detect search() in 
GROUP BY before it gets optimized
             bottomUp(new CheckSearchUsage()),
             // run CheckAnalysis before EliminateGroupByConstant in order to 
report error message correctly like bellow
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java
index 14203c9792e..8a3eade3f20 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java
@@ -217,7 +217,12 @@ public class ExpressionAnalyzer extends 
SubExprAnalyzer<ExpressionRewriteContext
      * 
********************************************************************************************
 */
     @Override
     public Expression visitUnboundVariable(UnboundVariable unboundVariable, 
ExpressionRewriteContext context) {
-        return resolveUnboundVariable(unboundVariable);
+        Variable variable = resolveUnboundVariable(unboundVariable);
+        if (wantToParseSqlFromSqlCache) {
+            getCascadesContext().getStatementContext().getSqlCacheContext()
+                    .ifPresent(sqlCacheContext -> 
sqlCacheContext.addUsedVariable(variable));
+        }
+        return variable.getRealExpression();
     }
 
     /** resolveUnboundVariable */
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/VariableToLiteral.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/VariableToLiteral.java
deleted file mode 100644
index 3f9be8ed677..00000000000
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/VariableToLiteral.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.doris.nereids.rules.analysis;
-
-import org.apache.doris.nereids.rules.expression.ExpressionRewrite;
-import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
-import org.apache.doris.nereids.rules.expression.ExpressionRewriteRule;
-import org.apache.doris.nereids.rules.expression.ExpressionRuleExecutor;
-import 
org.apache.doris.nereids.rules.expression.rules.ReplaceVariableByLiteral;
-
-import com.google.common.collect.ImmutableList;
-
-import java.util.List;
-
-/**
- * replace Variable To Literal
- */
-public class VariableToLiteral extends ExpressionRewrite {
-    public static final List<ExpressionRewriteRule<ExpressionRewriteContext>> 
NORMALIZE_REWRITE_RULES =
-            ImmutableList.of(bottomUp(ReplaceVariableByLiteral.INSTANCE));
-
-    public VariableToLiteral() {
-        super(new ExpressionRuleExecutor(NORMALIZE_REWRITE_RULES));
-    }
-}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleType.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleType.java
index f311d9a2d48..7fcb6285875 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleType.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleType.java
@@ -50,7 +50,6 @@ public enum ExpressionRuleType {
     NORMALIZE_BINARY_PREDICATES,
     NULL_SAFE_EQUAL_TO_EQUAL,
     PUSH_INTO_CASE_WHEN_BRANCH,
-    REPLACE_VARIABLE_BY_LITERAL,
     SIMPLIFY_ARITHMETIC_COMPARISON,
     SIMPLIFY_ARITHMETIC,
     SIMPLIFY_CAST,
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ReplaceVariableByLiteral.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ReplaceVariableByLiteral.java
deleted file mode 100644
index e800bf790c5..00000000000
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ReplaceVariableByLiteral.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.doris.nereids.rules.expression.rules;
-
-import org.apache.doris.nereids.SqlCacheContext;
-import org.apache.doris.nereids.StatementContext;
-import org.apache.doris.nereids.rules.expression.ExpressionPatternMatcher;
-import org.apache.doris.nereids.rules.expression.ExpressionPatternRuleFactory;
-import org.apache.doris.nereids.rules.expression.ExpressionRuleType;
-import org.apache.doris.nereids.trees.expressions.Expression;
-import org.apache.doris.nereids.trees.expressions.Variable;
-
-import com.google.common.collect.ImmutableList;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * replace varaible to real expression
- */
-public class ReplaceVariableByLiteral implements ExpressionPatternRuleFactory {
-    public static ReplaceVariableByLiteral INSTANCE = new 
ReplaceVariableByLiteral();
-
-    @Override
-    public List<ExpressionPatternMatcher<? extends Expression>> buildRules() {
-        return ImmutableList.of(
-            matchesType(Variable.class).thenApply(ctx -> {
-                StatementContext statementContext = 
ctx.cascadesContext.getStatementContext();
-                Variable variable = ctx.expr;
-                Optional<SqlCacheContext> sqlCacheContext = 
statementContext.getSqlCacheContext();
-                if (sqlCacheContext.isPresent()) {
-                    sqlCacheContext.get().addUsedVariable(variable);
-                }
-                return variable.getRealExpression();
-            }).toRule(ExpressionRuleType.REPLACE_VARIABLE_BY_LITERAL)
-        );
-    }
-}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ExpressionTrait.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ExpressionTrait.java
index f382964bcaf..8740a200cd7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ExpressionTrait.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ExpressionTrait.java
@@ -21,7 +21,6 @@ import org.apache.doris.nereids.annotation.Developing;
 import org.apache.doris.nereids.exceptions.UnboundException;
 import org.apache.doris.nereids.trees.TreeNode;
 import org.apache.doris.nereids.trees.expressions.Expression;
-import org.apache.doris.nereids.trees.expressions.Variable;
 import org.apache.doris.nereids.trees.expressions.VolatileExpression;
 import org.apache.doris.nereids.types.DataType;
 
@@ -52,38 +51,14 @@ public interface ExpressionTrait extends 
TreeNode<Expression> {
      * getArguments.
      */
     default List<Expression> getArguments() {
-        boolean hasVariableArg = false;
-        for (Expression arg : children()) {
-            if (arg instanceof Variable) {
-                hasVariableArg = true;
-                break;
-            }
-        }
-        if (hasVariableArg) {
-            ImmutableList.Builder<Expression> arguments = 
ImmutableList.builder();
-            for (Expression arg : children()) {
-                if (arg instanceof Variable) {
-                    arguments.add(((Variable) arg).getRealExpression());
-                } else {
-                    arguments.add(arg);
-                }
-            }
-            return arguments.build();
-        } else {
-            return children();
-        }
+        return children();
     }
 
     /**
      * getArgument.
      */
     default Expression getArgument(int index) {
-        Expression arg = child(index);
-        if (arg instanceof Variable) {
-            return ((Variable) arg).getRealExpression();
-        } else {
-            return arg;
-        }
+        return child(index);
     }
 
     default List<DataType> getArgumentsTypes() {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
index 35d87e65279..a938729ba52 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
@@ -57,6 +57,7 @@ import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.nereids.CascadesContext;
 import org.apache.doris.nereids.analyzer.Scope;
 import org.apache.doris.nereids.analyzer.UnboundSlot;
+import org.apache.doris.nereids.analyzer.UnboundVariable;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.glue.translator.ExpressionTranslator;
 import org.apache.doris.nereids.glue.translator.PlanTranslatorContext;
@@ -67,7 +68,6 @@ import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.expressions.SlotReference;
 import org.apache.doris.nereids.trees.expressions.SubqueryExpr;
-import org.apache.doris.nereids.trees.expressions.Variable;
 import org.apache.doris.nereids.trees.expressions.functions.BoundFunction;
 import org.apache.doris.nereids.trees.expressions.functions.Udf;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.GroupingScalarFunction;
@@ -1276,6 +1276,8 @@ public class CreateTableInfo {
                 throw new AnalysisException("Generated column does not support 
subquery.");
             } else if (e instanceof Lambda) {
                 throw new AnalysisException("Generated column does not support 
lambda.");
+            } else if (e instanceof UnboundVariable) {
+                throw new AnalysisException("Generated column expression 
cannot contain variable.");
             }
         });
     }
@@ -1283,9 +1285,7 @@ public class CreateTableInfo {
     void checkExpressionInGeneratedColumn(Expression expr, ColumnDefinition 
column,
             Map<String, ColumnDefinition> nameToColumnDefinition) {
         expr.foreach(e -> {
-            if (e instanceof Variable) {
-                throw new AnalysisException("Generated column expression 
cannot contain variable.");
-            } else if (e instanceof Slot && 
nameToColumnDefinition.containsKey(((Slot) e).getName())) {
+            if (e instanceof Slot && 
nameToColumnDefinition.containsKey(((Slot) e).getName())) {
                 ColumnDefinition columnDefinition = 
nameToColumnDefinition.get(((Slot) e).getName());
                 if (columnDefinition.getAutoIncInitValue() != -1) {
                     throw new AnalysisException(
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
index 1b3f83bdcf6..6ab9695c1ca 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
@@ -28,11 +28,8 @@ import org.apache.doris.nereids.analyzer.UnboundSlot;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.properties.PhysicalProperties;
 import org.apache.doris.nereids.rules.analysis.ExpressionAnalyzer;
-import org.apache.doris.nereids.rules.expression.ExpressionRewrite;
 import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
-import org.apache.doris.nereids.rules.expression.ExpressionRuleExecutor;
 import org.apache.doris.nereids.rules.expression.rules.FoldConstantRule;
-import 
org.apache.doris.nereids.rules.expression.rules.ReplaceVariableByLiteral;
 import 
org.apache.doris.nereids.rules.expression.rules.TrySimplifyPredicateWithMarkJoinSlot;
 import org.apache.doris.nereids.trees.SuperClassId;
 import org.apache.doris.nereids.trees.TreeNode;
@@ -1456,11 +1453,7 @@ public class ExpressionUtils {
             throw new UserException(expression + " must be constant value");
         }
         ExpressionRewriteContext context = new 
ExpressionRewriteContext(cascadesContext);
-        ExpressionRuleExecutor executor = new 
ExpressionRuleExecutor(ImmutableList.of(
-                ExpressionRewrite.bottomUp(ReplaceVariableByLiteral.INSTANCE)
-        ));
-        Expression rewrittenExpression = executor.rewrite(analyzedExpr, 
context);
-        Expression foldExpression = 
FoldConstantRule.evaluate(rewrittenExpression, context);
+        Expression foldExpression = FoldConstantRule.evaluate(analyzedExpr, 
context);
         if (foldExpression instanceof Literal) {
             return (Literal) foldExpression;
         } else {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/UserVariableAnalysisTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/UserVariableAnalysisTest.java
index 2dd8ca07be5..41e549f23d5 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/UserVariableAnalysisTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/UserVariableAnalysisTest.java
@@ -21,6 +21,12 @@ import org.apache.doris.analysis.DateLiteral;
 import org.apache.doris.analysis.IntLiteral;
 import org.apache.doris.analysis.LargeIntLiteral;
 import org.apache.doris.catalog.ScalarType;
+import org.apache.doris.nereids.CascadesContext;
+import org.apache.doris.nereids.analyzer.Scope;
+import org.apache.doris.nereids.analyzer.UnboundVariable;
+import org.apache.doris.nereids.analyzer.UnboundVariable.VariableType;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.Variable;
 import org.apache.doris.nereids.trees.expressions.literal.Literal;
 import org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteral;
 import org.apache.doris.nereids.types.BigIntType;
@@ -32,9 +38,12 @@ import org.apache.doris.nereids.types.TinyIntType;
 import org.apache.doris.nereids.util.MemoTestUtils;
 import org.apache.doris.qe.ConnectContext;
 
+import com.google.common.collect.ImmutableList;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import java.util.List;
+
 /** Tests for user variable handling in expression analysis. */
 public class UserVariableAnalysisTest {
 
@@ -70,4 +79,24 @@ public class UserVariableAnalysisTest {
         Assertions.assertEquals(TimeStampTzType.of(6), literal.getDataType());
         Assertions.assertEquals("2024-11-03 05:05:00.123456+00:00", 
literal.getStringValue());
     }
+
+    @Test
+    public void 
testBindUserVariableToRealExpressionAndRecordSqlCacheDependency() {
+        ConnectContext ctx = MemoTestUtils.createConnectContext();
+        ctx.setUserVar("v", new IntLiteral(42));
+        CascadesContext cascadesContext = 
MemoTestUtils.createCascadesContext(ctx, "select @v");
+        ExpressionAnalyzer analyzer = new ExpressionAnalyzer(null, new 
Scope(ImmutableList.of()),
+                cascadesContext, false, false);
+
+        Expression analyzed = analyzer.analyze(new UnboundVariable("v", 
VariableType.USER));
+
+        Assertions.assertInstanceOf(Literal.class, analyzed);
+        List<Variable> usedVariables = 
cascadesContext.getStatementContext().getSqlCacheContext()
+                .orElseThrow(() -> new IllegalStateException("SQL cache 
context is not initialized"))
+                .getUsedVariables();
+        Assertions.assertEquals(1, usedVariables.size());
+        Assertions.assertEquals("v", usedVariables.get(0).getName());
+        Assertions.assertEquals(VariableType.USER, 
usedVariables.get(0).getType());
+        Assertions.assertEquals(analyzed, 
usedVariables.get(0).getRealExpression());
+    }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/ExpressionTraitTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/ExpressionTraitTest.java
deleted file mode 100644
index 03a36c2c927..00000000000
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/ExpressionTraitTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package org.apache.doris.nereids.trees.expressions.functions;
-
-import org.apache.doris.nereids.analyzer.UnboundVariable.VariableType;
-import org.apache.doris.nereids.trees.expressions.Expression;
-import org.apache.doris.nereids.trees.expressions.Variable;
-import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
-import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
-import org.apache.doris.nereids.types.DataType;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-/**
- * Tests for ExpressionTrait behaviors when children are `Variable`.
- */
-public class ExpressionTraitTest {
-
-    static class DummyFunction extends Expression {
-        protected DummyFunction(List<Expression> children) {
-            super(children);
-        }
-
-        protected DummyFunction(Expression... children) {
-            super(children);
-        }
-
-        @Override
-        public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
-            return null;
-        }
-
-        @Override
-        public Expression withChildren(List<Expression> children) {
-            return new DummyFunction(children);
-        }
-
-        @Override
-        protected String computeToSql() {
-            return "dummy";
-        }
-
-        @Override
-        public boolean nullable() {
-            return false;
-        }
-    }
-
-    @Test
-    public void testVariable() {
-        IntegerLiteral lit = new IntegerLiteral(42);
-        Variable var = new Variable("v", VariableType.USER, lit);
-
-        DummyFunction func = new DummyFunction(var);
-
-        List<Expression> args = func.getArguments();
-        Assertions.assertEquals(1, args.size());
-        Assertions.assertEquals(lit, args.get(0));
-
-        Assertions.assertEquals(lit, func.getArgument(0));
-
-        List<DataType> types = func.getArgumentsTypes();
-        Assertions.assertEquals(1, types.size());
-        Assertions.assertEquals(lit.getDataType(), types.get(0));
-
-        Assertions.assertEquals(lit.getDataType(), func.getArgumentType(0));
-    }
-}
diff --git 
a/regression-test/suites/ddl_p0/test_create_table_generated_column/fault_tolerance_nereids.groovy
 
b/regression-test/suites/ddl_p0/test_create_table_generated_column/fault_tolerance_nereids.groovy
index 02409621bdc..62d73edb653 100644
--- 
a/regression-test/suites/ddl_p0/test_create_table_generated_column/fault_tolerance_nereids.groovy
+++ 
b/regression-test/suites/ddl_p0/test_create_table_generated_column/fault_tolerance_nereids.groovy
@@ -68,6 +68,16 @@ suite("test_generated_column_fault_tolerance_nereids") {
         exception "Generated column expression cannot contain variable."
     }
 
+    // Variables are resolved to literals during binding, so generated columns 
must reject them before binding.
+    test {
+        sql """
+        create table test_gen_col_var_in_function(a int, c int generated 
always as (abs(@myvar)) not null)
+        DISTRIBUTED BY HASH(a)
+        PROPERTIES("replication_num" = "1");
+        """
+        exception "Generated column expression cannot contain variable."
+    }
+
     test {
         sql """
         create table test_gen_col_auto_increment(a bigint not null 
auto_increment, b int, c int as (a*b)) 
@@ -200,4 +210,4 @@ suite("test_generated_column_fault_tolerance_nereids") {
     }
 
 
-}
\ No newline at end of file
+}
diff --git 
a/regression-test/suites/nereids_p0/cache/parse_sql_from_sql_cache.groovy 
b/regression-test/suites/nereids_p0/cache/parse_sql_from_sql_cache.groovy
index 477d20dd197..72e07321f73 100644
--- a/regression-test/suites/nereids_p0/cache/parse_sql_from_sql_cache.groovy
+++ b/regression-test/suites/nereids_p0/cache/parse_sql_from_sql_cache.groovy
@@ -677,6 +677,29 @@ suite("parse_sql_from_sql_cache") {
                         def result1 = sql "select @custom_variable from 
test_use_plan_cache17 where id = 1 and value = 1"
                         assertTrue(result1.size() == 1 && 
result1[0][0].toString().toInteger() == 10)
 
+                        def functionVariableSql = "select 
abs(@custom_variable_in_function) " +
+                                "from test_use_plan_cache17 where id = 1 and 
value = 1"
+                        sql "set @custom_variable_in_function=-10"
+                        assertNoCache functionVariableSql
+                        def functionResult = sql functionVariableSql
+                        assertTrue(functionResult.size() == 1
+                                && functionResult[0][0].toString().toInteger() 
== 10)
+                        assertHasCache functionVariableSql
+
+                        sql "set @custom_variable_in_function=-20"
+                        assertNoCache functionVariableSql
+                        functionResult = sql functionVariableSql
+                        assertTrue(functionResult.size() == 1
+                                && functionResult[0][0].toString().toInteger() 
== 20)
+                        assertHasCache functionVariableSql
+
+                        // switch back to the original value and reuse its 
value-aware cache
+                        sql "set @custom_variable_in_function=-10"
+                        assertHasCache functionVariableSql
+                        functionResult = sql functionVariableSql
+                        assertTrue(functionResult.size() == 1
+                                && functionResult[0][0].toString().toInteger() 
== 10)
+
                         sql "set @custom_variable2=1"
                         assertNoCache "select * from test_use_plan_cache17 
where id = @custom_variable2 and value = 1"
                         def res = sql "select * from test_use_plan_cache17 
where id = @custom_variable2 and value = 1"


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to