You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2026/04/07 03:09:34 UTC

(doris) branch master updated: [refactor](fe) Decouple SlotRef dependencies: GlobalVariable, Column serialization, Expr visitor (#61918)

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

morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 0a3bea51271 [refactor](fe) Decouple SlotRef dependencies: GlobalVariable, Column serialization, Expr visitor (#61918)
0a3bea51271 is described below

commit 0a3bea51271893b7e7ff1233e010249856c35ce1
Author: morrySnow <zh...@selectdb.com>
AuthorDate: Tue Apr 7 11:09:26 2026 +0800

    [refactor](fe) Decouple SlotRef dependencies: GlobalVariable, Column serialization, Expr visitor (#61918)
    
    ### What problem does this PR solve?
    
    Problem Summary:
    This PR performs several refactorings to decouple FE module
    dependencies:
    
    **Part A - TableNameInfo & Configuration:**
    - Move
    `isStoredTableNamesLowerCase`/`isTableNamesCaseInsensitive`/`isTableNamesCaseSensitive`
    from `Env` to `GlobalVariable`
    - Move `GlobalVariable` from fe-core to fe-common, extract `VarAttrDef`
    annotation class
    - Remove `TableNameInfo(TableIf)` constructor and `createOrNull` —
    callers use 3-arg String constructor
    - Create `NameSpaceContext` class in fe-catalog with
    `defaultCatalog`/`currentDb`/`currentDbId`
    - Move `INTERNAL_CATALOG_NAME` to `NameSpaceContext` (deprecated
    re-export in `InternalCatalog`)
    - Change `TableNameInfo.analyze()` parameter from `ConnectContext` to
    `NameSpaceContext`
    
    **Part B - Column Serialization:**
    - Create `PatternType` enum in fe-type (replacing `TPatternType`
    dependency in `Column`)
    - Create `ColumnToThrift` to extract `Column→TColumn` conversion
    (including `setIndexFlag`)
    - Create `ColumnToProtobuf` to extract `Column→ColumnPB` conversion
    - Remove `toThrift()`, `toPb()`, and related methods from `Column`
    
    **Part C - Expr Visitor Pattern:**
    - Create `ExprToExprNameVisitor` using visitor pattern
    - Remove `Expr.getExprName()` and overrides from all subclasses
    - Update callers to use visitor directly
    
    
    Co-authored-by: Copilot <22...@users.noreply.github.com>
---
 .../apache/doris/catalog/NameSpaceContext.java}    |  36 +-
 fe/fe-common/pom.xml                               |  48 ++
 .../java/org/apache/doris/qe/GlobalVariable.java   | 107 ++-
 .../main/java/org/apache/doris/qe/VarAttrDef.java  |  87 ++
 fe/fe-core/pom.xml                                 |  30 -
 .../main/java/org/apache/doris/alter/Alter.java    |   5 +-
 .../apache/doris/alter/SchemaChangeHandler.java    |  15 +-
 .../org/apache/doris/analysis/ColumnRefExpr.java   |  12 -
 .../main/java/org/apache/doris/analysis/Expr.java  |  14 -
 .../doris/analysis/ExprToColumnLabelVisitor.java   |  51 --
 .../doris/analysis/ExprToExprNameVisitor.java      |  65 ++
 .../apache/doris/analysis/FunctionCallExpr.java    |  11 -
 .../org/apache/doris/analysis/LiteralExpr.java     |   8 -
 .../java/org/apache/doris/analysis/SlotRef.java    |   9 -
 .../org/apache/doris/analysis/VirtualSlotRef.java  |   4 -
 .../java/org/apache/doris/backup/RestoreJob.java   |   7 +-
 .../apache/doris/catalog/CatalogRecycleBin.java    |   3 +-
 .../main/java/org/apache/doris/catalog/Column.java | 310 +------
 .../org/apache/doris/catalog/ColumnToProtobuf.java | 201 +++++
 .../org/apache/doris/catalog/ColumnToThrift.java   | 173 ++++
 .../java/org/apache/doris/catalog/Database.java    |  17 +-
 .../main/java/org/apache/doris/catalog/Env.java    |  27 +-
 .../java/org/apache/doris/catalog/OlapTable.java   |  13 +-
 .../catalog/constraint/ForeignKeyConstraint.java   |   5 +-
 .../cloud/datasource/CloudInternalCatalog.java     |   3 +-
 .../apache/doris/datasource/InternalCatalog.java   |   9 +-
 .../doris/datasource/iceberg/IcebergUtils.java     |  19 +-
 .../doris/datasource/jdbc/JdbcExternalCatalog.java |   7 +-
 .../maxcompute/source/MaxComputeScanNode.java      |  10 +-
 .../paimon/source/PaimonPredicateConverter.java    |   3 +-
 .../java/org/apache/doris/info/TableNameInfo.java  |  75 +-
 .../org/apache/doris/info/TableNameInfoUtils.java  | 104 +++
 .../java/org/apache/doris/info/TableRefInfo.java   |   4 +-
 .../main/java/org/apache/doris/load/DeleteJob.java |   3 +-
 .../org/apache/doris/mtmv/MTMVPartitionUtil.java   |   9 +-
 .../java/org/apache/doris/mtmv/MTMVService.java    |  12 +-
 .../doris/mysql/privilege/TablePrivEntry.java      |   4 +-
 .../doris/nereids/minidump/MinidumpUtils.java      |   4 +-
 .../nereids/rules/rewrite/ForeignKeyContext.java   |   5 +-
 .../trees/plans/commands/AddConstraintCommand.java |   9 +-
 .../commands/AdminCancelRepairTableCommand.java    |   2 +-
 .../plans/commands/AdminCompactTableCommand.java   |   2 +-
 .../plans/commands/AdminRepairTableCommand.java    |   2 +-
 .../commands/AdminSetPartitionVersionCommand.java  |   2 +-
 .../plans/commands/AdminSetTableStatusCommand.java |   2 +-
 .../plans/commands/AlterColumnStatsCommand.java    |   2 +-
 .../trees/plans/commands/AlterTableCommand.java    |   2 +-
 .../plans/commands/AlterTableStatsCommand.java     |   2 +-
 .../trees/plans/commands/AnalyzeTableCommand.java  |   2 +-
 .../plans/commands/CancelAlterTableCommand.java    |   2 +-
 .../plans/commands/CancelBuildIndexCommand.java    |   2 +-
 .../plans/commands/CleanQueryStatsCommand.java     |   2 +-
 .../trees/plans/commands/CreatePolicyCommand.java  |   2 +-
 .../trees/plans/commands/DescribeCommand.java      |   2 +-
 .../plans/commands/DropCachedStatsCommand.java     |   2 +-
 .../plans/commands/DropConstraintCommand.java      |   4 +-
 .../commands/DropMaterializedViewCommand.java      |   2 +-
 .../trees/plans/commands/DropRowPolicyCommand.java |   2 +-
 .../trees/plans/commands/DropStatsCommand.java     |   2 +-
 .../trees/plans/commands/DropStreamCommand.java    |   2 +-
 .../trees/plans/commands/DropTableCommand.java     |   2 +-
 .../trees/plans/commands/DropViewCommand.java      |   2 +-
 .../trees/plans/commands/ExecuteActionCommand.java |   2 +-
 .../trees/plans/commands/LockTablesCommand.java    |   2 +-
 .../plans/commands/RecoverPartitionCommand.java    |   2 +-
 .../trees/plans/commands/RecoverTableCommand.java  |   2 +-
 .../trees/plans/commands/ShowAnalyzeCommand.java   |   2 +-
 .../commands/ShowColumnHistogramStatsCommand.java  |   2 +-
 .../plans/commands/ShowColumnStatsCommand.java     |   2 +-
 .../trees/plans/commands/ShowColumnsCommand.java   |   2 +-
 .../plans/commands/ShowConstraintsCommand.java     |   4 +-
 .../ShowCreateMaterializedViewCommand.java         |   2 +-
 .../plans/commands/ShowCreateStreamCommand.java    |   2 +-
 .../plans/commands/ShowCreateTableCommand.java     |   2 +-
 .../plans/commands/ShowCreateViewCommand.java      |   2 +-
 .../trees/plans/commands/ShowDataCommand.java      |   2 +-
 .../trees/plans/commands/ShowDataSkewCommand.java  |   4 +-
 .../plans/commands/ShowIndexStatsCommand.java      |   2 +-
 .../plans/commands/ShowPartitionsCommand.java      |   2 +-
 .../plans/commands/ShowQueryStatsCommand.java      |   2 +-
 .../commands/ShowQueuedAnalyzeJobsCommand.java     |   2 +-
 .../commands/ShowReplicaDistributionCommand.java   |   2 +-
 .../plans/commands/ShowReplicaStatusCommand.java   |   2 +-
 .../plans/commands/ShowTableStatsCommand.java      |   2 +-
 .../commands/ShowTabletsFromTableCommand.java      |   2 +-
 .../trees/plans/commands/ShowViewCommand.java      |   4 +-
 .../trees/plans/commands/TruncateTableCommand.java |   2 +-
 .../trees/plans/commands/UnsetVariableCommand.java |   3 +-
 .../trees/plans/commands/WarmUpClusterCommand.java |   2 +-
 .../trees/plans/commands/info/AlterMTMVInfo.java   |   2 +-
 .../trees/plans/commands/info/AlterViewInfo.java   |   2 +-
 .../trees/plans/commands/info/BuildIndexOp.java    |   2 +-
 .../plans/commands/info/CancelMTMVTaskInfo.java    |   2 +-
 .../trees/plans/commands/info/CreateIndexOp.java   |   2 +-
 .../trees/plans/commands/info/CreateMTMVInfo.java  |   2 +-
 .../plans/commands/info/CreateStreamInfo.java      |   4 +-
 .../plans/commands/info/CreateTableLikeInfo.java   |   4 +-
 .../trees/plans/commands/info/CreateViewInfo.java  |   2 +-
 .../trees/plans/commands/info/DropIndexOp.java     |   2 +-
 .../trees/plans/commands/info/DropMTMVInfo.java    |   2 +-
 .../trees/plans/commands/info/LabelNameInfo.java   |   4 +-
 .../trees/plans/commands/info/PauseMTMVInfo.java   |   2 +-
 .../trees/plans/commands/info/RefreshMTMVInfo.java |   2 +-
 .../trees/plans/commands/info/ResumeMTMVInfo.java  |   2 +-
 .../plans/commands/info/ShowCreateMTMVInfo.java    |   2 +-
 .../commands/refresh/RefreshTableCommand.java      |   2 +-
 .../plans/logical/LogicalCatalogRelation.java      |   3 +-
 .../plans/physical/PhysicalCatalogRelation.java    |   3 +-
 .../apache/doris/nereids/types/VariantField.java   |  20 +-
 .../apache/doris/persist/GlobalVarPersistInfo.java |   8 +-
 .../apache/doris/planner/MaterializationNode.java  |   3 +-
 .../org/apache/doris/planner/OlapScanNode.java     |   5 +-
 .../org/apache/doris/planner/OlapTableSink.java    |   5 +-
 .../org/apache/doris/planner/TVFTableSink.java     |   3 +-
 .../java/org/apache/doris/qe/ConnectContext.java   |   5 +
 .../java/org/apache/doris/qe/SessionVariable.java  | 936 ++++++++++-----------
 .../main/java/org/apache/doris/qe/VariableMgr.java |  96 +--
 .../apache/doris/statistics/AnalysisManager.java   |   5 +-
 .../doris/statistics/StatisticsJobAppender.java    |   9 +-
 .../apache/doris/task/AlterInvertedIndexTask.java  |   3 +-
 .../org/apache/doris/task/AlterReplicaTask.java    |   3 +-
 .../org/apache/doris/task/CreateReplicaTask.java   |   3 +-
 .../apache/doris/info/TableNameInfoUtilsTest.java  | 181 ++++
 .../doris/nereids/trees/plans/ConstraintTest.java  |  37 +-
 .../trees/plans/CreateTableCommandTest.java        |  21 +-
 .../org/apache/doris/qe/SessionVariablesTest.java  |   2 +-
 .../org/apache/doris/catalog/PatternType.java}     |  31 +-
 .../org/apache/doris/catalog/VariantField.java     |  11 +-
 gensrc/script/Makefile                             |   2 +-
 gensrc/script/gen_build_version.sh                 |   4 +-
 130 files changed, 1735 insertions(+), 1349 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/VirtualSlotRef.java b/fe/fe-catalog/src/main/java/org/apache/doris/catalog/NameSpaceContext.java
similarity index 51%
copy from fe/fe-core/src/main/java/org/apache/doris/analysis/VirtualSlotRef.java
copy to fe/fe-catalog/src/main/java/org/apache/doris/catalog/NameSpaceContext.java
index e31bef9ca6f..0e39bd05ae9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/VirtualSlotRef.java
+++ b/fe/fe-catalog/src/main/java/org/apache/doris/catalog/NameSpaceContext.java
@@ -15,32 +15,34 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.analysis;
-
-import java.util.Map;
-import java.util.Set;
+package org.apache.doris.catalog;
 
 /**
- * It like a SlotRef except that it is not a real column exist in table.
+ * NameSpaceContext provides catalog/database context for name resolution.
+ * Used to decouple name analysis from ConnectContext.
  */
-@Deprecated
-public class VirtualSlotRef extends SlotRef {
+public class NameSpaceContext {
+    public static final String INTERNAL_CATALOG_NAME = "internal";
+
+    private final String defaultCatalog;
+    private final String currentDb;
+    private final long currentDbId;
 
-    protected VirtualSlotRef(VirtualSlotRef other) {
-        super(other);
+    public NameSpaceContext(String defaultCatalog, String currentDb, long currentDbId) {
+        this.defaultCatalog = defaultCatalog;
+        this.currentDb = currentDb;
+        this.currentDbId = currentDbId;
     }
 
-    @Override
-    public void getTableIdToColumnNames(Map<Long, Set<String>> tableIdToColumnNames) {
+    public String getDefaultCatalog() {
+        return defaultCatalog;
     }
 
-    @Override
-    public Expr clone() {
-        return new VirtualSlotRef(this);
+    public String getCurrentDb() {
+        return currentDb;
     }
 
-    @Override
-    public String getExprName() {
-        return super.getExprName();
+    public long getCurrentDbId() {
+        return currentDbId;
     }
 }
diff --git a/fe/fe-common/pom.xml b/fe/fe-common/pom.xml
index 216e49c6b0b..8c2282d418c 100644
--- a/fe/fe-common/pom.xml
+++ b/fe/fe-common/pom.xml
@@ -134,6 +134,54 @@ under the License.
         <finalName>doris-fe-common</finalName>
         <directory>${project.basedir}/target/</directory>
         <plugins>
+            <!-- run make to generate Version and builtin -->
+            <!-- also parse the proto for FE -->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <version>3.1.0</version>
+                <executions>
+                    <execution>
+                        <id>gensrc</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <environmentVariables>
+                                <DORIS_HOME>${doris.home}</DORIS_HOME>
+                            </environmentVariables>
+                            <environmentScript>${doris.home}/env.sh</environmentScript>
+                            <executable>make</executable>
+                            <arguments>
+                                <argument>-C</argument>
+                                <argument>${doris.home}/gensrc/script</argument>
+                            </arguments>
+                            <skip>${skip.plugin}</skip>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <!-- add generated Version.java as source -->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>3.2.0</version>
+                <executions>
+                    <execution>
+                        <id>add-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>${basedir}/target/generated-sources/build/</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
             <!--antlr-->
             <plugin>
                 <groupId>org.antlr</groupId>
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/GlobalVariable.java b/fe/fe-common/src/main/java/org/apache/doris/qe/GlobalVariable.java
similarity index 77%
rename from fe/fe-core/src/main/java/org/apache/doris/qe/GlobalVariable.java
rename to fe/fe-common/src/main/java/org/apache/doris/qe/GlobalVariable.java
index 3eb035bf747..d2ba60eb13e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/GlobalVariable.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/qe/GlobalVariable.java
@@ -19,14 +19,13 @@ package org.apache.doris.qe;
 
 import org.apache.doris.common.Config;
 import org.apache.doris.common.Version;
-import org.apache.doris.common.util.TimeUtils;
 
 import com.google.common.collect.Lists;
 
 import java.lang.reflect.Field;
 import java.util.List;
 
-// You can place your global variable in this class with public and VariableMgr.VarAttr annotation.
+// You can place your global variable in this class with public and VarAttrDef.VarAttr annotation.
 // You can get this variable from MySQL client with statement `SELECT @@variable_name`,
 // and change its value through `SET variable_name = xxx`
 // NOTE: If you want access your variable safe, please hold VariableMgr's lock before access.
@@ -92,60 +91,80 @@ public final class GlobalVariable {
     public static final String ENABLE_NEW_TYPE_COERCION_BEHAVIOR
             = "enable_new_type_coercion_behavior";
 
-    @VariableMgr.VarAttr(name = VARIABLE_VERSION, flag = VariableMgr.INVISIBLE
-            | VariableMgr.READ_ONLY | VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = VARIABLE_VERSION, flag = VarAttrDef.INVISIBLE
+            | VarAttrDef.READ_ONLY | VarAttrDef.GLOBAL)
     public static int variableVersion = CURRENT_VARIABLE_VERSION;
 
-    @VariableMgr.VarAttr(name = VERSION_COMMENT, flag = VariableMgr.READ_ONLY)
+    @VarAttrDef.VarAttr(name = VERSION_COMMENT, flag = VarAttrDef.READ_ONLY)
     public static String versionComment = Version.DORIS_BUILD_VERSION_PREFIX + " version "
             + Version.DORIS_BUILD_VERSION + "-" + Version.DORIS_BUILD_SHORT_HASH
             + (Config.isCloudMode() ? " (Cloud Mode)" : "");
 
-    @VariableMgr.VarAttr(name = VERSION)
+    @VarAttrDef.VarAttr(name = VERSION)
     public static String version = DEFAULT_SERVER_VERSION;
 
     // 0: table names are stored as specified and comparisons are case sensitive.
     // 1: table names are stored in lowercase on disk and comparisons are not case sensitive.
     // 2: table names are stored as given but compared in lowercase.
-    @VariableMgr.VarAttr(name = LOWER_CASE_TABLE_NAMES, flag = VariableMgr.READ_ONLY | VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = LOWER_CASE_TABLE_NAMES, flag = VarAttrDef.READ_ONLY | VarAttrDef.GLOBAL)
     public static int lowerCaseTableNames = 0;
 
-    @VariableMgr.VarAttr(name = LICENSE, flag = VariableMgr.READ_ONLY)
+    @VarAttrDef.VarAttr(name = LICENSE, flag = VarAttrDef.READ_ONLY)
     public static String license = "Apache License, Version 2.0";
 
-    @VariableMgr.VarAttr(name = LANGUAGE, flag = VariableMgr.READ_ONLY)
+    @VarAttrDef.VarAttr(name = LANGUAGE, flag = VarAttrDef.READ_ONLY)
     public static String language = "/palo/share/english/";
 
     // A string to be executed by the server for each client that connects
-    @VariableMgr.VarAttr(name = INIT_CONNECT, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = INIT_CONNECT, flag = VarAttrDef.GLOBAL)
     public static volatile String initConnect = "";
 
+    // Timezone alias map — must be initialized before systemTimeZone field below
+    private static final java.util.Map<String, String> TIMEZONE_ALIAS_MAP = buildTimezoneAliasMap();
+
+    private static java.util.Map<String, String> buildTimezoneAliasMap() {
+        java.util.Map<String, String> map = new java.util.TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        map.putAll(java.time.ZoneId.SHORT_IDS);
+        map.put("CST", "Asia/Shanghai");
+        map.put("PRC", "Asia/Shanghai");
+        map.put("UTC", "UTC");
+        map.put("GMT", "UTC");
+        return java.util.Collections.unmodifiableMap(map);
+    }
+
     // A string to be executed by the server for each client that connects
-    @VariableMgr.VarAttr(name = SYSTEM_TIME_ZONE, flag = VariableMgr.READ_ONLY)
-    public static String systemTimeZone = TimeUtils.getSystemTimeZone().getID();
+    @VarAttrDef.VarAttr(name = SYSTEM_TIME_ZONE, flag = VarAttrDef.READ_ONLY)
+    public static String systemTimeZone = resolveSystemTimeZone();
+
+    private static String resolveSystemTimeZone() {
+        // Replicate TimeUtils.getSystemTimeZone().getID() exactly:
+        // resolve through alias map, then normalize via TimeZone to get canonical ID
+        String id = java.util.TimeZone.getDefault().getID();
+        return java.util.TimeZone.getTimeZone(java.time.ZoneId.of(id, TIMEZONE_ALIAS_MAP)).getID();
+    }
 
     // The amount of memory allocated for caching query results
-    @VariableMgr.VarAttr(name = QUERY_CACHE_SIZE, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = QUERY_CACHE_SIZE, flag = VarAttrDef.GLOBAL)
     public static volatile long queryCacheSize = 1048576;
 
-    @VariableMgr.VarAttr(name = DEFAULT_ROWSET_TYPE, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = DEFAULT_ROWSET_TYPE, flag = VarAttrDef.GLOBAL)
     public static volatile String defaultRowsetType = "beta";
 
     // add performance schema to support MYSQL JDBC 8.0.16 or later versions.
-    @VariableMgr.VarAttr(name = PERFORMANCE_SCHEMA, flag = VariableMgr.READ_ONLY)
+    @VarAttrDef.VarAttr(name = PERFORMANCE_SCHEMA, flag = VarAttrDef.READ_ONLY)
     public static String performanceSchema = "OFF";
 
-    @VariableMgr.VarAttr(name = DEFAULT_PASSWORD_LIFETIME, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = DEFAULT_PASSWORD_LIFETIME, flag = VarAttrDef.GLOBAL)
     public static int defaultPasswordLifetime = 0;
 
-    @VariableMgr.VarAttr(name = PASSWORD_HISTORY, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = PASSWORD_HISTORY, flag = VarAttrDef.GLOBAL)
     public static int passwordHistory = 0;
     // 0: DISABLED
     // 2: STRONG
-    @VariableMgr.VarAttr(name = VALIDATE_PASSWORD_POLICY, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = VALIDATE_PASSWORD_POLICY, flag = VarAttrDef.GLOBAL)
     public static long validatePasswordPolicy = 0;
 
-    @VariableMgr.VarAttr(name = VALIDATE_PASSWORD_DICTIONARY_FILE, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = VALIDATE_PASSWORD_DICTIONARY_FILE, flag = VarAttrDef.GLOBAL,
             description = {"密码验证字典文件路径。文件为纯文本格式,每行一个词。"
                     + "当 validate_password_policy 为 STRONG(2) 时,密码中不能包含字典中的任何词(不区分大小写)。"
                     + "如果为空,则使用内置字典。",
@@ -159,25 +178,25 @@ public final class GlobalVariable {
     // If set to true, the db name of TABLE_SCHEMA column in tables in information_schema
     // database will be shown as `ctl.db`. Otherwise, show only `db`.
     // This is used to compatible with some MySQL tools.
-    @VariableMgr.VarAttr(name = SHOW_FULL_DBNAME_IN_INFO_SCHEMA_DB, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = SHOW_FULL_DBNAME_IN_INFO_SCHEMA_DB, flag = VarAttrDef.GLOBAL)
     public static boolean showFullDbNameInInfoSchemaDb = false;
 
-    @VariableMgr.VarAttr(name = SQL_CONVERTER_SERVICE_URL, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = SQL_CONVERTER_SERVICE_URL, flag = VarAttrDef.GLOBAL)
     public static String sqlConverterServiceUrl = "";
 
-    @VariableMgr.VarAttr(name = ENABLE_AUDIT_PLUGIN, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = ENABLE_AUDIT_PLUGIN, flag = VarAttrDef.GLOBAL)
     public static boolean enableAuditLoader = true;
 
-    @VariableMgr.VarAttr(name = AUDIT_PLUGIN_MAX_BATCH_BYTES, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = AUDIT_PLUGIN_MAX_BATCH_BYTES, flag = VarAttrDef.GLOBAL)
     public static long auditPluginMaxBatchBytes = 50 * 1024 * 1024;
 
-    @VariableMgr.VarAttr(name = AUDIT_PLUGIN_MAX_BATCH_INTERVAL_SEC, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = AUDIT_PLUGIN_MAX_BATCH_INTERVAL_SEC, flag = VarAttrDef.GLOBAL)
     public static long auditPluginMaxBatchInternalSec = 60;
 
-    @VariableMgr.VarAttr(name = AUDIT_PLUGIN_MAX_SQL_LENGTH, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = AUDIT_PLUGIN_MAX_SQL_LENGTH, flag = VarAttrDef.GLOBAL)
     public static int auditPluginMaxSqlLength = 2097152;
 
-    @VariableMgr.VarAttr(name = AUDIT_PLUGIN_MAX_INSERT_STMT_LENGTH, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = AUDIT_PLUGIN_MAX_INSERT_STMT_LENGTH, flag = VarAttrDef.GLOBAL,
             description = {"专门用于限制 INSERT 语句的长度。如果该值大于 AUDIT_PLUGIN_MAX_SQL_LENGTH,"
                     + "则使用 AUDIT_PLUGIN_MAX_SQL_LENGTH 的值。"
                     + "如果 INSERT 语句超过该长度,将会被截断。",
@@ -187,10 +206,10 @@ public final class GlobalVariable {
                             + "If an INSERT statement exceeds this length, it will be truncated."})
     public static int auditPluginMaxInsertStmtLength = Integer.MAX_VALUE;
 
-    @VariableMgr.VarAttr(name = AUDIT_PLUGIN_LOAD_TIMEOUT, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = AUDIT_PLUGIN_LOAD_TIMEOUT, flag = VarAttrDef.GLOBAL)
     public static int auditPluginLoadTimeoutS = 600;
 
-    @VariableMgr.VarAttr(name = ENABLE_GET_ROW_COUNT_FROM_FILE_LIST, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = ENABLE_GET_ROW_COUNT_FROM_FILE_LIST, flag = VarAttrDef.GLOBAL,
             description = {
                     "针对外表,是否允许根据文件列表估算表行数。获取文件列表可能是一个耗时的操作,"
                             + "如果不需要估算表行数或者对性能有影响,可以关闭该功能。",
@@ -200,36 +219,36 @@ public final class GlobalVariable {
                             + "or it affects performance, you can disable this feature."})
     public static boolean enable_get_row_count_from_file_list = true;
 
-    @VariableMgr.VarAttr(name = READ_ONLY, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = READ_ONLY, flag = VarAttrDef.GLOBAL,
             description = {"仅用于兼容 MySQL 生态,暂无实际意义",
                     "Only for compatibility with MySQL ecosystem, no practical meaning"})
     public static boolean read_only = true;
 
-    @VariableMgr.VarAttr(name = SUPER_READ_ONLY, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = SUPER_READ_ONLY, flag = VarAttrDef.GLOBAL,
             description = {"仅用于兼容 MySQL 生态,暂无实际意义",
                     "Only for compatibility with MySQL ecosystem, no practical meaning"})
     public static boolean super_read_only = true;
 
-    @VariableMgr.VarAttr(name = PARTITION_ANALYZE_BATCH_SIZE, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = PARTITION_ANALYZE_BATCH_SIZE, flag = VarAttrDef.GLOBAL,
             description = {
                 "批量收集分区信息的分区数",
                 "Number of partitions to collect in one batch."})
     public static int partitionAnalyzeBatchSize = 10;
 
-    @VariableMgr.VarAttr(name = HUGE_PARTITION_LOWER_BOUND_ROWS, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = HUGE_PARTITION_LOWER_BOUND_ROWS, flag = VarAttrDef.GLOBAL,
             description = {
                 "行数超过该值的分区将跳过自动分区收集",
                 "This defines the lower size bound for large partitions, which will skip auto partition analyze."})
     public static long hugePartitionLowerBoundRows = 100000000L;
 
-    @VariableMgr.VarAttr(name = ENABLE_FETCH_ICEBERG_STATS, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = ENABLE_FETCH_ICEBERG_STATS, flag = VarAttrDef.GLOBAL,
             description = {
                 "当 HMS catalog 中的 Iceberg 表没有统计信息时,是否通过 Iceberg Api 获取统计信息",
                 "Enable fetch stats for HMS Iceberg table when it's not analyzed."})
     public static boolean enableFetchIcebergStats = false;
 
 
-    @VariableMgr.VarAttr(name = ENABLE_ANSI_QUERY_ORGANIZATION_BEHAVIOR, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = ENABLE_ANSI_QUERY_ORGANIZATION_BEHAVIOR, flag = VarAttrDef.GLOBAL,
             description = {
                     "控制 query organization 的行为。当设置为 true 时使用 ANSI 的 query organization 行为,即作用于整个语句。"
                             + "当设置为 false 时,使用 Doris 历史版本的行为,"
@@ -240,7 +259,7 @@ public final class GlobalVariable {
                             + " applies to the last operand of the set operation."})
     public static boolean enable_ansi_query_organization_behavior = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_NEW_TYPE_COERCION_BEHAVIOR, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = ENABLE_NEW_TYPE_COERCION_BEHAVIOR, flag = VarAttrDef.GLOBAL,
             description = {
                     "控制隐式类型转换的行为,当设置为 true 时,使用新的行为。新行为更为合理。类型优先级从高到低为时间相关类型 > "
                             + "数值类型 > 复杂类型 / JSON 类型 / IP 类型 > 字符串类型 > VARIANT 类型。当两个或多个不同类型的表达式"
@@ -258,7 +277,7 @@ public final class GlobalVariable {
                             + " a numeric type and precision cannot be determined, the DECIMAL type is preferred."})
     public static boolean enableNewTypeCoercionBehavior = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_NESTED_NAMESPACE, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = ENABLE_NESTED_NAMESPACE, flag = VarAttrDef.GLOBAL,
             description = {
                     "是否允许访问 `ns1.ns2` 这种类型的 database。当前仅适用于 External Catalog 中映射 Database 并访问。"
                             + "不支持创建。",
@@ -275,11 +294,23 @@ public final class GlobalVariable {
     public static List<String> getPersistentGlobalVarNames() {
         List<String> varNames = Lists.newArrayList();
         for (Field field : GlobalVariable.class.getDeclaredFields()) {
-            VariableMgr.VarAttr attr = field.getAnnotation(VariableMgr.VarAttr.class);
-            if (attr != null && (attr.flag() & VariableMgr.GLOBAL) != 0) {
+            VarAttrDef.VarAttr attr = field.getAnnotation(VarAttrDef.VarAttr.class);
+            if (attr != null && (attr.flag() & VarAttrDef.GLOBAL) != 0) {
                 varNames.add(attr.name());
             }
         }
         return varNames;
     }
+
+    public static boolean isStoredTableNamesLowerCase() {
+        return lowerCaseTableNames == 1;
+    }
+
+    public static boolean isTableNamesCaseInsensitive() {
+        return lowerCaseTableNames == 2;
+    }
+
+    public static boolean isTableNamesCaseSensitive() {
+        return lowerCaseTableNames == 0;
+    }
 }
diff --git a/fe/fe-common/src/main/java/org/apache/doris/qe/VarAttrDef.java b/fe/fe-common/src/main/java/org/apache/doris/qe/VarAttrDef.java
new file mode 100644
index 00000000000..25de254eee0
--- /dev/null
+++ b/fe/fe-common/src/main/java/org/apache/doris/qe/VarAttrDef.java
@@ -0,0 +1,87 @@
+// 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.qe;
+
+import org.apache.doris.common.VariableAnnotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Variable attribute definitions for session and global variables.
+ */
+public class VarAttrDef {
+    // variable have this flag means that every session have a copy of this variable,
+    // and can modify its own variable.
+    public static final int SESSION = 1;
+    // Variables with this flag have only one instance in one process.
+    public static final int GLOBAL = 2;
+    // Variables with this flag only exist in each session.
+    public static final int SESSION_ONLY = 4;
+    // Variables with this flag can only be read.
+    public static final int READ_ONLY = 8;
+    // Variables with this flag can not be seen with `SHOW VARIABLES` statement.
+    public static final int INVISIBLE = 16;
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface VarAttr {
+        // Name in show variables and set statement;
+        String name();
+
+        String[] alias() default {};
+
+        int flag() default 0;
+
+        // TODO(zhaochun): min and max is not used.
+        String minValue() default "0";
+
+        String maxValue() default "0";
+
+        // the function name that check the VarAttr before setting it to sessionVariable
+        // only support check function: 0 argument and 0 return value, if an error occurs, throw an exception.
+        // the checker function should be: public void checker(String value), value is the input string.
+        String checker() default "";
+
+        // could specify the setter method for a variable, not depend on reflect mechanism
+        String setter() default "";
+
+        // Set to true if the variables need to be forwarded along with forward statement.
+        boolean needForward() default false;
+
+        // Set to true if this variable is fuzzy
+        boolean fuzzy() default false;
+
+        VariableAnnotation varType() default VariableAnnotation.NONE;
+
+        // description for this config item.
+        // There should be 2 elements in the array.
+        // The first element is the description in Chinese.
+        // The second element is the description in English.
+        String[] description() default {"待补充", "TODO"};
+
+        // Enum options for this config item, if it has.
+        String[] options() default {};
+
+        String convertBoolToLongMethod() default "";
+        // If the variable affects the outcome, set it to true.
+        // If this value is true, it will ignore needForward and enforce forwarding.
+        boolean affectQueryResultInPlan() default false;
+
+        boolean affectQueryResultInExecution() default false;
+    }
+}
diff --git a/fe/fe-core/pom.xml b/fe/fe-core/pom.xml
index d7fa6cfc77a..1a64a8ad238 100644
--- a/fe/fe-core/pom.xml
+++ b/fe/fe-core/pom.xml
@@ -876,35 +876,6 @@ under the License.
                     <skip>true</skip>
                 </configuration>
             </plugin>
-            <!-- run make to generate Version and builtin -->
-            <!-- also parse the proto for FE -->
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <version>3.1.0</version>
-                <executions>
-                    <execution>
-                        <id>gensrc</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>exec</goal>
-                        </goals>
-                        <configuration>
-                            <environmentVariables>
-                                <DORIS_HOME>${doris.home}</DORIS_HOME>
-                            </environmentVariables>
-                            <environmentScript>${doris.home}/env.sh</environmentScript>
-                            <executable>make</executable>
-                            <arguments>
-                                <argument>-C</argument>
-                                <argument>${doris.home}/gensrc/script</argument>
-                            </arguments>
-                            <skip>${skip.plugin}</skip>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-
             <!-- annotation processor -->
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
@@ -980,7 +951,6 @@ under the License.
                         <configuration>
                             <sources>
                                 <!-- add arbitrary num of src dirs here -->
-                                <source>${basedir}/target/generated-sources/build/</source>
                                 <source>${basedir}/target/generated-sources/</source>
                             </sources>
                         </configuration>
diff --git a/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java b/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java
index d87f77a40e2..a3f42d2eb78 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/alter/Alter.java
@@ -49,6 +49,7 @@ import org.apache.doris.datasource.ExternalTable;
 import org.apache.doris.datasource.iceberg.IcebergExternalCatalog;
 import org.apache.doris.datasource.iceberg.IcebergExternalTable;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.mtmv.BaseTableInfo;
 import org.apache.doris.nereids.trees.plans.commands.AlterSystemCommand;
 import org.apache.doris.nereids.trees.plans.commands.AlterTableCommand;
@@ -756,8 +757,8 @@ public class Alter {
         String newTblName = newTbl.getName();
 
         // Handle constraints for table replacement
-        TableNameInfo origTableInfo = new TableNameInfo(origTable);
-        TableNameInfo newTableInfo = new TableNameInfo(newTbl);
+        TableNameInfo origTableInfo = TableNameInfoUtils.fromDb(db, origTable.getName());
+        TableNameInfo newTableInfo = TableNameInfoUtils.fromDb(db, newTbl.getName());
         if (swapTable) {
             Env.getCurrentEnv().getConstraintManager().swapTableConstraints(origTableInfo, newTableInfo);
         } else {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java b/fe/fe-core/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java
index 818cd47ac82..106716c21d2 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java
@@ -24,6 +24,7 @@ import org.apache.doris.analysis.SlotRef;
 import org.apache.doris.catalog.AggregateType;
 import org.apache.doris.catalog.BinlogConfig;
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ColumnToThrift;
 import org.apache.doris.catalog.ColumnType;
 import org.apache.doris.catalog.Database;
 import org.apache.doris.catalog.DistributionInfo;
@@ -74,7 +75,7 @@ import org.apache.doris.common.util.PropertyAnalyzer;
 import org.apache.doris.common.util.TimeUtils;
 import org.apache.doris.common.util.Util;
 import org.apache.doris.datasource.InternalCatalog;
-import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.nereids.trees.plans.commands.AlterCommand;
 import org.apache.doris.nereids.trees.plans.commands.CancelAlterTableCommand;
@@ -409,7 +410,9 @@ public class SchemaChangeHandler extends AlterHandler {
         String dropColName = dropColumnOp.getColName();
 
         String constraintName = Env.getCurrentEnv().getConstraintManager()
-                .findConstraintWithColumn(new TableNameInfo(externalTable), dropColName);
+                .findConstraintWithColumn(TableNameInfoUtils.fromCatalogDb(
+                        externalTable.getDatabase().getCatalog(),
+                        externalTable.getDatabase(), externalTable), dropColName);
         if (constraintName != null) {
             throw new DdlException(String.format(
                     "Cannot drop column '%s' because it is used by constraint '%s'. "
@@ -455,7 +458,9 @@ public class SchemaChangeHandler extends AlterHandler {
         String dropColName = dropColumnOp.getColName();
 
         String constraintName = Env.getCurrentEnv().getConstraintManager()
-                .findConstraintWithColumn(new TableNameInfo(olapTable), dropColName);
+                .findConstraintWithColumn(TableNameInfoUtils.fromCatalogDb(
+                        olapTable.getDatabase().getCatalog(),
+                        olapTable.getDatabase(), olapTable), dropColName);
         if (constraintName != null) {
             throw new DdlException(String.format(
                     "Cannot drop column '%s' because it is used by constraint '%s'. "
@@ -3536,8 +3541,8 @@ public class SchemaChangeHandler extends AlterHandler {
                 MaterializedIndexMeta indexMeta = olapTable.getIndexMetaByIndexId(originIndexId);
                 List<Column> colList = indexMeta.getSchema(true);
                 for (Column col : colList) {
-                    TColumn tColumn = col.toThrift();
-                    col.setIndexFlag(tColumn, olapTable);
+                    TColumn tColumn = ColumnToThrift.toThrift(col);
+                    ColumnToThrift.setIndexFlag(tColumn, olapTable);
                 }
                 List<Index> indexList = indexMeta.getIndexes();
                 int schemaVersion = indexMeta.getSchemaVersion();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnRefExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnRefExpr.java
index 95691a02528..2b5143deb25 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnRefExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnRefExpr.java
@@ -17,10 +17,6 @@
 
 package org.apache.doris.analysis;
 
-import org.apache.doris.common.NameFormatUtils;
-
-import java.util.Optional;
-
 public class ColumnRefExpr extends Expr {
     private String columnName;
     private int columnId;
@@ -44,14 +40,6 @@ public class ColumnRefExpr extends Expr {
         return columnId;
     }
 
-    @Override
-    public String getExprName() {
-        if (!this.exprName.isPresent()) {
-            this.exprName = Optional.of(NameFormatUtils.normalizeName(getName(), DEFAULT_EXPR_NAME));
-        }
-        return this.exprName.get();
-    }
-
     public void setName(String name) {
         this.columnName = name;
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
index 46cff0a9657..1bf6552c8c9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
@@ -24,7 +24,6 @@ import org.apache.doris.catalog.AggStateType;
 import org.apache.doris.catalog.Function;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
-import org.apache.doris.common.NameFormatUtils;
 import org.apache.doris.common.TreeNode;
 
 import com.google.common.base.Joiner;
@@ -41,7 +40,6 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
 import java.util.function.Supplier;
 
@@ -64,8 +62,6 @@ public abstract class Expr extends TreeNode<Expr> implements Cloneable {
     // Cached value of IsConstant(), set during analyze() and valid if isAnalyzed_ is true.
     private Supplier<Boolean> isConstant = Suppliers.memoize(this::isConstantImpl);
 
-    protected Optional<String> exprName = Optional.empty();
-
     protected Expr() {
         super();
         type = Type.INVALID;
@@ -83,16 +79,6 @@ public abstract class Expr extends TreeNode<Expr> implements Cloneable {
     public void checkValueValid() throws AnalysisException {
     }
 
-    // Name of expr, this is used by generating column name automatically when there is no
-    // alias or is not slotRef
-    public String getExprName() {
-        if (!this.exprName.isPresent()) {
-            this.exprName = Optional.of(
-                    NameFormatUtils.normalizeName(this.getClass().getSimpleName(), DEFAULT_EXPR_NAME));
-        }
-        return this.exprName.get();
-    }
-
     public Type getType() {
         return type;
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToColumnLabelVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToColumnLabelVisitor.java
deleted file mode 100644
index 0534b50031f..00000000000
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToColumnLabelVisitor.java
+++ /dev/null
@@ -1,51 +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.analysis;
-
-/**
- * Visitor that produces the column-label string for any {@link Expr}.
- *
- * <p>For all expression types except {@link SlotRef}, the result is identical
- * to {@link ExprToSqlVisitor} (i.e. the standard SQL string).  For
- * {@link SlotRef} the result is the raw column name without table qualification
- * or backtick quoting, matching the legacy {@code SlotRef.toColumnLabel()}
- * behaviour.
- *
- * <p>Usage:
- * <pre>
- *     String label = expr.accept(ExprToColumnLabelVisitor.INSTANCE, null);
- * </pre>
- */
-public class ExprToColumnLabelVisitor extends ExprToSqlVisitor {
-
-    /** Singleton — the visitor is stateless. */
-    public static final ExprToColumnLabelVisitor INSTANCE = new ExprToColumnLabelVisitor();
-
-    private ExprToColumnLabelVisitor() {
-    }
-
-    /**
-     * For a {@link SlotRef} the column label is the raw column name only
-     * (no table prefix, no backtick quoting), matching the legacy
-     * {@code SlotRef.toColumnLabel()} override that simply returned {@code col}.
-     */
-    @Override
-    public String visitSlotRef(SlotRef expr, ToSqlParams context) {
-        return expr.getCol();
-    }
-}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToExprNameVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToExprNameVisitor.java
new file mode 100644
index 00000000000..b9ccd115bd3
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToExprNameVisitor.java
@@ -0,0 +1,65 @@
+// 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.analysis;
+
+import org.apache.doris.common.NameFormatUtils;
+
+/**
+ * Visitor that computes the "expr name" for an {@link Expr} tree.
+ *
+ * <p>The expr name is a short, normalized identifier used for column labels
+ * and other metadata — it is <b>not</b> a full SQL representation.
+ *
+ * <ul>
+ *   <li>{@link SlotRef} → raw column name</li>
+ *   <li>{@link FunctionCallExpr} → normalized function name</li>
+ *   <li>{@link ColumnRefExpr} → normalized column name</li>
+ *   <li>{@link LiteralExpr} (all subtypes) → {@code "literal"}</li>
+ *   <li>Everything else → normalized simple class name</li>
+ * </ul>
+ */
+public class ExprToExprNameVisitor extends ExprVisitor<String, Void> {
+
+    public static final ExprToExprNameVisitor INSTANCE = new ExprToExprNameVisitor();
+
+    private ExprToExprNameVisitor() {
+    }
+
+    @Override
+    public String visit(Expr expr, Void context) {
+        if (expr instanceof LiteralExpr) {
+            return "literal";
+        }
+        return NameFormatUtils.normalizeName(expr.getClass().getSimpleName(), Expr.DEFAULT_EXPR_NAME);
+    }
+
+    @Override
+    public String visitSlotRef(SlotRef expr, Void context) {
+        return expr.getCol();
+    }
+
+    @Override
+    public String visitFunctionCallExpr(FunctionCallExpr expr, Void context) {
+        return NameFormatUtils.normalizeName(expr.getFnName().getFunction(), Expr.DEFAULT_EXPR_NAME);
+    }
+
+    @Override
+    public String visitColumnRefExpr(ColumnRefExpr expr, Void context) {
+        return NameFormatUtils.normalizeName(expr.getName(), Expr.DEFAULT_EXPR_NAME);
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
index cf3b33e1d47..5a934cd6ca4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
@@ -23,7 +23,6 @@ package org.apache.doris.analysis;
 import org.apache.doris.catalog.AggregateFunction;
 import org.apache.doris.catalog.Function;
 import org.apache.doris.catalog.FunctionName;
-import org.apache.doris.common.NameFormatUtils;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Objects;
@@ -33,7 +32,6 @@ import com.google.gson.annotations.SerializedName;
 
 import java.text.StringCharacterIterator;
 import java.util.List;
-import java.util.Optional;
 
 // TODO: for aggregations, we need to unify the code paths for builtins and UDAs.
 public class FunctionCallExpr extends Expr {
@@ -100,15 +98,6 @@ public class FunctionCallExpr extends Expr {
         super();
     }
 
-    @Override
-    public String getExprName() {
-        if (!this.exprName.isPresent()) {
-            this.exprName = Optional.of(
-                    NameFormatUtils.normalizeName(this.getFnName().getFunction(), DEFAULT_EXPR_NAME));
-        }
-        return this.exprName.get();
-    }
-
     public FunctionCallExpr(String functionName, List<Expr> params, boolean nullable) {
         super();
         this.fnName = new FunctionName(functionName);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java
index bb140cdcdfd..79eda90a079 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java
@@ -27,7 +27,6 @@ import org.apache.doris.common.AnalysisException;
 import com.google.common.base.Preconditions;
 
 import java.nio.ByteBuffer;
-import java.util.Optional;
 
 public abstract class LiteralExpr extends Expr implements Comparable<LiteralExpr> {
     public LiteralExpr() {
@@ -191,11 +190,4 @@ public abstract class LiteralExpr extends Expr implements Comparable<LiteralExpr
         return getStringValue();
     }
 
-    @Override
-    public String getExprName() {
-        if (!this.exprName.isPresent()) {
-            this.exprName = Optional.of("literal");
-        }
-        return this.exprName.get();
-    }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotRef.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotRef.java
index 1e8dd5d0dea..c1baa8cdf5b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotRef.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotRef.java
@@ -32,7 +32,6 @@ import org.apache.commons.collections4.CollectionUtils;
 
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
 import java.util.TreeSet;
 
@@ -166,14 +165,6 @@ public class SlotRef extends Expr {
         return visitor.visitSlotRef(this, context);
     }
 
-    @Override
-    public String getExprName() {
-        if (!this.exprName.isPresent()) {
-            this.exprName = Optional.of(accept(ExprToColumnLabelVisitor.INSTANCE, null));
-        }
-        return this.exprName.get();
-    }
-
     @Override
     public int hashCode() {
         if (desc != null) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/VirtualSlotRef.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/VirtualSlotRef.java
index e31bef9ca6f..e33f42701f2 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/VirtualSlotRef.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/VirtualSlotRef.java
@@ -39,8 +39,4 @@ public class VirtualSlotRef extends SlotRef {
         return new VirtualSlotRef(this);
     }
 
-    @Override
-    public String getExprName() {
-        return super.getExprName();
-    }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java b/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java
index 0395378de47..9b726d337aa 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java
@@ -71,6 +71,7 @@ import org.apache.doris.nereids.trees.plans.commands.RestoreCommand;
 import org.apache.doris.persist.ColocatePersistInfo;
 import org.apache.doris.persist.gson.GsonPostProcessable;
 import org.apache.doris.persist.gson.GsonUtils;
+import org.apache.doris.qe.GlobalVariable;
 import org.apache.doris.resource.Tag;
 import org.apache.doris.task.AgentBatchTask;
 import org.apache.doris.task.AgentBoundedBatchTask;
@@ -999,7 +1000,7 @@ public class RestoreJob extends AbstractJob implements GsonPostProcessable {
                 }
                 // set restored table's new name after all 'genFileMapping'
                 String tableName = jobInfo.getAliasByOriginNameIfSet(restoreTbl.getName());
-                if (Env.isStoredTableNamesLowerCase()) {
+                if (GlobalVariable.isStoredTableNamesLowerCase()) {
                     tableName = tableName.toLowerCase();
                 }
                 if ((restoreTbl.getType() == TableType.OLAP || restoreTbl
@@ -2538,7 +2539,7 @@ public class RestoreJob extends AbstractJob implements GsonPostProcessable {
     private Status atomicReplaceOlapTables(Database db, boolean isReplay) {
         for (String tableName : jobInfo.backupOlapTableObjects.keySet()) {
             String originName = jobInfo.getAliasByOriginNameIfSet(tableName);
-            if (Env.isStoredTableNamesLowerCase()) {
+            if (GlobalVariable.isStoredTableNamesLowerCase()) {
                 originName = originName.toLowerCase();
             }
             String aliasName = tableAliasWithAtomicRestore(originName);
@@ -2620,7 +2621,7 @@ public class RestoreJob extends AbstractJob implements GsonPostProcessable {
         }
         for (BackupJobInfo.BackupViewInfo backupViewInfo : jobInfo.newBackupObjects.views) {
             String originName = jobInfo.getAliasByOriginNameIfSet(backupViewInfo.name);
-            if (Env.isStoredTableNamesLowerCase()) {
+            if (GlobalVariable.isStoredTableNamesLowerCase()) {
                 originName = originName.toLowerCase();
             }
             String aliasName = tableAliasWithAtomicRestore(originName);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/CatalogRecycleBin.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/CatalogRecycleBin.java
index e5f10c96d93..207a110d8ae 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/CatalogRecycleBin.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/CatalogRecycleBin.java
@@ -31,6 +31,7 @@ import org.apache.doris.common.util.MasterDaemon;
 import org.apache.doris.common.util.TimeUtils;
 import org.apache.doris.persist.RecoverInfo;
 import org.apache.doris.persist.gson.GsonUtils;
+import org.apache.doris.qe.GlobalVariable;
 import org.apache.doris.thrift.TStorageMedium;
 
 import com.google.common.base.Preconditions;
@@ -919,7 +920,7 @@ public class CatalogRecycleBin extends MasterDaemon implements Writable {
         table.writeLock();
         try {
             if (!Strings.isNullOrEmpty(newTableName)) {
-                if (Env.isStoredTableNamesLowerCase()) {
+                if (GlobalVariable.isStoredTableNamesLowerCase()) {
                     newTableName = newTableName.toLowerCase();
                 }
                 if (!tableName.equals(newTableName)) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
index d5d6e1559de..368394f6848 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
@@ -21,23 +21,14 @@ import org.apache.doris.analysis.DefaultValueExprDef;
 import org.apache.doris.analysis.Expr;
 import org.apache.doris.analysis.SlotRef;
 import org.apache.doris.common.CaseSensibility;
-import org.apache.doris.common.Config;
 import org.apache.doris.common.DdlException;
 import org.apache.doris.common.util.SqlUtils;
 import org.apache.doris.persist.gson.GsonPostProcessable;
-import org.apache.doris.proto.OlapFile;
-import org.apache.doris.proto.OlapFile.PatternTypePB;
-import org.apache.doris.thrift.TAggregationType;
-import org.apache.doris.thrift.TColumn;
-import org.apache.doris.thrift.TColumnType;
-import org.apache.doris.thrift.TPatternType;
-import org.apache.doris.thrift.TPrimitiveType;
 
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.gson.annotations.SerializedName;
-import com.google.protobuf.ByteString;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.LogManager;
@@ -153,7 +144,7 @@ public class Column implements GsonPostProcessable {
 
     // used for variant sub-field pattern type
     @SerializedName(value = "fpt")
-    private TPatternType fieldPatternType;
+    private PatternType fieldPatternType;
 
     // used for saving some extra information, such as timezone info of datetime column
     // Maybe deprecated if we implement real timestamp with timezone type.
@@ -545,6 +536,10 @@ public class Column implements GsonPostProcessable {
         return this.defaultValue;
     }
 
+    public String getRealDefaultValue() {
+        return realDefaultValue;
+    }
+
     public String getDefaultValueSql() {
         if (defaultValue == null) {
             return null;
@@ -592,292 +587,8 @@ public class Column implements GsonPostProcessable {
         return onUpdateDefaultValueExprDef.getSql();
     }
 
-    public TColumn toThrift() {
-        TColumn tColumn = new TColumn();
-        tColumn.setColumnName(removeNamePrefix(this.name));
-
-        TColumnType tColumnType = new TColumnType();
-        tColumnType.setType(this.getDataType().toThrift());
-        tColumnType.setLen(this.getStrLen());
-        tColumnType.setPrecision(this.getPrecision());
-        tColumnType.setScale(this.getScale());
-        tColumnType.setVariantMaxSubcolumnsCount(this.getVariantMaxSubcolumnsCount());
-        tColumnType.setVariantEnableDocMode(this.getVariantEnableDocMode());
-
-        tColumnType.setIndexLen(this.getOlapColumnIndexSize());
-
-        tColumn.setColumnType(tColumnType);
-        if (null != this.aggregationType) {
-            tColumn.setAggregationType(this.aggregationType.toThrift());
-        } else {
-            tColumn.setAggregationType(TAggregationType.NONE);
-        }
-
-        tColumn.setIsKey(this.isKey);
-        tColumn.setIsAllowNull(this.isAllowNull);
-        tColumn.setIsAutoIncrement(this.isAutoInc);
-        tColumn.setIsOnUpdateCurrentTimestamp(this.hasOnUpdateDefaultValue);
-        // keep compatibility
-        tColumn.setDefaultValue(this.realDefaultValue == null ? this.defaultValue : this.realDefaultValue);
-        tColumn.setVisible(visible);
-        toChildrenThrift(this, tColumn);
-
-        tColumn.setColUniqueId(uniqueId);
-
-        if (type.isAggStateType()) {
-            AggStateType aggState = (AggStateType) type;
-            tColumn.setAggregation(aggState.getFunctionName());
-            tColumn.setResultIsNullable(aggState.getResultIsNullable());
-            if (children != null) {
-                for (Column column : children) {
-                    tColumn.addToChildrenColumn(column.toThrift());
-                }
-            }
-            tColumn.setBeExecVersion(Config.be_exec_version);
-        }
-        tColumn.setClusterKeyId(this.clusterKeyId);
-        tColumn.setVariantEnableTypedPathsToSparse(this.getVariantEnableTypedPathsToSparse());
-        tColumn.setVariantMaxSparseColumnStatisticsSize(this.getVariantMaxSparseColumnStatisticsSize());
-        tColumn.setVariantSparseHashShardCount(this.getVariantSparseHashShardCount());
-        tColumn.setVariantEnableDocMode(this.getVariantEnableDocMode());
-        tColumn.setVariantDocMaterializationMinRows(this.getvariantDocMaterializationMinRows());
-        tColumn.setVariantDocHashShardCount(this.getVariantDocShardCount());
-        tColumn.setVariantEnableNestedGroup(this.getVariantEnableNestedGroup());
-        // ATTN:
-        // Currently, this `toThrift()` method is only used from CreateReplicaTask.
-        // And CreateReplicaTask does not need `defineExpr` field.
-        // The `defineExpr` is only used when creating `TAlterMaterializedViewParam`, which is in `AlterReplicaTask`.
-        // And when creating `TAlterMaterializedViewParam`, the `defineExpr` is certainly analyzed.
-        // If we need to use `defineExpr` and call defineExpr.treeToThrift(),
-        // make sure it is analyzed, or NPE will thrown.
-        return tColumn;
-    }
-
-    private void setChildrenTColumn(Column children, TColumn tColumn) {
-        TColumn childrenTColumn = new TColumn();
-        childrenTColumn.setColumnName(children.name);
-
-        TColumnType childrenTColumnType = new TColumnType();
-        childrenTColumnType.setType(children.getDataType().toThrift());
-        childrenTColumnType.setLen(children.getStrLen());
-        childrenTColumnType.setPrecision(children.getPrecision());
-        childrenTColumnType.setScale(children.getScale());
-        childrenTColumnType.setIndexLen(children.getOlapColumnIndexSize());
-
-        childrenTColumn.setColumnType(childrenTColumnType);
-        childrenTColumn.setIsAllowNull(children.isAllowNull());
-        // TODO: If we don't set the aggregate type for children, the type will be
-        //  considered as TAggregationType::SUM after deserializing in BE.
-        //  For now, we make children inherit the aggregate type from their parent.
-        if (tColumn.getAggregationType() != null) {
-            childrenTColumn.setAggregationType(tColumn.getAggregationType());
-        }
-        if (children.fieldPatternType != null) {
-            childrenTColumn.setPatternType(children.fieldPatternType);
-        }
-        childrenTColumn.setClusterKeyId(children.clusterKeyId);
-
-        tColumn.children_column.add(childrenTColumn);
-        toChildrenThrift(children, childrenTColumn);
-    }
-
-    private void addChildren(Column column, TColumn tColumn) {
-        if (column.getChildren() != null) {
-            List<Column> childrenColumns = column.getChildren();
-            tColumn.setChildrenColumn(new ArrayList<>());
-            for (Column c : childrenColumns) {
-                setChildrenTColumn(c, tColumn);
-            }
-        }
-    }
-
-    private void addChildren(OlapFile.ColumnPB.Builder builder) throws DdlException {
-        if (this.getChildren() != null) {
-            List<Column> childrenColumns = this.getChildren();
-            for (Column c : childrenColumns) {
-                builder.addChildrenColumns(c.toPb(Sets.newHashSet(), Lists.newArrayList()));
-            }
-        }
-    }
-
-    private void toChildrenThrift(Column column, TColumn tColumn) {
-        if (column.type.isArrayType()) {
-            Column children = column.getChildren().get(0);
-            tColumn.setChildrenColumn(new ArrayList<>());
-            setChildrenTColumn(children, tColumn);
-        } else if (column.type.isMapType()) {
-            Column k = column.getChildren().get(0);
-            Column v = column.getChildren().get(1);
-            tColumn.setChildrenColumn(new ArrayList<>());
-            setChildrenTColumn(k, tColumn);
-            setChildrenTColumn(v, tColumn);
-        } else if (column.type.isStructType()) {
-            List<Column> childrenColumns = column.getChildren();
-            tColumn.setChildrenColumn(new ArrayList<>());
-            for (Column children : childrenColumns) {
-                setChildrenTColumn(children, tColumn);
-            }
-        } else if (column.type.isVariantType()) {
-            // variant may contain predefined structured fields
-            addChildren(column, tColumn);
-        }
-    }
-
     // CLOUD_CODE_BEGIN
-    public int getFieldLengthByType(TPrimitiveType type, int stringLength) throws DdlException {
-        switch (type) {
-            case TINYINT:
-            case BOOLEAN:
-                return 1;
-            case SMALLINT:
-                return 2;
-            case INT:
-                return 4;
-            case BIGINT:
-                return 8;
-            case LARGEINT:
-                return 16;
-            case DATE:
-                return 3;
-            case DATEV2:
-                return 4;
-            case DATETIME:
-                return 8;
-            case DATETIMEV2:
-            case TIMESTAMPTZ:
-                return 8;
-            case FLOAT:
-                return 4;
-            case DOUBLE:
-                return 8;
-            case QUANTILE_STATE:
-            case BITMAP:
-                return 16;
-            case CHAR:
-                return stringLength;
-            case VARCHAR:
-            case HLL:
-            case AGG_STATE:
-                return stringLength + 2; // sizeof(OLAP_VARCHAR_MAX_LENGTH)
-            case STRING:
-                return stringLength + 4; // sizeof(OLAP_STRING_MAX_LENGTH)
-            case JSONB:
-                return stringLength + 4; // sizeof(OLAP_JSONB_MAX_LENGTH)
-            case ARRAY:
-                return 65535; // OLAP_ARRAY_MAX_LENGTH
-            case DECIMAL32:
-                return 4;
-            case DECIMAL64:
-                return 8;
-            case DECIMAL128I:
-                return 16;
-            case DECIMAL256:
-                return 32;
-            case DECIMALV2:
-                return 12; // use 12 bytes in olap engine.
-            case STRUCT:
-                return 65535;
-            case MAP:
-                return 65535;
-            case IPV4:
-                return 4;
-            case IPV6:
-                return 16;
-            case VARIANT:
-                return stringLength + 4; // sizeof(OLAP_STRING_MAX_LENGTH)
-            default:
-                LOG.warn("unknown field type. [type= << {} << ]", type);
-                throw new DdlException("unknown field type. type: " + type);
-        }
-    }
-
-    public OlapFile.ColumnPB toPb(Set<String> bfColumns, List<Index> indexes) throws DdlException {
-        OlapFile.ColumnPB.Builder builder = OlapFile.ColumnPB.newBuilder();
 
-        // when doing schema change, some modified column has a prefix in name.
-        // this prefix is only used in FE, not visible to BE, so we should remove this prefix.
-        builder.setName(name.startsWith(SHADOW_NAME_PREFIX)
-                ? name.substring(SHADOW_NAME_PREFIX.length()) : name);
-
-        builder.setUniqueId(uniqueId);
-        builder.setType(this.getDataType().toThrift().name());
-        builder.setIsKey(this.isKey);
-        if (fieldPatternType != null) {
-            if (fieldPatternType == TPatternType.MATCH_NAME) {
-                builder.setPatternType(PatternTypePB.MATCH_NAME);
-            } else {
-                builder.setPatternType(PatternTypePB.MATCH_NAME_GLOB);
-            }
-        }
-        if (null != this.aggregationType) {
-            if (type.isAggStateType()) {
-                AggStateType aggState = (AggStateType) type;
-                builder.setAggregation(aggState.getFunctionName());
-                builder.setResultIsNullable(aggState.getResultIsNullable());
-                builder.setBeExecVersion(Config.be_exec_version);
-                if (children != null) {
-                    for (Column column : children) {
-                        builder.addChildrenColumns(column.toPb(Sets.newHashSet(), Lists.newArrayList()));
-                    }
-                }
-            } else {
-                builder.setAggregation(this.aggregationType.toString());
-            }
-        } else {
-            builder.setAggregation("NONE");
-        }
-        builder.setIsNullable(this.isAllowNull);
-        if (this.defaultValue != null) {
-            builder.setDefaultValue(ByteString.copyFrom(this.defaultValue.getBytes()));
-        }
-        builder.setPrecision(this.getPrecision());
-        builder.setFrac(this.getScale());
-
-        int length = getFieldLengthByType(this.getDataType().toThrift(), this.getStrLen());
-
-        builder.setLength(length);
-        builder.setIndexLength(length);
-        if (this.getDataType().toThrift() == TPrimitiveType.VARCHAR
-                || this.getDataType().toThrift() == TPrimitiveType.STRING) {
-            builder.setIndexLength(this.getOlapColumnIndexSize());
-        }
-
-        if (bfColumns != null && bfColumns.contains(this.name)) {
-            builder.setIsBfColumn(true);
-        } else {
-            builder.setIsBfColumn(false);
-        }
-        builder.setVisible(visible);
-
-        if (this.type.isArrayType()) {
-            Column child = this.getChildren().get(0);
-            builder.addChildrenColumns(child.toPb(Sets.newHashSet(), Lists.newArrayList()));
-        } else if (this.type.isMapType()) {
-            Column k = this.getChildren().get(0);
-            builder.addChildrenColumns(k.toPb(Sets.newHashSet(), Lists.newArrayList()));
-            Column v = this.getChildren().get(1);
-            builder.addChildrenColumns(v.toPb(Sets.newHashSet(), Lists.newArrayList()));
-        } else if (this.type.isStructType()) {
-            List<Column> childrenColumns = this.getChildren();
-            for (Column c : childrenColumns) {
-                builder.addChildrenColumns(c.toPb(Sets.newHashSet(), Lists.newArrayList()));
-            }
-        } else if (this.type.isVariantType()) {
-            builder.setVariantMaxSubcolumnsCount(this.getVariantMaxSubcolumnsCount());
-            builder.setVariantEnableTypedPathsToSparse(this.getVariantEnableTypedPathsToSparse());
-            builder.setVariantMaxSparseColumnStatisticsSize(this.getVariantMaxSparseColumnStatisticsSize());
-            builder.setVariantSparseHashShardCount(this.getVariantSparseHashShardCount());
-            builder.setVariantEnableDocMode(this.getVariantEnableDocMode());
-            builder.setVariantDocMaterializationMinRows(this.getvariantDocMaterializationMinRows());
-            builder.setVariantDocHashShardCount(this.getVariantDocShardCount());
-            builder.setVariantEnableNestedGroup(this.getVariantEnableNestedGroup());
-            // variant may contain predefined structured fields
-            addChildren(builder);
-        }
-
-        OlapFile.ColumnPB col = builder.build();
-        return col;
-    }
     // CLOUD_CODE_END
 
     public void checkSchemaChangeAllowed(Column other) throws DdlException {
@@ -1217,13 +928,6 @@ public class Column implements GsonPostProcessable {
         return this.autoIncInitValue;
     }
 
-    public void setIndexFlag(TColumn tColumn, OlapTable olapTable) {
-        Set<String> bfColumns = olapTable.getCopiedBfColumns();
-        if (bfColumns != null && bfColumns.contains(tColumn.getColumnName())) {
-            tColumn.setIsBloomFilterColumn(true);
-        }
-    }
-
     public boolean isCompoundKey() {
         return isCompoundKey;
     }
@@ -1325,11 +1029,11 @@ public class Column implements GsonPostProcessable {
         return type.isVariantType() ? ((ScalarType) type).getVariantEnableNestedGroup() : false;
     }
 
-    public void setFieldPatternType(TPatternType type) {
+    public void setFieldPatternType(PatternType type) {
         fieldPatternType = type;
     }
 
-    public TPatternType getFieldPatternType() {
+    public PatternType getFieldPatternType() {
         return fieldPatternType;
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnToProtobuf.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnToProtobuf.java
new file mode 100644
index 00000000000..d9c17012a64
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnToProtobuf.java
@@ -0,0 +1,201 @@
+// 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.catalog;
+
+import org.apache.doris.common.Config;
+import org.apache.doris.common.DdlException;
+import org.apache.doris.proto.OlapFile;
+import org.apache.doris.proto.OlapFile.PatternTypePB;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.protobuf.ByteString;
+
+import java.util.List;
+import java.util.Set;
+
+public class ColumnToProtobuf {
+    public static OlapFile.ColumnPB toPb(Column column, Set<String> bfColumns, List<Index> indexes)
+            throws DdlException {
+        OlapFile.ColumnPB.Builder builder = OlapFile.ColumnPB.newBuilder();
+
+        // when doing schema change, some modified column has a prefix in name.
+        // this prefix is only used in FE, not visible to BE, so we should remove this prefix.
+        String name = column.getName();
+        builder.setName(name.startsWith(Column.SHADOW_NAME_PREFIX)
+                ? name.substring(Column.SHADOW_NAME_PREFIX.length()) : name);
+
+        builder.setUniqueId(column.getUniqueId());
+        builder.setType(column.getDataType().toThrift().name());
+        builder.setIsKey(column.isKey());
+        if (column.getFieldPatternType() != null) {
+            switch (column.getFieldPatternType()) {
+                case MATCH_NAME:
+                    builder.setPatternType(PatternTypePB.MATCH_NAME);
+                    break;
+                case MATCH_NAME_GLOB:
+                    builder.setPatternType(PatternTypePB.MATCH_NAME_GLOB);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown PatternType: " + column.getFieldPatternType());
+            }
+        }
+        if (column.getAggregationType() != null) {
+            if (column.getType().isAggStateType()) {
+                AggStateType aggState = (AggStateType) column.getType();
+                builder.setAggregation(aggState.getFunctionName());
+                builder.setResultIsNullable(aggState.getResultIsNullable());
+                builder.setBeExecVersion(Config.be_exec_version);
+                if (column.getChildren() != null) {
+                    for (Column child : column.getChildren()) {
+                        builder.addChildrenColumns(toPb(child, Sets.newHashSet(), Lists.newArrayList()));
+                    }
+                }
+            } else {
+                builder.setAggregation(column.getAggregationType().toString());
+            }
+        } else {
+            builder.setAggregation("NONE");
+        }
+        builder.setIsNullable(column.isAllowNull());
+        if (column.getDefaultValue() != null) {
+            builder.setDefaultValue(ByteString.copyFrom(column.getDefaultValue().getBytes()));
+        }
+        builder.setPrecision(column.getPrecision());
+        builder.setFrac(column.getScale());
+
+        int length = getFieldLengthByType(column.getDataType(), column.getStrLen());
+
+        builder.setLength(length);
+        builder.setIndexLength(length);
+        if (column.getDataType() == PrimitiveType.VARCHAR
+                || column.getDataType() == PrimitiveType.STRING) {
+            builder.setIndexLength(column.getOlapColumnIndexSize());
+        }
+
+        if (bfColumns != null && bfColumns.contains(column.getName())) {
+            builder.setIsBfColumn(true);
+        } else {
+            builder.setIsBfColumn(false);
+        }
+        builder.setVisible(column.isVisible());
+
+        if (column.getType().isArrayType()) {
+            Column child = column.getChildren().get(0);
+            builder.addChildrenColumns(toPb(child, Sets.newHashSet(), Lists.newArrayList()));
+        } else if (column.getType().isMapType()) {
+            Column k = column.getChildren().get(0);
+            builder.addChildrenColumns(toPb(k, Sets.newHashSet(), Lists.newArrayList()));
+            Column v = column.getChildren().get(1);
+            builder.addChildrenColumns(toPb(v, Sets.newHashSet(), Lists.newArrayList()));
+        } else if (column.getType().isStructType()) {
+            List<Column> childrenColumns = column.getChildren();
+            for (Column c : childrenColumns) {
+                builder.addChildrenColumns(toPb(c, Sets.newHashSet(), Lists.newArrayList()));
+            }
+        } else if (column.getType().isVariantType()) {
+            builder.setVariantMaxSubcolumnsCount(column.getVariantMaxSubcolumnsCount());
+            builder.setVariantEnableTypedPathsToSparse(column.getVariantEnableTypedPathsToSparse());
+            builder.setVariantMaxSparseColumnStatisticsSize(column.getVariantMaxSparseColumnStatisticsSize());
+            builder.setVariantSparseHashShardCount(column.getVariantSparseHashShardCount());
+            builder.setVariantEnableDocMode(column.getVariantEnableDocMode());
+            builder.setVariantDocMaterializationMinRows(column.getvariantDocMaterializationMinRows());
+            builder.setVariantDocHashShardCount(column.getVariantDocShardCount());
+            builder.setVariantEnableNestedGroup(column.getVariantEnableNestedGroup());
+            // variant may contain predefined structured fields
+            addChildren(column, builder);
+        }
+
+        return builder.build();
+    }
+
+    public static void addChildren(Column column, OlapFile.ColumnPB.Builder builder) throws DdlException {
+        if (column.getChildren() != null) {
+            List<Column> childrenColumns = column.getChildren();
+            for (Column c : childrenColumns) {
+                builder.addChildrenColumns(toPb(c, Sets.newHashSet(), Lists.newArrayList()));
+            }
+        }
+    }
+
+    static int getFieldLengthByType(PrimitiveType type, int stringLength) throws DdlException {
+        switch (type) {
+            case TINYINT:
+            case BOOLEAN:
+                return 1;
+            case SMALLINT:
+                return 2;
+            case INT:
+                return 4;
+            case BIGINT:
+                return 8;
+            case LARGEINT:
+                return 16;
+            case DATE:
+                return 3;
+            case DATEV2:
+                return 4;
+            case DATETIME:
+                return 8;
+            case DATETIMEV2:
+            case TIMESTAMPTZ:
+                return 8;
+            case FLOAT:
+                return 4;
+            case DOUBLE:
+                return 8;
+            case QUANTILE_STATE:
+            case BITMAP:
+                return 16;
+            case CHAR:
+                return stringLength;
+            case VARCHAR:
+            case HLL:
+            case AGG_STATE:
+                return stringLength + 2; // sizeof(OLAP_VARCHAR_MAX_LENGTH)
+            case STRING:
+                return stringLength + 4; // sizeof(OLAP_STRING_MAX_LENGTH)
+            case JSONB:
+                return stringLength + 4; // sizeof(OLAP_JSONB_MAX_LENGTH)
+            case ARRAY:
+                return 65535; // OLAP_ARRAY_MAX_LENGTH
+            case DECIMAL32:
+                return 4;
+            case DECIMAL64:
+                return 8;
+            case DECIMAL128:
+                return 16;
+            case DECIMAL256:
+                return 32;
+            case DECIMALV2:
+                return 12; // use 12 bytes in olap engine.
+            case STRUCT:
+                return 65535;
+            case MAP:
+                return 65535;
+            case IPV4:
+                return 4;
+            case IPV6:
+                return 16;
+            case VARIANT:
+                return stringLength + 4; // sizeof(OLAP_STRING_MAX_LENGTH)
+            default:
+                throw new DdlException("unknown field type. type: " + type);
+        }
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnToThrift.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnToThrift.java
new file mode 100644
index 00000000000..30da804b4d3
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnToThrift.java
@@ -0,0 +1,173 @@
+// 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.catalog;
+
+import org.apache.doris.common.Config;
+import org.apache.doris.thrift.TAggregationType;
+import org.apache.doris.thrift.TColumn;
+import org.apache.doris.thrift.TColumnType;
+import org.apache.doris.thrift.TPatternType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class ColumnToThrift {
+
+    public static void setIndexFlag(TColumn tColumn, OlapTable olapTable) {
+        Set<String> bfColumns = olapTable.getCopiedBfColumns();
+        if (bfColumns != null && bfColumns.contains(tColumn.getColumnName())) {
+            tColumn.setIsBloomFilterColumn(true);
+        }
+    }
+
+    public static TColumn toThrift(Column column) {
+        TColumn tColumn = new TColumn();
+        tColumn.setColumnName(column.getNonShadowName());
+
+        TColumnType tColumnType = new TColumnType();
+        tColumnType.setType(column.getDataType().toThrift());
+        tColumnType.setLen(column.getStrLen());
+        tColumnType.setPrecision(column.getPrecision());
+        tColumnType.setScale(column.getScale());
+        tColumnType.setVariantMaxSubcolumnsCount(column.getVariantMaxSubcolumnsCount());
+        tColumnType.setVariantEnableDocMode(column.getVariantEnableDocMode());
+        tColumnType.setIndexLen(column.getOlapColumnIndexSize());
+        tColumn.setColumnType(tColumnType);
+
+        if (column.getAggregationType() != null) {
+            tColumn.setAggregationType(column.getAggregationType().toThrift());
+        } else {
+            tColumn.setAggregationType(TAggregationType.NONE);
+        }
+
+        tColumn.setIsKey(column.isKey());
+        tColumn.setIsAllowNull(column.isAllowNull());
+        tColumn.setIsAutoIncrement(column.isAutoInc());
+        tColumn.setIsOnUpdateCurrentTimestamp(column.hasOnUpdateDefaultValue());
+        tColumn.setDefaultValue(
+                column.getRealDefaultValue() == null ? column.getDefaultValue() : column.getRealDefaultValue());
+        tColumn.setVisible(column.isVisible());
+        toChildrenThrift(column, tColumn);
+
+        tColumn.setColUniqueId(column.getUniqueId());
+
+        if (column.getType().isAggStateType()) {
+            AggStateType aggState = (AggStateType) column.getType();
+            tColumn.setAggregation(aggState.getFunctionName());
+            tColumn.setResultIsNullable(aggState.getResultIsNullable());
+            if (column.getChildren() != null) {
+                for (Column child : column.getChildren()) {
+                    tColumn.addToChildrenColumn(toThrift(child));
+                }
+            }
+            tColumn.setBeExecVersion(Config.be_exec_version);
+        }
+        tColumn.setClusterKeyId(column.getClusterKeyId());
+        tColumn.setVariantEnableTypedPathsToSparse(column.getVariantEnableTypedPathsToSparse());
+        tColumn.setVariantMaxSparseColumnStatisticsSize(column.getVariantMaxSparseColumnStatisticsSize());
+        tColumn.setVariantSparseHashShardCount(column.getVariantSparseHashShardCount());
+        tColumn.setVariantEnableDocMode(column.getVariantEnableDocMode());
+        tColumn.setVariantDocMaterializationMinRows(column.getvariantDocMaterializationMinRows());
+        tColumn.setVariantDocHashShardCount(column.getVariantDocShardCount());
+        tColumn.setVariantEnableNestedGroup(column.getVariantEnableNestedGroup());
+        // ATTN:
+        // Currently, this `toThrift()` method is only used from CreateReplicaTask.
+        // And CreateReplicaTask does not need `defineExpr` field.
+        // The `defineExpr` is only used when creating `TAlterMaterializedViewParam`, which is in `AlterReplicaTask`.
+        // And when creating `TAlterMaterializedViewParam`, the `defineExpr` is certainly analyzed.
+        // If we need to use `defineExpr` and call defineExpr.treeToThrift(),
+        // make sure it is analyzed, or NPE will thrown.
+        return tColumn;
+    }
+
+    public static void setChildrenTColumn(Column children, TColumn tColumn) {
+        TColumn childrenTColumn = new TColumn();
+        childrenTColumn.setColumnName(children.getName());
+
+        TColumnType childrenTColumnType = new TColumnType();
+        childrenTColumnType.setType(children.getDataType().toThrift());
+        childrenTColumnType.setLen(children.getStrLen());
+        childrenTColumnType.setPrecision(children.getPrecision());
+        childrenTColumnType.setScale(children.getScale());
+        childrenTColumnType.setIndexLen(children.getOlapColumnIndexSize());
+
+        childrenTColumn.setColumnType(childrenTColumnType);
+        childrenTColumn.setIsAllowNull(children.isAllowNull());
+        // TODO: If we don't set the aggregate type for children, the type will be
+        //  considered as TAggregationType::SUM after deserializing in BE.
+        //  For now, we make children inherit the aggregate type from their parent.
+        if (tColumn.getAggregationType() != null) {
+            childrenTColumn.setAggregationType(tColumn.getAggregationType());
+        }
+        if (children.getFieldPatternType() != null) {
+            childrenTColumn.setPatternType(toThriftPatternType(children.getFieldPatternType()));
+        }
+        childrenTColumn.setClusterKeyId(children.getClusterKeyId());
+
+        tColumn.children_column.add(childrenTColumn);
+        toChildrenThrift(children, childrenTColumn);
+    }
+
+    public static void addChildren(Column column, TColumn tColumn) {
+        if (column.getChildren() != null) {
+            List<Column> childrenColumns = column.getChildren();
+            tColumn.setChildrenColumn(new ArrayList<>());
+            for (Column c : childrenColumns) {
+                setChildrenTColumn(c, tColumn);
+            }
+        }
+    }
+
+    public static void toChildrenThrift(Column column, TColumn tColumn) {
+        if (column.getType().isArrayType()) {
+            Column children = column.getChildren().get(0);
+            tColumn.setChildrenColumn(new ArrayList<>());
+            setChildrenTColumn(children, tColumn);
+        } else if (column.getType().isMapType()) {
+            Column k = column.getChildren().get(0);
+            Column v = column.getChildren().get(1);
+            tColumn.setChildrenColumn(new ArrayList<>());
+            setChildrenTColumn(k, tColumn);
+            setChildrenTColumn(v, tColumn);
+        } else if (column.getType().isStructType()) {
+            List<Column> childrenColumns = column.getChildren();
+            tColumn.setChildrenColumn(new ArrayList<>());
+            for (Column children : childrenColumns) {
+                setChildrenTColumn(children, tColumn);
+            }
+        } else if (column.getType().isVariantType()) {
+            // variant may contain predefined structured fields
+            addChildren(column, tColumn);
+        }
+    }
+
+    public static TPatternType toThriftPatternType(PatternType pt) {
+        if (pt == null) {
+            return null;
+        }
+        switch (pt) {
+            case MATCH_NAME:
+                return TPatternType.MATCH_NAME;
+            case MATCH_NAME_GLOB:
+                return TPatternType.MATCH_NAME_GLOB;
+            default:
+                throw new IllegalArgumentException("Unknown pattern type: " + pt);
+        }
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
index 3e26d7ee146..98384f2dcf2 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
@@ -38,6 +38,7 @@ import org.apache.doris.mtmv.MTMVRefreshEnum.RefreshTrigger;
 import org.apache.doris.persist.CreateTableInfo;
 import org.apache.doris.persist.gson.GsonPostProcessable;
 import org.apache.doris.persist.gson.GsonUtils;
+import org.apache.doris.qe.GlobalVariable;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
@@ -395,7 +396,7 @@ public class Database extends MetaObject implements Writable, DatabaseIf<Table>,
     }
 
     public boolean isTableExist(String tableName) {
-        if (Env.isTableNamesCaseInsensitive()) {
+        if (GlobalVariable.isTableNamesCaseInsensitive()) {
             tableName = lowerCaseToTableName.get(tableName.toLowerCase());
             if (tableName == null) {
                 return false;
@@ -424,7 +425,7 @@ public class Database extends MetaObject implements Writable, DatabaseIf<Table>,
         boolean isTableExist = false;
         table.setQualifiedDbName(fullQualifiedName);
         String tableName = table.getName();
-        if (Env.isStoredTableNamesLowerCase()) {
+        if (GlobalVariable.isStoredTableNamesLowerCase()) {
             tableName = tableName.toLowerCase();
         }
         if (isTableExist(tableName)) {
@@ -458,7 +459,7 @@ public class Database extends MetaObject implements Writable, DatabaseIf<Table>,
         Table olapTable = (Table) table;
         olapTable.setQualifiedDbName(fullQualifiedName);
         String tableName = olapTable.getName();
-        if (Env.isStoredTableNamesLowerCase()) {
+        if (GlobalVariable.isStoredTableNamesLowerCase()) {
             tableName = tableName.toLowerCase();
         }
         if (isTableExist(tableName)) {
@@ -477,7 +478,7 @@ public class Database extends MetaObject implements Writable, DatabaseIf<Table>,
 
     @Override
     public void unregisterTable(String tableName) {
-        if (Env.isStoredTableNamesLowerCase()) {
+        if (GlobalVariable.isStoredTableNamesLowerCase()) {
             tableName = tableName.toLowerCase();
         }
         Table table = getTableNullable(tableName);
@@ -601,10 +602,10 @@ public class Database extends MetaObject implements Writable, DatabaseIf<Table>,
      */
     @Override
     public Table getTableNullable(String tableName) {
-        if (Env.isStoredTableNamesLowerCase()) {
+        if (GlobalVariable.isStoredTableNamesLowerCase()) {
             tableName = tableName.toLowerCase();
         }
-        if (Env.isTableNamesCaseInsensitive()) {
+        if (GlobalVariable.isTableNamesCaseInsensitive()) {
             tableName = lowerCaseToTableName.get(tableName.toLowerCase());
             if (tableName == null) {
                 return null;
@@ -625,10 +626,10 @@ public class Database extends MetaObject implements Writable, DatabaseIf<Table>,
      */
     @Override
     public Table getNonTempTableNullable(String tableName) {
-        if (Env.isStoredTableNamesLowerCase()) {
+        if (GlobalVariable.isStoredTableNamesLowerCase()) {
             tableName = tableName.toLowerCase();
         }
-        if (Env.isTableNamesCaseInsensitive()) {
+        if (GlobalVariable.isTableNamesCaseInsensitive()) {
             tableName = lowerCaseToTableName.get(tableName.toLowerCase());
             if (tableName == null) {
                 return null;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
index 15b413a4e81..1147d973f69 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
@@ -123,6 +123,7 @@ import org.apache.doris.httpv2.meta.MetaBaseAction;
 import org.apache.doris.httpv2.rest.RestApiStatusCode;
 import org.apache.doris.indexpolicy.IndexPolicyMgr;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.insertoverwrite.InsertOverwriteManager;
 import org.apache.doris.job.base.AbstractJob;
 import org.apache.doris.job.extensions.mtmv.MTMVTask;
@@ -5554,7 +5555,7 @@ public class Env {
                 }
 
                 String oldTableName = table.getName();
-                if (Env.isStoredTableNamesLowerCase() && !Strings.isNullOrEmpty(newTableName)) {
+                if (GlobalVariable.isStoredTableNamesLowerCase() && !Strings.isNullOrEmpty(newTableName)) {
                     newTableName = newTableName.toLowerCase();
                 }
                 if (oldTableName.equals(newTableName)) {
@@ -5589,10 +5590,8 @@ public class Env {
                         newTableName);
                 editLog.logTableRename(tableInfo);
                 constraintManager.renameTable(
-                        new TableNameInfo(InternalCatalog.INTERNAL_CATALOG_NAME,
-                                db.getFullName(), oldTableName),
-                        new TableNameInfo(InternalCatalog.INTERNAL_CATALOG_NAME,
-                                db.getFullName(), newTableName));
+                        TableNameInfoUtils.fromDb(db, oldTableName),
+                        TableNameInfoUtils.fromDb(db, newTableName));
                 LOG.info("rename table[{}] to {}", oldTableName, newTableName);
             } finally {
                 table.writeUnlock();
@@ -5625,10 +5624,8 @@ public class Env {
                 table.setName(newTableName);
                 db.registerTable(table);
                 constraintManager.renameTable(
-                        new TableNameInfo(InternalCatalog.INTERNAL_CATALOG_NAME,
-                                db.getFullName(), tableName),
-                        new TableNameInfo(InternalCatalog.INTERNAL_CATALOG_NAME,
-                                db.getFullName(), newTableName));
+                        TableNameInfoUtils.fromDb(db, tableName),
+                        TableNameInfoUtils.fromDb(db, newTableName));
                 LOG.info("replay rename table[{}] to {}", tableName, newTableName);
             } finally {
                 table.writeUnlock();
@@ -7190,18 +7187,6 @@ public class Env {
         return result;
     }
 
-    public static boolean isStoredTableNamesLowerCase() {
-        return GlobalVariable.lowerCaseTableNames == 1;
-    }
-
-    public static boolean isTableNamesCaseInsensitive() {
-        return GlobalVariable.lowerCaseTableNames == 2;
-    }
-
-    public static boolean isTableNamesCaseSensitive() {
-        return GlobalVariable.lowerCaseTableNames == 0;
-    }
-
     public static int getLowerCaseTableNames(String catalogName) {
         if (catalogName == null) {
             return GlobalVariable.lowerCaseTableNames;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
index ba1b8d3c715..253256ebf00 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
@@ -86,7 +86,6 @@ import org.apache.doris.thrift.TInvertedIndexFileStorageFormat;
 import org.apache.doris.thrift.TNodeInfo;
 import org.apache.doris.thrift.TOlapTable;
 import org.apache.doris.thrift.TPaloNodesInfo;
-import org.apache.doris.thrift.TPatternType;
 import org.apache.doris.thrift.TPrimitiveType;
 import org.apache.doris.thrift.TSortType;
 import org.apache.doris.thrift.TStorageFormat;
@@ -3210,8 +3209,8 @@ public class OlapTable extends Table implements MTMVRelatedTableIf, GsonPostProc
                 // if (!materializedColumnNames.contains(col.getName())) {
                 //     continue;
                 // }
-                TColumn tColumn = col.toThrift();
-                col.setIndexFlag(tColumn, this);
+                TColumn tColumn = ColumnToThrift.toThrift(col);
+                ColumnToThrift.setIndexFlag(tColumn, this);
                 if (columnsDesc != null) {
                     columnsDesc.add(tColumn);
                 }
@@ -3231,8 +3230,8 @@ public class OlapTable extends Table implements MTMVRelatedTableIf, GsonPostProc
             List<TPrimitiveType> keyColumnTypes) {
         if (selectedIndexId != -1) {
             for (Column col : this.getSchemaByIndexId(selectedIndexId, true)) {
-                TColumn tColumn = col.toThrift();
-                col.setIndexFlag(tColumn, this);
+                TColumn tColumn = ColumnToThrift.toThrift(col);
+                ColumnToThrift.setIndexFlag(tColumn, this);
                 if (columnsDesc != null) {
                     columnsDesc.add(tColumn);
                 }
@@ -3858,7 +3857,7 @@ public class OlapTable extends Table implements MTMVRelatedTableIf, GsonPostProc
         if (column.getChildren() != null) {
             for (Column child : column.getChildren()) {
                 String childName = child.getName();
-                if (child.getFieldPatternType() == TPatternType.MATCH_NAME_GLOB) {
+                if (child.getFieldPatternType() == PatternType.MATCH_NAME_GLOB) {
                     try {
                         com.google.re2j.Pattern compiled = GlobRegexUtil.getOrCompilePattern(childName);
                         if (compiled.matcher(subPathString).matches()) {
@@ -3867,7 +3866,7 @@ public class OlapTable extends Table implements MTMVRelatedTableIf, GsonPostProc
                     } catch (com.google.re2j.PatternSyntaxException | IllegalArgumentException e) {
                         continue;
                     }
-                } else if (child.getFieldPatternType() == TPatternType.MATCH_NAME) {
+                } else if (child.getFieldPatternType() == PatternType.MATCH_NAME) {
                     if (childName.equals(subPathString)) {
                         fieldPattern = childName;
                     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/ForeignKeyConstraint.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/ForeignKeyConstraint.java
index 2e23d345926..35c96fc490d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/ForeignKeyConstraint.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/constraint/ForeignKeyConstraint.java
@@ -60,7 +60,10 @@ public class ForeignKeyConstraint extends Constraint implements GsonPostProcessa
         Preconditions.checkArgument(ImmutableSet.copyOf(referencedColumns).size() == referencedColumns.size(),
                 "Reference keys contains duplicate slots.");
         this.referencedTable = new TableIdentifier(refTable);
-        this.referencedTableInfo = new TableNameInfo(refTable);
+        this.referencedTableInfo = new TableNameInfo(
+                refTable.getDatabase().getCatalog().getName(),
+                refTable.getDatabase().getFullName(),
+                refTable.getName());
         this.referencedTableNameStr = referencedTableInfo.getCtl() + "."
                 + referencedTableInfo.getDb() + "." + referencedTableInfo.getTbl();
         for (int i = 0; i < columns.size(); i++) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/cloud/datasource/CloudInternalCatalog.java b/fe/fe-core/src/main/java/org/apache/doris/cloud/datasource/CloudInternalCatalog.java
index 1c1c0385c5b..302681a8598 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/cloud/datasource/CloudInternalCatalog.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/cloud/datasource/CloudInternalCatalog.java
@@ -20,6 +20,7 @@ package org.apache.doris.cloud.datasource;
 import org.apache.doris.analysis.DataSortInfo;
 import org.apache.doris.catalog.BinlogConfig;
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ColumnToProtobuf;
 import org.apache.doris.catalog.DataProperty;
 import org.apache.doris.catalog.Database;
 import org.apache.doris.catalog.DistributionInfo;
@@ -344,7 +345,7 @@ public class CloudInternalCatalog extends InternalCatalog {
         schemaBuilder.setSortColNum(dataSortInfo.getColNum());
         for (int i = 0; i < schemaColumns.size(); i++) {
             Column column = schemaColumns.get(i);
-            schemaBuilder.addColumn(column.toPb(bfColumns, indexes));
+            schemaBuilder.addColumn(ColumnToProtobuf.toPb(column, bfColumns, indexes));
         }
 
         Map<Integer, Column> columnMap = Maps.newHashMap();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
index b97304e618c..911c18fab7e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
@@ -109,7 +109,7 @@ import org.apache.doris.common.util.TimeUtils;
 import org.apache.doris.common.util.Util;
 import org.apache.doris.event.DropPartitionEvent;
 import org.apache.doris.foundation.type.ResultOr;
-import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.mtmv.BaseTableInfo;
 import org.apache.doris.mtmv.MTMVUtil;
 import org.apache.doris.mysql.privilege.PrivPredicate;
@@ -193,7 +193,9 @@ import java.util.stream.Collectors;
  * There is only one internal catalog in a cluster. And its id is always 0.
  */
 public class InternalCatalog implements CatalogIf<Database> {
-    public static final String INTERNAL_CATALOG_NAME = "internal";
+    /** @deprecated Use {@link org.apache.doris.catalog.NameSpaceContext#INTERNAL_CATALOG_NAME} instead. */
+    @Deprecated
+    public static final String INTERNAL_CATALOG_NAME = org.apache.doris.catalog.NameSpaceContext.INTERNAL_CATALOG_NAME;
     public static final long INTERNAL_CATALOG_ID = 0L;
 
     private static final Logger LOG = LogManager.getLogger(InternalCatalog.class);
@@ -1038,7 +1040,8 @@ public class InternalCatalog implements CatalogIf<Database> {
         Env.getCurrentEnv().getDictionaryManager().dropTableDictionaries(db.getName(), table.getName());
         Env.getCurrentEnv().getQueryStats().clear(Env.getCurrentInternalCatalog().getId(), db.getId(), table.getId());
         Env.getCurrentEnv().getConstraintManager().checkAndDropTableConstraints(
-                new TableNameInfo(table), !isForceDrop && !isReplay);
+                TableNameInfoUtils.fromDb(db, table.getName()),
+                !isForceDrop && !isReplay);
         db.unregisterTable(table.getId());
         StopWatch watch = StopWatch.createStarted();
         Env.getCurrentRecycleBin().recycleTable(db.getId(), table, isReplay, isForceDrop, recycleTime);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergUtils.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergUtils.java
index a4286e11886..e1be224fda0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergUtils.java
@@ -24,6 +24,7 @@ import org.apache.doris.analysis.CompoundPredicate;
 import org.apache.doris.analysis.DateLiteral;
 import org.apache.doris.analysis.DecimalLiteral;
 import org.apache.doris.analysis.Expr;
+import org.apache.doris.analysis.ExprToExprNameVisitor;
 import org.apache.doris.analysis.FloatLiteral;
 import org.apache.doris.analysis.FunctionCallExpr;
 import org.apache.doris.analysis.InPredicate;
@@ -530,32 +531,36 @@ public class IcebergUtils {
             if (expr instanceof SlotRef) {
                 builder.identity(((SlotRef) expr).getColumnName());
             } else if (expr instanceof FunctionCallExpr) {
-                String exprName = expr.getExprName();
+                String exprName = expr.accept(ExprToExprNameVisitor.INSTANCE, null);
                 List<Expr> params = ((FunctionCallExpr) expr).getParams().exprs();
                 switch (exprName.toLowerCase()) {
                     case "bucket":
-                        builder.bucket(params.get(1).getExprName(), Integer.parseInt(params.get(0).getStringValue()));
+                        builder.bucket(
+                                params.get(1).accept(ExprToExprNameVisitor.INSTANCE, null),
+                                Integer.parseInt(params.get(0).getStringValue()));
                         break;
                     case "year":
                     case "years":
-                        builder.year(params.get(0).getExprName());
+                        builder.year(params.get(0).accept(ExprToExprNameVisitor.INSTANCE, null));
                         break;
                     case "month":
                     case "months":
-                        builder.month(params.get(0).getExprName());
+                        builder.month(params.get(0).accept(ExprToExprNameVisitor.INSTANCE, null));
                         break;
                     case "date":
                     case "day":
                     case "days":
-                        builder.day(params.get(0).getExprName());
+                        builder.day(params.get(0).accept(ExprToExprNameVisitor.INSTANCE, null));
                         break;
                     case "date_hour":
                     case "hour":
                     case "hours":
-                        builder.hour(params.get(0).getExprName());
+                        builder.hour(params.get(0).accept(ExprToExprNameVisitor.INSTANCE, null));
                         break;
                     case "truncate":
-                        builder.truncate(params.get(1).getExprName(), Integer.parseInt(params.get(0).getStringValue()));
+                        builder.truncate(
+                                params.get(1).accept(ExprToExprNameVisitor.INSTANCE, null),
+                                Integer.parseInt(params.get(0).getStringValue()));
                         break;
                     default:
                         throw new UserException("unsupported partition for " + exprName);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
index 99e8b2597d4..6a7d58d2f3f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/JdbcExternalCatalog.java
@@ -39,6 +39,7 @@ import org.apache.doris.datasource.mapping.JdbcIdentifierMapping;
 import org.apache.doris.proto.InternalService;
 import org.apache.doris.proto.InternalService.PJdbcTestConnectionRequest;
 import org.apache.doris.proto.InternalService.PJdbcTestConnectionResult;
+import org.apache.doris.qe.GlobalVariable;
 import org.apache.doris.resource.computegroup.ComputeGroupMgr;
 import org.apache.doris.rpc.BackendServiceProxy;
 import org.apache.doris.rpc.RpcException;
@@ -87,7 +88,7 @@ public class JdbcExternalCatalog extends ExternalCatalog {
         super(catalogId, name, InitCatalogLog.Type.JDBC, comment);
         this.catalogProperty = new CatalogProperty(resource, processCompatibleProperties(props));
         this.identifierMapping = new JdbcIdentifierMapping(
-                (Env.isTableNamesCaseInsensitive() || Env.isStoredTableNamesLowerCase()),
+                (GlobalVariable.isTableNamesCaseInsensitive() || GlobalVariable.isStoredTableNamesLowerCase()),
                 Boolean.parseBoolean(getLowerCaseMetaNames()),
                 getMetaNamesMapping());
     }
@@ -138,7 +139,7 @@ public class JdbcExternalCatalog extends ExternalCatalog {
     public void resetToUninitialized(boolean invalidCache) {
         super.resetToUninitialized(invalidCache);
         this.identifierMapping = new JdbcIdentifierMapping(
-                (Env.isTableNamesCaseInsensitive() || Env.isStoredTableNamesLowerCase()),
+                (GlobalVariable.isTableNamesCaseInsensitive() || GlobalVariable.isStoredTableNamesLowerCase()),
                 Boolean.parseBoolean(getLowerCaseMetaNames()),
                 getMetaNamesMapping());
     }
@@ -264,7 +265,7 @@ public class JdbcExternalCatalog extends ExternalCatalog {
         super.gsonPostProcess();
         if (this.identifierMapping == null) {
             identifierMapping = new JdbcIdentifierMapping(
-                    (Env.isTableNamesCaseInsensitive() || Env.isStoredTableNamesLowerCase()),
+                    (GlobalVariable.isTableNamesCaseInsensitive() || GlobalVariable.isStoredTableNamesLowerCase()),
                     Boolean.parseBoolean(getLowerCaseMetaNames()),
                     getMetaNamesMapping());
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNode.java
index 1925ca7a0ac..d79e43aed74 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/source/MaxComputeScanNode.java
@@ -22,6 +22,7 @@ import org.apache.doris.analysis.CompoundPredicate;
 import org.apache.doris.analysis.CompoundPredicate.Operator;
 import org.apache.doris.analysis.DateLiteral;
 import org.apache.doris.analysis.Expr;
+import org.apache.doris.analysis.ExprToExprNameVisitor;
 import org.apache.doris.analysis.InPredicate;
 import org.apache.doris.analysis.IsNullPredicate;
 import org.apache.doris.analysis.LiteralExpr;
@@ -508,7 +509,8 @@ public class MaxComputeScanNode extends FileQueryScanNode {
 
         if (odpsPredicate == null) {
             throw new AnalysisException("Do not support convert ["
-                    + expr.getExprName() + "] in convertExprToOdpsPredicate.");
+                    + expr.accept(ExprToExprNameVisitor.INSTANCE, null)
+                    + "] in convertExprToOdpsPredicate.");
         }
         return odpsPredicate;
     }
@@ -519,14 +521,16 @@ public class MaxComputeScanNode extends FileQueryScanNode {
         }
 
         throw new AnalysisException("Do not support convert ["
-                + expr.getExprName() + "] in convertSlotRefToAttribute.");
+                + expr.accept(ExprToExprNameVisitor.INSTANCE, null)
+                + "] in convertSlotRefToAttribute.");
 
     }
 
     private String convertLiteralToOdpsValues(OdpsType odpsType, Expr expr) throws AnalysisException {
         if (!(expr instanceof LiteralExpr)) {
             throw new AnalysisException("Do not support convert ["
-                    + expr.getExprName() + "] in convertSlotRefToAttribute.");
+                    + expr.accept(ExprToExprNameVisitor.INSTANCE, null)
+                    + "] in convertSlotRefToAttribute.");
         }
         LiteralExpr literalExpr = (LiteralExpr) expr;
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/source/PaimonPredicateConverter.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/source/PaimonPredicateConverter.java
index cfc27383a46..963904a4ff4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/source/PaimonPredicateConverter.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/source/PaimonPredicateConverter.java
@@ -21,6 +21,7 @@ import org.apache.doris.analysis.BinaryPredicate;
 import org.apache.doris.analysis.CastExpr;
 import org.apache.doris.analysis.CompoundPredicate;
 import org.apache.doris.analysis.Expr;
+import org.apache.doris.analysis.ExprToExprNameVisitor;
 import org.apache.doris.analysis.FunctionCallExpr;
 import org.apache.doris.analysis.InPredicate;
 import org.apache.doris.analysis.IsNullPredicate;
@@ -158,7 +159,7 @@ public class PaimonPredicateConverter {
                     return null;
             }
         } else if (dorisExpr instanceof FunctionCallExpr) {
-            String name = dorisExpr.getExprName().toLowerCase();
+            String name = dorisExpr.accept(ExprToExprNameVisitor.INSTANCE, null).toLowerCase();
             String s = value.toString();
             if (name.equals("like") && !s.startsWith("%") && s.endsWith("%")) {
                 return builder.startsWith(idx, BinaryString.fromString(s.substring(0, s.length() - 1)));
diff --git a/fe/fe-core/src/main/java/org/apache/doris/info/TableNameInfo.java b/fe/fe-core/src/main/java/org/apache/doris/info/TableNameInfo.java
index 0f349f56529..29a80703fb8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/info/TableNameInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/info/TableNameInfo.java
@@ -20,18 +20,13 @@
 
 package org.apache.doris.info;
 
-import org.apache.doris.catalog.DatabaseIf;
-import org.apache.doris.catalog.Env;
-import org.apache.doris.catalog.TableIf;
-import org.apache.doris.datasource.CatalogIf;
-import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.catalog.NameSpaceContext;
 import org.apache.doris.nereids.exceptions.AnalysisException;
-import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.qe.GlobalVariable;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.gson.annotations.SerializedName;
-import org.apache.commons.lang3.StringUtils;
 
 import java.util.List;
 import java.util.Objects;
@@ -52,6 +47,7 @@ public class TableNameInfo {
 
     }
 
+
     /**
      * TableNameInfo
      * @param parts like [ctl1,db1,tbl1] or [db1,tbl1] or [tbl1]
@@ -61,7 +57,7 @@ public class TableNameInfo {
         int size = parts.size();
         Preconditions.checkArgument(size > 0, "table name can't be empty");
         tbl = parts.get(size - 1);
-        if (Env.isStoredTableNamesLowerCase() && !Strings.isNullOrEmpty(tbl)) {
+        if (GlobalVariable.isStoredTableNamesLowerCase() && !Strings.isNullOrEmpty(tbl)) {
             tbl = tbl.toLowerCase();
         }
         if (size >= 2) {
@@ -80,9 +76,9 @@ public class TableNameInfo {
     public TableNameInfo(String db, String tbl) {
         Objects.requireNonNull(tbl, "require tbl object");
         Objects.requireNonNull(db, "require db object");
-        this.ctl = InternalCatalog.INTERNAL_CATALOG_NAME;
+        this.ctl = NameSpaceContext.INTERNAL_CATALOG_NAME;
         this.tbl = tbl;
-        if (Env.isStoredTableNamesLowerCase()) {
+        if (GlobalVariable.isStoredTableNamesLowerCase()) {
             this.tbl = tbl.toLowerCase();
         }
         this.db = db;
@@ -98,7 +94,7 @@ public class TableNameInfo {
         Objects.requireNonNull(tbl, "require tbl object");
         this.ctl = ctl;
         this.tbl = tbl;
-        if (Env.isStoredTableNamesLowerCase()) {
+        if (GlobalVariable.isStoredTableNamesLowerCase()) {
             this.tbl = tbl.toLowerCase();
         }
         this.db = db;
@@ -112,7 +108,7 @@ public class TableNameInfo {
         String[] parts = alias.split("\\.");
         Preconditions.checkArgument(parts.length > 0, "table name can't be empty");
         tbl = parts[parts.length - 1];
-        if (Env.isStoredTableNamesLowerCase() && !Strings.isNullOrEmpty(tbl)) {
+        if (GlobalVariable.isStoredTableNamesLowerCase() && !Strings.isNullOrEmpty(tbl)) {
             tbl = tbl.toLowerCase();
         }
         if (parts.length >= 2) {
@@ -123,68 +119,19 @@ public class TableNameInfo {
         }
     }
 
-    /**
-     * TableNameInfo
-     * @param tableIf tableIf
-     * @throws AnalysisException AnalysisException
-     */
-    public TableNameInfo(TableIf tableIf) throws AnalysisException {
-        String tableName = tableIf.getName();
-        if (StringUtils.isEmpty(tableName)) {
-            throw new AnalysisException("tableName is empty");
-        }
-        DatabaseIf db = tableIf.getDatabase();
-        if (db == null) {
-            throw new AnalysisException("db is null, tableName: " + tableName);
-        }
-        CatalogIf catalog = db.getCatalog();
-        if (catalog == null) {
-            throw new AnalysisException("catalog is null, dbName: " + db.getFullName());
-        }
-        if (Env.isStoredTableNamesLowerCase()) {
-            tableName = tableName.toLowerCase();
-        }
-        this.ctl = catalog.getName();
-        this.db = db.getFullName();
-        this.tbl = tableName;
-    }
-
-    /**
-     * Create TableNameInfo from a TableIf, returning null if the table
-     * lacks a database or catalog (e.g., standalone tables in unit tests).
-     */
-    public static TableNameInfo createOrNull(TableIf tableIf) {
-        if (tableIf == null || StringUtils.isEmpty(tableIf.getName())) {
-            return null;
-        }
-        DatabaseIf db = tableIf.getDatabase();
-        if (db == null) {
-            return null;
-        }
-        CatalogIf catalog = db.getCatalog();
-        if (catalog == null) {
-            return null;
-        }
-        String tableName = tableIf.getName();
-        if (Env.isStoredTableNamesLowerCase()) {
-            tableName = tableName.toLowerCase();
-        }
-        return new TableNameInfo(catalog.getName(), db.getFullName(), tableName);
-    }
-
     /**
      * analyze tableNameInfo
      * @param ctx ctx
      */
-    public void analyze(ConnectContext ctx) {
+    public void analyze(NameSpaceContext ctx) {
         if (Strings.isNullOrEmpty(ctl)) {
             ctl = ctx.getDefaultCatalog();
             if (Strings.isNullOrEmpty(ctl)) {
-                ctl = InternalCatalog.INTERNAL_CATALOG_NAME;
+                ctl = NameSpaceContext.INTERNAL_CATALOG_NAME;
             }
         }
         if (Strings.isNullOrEmpty(db)) {
-            db = ctx.getDatabase();
+            db = ctx.getCurrentDb();
             if (Strings.isNullOrEmpty(db)) {
                 throw new AnalysisException("No database selected");
             }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/info/TableNameInfoUtils.java b/fe/fe-core/src/main/java/org/apache/doris/info/TableNameInfoUtils.java
new file mode 100644
index 00000000000..a106812cdd6
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/info/TableNameInfoUtils.java
@@ -0,0 +1,104 @@
+// 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.info;
+
+import org.apache.doris.catalog.Database;
+import org.apache.doris.catalog.DatabaseIf;
+import org.apache.doris.catalog.NameSpaceContext;
+import org.apache.doris.catalog.TableIf;
+import org.apache.doris.datasource.CatalogIf;
+import org.apache.doris.qe.GlobalVariable;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Objects;
+
+/**
+ * Utility methods for creating {@link TableNameInfo} from catalog objects.
+ * Kept separate from {@code TableNameInfo} to avoid coupling that class to
+ * {@code Database}/{@code TableIf}/{@code CatalogIf}.
+ *
+ * <p>All factory methods apply case conversion via
+ * {@link GlobalVariable#isStoredTableNamesLowerCase()} consistently,
+ * matching the behavior of the {@code TableNameInfo} constructors.</p>
+ */
+public class TableNameInfoUtils {
+
+    private TableNameInfoUtils() {
+    }
+
+    /**
+     * Apply lower-case conversion to a table name if the global config requires it.
+     */
+    private static String normalizeTableName(String tableName) {
+        if (GlobalVariable.isStoredTableNamesLowerCase() && !StringUtils.isEmpty(tableName)) {
+            return tableName.toLowerCase();
+        }
+        return tableName;
+    }
+
+    /**
+     * Create a TableNameInfo from a Database and table name.
+     * Uses the database's catalog name, falling back to INTERNAL_CATALOG_NAME.
+     */
+    public static TableNameInfo fromDb(Database db, String tableName) {
+        Objects.requireNonNull(db, "db must not be null");
+        String catalogName = db.getCatalog() != null ? db.getCatalog().getName()
+                : NameSpaceContext.INTERNAL_CATALOG_NAME;
+        return new TableNameInfo(catalogName, db.getFullName(), normalizeTableName(tableName));
+    }
+
+    /**
+     * Create a TableNameInfo from catalog, database, and table name string.
+     */
+    public static TableNameInfo fromCatalogDb(CatalogIf<?> catalog, DatabaseIf<?> db, String tableName) {
+        Objects.requireNonNull(catalog, "catalog must not be null");
+        Objects.requireNonNull(db, "db must not be null");
+        return new TableNameInfo(catalog.getName(), db.getFullName(), normalizeTableName(tableName));
+    }
+
+    /**
+     * Create a TableNameInfo from catalog, database, and table objects.
+     */
+    public static TableNameInfo fromCatalogDb(CatalogIf<?> catalog, DatabaseIf<?> db, TableIf table) {
+        Objects.requireNonNull(catalog, "catalog must not be null");
+        Objects.requireNonNull(db, "db must not be null");
+        Objects.requireNonNull(table, "table must not be null");
+        return new TableNameInfo(catalog.getName(), db.getFullName(), normalizeTableName(table.getName()));
+    }
+
+    /**
+     * Create a TableNameInfo from a TableIf, looking up its database and catalog.
+     * Returns null if the table is null, its name is empty, or its database/catalog
+     * is not available — matching the old {@code TableNameInfo.createOrNull} contract.
+     */
+    public static TableNameInfo fromTableOrNull(TableIf table) {
+        if (table == null || StringUtils.isEmpty(table.getName())) {
+            return null;
+        }
+        DatabaseIf<?> db = table.getDatabase();
+        if (db == null) {
+            return null;
+        }
+        CatalogIf<?> catalog = db.getCatalog();
+        if (catalog == null) {
+            return null;
+        }
+        return new TableNameInfo(catalog.getName(), db.getFullName(), normalizeTableName(table.getName()));
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/info/TableRefInfo.java b/fe/fe-core/src/main/java/org/apache/doris/info/TableRefInfo.java
index ff561db9c3d..553f55764e9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/info/TableRefInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/info/TableRefInfo.java
@@ -22,10 +22,10 @@ import org.apache.doris.analysis.JoinOperator;
 import org.apache.doris.analysis.TableScanParams;
 import org.apache.doris.analysis.TableSnapshot;
 import org.apache.doris.analysis.TupleDescriptor;
+import org.apache.doris.catalog.NameSpaceContext;
 import org.apache.doris.catalog.info.PartitionNamesInfo;
 import org.apache.doris.common.UserException;
 import org.apache.doris.nereids.trees.TableSample;
-import org.apache.doris.qe.ConnectContext;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -119,7 +119,7 @@ public class TableRefInfo {
         return partitionNamesInfo;
     }
 
-    public void analyze(ConnectContext ctx) throws UserException {
+    public void analyze(NameSpaceContext ctx) throws UserException {
         tableNameInfo.analyze(ctx);
         if (partitionNamesInfo != null) {
             partitionNamesInfo.validate();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/DeleteJob.java b/fe/fe-core/src/main/java/org/apache/doris/load/DeleteJob.java
index 99e22aa2a08..ec4520c3e48 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/load/DeleteJob.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/load/DeleteJob.java
@@ -26,6 +26,7 @@ import org.apache.doris.analysis.Predicate;
 import org.apache.doris.analysis.SlotRef;
 import org.apache.doris.analysis.ToSqlParams;
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ColumnToThrift;
 import org.apache.doris.catalog.Database;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.Index;
@@ -318,7 +319,7 @@ public class DeleteJob extends AbstractTxnStateChangeCallback implements DeleteJ
                 List<Column> columns = indexMeta.getSchema(true);
                 // using to update schema of the rowset, so full columns should be included
                 for (Column column : columns) {
-                    TColumn tCol = column.toThrift();
+                    TColumn tCol = ColumnToThrift.toThrift(column);
                     columnsDesc.add(tCol);
                     String colName = column.tryGetBaseColumnName();
                     colNameToColDesc.put(colName, tCol);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionUtil.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionUtil.java
index 924f51ce064..9ceb7905a03 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionUtil.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionUtil.java
@@ -33,6 +33,7 @@ import org.apache.doris.common.DdlException;
 import org.apache.doris.common.Pair;
 import org.apache.doris.datasource.mvcc.MvccUtil;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.mtmv.MTMVPartitionInfo.MTMVPartitionType;
 import org.apache.doris.nereids.trees.plans.commands.info.AddPartitionOp;
 import org.apache.doris.nereids.trees.plans.commands.info.DropPartitionOp;
@@ -103,7 +104,9 @@ public class MTMVPartitionUtil {
             for (MTMVRelatedTableIf pctTable : pctTables) {
                 Set<String> relatedPartitionNames = partitionMappings.getOrDefault(pctTable, Sets.newHashSet());
                 // if follow base table, not need compare with related table, only should compare with related partition
-                excludedTriggerTables.add(new TableNameInfo(pctTable));
+                excludedTriggerTables.add(TableNameInfoUtils.fromCatalogDb(
+                        pctTable.getDatabase().getCatalog(),
+                        pctTable.getDatabase(), pctTable));
                 if (!isSyncWithPartitions(refreshContext, partitionName, relatedPartitionNames, pctTable)) {
                     return false;
                 }
@@ -427,7 +430,9 @@ public class MTMVPartitionUtil {
                 LOG.warn("get table failed, {}", baseTableInfo, e);
                 return false;
             }
-            if (isTableExcluded(excludedTriggerTables, new TableNameInfo(table))) {
+            if (isTableExcluded(excludedTriggerTables, TableNameInfoUtils.fromCatalogDb(
+                    table.getDatabase().getCatalog(), table.getDatabase(),
+                    table))) {
                 continue;
             }
             boolean syncWithBaseTable = isSyncWithBaseTable(context, mtmvPartitionName, baseTableInfo);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVService.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVService.java
index 299e9b5f66d..05c21d5c6b7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVService.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVService.java
@@ -30,6 +30,7 @@ import org.apache.doris.event.EventException;
 import org.apache.doris.event.EventListener;
 import org.apache.doris.event.TableEvent;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.job.exception.JobException;
 import org.apache.doris.job.extensions.mtmv.MTMVTask;
 import org.apache.doris.mtmv.MTMVRefreshEnum.RefreshTrigger;
@@ -214,10 +215,15 @@ public class MTMVService implements EventListener {
     private boolean shouldRefreshOnBaseTableDataChange(MTMV mtmv, TableIf table) {
         TableNameInfo tableName = null;
         try {
-            tableName = new TableNameInfo(table);
-        } catch (org.apache.doris.nereids.exceptions.AnalysisException e) {
+            tableName = TableNameInfoUtils.fromTableOrNull(table);
+        } catch (Exception e) {
             LOG.warn("skip refresh mtmv: {}, because get TableName failed: {}",
-                    mtmv.getName(), table.getName());
+                    mtmv.getName(), table == null ? "null" : table.getName());
+            return false;
+        }
+        if (tableName == null) {
+            LOG.warn("skip refresh mtmv: {}, because get TableName failed: {}",
+                    mtmv.getName(), table == null ? "null" : table.getName());
             return false;
         }
         if (MTMVPartitionUtil.isTableExcluded(mtmv.getExcludedTriggerTables(), tableName)) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java
index 64f4630cc5b..9f5ccf544f3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java
@@ -17,11 +17,11 @@
 
 package org.apache.doris.mysql.privilege;
 
-import org.apache.doris.catalog.Env;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.CaseSensibility;
 import org.apache.doris.common.PatternMatcher;
 import org.apache.doris.common.PatternMatcherException;
+import org.apache.doris.qe.GlobalVariable;
 
 public class TablePrivEntry extends DbPrivEntry {
     private static final String ANY_TBL = "*";
@@ -55,7 +55,7 @@ public class TablePrivEntry extends DbPrivEntry {
                 ctl, CaseSensibility.CATALOG.getCaseSensibility(), ctl.equals(ANY_CTL));
 
         PatternMatcher tblPattern = PatternMatcher.createFlatPattern(
-                tbl, Env.isTableNamesCaseSensitive(), tbl.equals(ANY_TBL));
+                tbl, GlobalVariable.isTableNamesCaseSensitive(), tbl.equals(ANY_TBL));
 
         if (privs.containsNodePriv() || privs.containsResourcePriv()) {
             throw new AnalysisException("Table privilege can not contains global or resource privileges: " + privs);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/minidump/MinidumpUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/minidump/MinidumpUtils.java
index b0bdf41dafc..7ed1c6a1d77 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/minidump/MinidumpUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/minidump/MinidumpUtils.java
@@ -40,7 +40,7 @@ import org.apache.doris.persist.gson.GsonUtils;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.qe.OriginStatement;
 import org.apache.doris.qe.SessionVariable;
-import org.apache.doris.qe.VariableMgr;
+import org.apache.doris.qe.VarAttrDef;
 import org.apache.doris.statistics.ColumnStatistic;
 import org.apache.doris.statistics.ColumnStatisticBuilder;
 import org.apache.doris.statistics.Histogram;
@@ -482,7 +482,7 @@ public class MinidumpUtils {
         JSONObject root = new JSONObject();
         try {
             for (Field field : SessionVariable.class.getDeclaredFields()) {
-                VariableMgr.VarAttr attr = field.getAnnotation(VariableMgr.VarAttr.class);
+                VarAttrDef.VarAttr attr = field.getAnnotation(VarAttrDef.VarAttr.class);
                 if (attr == null) {
                     continue;
                 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ForeignKeyContext.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ForeignKeyContext.java
index 4b526691dfa..aa3d08b1f85 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ForeignKeyContext.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ForeignKeyContext.java
@@ -23,6 +23,7 @@ import org.apache.doris.catalog.TableIf;
 import org.apache.doris.catalog.constraint.ForeignKeyConstraint;
 import org.apache.doris.catalog.constraint.PrimaryKeyConstraint;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.nereids.trees.expressions.Alias;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.NamedExpression;
@@ -102,7 +103,7 @@ public class ForeignKeyContext {
     }
 
     void putAllForeignKeys(TableIf table) {
-        TableNameInfo tableNameInfo = TableNameInfo.createOrNull(table);
+        TableNameInfo tableNameInfo = TableNameInfoUtils.fromTableOrNull(table);
         if (tableNameInfo == null) {
             return;
         }
@@ -115,7 +116,7 @@ public class ForeignKeyContext {
     }
 
     void putAllPrimaryKeys(TableIf table) {
-        TableNameInfo tableNameInfo = TableNameInfo.createOrNull(table);
+        TableNameInfo tableNameInfo = TableNameInfoUtils.fromTableOrNull(table);
         if (tableNameInfo == null) {
             return;
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AddConstraintCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AddConstraintCommand.java
index b66010c9862..41c7a3511f7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AddConstraintCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AddConstraintCommand.java
@@ -24,6 +24,7 @@ import org.apache.doris.catalog.constraint.PrimaryKeyConstraint;
 import org.apache.doris.catalog.constraint.UniqueConstraint;
 import org.apache.doris.common.Pair;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.nereids.NereidsPlanner;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.properties.PhysicalProperties;
@@ -68,13 +69,17 @@ public class AddConstraintCommand extends Command implements ForwardWithSync {
     public void run(ConnectContext ctx, StmtExecutor executor) throws Exception {
         Pair<ImmutableList<String>, TableIf> columnsAndTable = extractColumnsAndTable(ctx, constraint.toProject());
         TableIf table = columnsAndTable.second;
-        TableNameInfo tableNameInfo = new TableNameInfo(table);
+        TableNameInfo tableNameInfo = TableNameInfoUtils.fromCatalogDb(
+                table.getDatabase().getCatalog(), table.getDatabase(), table);
         ImmutableList<String> columns = columnsAndTable.first;
 
         if (constraint.isForeignKey()) {
             Pair<ImmutableList<String>, TableIf> refColumnsAndTable
                     = extractColumnsAndTable(ctx, constraint.toReferenceProject());
-            TableNameInfo refTableInfo = new TableNameInfo(refColumnsAndTable.second);
+            TableIf refTable = refColumnsAndTable.second;
+            TableNameInfo refTableInfo = TableNameInfoUtils.fromCatalogDb(
+                    refTable.getDatabase().getCatalog(),
+                    refTable.getDatabase(), refTable);
             ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint(
                     name, columns, refTableInfo, refColumnsAndTable.first);
             Env.getCurrentEnv().getConstraintManager().addConstraint(
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminCancelRepairTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminCancelRepairTableCommand.java
index 4912cb26002..d10d3a3f42f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminCancelRepairTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminCancelRepairTableCommand.java
@@ -82,7 +82,7 @@ public class AdminCancelRepairTableCommand extends Command implements ForwardWit
             ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN");
         }
 
-        tableRefInfo.getTableNameInfo().analyze(ctx);
+        tableRefInfo.getTableNameInfo().analyze(ctx.getNameSpaceContext());
         Util.prohibitExternalCatalog(tableRefInfo.getTableNameInfo().getCtl(), this.getClass().getSimpleName());
 
         PartitionNamesInfo partitionNamesInfo = tableRefInfo.getPartitionNamesInfo();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminCompactTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminCompactTableCommand.java
index a32d689e22d..f41d24f4b62 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminCompactTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminCompactTableCommand.java
@@ -77,7 +77,7 @@ public class AdminCompactTableCommand extends Command implements ForwardWithSync
         if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)) {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN");
         }
-        tableRefInfo.analyze(ctx);
+        tableRefInfo.analyze(ctx.getNameSpaceContext());
         Util.prohibitExternalCatalog(tableRefInfo.getTableNameInfo().getCtl(), this.getClass().getSimpleName());
 
         List<String> partitionNames = tableRefInfo.getPartitionNamesInfo().getPartitionNames();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminRepairTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminRepairTableCommand.java
index f4aaafbafeb..cf9241a2dd9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminRepairTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminRepairTableCommand.java
@@ -86,7 +86,7 @@ public class AdminRepairTableCommand extends Command implements ForwardWithSync
             ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN");
         }
 
-        tableRefInfo.getTableNameInfo().analyze(ctx);
+        tableRefInfo.getTableNameInfo().analyze(ctx.getNameSpaceContext());
         Util.prohibitExternalCatalog(tableRefInfo.getTableNameInfo().getCtl(), this.getClass().getSimpleName());
 
         PartitionNamesInfo partitionNamesInfo = tableRefInfo.getPartitionNamesInfo();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetPartitionVersionCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetPartitionVersionCommand.java
index 6c58d4fdd37..8daad8d7a55 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetPartitionVersionCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetPartitionVersionCommand.java
@@ -75,7 +75,7 @@ public class AdminSetPartitionVersionCommand extends Command implements ForwardW
             ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN");
         }
 
-        tableName.analyze(ctx);
+        tableName.analyze(ctx.getNameSpaceContext());
         Util.prohibitExternalCatalog(tableName.getCtl(), this.getClass().getSimpleName());
 
         checkProperties();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetTableStatusCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetTableStatusCommand.java
index 05f629f14cb..b501a058cb2 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetTableStatusCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminSetTableStatusCommand.java
@@ -63,7 +63,7 @@ public class AdminSetTableStatusCommand extends Command implements ForwardWithSy
             ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN");
         }
 
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         Util.prohibitExternalCatalog(tableNameInfo.getCtl(), this.getClass().getSimpleName());
 
         checkProperties();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterColumnStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterColumnStatsCommand.java
index 96a3f138c06..62a7e2bb3b7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterColumnStatsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterColumnStatsCommand.java
@@ -133,7 +133,7 @@ public class AlterColumnStatsCommand extends AlterCommand {
         }
 
         // check table name
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
 
         if (!Env.getCurrentEnv().getAccessManager()
                     .checkTblPriv(ConnectContext.get(), tableNameInfo.getCtl(), tableNameInfo.getDb(),
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterTableCommand.java
index 677cd6dff9f..52686cf59e8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterTableCommand.java
@@ -102,7 +102,7 @@ public class AlterTableCommand extends Command implements ForwardWithSync {
         if (tbl == null) {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_NO_TABLES_USED);
         }
-        tbl.analyze(ctx);
+        tbl.analyze(ctx.getNameSpaceContext());
         InternalDatabaseUtil.checkDatabase(tbl.getDb(), ConnectContext.get());
         if (!Env.getCurrentEnv().getAccessManager()
                 .checkTblPriv(ConnectContext.get(), tbl.getCtl(), tbl.getDb(), tbl.getTbl(),
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterTableStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterTableStatsCommand.java
index e2d05e2212a..52b7a0586ee 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterTableStatsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterTableStatsCommand.java
@@ -102,7 +102,7 @@ public class AlterTableStatsCommand extends AlterCommand {
                 + " in your FE conf file");
         }
 
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
 
         if (!Env.getCurrentEnv().getAccessManager()
                 .checkTblPriv(ConnectContext.get(), tableNameInfo.getCtl(), tableNameInfo.getDb(),
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AnalyzeTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AnalyzeTableCommand.java
index 9102af0cfe6..46223280a5e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AnalyzeTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AnalyzeTableCommand.java
@@ -100,7 +100,7 @@ public class AnalyzeTableCommand extends AnalyzeCommand {
     @Override
     public void validate(ConnectContext ctx) throws UserException {
         super.validate(ctx);
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         String catalogName = tableNameInfo.getCtl();
         String dbName = tableNameInfo.getDb();
         String tblName = tableNameInfo.getTbl();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CancelAlterTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CancelAlterTableCommand.java
index 832012e962e..6bbb5ac3703 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CancelAlterTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CancelAlterTableCommand.java
@@ -90,7 +90,7 @@ public class CancelAlterTableCommand extends CancelCommand {
      * validate
      */
     public void validate(ConnectContext ctx) throws AnalysisException {
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         // disallow external catalog
         Util.prohibitExternalCatalog(tableNameInfo.getCtl(), this.getClass().getSimpleName());
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CancelBuildIndexCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CancelBuildIndexCommand.java
index 9cabc5bd52c..8bec26ca031 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CancelBuildIndexCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CancelBuildIndexCommand.java
@@ -75,7 +75,7 @@ public class CancelBuildIndexCommand extends CancelCommand {
      * validate
      */
     public void validate(ConnectContext ctx) throws AnalysisException {
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         // disallow external catalog
         Util.prohibitExternalCatalog(tableNameInfo.getCtl(), this.getClass().getSimpleName());
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CleanQueryStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CleanQueryStatsCommand.java
index 50192a1e557..c60cdd13e3a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CleanQueryStatsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CleanQueryStatsCommand.java
@@ -109,7 +109,7 @@ public class CleanQueryStatsCommand extends Command implements ForwardWithSync {
                 }
                 break;
             case TABLE:
-                tableNameInfo.analyze(ctx);
+                tableNameInfo.analyze(ctx.getNameSpaceContext());
                 dbName = tableNameInfo.getDb();
                 if (StringUtils.isEmpty(dbName)) {
                     ErrorReport.reportAnalysisException(ErrorCode.ERR_NO_DB_ERROR);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreatePolicyCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreatePolicyCommand.java
index 2e75bc32144..e3298f7bbca 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreatePolicyCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreatePolicyCommand.java
@@ -129,7 +129,7 @@ public class CreatePolicyCommand extends Command implements ForwardWithSync {
                     ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR,
                             PrivPredicate.GRANT.getPrivs().toString());
                 }
-                tableNameInfo.analyze(ctx);
+                tableNameInfo.analyze(ctx.getNameSpaceContext());
                 if (user != null) {
                     user.analyze();
                     if (user.isRootUser() || user.isAdminUser()) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DescribeCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DescribeCommand.java
index d425cace629..c7a68691e05 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DescribeCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DescribeCommand.java
@@ -195,7 +195,7 @@ public class DescribeCommand extends ShowCommand {
     @Override
     public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception {
         if (dbTableName != null) {
-            dbTableName.analyze(ctx);
+            dbTableName.analyze(ctx.getNameSpaceContext());
             CatalogIf catalog = Env.getCurrentEnv().getCatalogMgr().getCatalogOrAnalysisException(dbTableName.getCtl());
             DatabaseIf db = catalog.getDbOrAnalysisException(dbTableName.getDb());
             TableIf fullTable = db.getTableNullable(dbTableName.getTbl());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropCachedStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropCachedStatsCommand.java
index 69c7a2ef4cd..ab9561b8791 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropCachedStatsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropCachedStatsCommand.java
@@ -68,7 +68,7 @@ public class DropCachedStatsCommand extends Command implements NoForward {
                 + " in your FE conf file");
         }
 
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         String catalogName = tableNameInfo.getCtl();
         String dbName = tableNameInfo.getDb();
         String tblName = tableNameInfo.getTbl();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropConstraintCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropConstraintCommand.java
index 671cbd4ff9a..467064296e7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropConstraintCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropConstraintCommand.java
@@ -20,6 +20,7 @@ package org.apache.doris.nereids.trees.plans.commands;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.TableIf;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.nereids.NereidsPlanner;
 import org.apache.doris.nereids.analyzer.UnboundRelation;
 import org.apache.doris.nereids.exceptions.AnalysisException;
@@ -62,7 +63,8 @@ public class DropConstraintCommand extends Command implements ForwardWithSync {
         TableNameInfo tableNameInfo;
         try {
             TableIf table = extractTable(ctx, plan);
-            tableNameInfo = new TableNameInfo(table);
+            tableNameInfo = TableNameInfoUtils.fromCatalogDb(
+                    table.getDatabase().getCatalog(), table.getDatabase(), table);
         } catch (Exception e) {
             // Table may no longer exist (e.g., external table deleted by another system).
             // Fall back to extracting the table name from the unresolved plan.
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropMaterializedViewCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropMaterializedViewCommand.java
index 1b0e853a305..36363373594 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropMaterializedViewCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropMaterializedViewCommand.java
@@ -60,7 +60,7 @@ public class DropMaterializedViewCommand extends Command implements ForwardWithS
      */
     @VisibleForTesting
     public void validate(ConnectContext ctx) throws AnalysisException {
-        tableName.analyze(ctx);
+        tableName.analyze(ctx.getNameSpaceContext());
         // disallow external catalog
         Util.prohibitExternalCatalog(tableName.getCtl(), this.getClass().getSimpleName());
         // check access
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropRowPolicyCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropRowPolicyCommand.java
index 9602738380d..67d5dfefc40 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropRowPolicyCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropRowPolicyCommand.java
@@ -70,7 +70,7 @@ public class DropRowPolicyCommand extends DropCommand {
      * validate
      */
     public void validate(ConnectContext ctx) throws AnalysisException {
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         if (user != null) {
             user.analyze();
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStatsCommand.java
index 3c81ed91642..83afbc6f33f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStatsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStatsCommand.java
@@ -109,7 +109,7 @@ public class DropStatsCommand extends DropCommand {
                 + " in your FE conf file");
         }
 
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         String catalogName = tableNameInfo.getCtl();
         String dbName = tableNameInfo.getDb();
         String tblName = tableNameInfo.getTbl();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStreamCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStreamCommand.java
index 9c4bc2b64ef..508e2599f13 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStreamCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropStreamCommand.java
@@ -60,7 +60,7 @@ public class DropStreamCommand extends Command implements ForwardWithSync {
         if (Strings.isNullOrEmpty(tableName.getDb())) {
             tableName.setDb(ctx.getDatabase());
         }
-        tableName.analyze(ctx);
+        tableName.analyze(ctx.getNameSpaceContext());
         InternalDatabaseUtil.checkDatabase(tableName.getDb(), ctx);
         // check access
         if (!Env.getCurrentEnv().getAccessManager()
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropTableCommand.java
index df295850dc4..d947b8a65b7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropTableCommand.java
@@ -78,7 +78,7 @@ public class DropTableCommand extends Command implements ForwardWithSync {
         if (Strings.isNullOrEmpty(tableName.getDb())) {
             tableName.setDb(ctx.getDatabase());
         }
-        tableName.analyze(ctx);
+        tableName.analyze(ctx.getNameSpaceContext());
         InternalDatabaseUtil.checkDatabase(tableName.getDb(), ctx);
         // check access
         if (!Env.getCurrentEnv().getAccessManager()
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropViewCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropViewCommand.java
index 9701d7c76df..7708b0c4a30 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropViewCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DropViewCommand.java
@@ -58,7 +58,7 @@ public class DropViewCommand extends Command implements ForwardWithSync {
         if (Strings.isNullOrEmpty(tableName.getDb())) {
             tableName.setDb(ctx.getDatabase());
         }
-        tableName.analyze(ctx);
+        tableName.analyze(ctx.getNameSpaceContext());
         InternalDatabaseUtil.checkDatabase(tableName.getDb(), ctx);
         // check access
         if (!Env.getCurrentEnv().getAccessManager()
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ExecuteActionCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ExecuteActionCommand.java
index e10de1adcad..9ab06d3121d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ExecuteActionCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ExecuteActionCommand.java
@@ -75,7 +75,7 @@ public class ExecuteActionCommand extends Command implements ForwardWithSync {
 
     @Override
     public void run(ConnectContext ctx, StmtExecutor executor) throws Exception {
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         CatalogIf<?> catalog = Env.getCurrentEnv().getCatalogMgr().getCatalog(tableNameInfo.getCtl());
         if (catalog == null) {
             throw new AnalysisException("Catalog " + tableNameInfo.getCtl() + " does not exist");
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/LockTablesCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/LockTablesCommand.java
index b2083eb4688..dd0768c7e75 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/LockTablesCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/LockTablesCommand.java
@@ -48,7 +48,7 @@ public class LockTablesCommand extends Command implements NoForward {
     public void run(ConnectContext ctx, StmtExecutor executor) throws Exception {
         for (LockTableInfo lockTable : lockTables) {
             TableNameInfo tableNameInfo = lockTable.getTableNameInfo();
-            tableNameInfo.analyze(ctx);
+            tableNameInfo.analyze(ctx.getNameSpaceContext());
             Database db = ctx.getEnv().getInternalCatalog().getDbOrAnalysisException(tableNameInfo.getDb());
             db.getTableOrAnalysisException(tableNameInfo.getTbl());
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/RecoverPartitionCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/RecoverPartitionCommand.java
index e9228d0d9b7..a6aca7adc3b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/RecoverPartitionCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/RecoverPartitionCommand.java
@@ -52,7 +52,7 @@ public class RecoverPartitionCommand extends RecoverCommand {
 
     @Override
     public void doRun(ConnectContext ctx, StmtExecutor executor) throws UserException {
-        dbTblName.analyze(ctx);
+        dbTblName.analyze(ctx.getNameSpaceContext());
 
         // disallow external catalog
         Util.prohibitExternalCatalog(dbTblName.getCtl(), this.getClass().getSimpleName());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/RecoverTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/RecoverTableCommand.java
index 5b60fc83187..f0ada745dd9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/RecoverTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/RecoverTableCommand.java
@@ -49,7 +49,7 @@ public class RecoverTableCommand extends RecoverCommand {
 
     @Override
     public void doRun(ConnectContext ctx, StmtExecutor executor) throws UserException {
-        dbTblName.analyze(ctx);
+        dbTblName.analyze(ctx.getNameSpaceContext());
 
         // disallow external catalog
         Util.prohibitExternalCatalog(dbTblName.getCtl(), this.getClass().getSimpleName());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowAnalyzeCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowAnalyzeCommand.java
index c0f5b8c4387..aec01284cf4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowAnalyzeCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowAnalyzeCommand.java
@@ -111,7 +111,7 @@ public class ShowAnalyzeCommand extends ShowCommand {
     private void validate(ConnectContext ctx) throws AnalysisException {
         checkShowAnalyzePriv(ctx);
         if (tableNameInfo != null) {
-            tableNameInfo.analyze(ctx);
+            tableNameInfo.analyze(ctx.getNameSpaceContext());
             ctl = tableNameInfo.getCtl();
             db = tableNameInfo.getDb();
             table = tableNameInfo.getTbl();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnHistogramStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnHistogramStatsCommand.java
index 8506183ec03..858f13d8287 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnHistogramStatsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnHistogramStatsCommand.java
@@ -81,7 +81,7 @@ public class ShowColumnHistogramStatsCommand extends ShowCommand {
      * validate
      */
     public void validate(ConnectContext ctx) throws UserException {
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
 
         // disallow external catalog
         Util.prohibitExternalCatalog(tableNameInfo.getCtl(), this.getClass().getSimpleName());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnStatsCommand.java
index aeb0821f55c..a26838de5d0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnStatsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnStatsCommand.java
@@ -123,7 +123,7 @@ public class ShowColumnStatsCommand extends ShowCommand {
     }
 
     private void validate(ConnectContext ctx) throws Exception {
-        tableName.analyze(ctx);
+        tableName.analyze(ctx.getNameSpaceContext());
         if (partitionNames != null) {
             partitionNames.validate();
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnsCommand.java
index 221482dba7d..b7e01114454 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnsCommand.java
@@ -101,7 +101,7 @@ public class ShowColumnsCommand extends ShowCommand {
         if (!Strings.isNullOrEmpty(databaseName)) {
             tableNameInfo.setDb(databaseName);
         }
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         if (!Env.getCurrentEnv().getAccessManager()
                 .checkTblPriv(ConnectContext.get(), tableNameInfo.getCtl(), tableNameInfo.getDb(),
                         tableNameInfo.getTbl(), PrivPredicate.SHOW)) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowConstraintsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowConstraintsCommand.java
index d24289b0877..06c98d20252 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowConstraintsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowConstraintsCommand.java
@@ -24,6 +24,7 @@ import org.apache.doris.catalog.ScalarType;
 import org.apache.doris.catalog.TableIf;
 import org.apache.doris.catalog.constraint.Constraint;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.nereids.trees.plans.PlanType;
 import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
 import org.apache.doris.nereids.util.RelationUtil;
@@ -69,7 +70,8 @@ public class ShowConstraintsCommand extends ShowCommand {
     public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception {
         TableIf tableIf = RelationUtil.getDbAndTable(
                 RelationUtil.getQualifierName(ctx, nameParts), ctx.getEnv(), Optional.empty()).value();
-        TableNameInfo tableNameInfo = new TableNameInfo(tableIf);
+        TableNameInfo tableNameInfo = TableNameInfoUtils.fromCatalogDb(
+                tableIf.getDatabase().getCatalog(), tableIf.getDatabase(), tableIf);
         Map<String, Constraint> constraints = Env.getCurrentEnv().getConstraintManager()
                 .getConstraints(tableNameInfo);
         List<List<String>> res = constraints.entrySet().stream()
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateMaterializedViewCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateMaterializedViewCommand.java
index 87d9b0daa1f..8df4f0c978b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateMaterializedViewCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateMaterializedViewCommand.java
@@ -61,7 +61,7 @@ public class ShowCreateMaterializedViewCommand extends ShowCommand {
     }
 
     private void validate(ConnectContext ctx) throws AnalysisException {
-        tblNameInfo.analyze(ctx);
+        tblNameInfo.analyze(ctx.getNameSpaceContext());
 
         // disallow external catalog
         Util.prohibitExternalCatalog(tblNameInfo.getCtl(), this.getClass().getSimpleName());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateStreamCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateStreamCommand.java
index 21413739719..502fb7dd0f0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateStreamCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateStreamCommand.java
@@ -57,7 +57,7 @@ public class ShowCreateStreamCommand extends ShowCommand {
     }
 
     private void validate(ConnectContext ctx) throws AnalysisException {
-        tblNameInfo.analyze(ctx);
+        tblNameInfo.analyze(ctx.getNameSpaceContext());
 
         TableIf tableIf = Env.getCurrentEnv().getCatalogMgr()
                 .getCatalogOrAnalysisException(tblNameInfo.getCtl())
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateTableCommand.java
index c534d62d01d..91a448922d2 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateTableCommand.java
@@ -94,7 +94,7 @@ public class ShowCreateTableCommand extends ShowCommand {
     }
 
     private void validate(ConnectContext ctx) throws AnalysisException {
-        tblNameInfo.analyze(ctx);
+        tblNameInfo.analyze(ctx.getNameSpaceContext());
 
         DatabaseIf db = Env.getCurrentEnv().getCatalogMgr()
                 .getCatalogOrAnalysisException(tblNameInfo.getCtl())
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateViewCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateViewCommand.java
index 047f8372312..16c5e206e61 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateViewCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCreateViewCommand.java
@@ -60,7 +60,7 @@ public class ShowCreateViewCommand extends ShowCommand {
     }
 
     private void validate(ConnectContext ctx) throws AnalysisException {
-        tblNameInfo.analyze(ctx);
+        tblNameInfo.analyze(ctx.getNameSpaceContext());
 
         TableIf tableIf = Env.getCurrentEnv().getCatalogMgr()
                 .getCatalogOrAnalysisException(tblNameInfo.getCtl())
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowDataCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowDataCommand.java
index 5481e7b9253..23d7ac1f88e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowDataCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowDataCommand.java
@@ -183,7 +183,7 @@ public class ShowDataCommand extends ShowCommand {
             return;
         }
         if (tableName != null) {
-            tableName.analyze(ctx);
+            tableName.analyze(ctx.getNameSpaceContext());
             // disallow external catalog
             Util.prohibitExternalCatalog(tableName.getCtl(), this.getClass().getSimpleName());
             dbName = tableName.getDb();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowDataSkewCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowDataSkewCommand.java
index 1065741d3aa..5c356f618f8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowDataSkewCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowDataSkewCommand.java
@@ -61,7 +61,7 @@ public class ShowDataSkewCommand extends ShowCommand {
 
     @Override
     public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception {
-        tableRefInfo.analyze(ctx);
+        tableRefInfo.analyze(ctx.getNameSpaceContext());
         // disallow external catalog
         Util.prohibitExternalCatalog(tableRefInfo.getTableNameInfo().getCtl(), this.getClass().getSimpleName());
         if (!Env.getCurrentEnv().getAccessManager()
@@ -74,7 +74,7 @@ public class ShowDataSkewCommand extends ShowCommand {
                     tableRefInfo.getTableNameInfo().getDb() + "." + tableRefInfo.getTableNameInfo().getTbl());
         }
         try {
-            tableRefInfo.analyze(ctx);
+            tableRefInfo.analyze(ctx.getNameSpaceContext());
             Util.prohibitExternalCatalog(tableRefInfo.getTableNameInfo().getCtl(), this.getClass().getSimpleName());
 
             List<List<String>> results = MetadataViewer.getDataSkew(tableRefInfo.getTableNameInfo().getDb(),
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowIndexStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowIndexStatsCommand.java
index 480deef2d3c..0fd6b5215f7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowIndexStatsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowIndexStatsCommand.java
@@ -71,7 +71,7 @@ public class ShowIndexStatsCommand extends ShowCommand {
      * validate
      */
     public void validate(ConnectContext ctx) throws AnalysisException {
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
 
         CatalogIf<DatabaseIf> catalog = Env.getCurrentEnv().getCatalogMgr().getCatalog(tableNameInfo.getCtl());
         if (catalog == null) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowPartitionsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowPartitionsCommand.java
index b4e6a664752..bc3c5274ff0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowPartitionsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowPartitionsCommand.java
@@ -191,7 +191,7 @@ public class ShowPartitionsCommand extends ShowCommand {
         if (Strings.isNullOrEmpty(tableName.getDb())) {
             tableName.setDb(ctx.getDatabase());
         }
-        tableName.analyze(ctx);
+        tableName.analyze(ctx.getNameSpaceContext());
 
         catalog = Env.getCurrentEnv().getCatalogMgr().getCatalog(tableName.getCtl());
         if (catalog == null) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowQueryStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowQueryStatsCommand.java
index df873fe3d40..4b4823b6846 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowQueryStatsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowQueryStatsCommand.java
@@ -102,7 +102,7 @@ public class ShowQueryStatsCommand extends ShowCommand {
             return;
         }
         if (tableNameInfo != null) {
-            tableNameInfo.analyze(ctx);
+            tableNameInfo.analyze(ctx.getNameSpaceContext());
             dbName = tableNameInfo.getDb();
         }
         DatabaseIf db = Env.getCurrentEnv().getCurrentCatalog().getDbOrDdlException(dbName);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowQueuedAnalyzeJobsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowQueuedAnalyzeJobsCommand.java
index c8a13146d26..54b61acdc9b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowQueuedAnalyzeJobsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowQueuedAnalyzeJobsCommand.java
@@ -95,7 +95,7 @@ public class ShowQueuedAnalyzeJobsCommand extends ShowCommand {
     private void validate(ConnectContext ctx) throws AnalysisException {
         checkShowQueuedAnalyzeJobsPriv(ctx);
         if (tableNameInfo != null) {
-            tableNameInfo.analyze(ctx);
+            tableNameInfo.analyze(ctx.getNameSpaceContext());
             ctl = tableNameInfo.getCtl();
             db = tableNameInfo.getDb();
             table = tableNameInfo.getTbl();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowReplicaDistributionCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowReplicaDistributionCommand.java
index 4f8c5fe8409..3614f4bad5a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowReplicaDistributionCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowReplicaDistributionCommand.java
@@ -71,7 +71,7 @@ public class ShowReplicaDistributionCommand extends ShowCommand {
         if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)) {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN");
         }
-        tableRefInfo.analyze(ctx);
+        tableRefInfo.analyze(ctx.getNameSpaceContext());
         Util.prohibitExternalCatalog(tableRefInfo.getTableNameInfo().getCtl(), this.getClass().getSimpleName());
 
         List<List<String>> results;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowReplicaStatusCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowReplicaStatusCommand.java
index ecc9168db95..b3c09ca35b0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowReplicaStatusCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowReplicaStatusCommand.java
@@ -84,7 +84,7 @@ public class ShowReplicaStatusCommand extends ShowCommand {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN");
         }
 
-        tableRefInfo.getTableNameInfo().analyze(ctx);
+        tableRefInfo.getTableNameInfo().analyze(ctx.getNameSpaceContext());
         Util.prohibitExternalCatalog(tableRefInfo.getTableNameInfo().getCtl(), this.getClass().getSimpleName());
 
         PartitionNamesInfo partitionNamesInfo = tableRefInfo.getPartitionNamesInfo();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTableStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTableStatsCommand.java
index 9b94ca7b561..5633bf7c781 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTableStatsCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTableStatsCommand.java
@@ -142,7 +142,7 @@ public class ShowTableStatsCommand extends ShowCommand {
             return;
         }
         assert tableNameInfo != null;
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         if (partitionNamesInfo != null) {
             partitionNamesInfo.validate();
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsFromTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsFromTableCommand.java
index 986eb21924e..15794db5a1b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsFromTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsFromTableCommand.java
@@ -105,7 +105,7 @@ public class ShowTabletsFromTableCommand extends ShowCommand {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "SHOW TABLETS");
         }
 
-        dbTableName.analyze(ctx);
+        dbTableName.analyze(ctx.getNameSpaceContext());
         Util.prohibitExternalCatalog(dbTableName.getCtl(), this.getClass().getSimpleName());
 
         if (partitionNames != null) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowViewCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowViewCommand.java
index 4504fa8d227..9085d7c3062 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowViewCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowViewCommand.java
@@ -82,7 +82,7 @@ public class ShowViewCommand extends ShowCommand {
             // this act same as in MySQL
             tbl.setDb(db);
         }
-        tbl.analyze(ctx);
+        tbl.analyze(ctx.getNameSpaceContext());
         // disallow external catalog
         Util.prohibitExternalCatalog(tbl.getCtl(), this.getClass().getSimpleName());
 
@@ -102,7 +102,7 @@ public class ShowViewCommand extends ShowCommand {
             // get table refs instead of get tables because it don't need to check table's validity
             List<TableNameInfo> tableNameInfos = getTableNames(ctx, view.getInlineViewDef());
             for (TableNameInfo tableNameInfo : tableNameInfos) {
-                tableNameInfo.analyze(ctx);
+                tableNameInfo.analyze(ctx.getNameSpaceContext());
                 if (tableNameInfo.equals(tbl)) {
                     matchViews.add(view);
                 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/TruncateTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/TruncateTableCommand.java
index 86e3c6efca7..1ae4bf89567 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/TruncateTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/TruncateTableCommand.java
@@ -60,7 +60,7 @@ public class TruncateTableCommand extends Command implements ForwardWithSync {
      * validate
      */
     public void validate(ConnectContext ctx) throws AnalysisException {
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
 
         InternalDatabaseUtil.checkDatabase(tableNameInfo.getDb(), ctx);
         // check access
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UnsetVariableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UnsetVariableCommand.java
index 186e4154e73..cf0bde2b368 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UnsetVariableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UnsetVariableCommand.java
@@ -32,6 +32,7 @@ import org.apache.doris.nereids.trees.plans.PlanType;
 import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.qe.StmtExecutor;
+import org.apache.doris.qe.VarAttrDef;
 import org.apache.doris.qe.VariableMgr;
 import org.apache.doris.qe.VariableMgr.VarContext;
 
@@ -129,7 +130,7 @@ public class UnsetVariableCommand extends Command implements Forward {
             VarContext varCtx = VariableMgr.getVarContext(var.getVariable());
             // only unset for session variable.
             // If this is a global variable, no need to do this because it has been synced from editlog already.
-            if (varCtx != null && (varCtx.getFlag() & VariableMgr.SESSION) != 0) {
+            if (varCtx != null && (varCtx.getFlag() & VarAttrDef.SESSION) != 0) {
                 VariableMgr.setVar(context.getSessionVariable(), var);
             }
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/WarmUpClusterCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/WarmUpClusterCommand.java
index e77585f78bc..0a62da1b8f5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/WarmUpClusterCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/WarmUpClusterCommand.java
@@ -184,7 +184,7 @@ public class WarmUpClusterCommand extends Command implements ForwardWithSync {
             for (WarmUpItem warmUpItem : warmUpItems) {
                 TableNameInfo tableNameInfo = warmUpItem.getTableNameInfo();
                 String partitionName = warmUpItem.getPartitionName();
-                tableNameInfo.analyze(connectContext);
+                tableNameInfo.analyze(connectContext.getNameSpaceContext());
                 String dbName = tableNameInfo.getDb();
                 if (Strings.isNullOrEmpty(dbName)) {
                     ErrorReport.reportAnalysisException(ErrorCode.ERR_NO_DB_ERROR, dbName);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterMTMVInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterMTMVInfo.java
index bde55ba8ebe..769c99de3e9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterMTMVInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterMTMVInfo.java
@@ -46,7 +46,7 @@ public abstract class AlterMTMVInfo {
      * analyze alter table info
      */
     public void analyze(ConnectContext ctx) throws AnalysisException {
-        mvName.analyze(ctx);
+        mvName.analyze(ctx.getNameSpaceContext());
         if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ctx, mvName.getCtl(), mvName.getDb(),
                 mvName.getTbl(), PrivPredicate.ALTER)) {
             String message = ErrorCode.ERR_TABLEACCESS_DENIED_ERROR.formatErrorMsg("ALTER",
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterViewInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterViewInfo.java
index 2af1db16849..b7886767021 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterViewInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterViewInfo.java
@@ -58,7 +58,7 @@ public class AlterViewInfo extends BaseViewInfo {
         if (viewName == null) {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_NO_TABLES_USED);
         }
-        viewName.analyze(ctx);
+        viewName.analyze(ctx.getNameSpaceContext());
         FeNameFormat.checkTableName(viewName.getTbl());
         // disallow external catalog
         Util.prohibitExternalCatalog(viewName.getCtl(), "AlterViewCommand");
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/BuildIndexOp.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/BuildIndexOp.java
index 1c6f2491983..867aa923a26 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/BuildIndexOp.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/BuildIndexOp.java
@@ -82,7 +82,7 @@ public class BuildIndexOp extends AlterTableOp {
 
     @Override
     public void validate(ConnectContext ctx) throws UserException {
-        tableName.analyze(ctx);
+        tableName.analyze(ctx.getNameSpaceContext());
         DatabaseIf<Table> db = Env.getCurrentEnv().getCatalogMgr().getInternalCatalog()
                 .getDb(tableName.getDb()).orElse(null);
         if (db == null) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CancelMTMVTaskInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CancelMTMVTaskInfo.java
index 158378b89f3..2ba2c69bf14 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CancelMTMVTaskInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CancelMTMVTaskInfo.java
@@ -48,7 +48,7 @@ public class CancelMTMVTaskInfo {
      * @param ctx ConnectContext
      */
     public void analyze(ConnectContext ctx) {
-        mvName.analyze(ctx);
+        mvName.analyze(ctx.getNameSpaceContext());
         if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ConnectContext.get(), mvName.getCtl(), mvName.getDb(),
                 mvName.getTbl(), PrivPredicate.CREATE)) {
             String message = ErrorCode.ERR_TABLEACCESS_DENIED_ERROR.formatErrorMsg("CREATE",
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateIndexOp.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateIndexOp.java
index 765dd1875ca..e5f1b86e19e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateIndexOp.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateIndexOp.java
@@ -74,7 +74,7 @@ public class CreateIndexOp extends AlterTableOp {
             throw new AnalysisException("index definition expected.");
         }
         if (tableName != null) {
-            tableName.analyze(ctx);
+            tableName.analyze(ctx.getNameSpaceContext());
         }
 
         indexDef.validate();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateMTMVInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateMTMVInfo.java
index 96b9981819f..1a2e570bff8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateMTMVInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateMTMVInfo.java
@@ -125,7 +125,7 @@ public class CreateMTMVInfo extends CreateTableInfo {
      */
     public void analyze(ConnectContext ctx) throws Exception {
         // analyze table name
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         if (!InternalCatalog.INTERNAL_CATALOG_NAME.equals(tableNameInfo.getCtl())) {
             throw new AnalysisException("Only support creating asynchronous materialized views in internal catalog");
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateStreamInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateStreamInfo.java
index bd8d0430924..171f2e1c918 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateStreamInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateStreamInfo.java
@@ -58,7 +58,7 @@ public class CreateStreamInfo {
      * validate create table stream info.
      */
     public void validate(ConnectContext ctx) throws UserException {
-        tableStreamName.analyze(ctx);
+        tableStreamName.analyze(ctx.getNameSpaceContext());
         FeNameFormat.checkTableName(tableStreamName.getTbl());
 
         // disallow external catalog
@@ -72,7 +72,7 @@ public class CreateStreamInfo {
         }
 
         // check base table
-        baseTableName.analyze(ctx);
+        baseTableName.analyze(ctx.getNameSpaceContext());
         if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ctx,
                 baseTableName.getCtl(), baseTableName.getDb(), baseTableName.getTbl(),
                 PrivPredicate.SELECT)) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableLikeInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableLikeInfo.java
index 67658f7d6bc..06d59cdd2bd 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableLikeInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableLikeInfo.java
@@ -53,7 +53,7 @@ public class CreateTableLikeInfo {
 
     /** validate */
     public void validate(ConnectContext ctx) throws AnalysisException {
-        existedTableName.analyze(ctx);
+        existedTableName.analyze(ctx.getNameSpaceContext());
         // disallow external catalog
         Util.prohibitExternalCatalog(existedTableName.getCtl(), "CreateTableLikeCommand");
         //check privilege
@@ -63,7 +63,7 @@ public class CreateTableLikeInfo {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "SELECT");
         }
 
-        tableName.analyze(ctx);
+        tableName.analyze(ctx.getNameSpaceContext());
         // disallow external catalog
         Util.prohibitExternalCatalog(tableName.getCtl(), "CreateTableLikeCommand");
         FeNameFormat.checkTableName(tableName.getTbl());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateViewInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateViewInfo.java
index 202b5b58e4c..71a68506cb4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateViewInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateViewInfo.java
@@ -54,7 +54,7 @@ public class CreateViewInfo extends BaseViewInfo {
 
     /** init */
     public void init(ConnectContext ctx) throws UserException {
-        viewName.analyze(ctx);
+        viewName.analyze(ctx.getNameSpaceContext());
         FeNameFormat.checkTableName(viewName.getTbl());
         // disallow external catalog
         Util.prohibitExternalCatalog(viewName.getCtl(), "CreateViewCommand");
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DropIndexOp.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DropIndexOp.java
index 30cc6849bb2..847f67fc49f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DropIndexOp.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DropIndexOp.java
@@ -71,7 +71,7 @@ public class DropIndexOp extends AlterTableOp {
             throw new AnalysisException("index name is excepted");
         }
         if (tableName != null) {
-            tableName.analyze(ctx);
+            tableName.analyze(ctx.getNameSpaceContext());
         }
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DropMTMVInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DropMTMVInfo.java
index c170d914c4d..7445544ccb6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DropMTMVInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/DropMTMVInfo.java
@@ -44,7 +44,7 @@ public class DropMTMVInfo {
      * @param ctx ConnectContext
      */
     public void analyze(ConnectContext ctx) {
-        mvName.analyze(ctx);
+        mvName.analyze(ctx.getNameSpaceContext());
         if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ctx, mvName.getCtl(), mvName.getDb(),
                 mvName.getTbl(), PrivPredicate.DROP)) {
             String message = ErrorCode.ERR_TABLEACCESS_DENIED_ERROR.formatErrorMsg("DROP",
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/LabelNameInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/LabelNameInfo.java
index 321172c2c21..eecacc3d7aa 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/LabelNameInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/LabelNameInfo.java
@@ -20,10 +20,10 @@
 
 package org.apache.doris.nereids.trees.plans.commands.info;
 
-import org.apache.doris.catalog.Env;
 import org.apache.doris.common.FeNameFormat;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.qe.GlobalVariable;
 
 import com.google.common.base.Strings;
 
@@ -48,7 +48,7 @@ public class LabelNameInfo {
     public LabelNameInfo(String db, String label) {
         Objects.requireNonNull(label, "require label object");
         this.label = label;
-        if (Env.isStoredTableNamesLowerCase()) {
+        if (GlobalVariable.isStoredTableNamesLowerCase()) {
             this.label = label.toLowerCase();
         }
         this.db = db;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/PauseMTMVInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/PauseMTMVInfo.java
index cec4e7b9afe..b4615996dce 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/PauseMTMVInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/PauseMTMVInfo.java
@@ -46,7 +46,7 @@ public class PauseMTMVInfo {
      * @param ctx ConnectContext
      */
     public void analyze(ConnectContext ctx) {
-        mvName.analyze(ctx);
+        mvName.analyze(ctx.getNameSpaceContext());
         if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ConnectContext.get(), mvName.getCtl(), mvName.getDb(),
                 mvName.getTbl(), PrivPredicate.CREATE)) {
             String message = ErrorCode.ERR_TABLEACCESS_DENIED_ERROR.formatErrorMsg("CREATE",
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/RefreshMTMVInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/RefreshMTMVInfo.java
index c61362bddbb..03e8a225240 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/RefreshMTMVInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/RefreshMTMVInfo.java
@@ -66,7 +66,7 @@ public class RefreshMTMVInfo {
      * @param ctx ConnectContext
      */
     public void analyze(ConnectContext ctx) {
-        mvName.analyze(ctx);
+        mvName.analyze(ctx.getNameSpaceContext());
         if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ctx, mvName.getCtl(), mvName.getDb(),
                 mvName.getTbl(), PrivPredicate.CREATE)) {
             String message = ErrorCode.ERR_TABLEACCESS_DENIED_ERROR.formatErrorMsg("CREATE",
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ResumeMTMVInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ResumeMTMVInfo.java
index 8fbfd9d5bdc..b622044edcc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ResumeMTMVInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ResumeMTMVInfo.java
@@ -46,7 +46,7 @@ public class ResumeMTMVInfo {
      * @param ctx ConnectContext
      */
     public void analyze(ConnectContext ctx) {
-        mvName.analyze(ctx);
+        mvName.analyze(ctx.getNameSpaceContext());
         if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ConnectContext.get(), mvName.getCtl(), mvName.getDb(),
                 mvName.getTbl(), PrivPredicate.CREATE)) {
             String message = ErrorCode.ERR_TABLEACCESS_DENIED_ERROR.formatErrorMsg("CREATE",
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ShowCreateMTMVInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ShowCreateMTMVInfo.java
index 5cb91bd3d85..18387a0deac 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ShowCreateMTMVInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ShowCreateMTMVInfo.java
@@ -62,7 +62,7 @@ public class ShowCreateMTMVInfo {
      * @param ctx ConnectContext
      */
     public void analyze(ConnectContext ctx) {
-        mvName.analyze(ctx);
+        mvName.analyze(ctx.getNameSpaceContext());
         if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ConnectContext.get(), mvName.getCtl(), mvName.getDb(),
                 mvName.getTbl(), PrivPredicate.SHOW)) {
             String message = ErrorCode.ERR_TABLEACCESS_DENIED_ERROR.formatErrorMsg("SHOW",
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/refresh/RefreshTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/refresh/RefreshTableCommand.java
index 232e82a6b59..a58c0ff32a3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/refresh/RefreshTableCommand.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/refresh/RefreshTableCommand.java
@@ -48,7 +48,7 @@ public class RefreshTableCommand extends Command implements ForwardWithSync {
 
     @Override
     public void run(ConnectContext ctx, StmtExecutor executor) throws Exception {
-        tableNameInfo.analyze(ctx);
+        tableNameInfo.analyze(ctx.getNameSpaceContext());
         checkRefreshTableAccess();
         // refresh table execute logic
         Env.getCurrentEnv().getRefreshManager()
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCatalogRelation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCatalogRelation.java
index e3a36a9815f..3b25a969f27 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCatalogRelation.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCatalogRelation.java
@@ -28,6 +28,7 @@ import org.apache.doris.common.IdGenerator;
 import org.apache.doris.common.util.Util;
 import org.apache.doris.datasource.CatalogIf;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.memo.GroupExpression;
 import org.apache.doris.nereids.properties.DataTrait;
@@ -196,7 +197,7 @@ public abstract class LogicalCatalogRelation extends LogicalRelation implements
     @Override
     public void computeUnique(DataTrait.Builder builder) {
         Set<Slot> outputSet = Utils.fastToImmutableSet(getOutputSet());
-        TableNameInfo tableNameInfo = TableNameInfo.createOrNull(table);
+        TableNameInfo tableNameInfo = TableNameInfoUtils.fromTableOrNull(table);
         if (tableNameInfo == null) {
             return;
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalCatalogRelation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalCatalogRelation.java
index f7dfd70fb49..3a3fa26e22f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalCatalogRelation.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalCatalogRelation.java
@@ -27,6 +27,7 @@ import org.apache.doris.catalog.constraint.UniqueConstraint;
 import org.apache.doris.common.IdGenerator;
 import org.apache.doris.datasource.CatalogIf;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.memo.GroupExpression;
 import org.apache.doris.nereids.processor.post.runtimefilterv2.RuntimeFilterV2;
@@ -211,7 +212,7 @@ public abstract class PhysicalCatalogRelation extends PhysicalRelation implement
     @Override
     public void computeUnique(DataTrait.Builder builder) {
         Set<Slot> outputSet = Utils.fastToImmutableSet(getOutputSet());
-        TableNameInfo tableNameInfo = TableNameInfo.createOrNull(table);
+        TableNameInfo tableNameInfo = TableNameInfoUtils.fromTableOrNull(table);
         if (tableNameInfo == null) {
             return;
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/VariantField.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/VariantField.java
index a8e3bd9ded1..7e5b87878c4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/VariantField.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/VariantField.java
@@ -17,9 +17,9 @@
 
 package org.apache.doris.nereids.types;
 
+import org.apache.doris.catalog.PatternType;
 import org.apache.doris.common.GlobRegexUtil;
 import org.apache.doris.nereids.util.Utils;
-import org.apache.doris.thrift.TPatternType;
 
 import com.google.re2j.Pattern;
 import com.google.re2j.PatternSyntaxException;
@@ -33,10 +33,10 @@ public class VariantField {
     private final String pattern;
     private final DataType dataType;
     private final String comment;
-    private final TPatternType patternType;
+    private final PatternType patternType;
 
     public VariantField(String pattern, DataType dataType, String comment) {
-        this(pattern, dataType, comment, TPatternType.MATCH_NAME_GLOB.name());
+        this(pattern, dataType, comment, PatternType.MATCH_NAME_GLOB.name());
     }
 
     /**
@@ -50,11 +50,11 @@ public class VariantField {
         this.pattern = Objects.requireNonNull(pattern, "pattern should not be null");
         this.dataType = Objects.requireNonNull(dataType, "dataType should not be null");
         this.comment = Objects.requireNonNull(comment, "comment should not be null");
-        TPatternType type;
-        if (TPatternType.MATCH_NAME.name().equalsIgnoreCase(patternType)) {
-            type = TPatternType.MATCH_NAME;
+        PatternType type;
+        if (PatternType.MATCH_NAME.name().equalsIgnoreCase(patternType)) {
+            type = PatternType.MATCH_NAME;
         } else {
-            type = TPatternType.MATCH_NAME_GLOB;
+            type = PatternType.MATCH_NAME_GLOB;
         }
         this.patternType = Objects.requireNonNull(type, "patternType should not be null");
     }
@@ -86,10 +86,10 @@ public class VariantField {
      * @return true if the field name matches the pattern
      */
     public boolean matches(String fieldName) {
-        if (patternType == TPatternType.MATCH_NAME) {
+        if (patternType == PatternType.MATCH_NAME) {
             return pattern.equals(fieldName);
         }
-        if (patternType != TPatternType.MATCH_NAME_GLOB) {
+        if (patternType != PatternType.MATCH_NAME_GLOB) {
             return false;
         }
         try {
@@ -111,7 +111,7 @@ public class VariantField {
      */
     public String toSql() {
         StringBuilder sb = new StringBuilder();
-        if (patternType == TPatternType.MATCH_NAME) {
+        if (patternType == PatternType.MATCH_NAME) {
             sb.append(patternType.toString()).append(" ");
         }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/persist/GlobalVarPersistInfo.java b/fe/fe-core/src/main/java/org/apache/doris/persist/GlobalVarPersistInfo.java
index 4569a5d4f2f..bd8b07b2532 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/persist/GlobalVarPersistInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/persist/GlobalVarPersistInfo.java
@@ -21,7 +21,7 @@ import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
 import org.apache.doris.qe.GlobalVariable;
 import org.apache.doris.qe.SessionVariable;
-import org.apache.doris.qe.VariableMgr;
+import org.apache.doris.qe.VarAttrDef;
 
 import com.google.common.base.Preconditions;
 import org.apache.logging.log4j.LogManager;
@@ -74,7 +74,7 @@ public class GlobalVarPersistInfo implements Writable {
                 boolean found = false;
                 // 1. first find in defaultSessionVariable
                 for (Field field : SessionVariable.class.getDeclaredFields()) {
-                    VariableMgr.VarAttr attr = field.getAnnotation(VariableMgr.VarAttr.class);
+                    VarAttrDef.VarAttr attr = field.getAnnotation(VarAttrDef.VarAttr.class);
                     if (attr == null) {
                         continue;
                     }
@@ -89,7 +89,7 @@ public class GlobalVarPersistInfo implements Writable {
                 if (!found) {
                     // find in GlobalVariables
                     for (Field field : GlobalVariable.class.getDeclaredFields()) {
-                        VariableMgr.VarAttr attr = field.getAnnotation(VariableMgr.VarAttr.class);
+                        VarAttrDef.VarAttr attr = field.getAnnotation(VarAttrDef.VarAttr.class);
                         if (attr == null) {
                             continue;
                         }
@@ -105,7 +105,7 @@ public class GlobalVarPersistInfo implements Writable {
                 Preconditions.checkState(found, varName);
 
                 theField.setAccessible(true);
-                String fieldName = theField.getAnnotation(VariableMgr.VarAttr.class).name();
+                String fieldName = theField.getAnnotation(VarAttrDef.VarAttr.class).name();
                 switch (theField.getType().getSimpleName()) {
                     case "boolean":
                         root.put(fieldName, (Boolean) theField.get(varInstance));
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/MaterializationNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/MaterializationNode.java
index 1acb473d851..3a21ae34868 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/MaterializationNode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/MaterializationNode.java
@@ -21,6 +21,7 @@ import org.apache.doris.analysis.Expr;
 import org.apache.doris.analysis.ExprToThriftVisitor;
 import org.apache.doris.analysis.TupleDescriptor;
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ColumnToThrift;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.resource.computegroup.ComputeGroup;
 import org.apache.doris.system.Backend;
@@ -189,7 +190,7 @@ public class MaterializationNode extends PlanNode {
         for (List<Column> cols : lazyColumns) {
             List<TColumn> array = new ArrayList<>();
             for (Column col : cols) {
-                array.add(col.toThrift());
+                array.add(ColumnToThrift.toThrift(col));
             }
             thriftCols.add(array);
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java
index 5970f05cb90..155a0a2fa6f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java
@@ -31,6 +31,7 @@ import org.apache.doris.analysis.TupleDescriptor;
 import org.apache.doris.analysis.TupleId;
 import org.apache.doris.catalog.AggregateType;
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ColumnToThrift;
 import org.apache.doris.catalog.DiskInfo;
 import org.apache.doris.catalog.DistributionInfo;
 import org.apache.doris.catalog.HashDistributionInfo;
@@ -1095,7 +1096,7 @@ public class OlapScanNode extends ScanNode {
                     .map(Column::getName).collect(Collectors.toSet());
             olapTable.getColumnDesc(selectedIndexId, columnsDesc, keyColumnNames, keyColumnTypes,
                     materializedColumnNames);
-            columnsDesc.add(globalRowIdColumn.toThrift());
+            columnsDesc.add(ColumnToThrift.toThrift(globalRowIdColumn));
         } else {
             olapTable.getColumnDesc(selectedIndexId, columnsDesc, keyColumnNames, keyColumnTypes);
 
@@ -1120,7 +1121,7 @@ public class OlapScanNode extends ScanNode {
         // get correct table_schema.
         for (SlotDescriptor slot : desc.getSlots()) {
             if (slot.getVirtualColumn() != null) {
-                TColumn tColumn = slot.getColumn().toThrift();
+                TColumn tColumn = ColumnToThrift.toThrift(slot.getColumn());
                 columnsDesc.add(tColumn);
             }
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapTableSink.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapTableSink.java
index 699a4c31d49..56c877bb63e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapTableSink.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapTableSink.java
@@ -26,6 +26,7 @@ import org.apache.doris.analysis.SlotDescriptor;
 import org.apache.doris.analysis.ToSqlParams;
 import org.apache.doris.analysis.TupleDescriptor;
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ColumnToThrift;
 import org.apache.doris.catalog.DistributionInfo;
 import org.apache.doris.catalog.DistributionInfo.DistributionInfoType;
 import org.apache.doris.catalog.Env;
@@ -411,14 +412,14 @@ public class OlapTableSink extends DataSink {
             List<TOlapTableIndex> indexDesc = Lists.newArrayList();
             columns.addAll(indexMeta.getSchema().stream().map(Column::getNonShadowName).collect(Collectors.toList()));
             for (Column column : indexMeta.getSchema()) {
-                TColumn tColumn = column.toThrift();
+                TColumn tColumn = ColumnToThrift.toThrift(column);
                 // When schema change is doing, some modified column has prefix in name. Columns here
                 // is for the schema in rowset meta, which should be no column with shadow prefix.
                 // So we should remove the shadow prefix here.
                 if (column.getName().startsWith(Column.SHADOW_NAME_PREFIX)) {
                     tColumn.setColumnName(column.getNonShadowName());
                 }
-                column.setIndexFlag(tColumn, table);
+                ColumnToThrift.setIndexFlag(tColumn, table);
                 columnsDesc.add(tColumn);
             }
             List<Index> indexes = indexMeta.getIndexes();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/TVFTableSink.java b/fe/fe-core/src/main/java/org/apache/doris/planner/TVFTableSink.java
index b8c184ca401..c1e292c17fe 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/TVFTableSink.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/TVFTableSink.java
@@ -18,6 +18,7 @@
 package org.apache.doris.planner;
 
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ColumnToThrift;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.util.Util;
 import org.apache.doris.datasource.property.fileformat.CsvFileFormatProperties;
@@ -132,7 +133,7 @@ public class TVFTableSink extends DataSink {
         // Set columns
         List<TColumn> tColumns = new ArrayList<>();
         for (Column col : cols) {
-            tColumns.add(col.toThrift());
+            tColumns.add(ColumnToThrift.toThrift(col));
         }
         tSink.setColumns(tColumns);
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
index 401bd95d0f3..7f3065e13b9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
@@ -33,6 +33,7 @@ import org.apache.doris.catalog.Database;
 import org.apache.doris.catalog.DatabaseIf;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.FunctionRegistry;
+import org.apache.doris.catalog.NameSpaceContext;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.cloud.qe.ComputeGroupException;
 import org.apache.doris.cloud.system.CloudSystemInfoService;
@@ -871,6 +872,10 @@ public class ConnectContext {
         return currentDb;
     }
 
+    public NameSpaceContext getNameSpaceContext() {
+        return new NameSpaceContext(defaultCatalog, currentDb, currentDbId);
+    }
+
     public void setDatabase(String db) {
         currentDb = db;
         Optional<DatabaseIf> dbInstance = getCurrentCatalog().getDb(db);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index 139f4bd9fda..92b5a573d3d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -38,7 +38,7 @@ import org.apache.doris.nereids.parser.Dialect;
 import org.apache.doris.nereids.rules.RuleType;
 import org.apache.doris.nereids.rules.expression.ExpressionRuleType;
 import org.apache.doris.planner.GroupCommitBlockSink;
-import org.apache.doris.qe.VariableMgr.VarAttr;
+import org.apache.doris.qe.VarAttrDef.VarAttr;
 import org.apache.doris.thrift.TGroupCommitMode;
 import org.apache.doris.thrift.TPartialUpdateNewRowPolicy;
 import org.apache.doris.thrift.TQueryOptions;
@@ -881,13 +881,13 @@ public class SessionVariable implements Serializable, Writable {
             = "decompose_repeat_shuffle_index_in_max_group";
 
     public static final String HOT_VALUE_COLLECT_COUNT = "hot_value_collect_count";
-    @VariableMgr.VarAttr(name = HOT_VALUE_COLLECT_COUNT, needForward = true,
+    @VarAttrDef.VarAttr(name = HOT_VALUE_COLLECT_COUNT, needForward = true,
                 description = {"列统计信息收集时,收集占比排名前 HOT_VALUE_COLLECT_COUNT 的值作为 hot value",
                         "When collecting column statistics, collect the top values ranked by their "
                                 + "proportion as hot values, up to HOT_VALUE_COLLECT_COUNT."})
     public int hotValueCollectCount = 10; // Select the values that account for at least 10% of the column
 
-    @VariableMgr.VarAttr(name = ENABLE_INVERTED_INDEX_WAND_QUERY,
+    @VarAttrDef.VarAttr(name = ENABLE_INVERTED_INDEX_WAND_QUERY,
             description = {"是否开启倒排索引WAND查询优化", "Whether to enable inverted index WAND query optimization"})
     public boolean enableInvertedIndexWandQuery = true;
 
@@ -910,7 +910,7 @@ public class SessionVariable implements Serializable, Writable {
     public static final String SKEW_VALUE_THRESHOLD = "skew_value_threshold";
 
 
-    @VariableMgr.VarAttr(name = SKEW_VALUE_THRESHOLD, needForward = true,
+    @VarAttrDef.VarAttr(name = SKEW_VALUE_THRESHOLD, needForward = true,
                 description = {"当列中某个特定值的出现次数大于等于(rowCount/ndv)× skewValueThreshold 时,该值即被视为热点值",
                         "When the occurrence of a value in a column is greater than "
                                 + "skewValueThreshold tmies of average occurences "
@@ -931,7 +931,7 @@ public class SessionVariable implements Serializable, Writable {
     }
 
     public static final String HOT_VALUE_THRESHOLD = "hot_value_threshold";
-    @VariableMgr.VarAttr(name = HOT_VALUE_THRESHOLD, needForward = true,
+    @VarAttrDef.VarAttr(name = HOT_VALUE_THRESHOLD, needForward = true,
             description = {"hot value 在列中出现的最小比例",
                     "The minimum ratio of occurrences of a hot value in a column"})
     private double hotValueThreshold = 0.10d;
@@ -1011,7 +1011,7 @@ public class SessionVariable implements Serializable, Writable {
     /**
      * If set false, user couldn't submit analyze SQL and FE won't allocate any related resources.
      */
-    @VariableMgr.VarAttr(name = ENABLE_STATS)
+    @VarAttrDef.VarAttr(name = ENABLE_STATS)
     public boolean enableStats = true;
 
     // session origin value
@@ -1020,103 +1020,103 @@ public class SessionVariable implements Serializable, Writable {
     // if it is setStmt, we needn't collect session origin value
     public boolean isSingleSetVar = false;
 
-    @VariableMgr.VarAttr(name = EXPAND_RUNTIME_FILTER_BY_INNER_JION)
+    @VarAttrDef.VarAttr(name = EXPAND_RUNTIME_FILTER_BY_INNER_JION)
     public boolean expandRuntimeFilterByInnerJoin = true;
 
-    @VariableMgr.VarAttr(name = "enable_aggregate_cse", needForward = true)
+    @VarAttrDef.VarAttr(name = "enable_aggregate_cse", needForward = true)
     public boolean enableAggregateCse = true;
 
     // Experimental: enable pushing down virtual slots (common sub-expressions) into OlapScan.
     // When false (default), the optimizer rule PushDownVirtualColumnsIntoOlapScan will not apply.
-    @VariableMgr.VarAttr(name = "enable_virtual_slot_for_cse", needForward = true,
+    @VarAttrDef.VarAttr(name = "enable_virtual_slot_for_cse", needForward = true,
             varType = VariableAnnotation.EXPERIMENTAL,
             description = {"是否启用将公共子表达式作为虚拟列下推到 OlapScan(实验特性)",
                     "Enable pushing common sub-expressions as virtual columns into OlapScan (experimental)"})
     public boolean experimentalEnableVirtualSlotForCse = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_NEW_SHUFFLE_HASH_METHOD)
+    @VarAttrDef.VarAttr(name = ENABLE_NEW_SHUFFLE_HASH_METHOD)
     public boolean enableNewShffleHashMethod = true;
 
-    @VariableMgr.VarAttr(name = JDBC_CLICKHOUSE_QUERY_FINAL, needForward = true,
+    @VarAttrDef.VarAttr(name = JDBC_CLICKHOUSE_QUERY_FINAL, needForward = true,
             description = {"是否在查询 ClickHouse JDBC 外部表时,对查询 SQL 添加 FINAL 关键字。",
                     "Whether to add the FINAL keyword to the query SQL when querying ClickHouse JDBC external tables."})
     public boolean jdbcClickhouseQueryFinal = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_JDBC_ORACLE_NULL_PREDICATE_PUSH_DOWN, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_JDBC_ORACLE_NULL_PREDICATE_PUSH_DOWN, needForward = true,
             description = {"是否允许将 NULL 谓词下推到 Oracle JDBC 外部表。",
                     "Whether to allow NULL predicates to be pushed down to Oracle JDBC external tables."})
     public boolean enableJdbcOracleNullPredicatePushDown = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_JDBC_CAST_PREDICATE_PUSH_DOWN, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_JDBC_CAST_PREDICATE_PUSH_DOWN, needForward = true,
             description = {"是否允许将带有 CAST 表达式的谓词下推到 JDBC 外部表。",
                     "Whether to allow predicates with CAST expressions to be pushed down to JDBC external tables."})
     public boolean enableJdbcCastPredicatePushDown = true;
 
-    @VariableMgr.VarAttr(name = INSERT_VISIBLE_TIMEOUT_MS, needForward = true)
+    @VarAttrDef.VarAttr(name = INSERT_VISIBLE_TIMEOUT_MS, needForward = true)
     public long insertVisibleTimeoutMs = DEFAULT_INSERT_VISIBLE_TIMEOUT_MS;
 
     // max memory used on every backend. Default value to 100G.
-    @VariableMgr.VarAttr(name = EXEC_MEM_LIMIT, needForward = true)
+    @VarAttrDef.VarAttr(name = EXEC_MEM_LIMIT, needForward = true)
     public long maxExecMemByte = 100147483648L;
-    @VariableMgr.VarAttr(name = MAX_SCAN_MEM_RATIO, needForward = true)
+    @VarAttrDef.VarAttr(name = MAX_SCAN_MEM_RATIO, needForward = true)
     public double maxScanMemRatio = 0.3;
-    @VariableMgr.VarAttr(name = ENABLE_ADAPTIVE_SCAN, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_ADAPTIVE_SCAN, needForward = true)
     public boolean enableAdaptiveScan = true;
 
-    @VariableMgr.VarAttr(name = SCAN_QUEUE_MEM_LIMIT, needForward = true,
+    @VarAttrDef.VarAttr(name = SCAN_QUEUE_MEM_LIMIT, needForward = true,
             description = {"每个 Scan Instance 的 block queue 能够保存多少字节的 block",
                     "How many bytes of block can be saved in the block queue of each Scan Instance"})
     // 100MB
     public long maxScanQueueMemByte = 2147483648L / 20;
 
-    @VariableMgr.VarAttr(name = MAX_SCANNERS_CONCURRENCY, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = MAX_SCANNERS_CONCURRENCY, needForward = true, description = {
             "ScanNode 扫描数据的最大并发,默认为 4", "The max threads to read data of ScanNode, default 4"})
     public int maxScannersConcurrency = 4;
 
-    @VariableMgr.VarAttr(name = MAX_FILE_SCANNERS_CONCURRENCY, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = MAX_FILE_SCANNERS_CONCURRENCY, needForward = true, description = {
             "FileScanNode 扫描数据的最大并发,默认为 16", "The max threads to read data of FileScanNode, default 16"})
     public int maxFileScannersConcurrency = 16;
 
-    @VariableMgr.VarAttr(name = LOCAL_EXCHANGE_FREE_BLOCKS_LIMIT)
+    @VarAttrDef.VarAttr(name = LOCAL_EXCHANGE_FREE_BLOCKS_LIMIT)
     public int localExchangeFreeBlocksLimit = 4;
 
-    @VariableMgr.VarAttr(name = MIN_SCANNERS_CONCURRENCY, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = MIN_SCANNERS_CONCURRENCY, needForward = true, description = {
         "Scanner 的最小并发度,默认为 1", "The min concurrency of Scanner, default 1"
     })
     public int minScannersConcurrency = 1;
 
-    @VariableMgr.VarAttr(name = MIN_FILE_SCANNERS_CONCURRENCY, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = MIN_FILE_SCANNERS_CONCURRENCY, needForward = true, description = {
         "外表Scanner 的最小并发度,默认为 1", "The min concurrency of Remote Scanner, default 1"
     })
     public int minFileScannersConcurrency = 1;
 
-    @VariableMgr.VarAttr(name = MIN_SCAN_SCHEDULER_CONCURRENCY, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = MIN_SCAN_SCHEDULER_CONCURRENCY, needForward = true, description = {
         "ScanScheduler 的最小并发度,默认值 0 表示使用 Scan 线程池线程数量的两倍", "The min concurrency of ScanScheduler, "
             + "default 0 means use twice the number of Scan thread pool threads"
     }, varType = VariableAnnotation.DEPRECATED)
     public int minScanSchedulerConcurrency = 0;
 
-    @VariableMgr.VarAttr(name = CTE_MAX_RECURSION_DEPTH, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = CTE_MAX_RECURSION_DEPTH, needForward = true, description = {
             "CTE递归的最大深度,默认值100",
             "The maximum depth of CTE recursion. Default is 100" })
     public int cteMaxRecursionDepth = 100;
 
     // By default, the number of Limit items after OrderBy is changed from 65535 items
     // before v1.2.0 (not included), to return all items by default
-    @VariableMgr.VarAttr(name = DEFAULT_ORDER_BY_LIMIT, affectQueryResultInExecution = true)
+    @VarAttrDef.VarAttr(name = DEFAULT_ORDER_BY_LIMIT, affectQueryResultInExecution = true)
     private long defaultOrderByLimit = -1;
 
     // query timeout in second.
-    @VariableMgr.VarAttr(name = QUERY_TIMEOUT, needForward = true,
+    @VarAttrDef.VarAttr(name = QUERY_TIMEOUT, needForward = true,
             checker = "checkQueryTimeoutValid", setter = "setQueryTimeoutS")
     private int queryTimeoutS = 900;
 
     // query timeout in second.
-    @VariableMgr.VarAttr(name = ANALYZE_TIMEOUT, flag = VariableMgr.GLOBAL, needForward = true)
+    @VarAttrDef.VarAttr(name = ANALYZE_TIMEOUT, flag = VarAttrDef.GLOBAL, needForward = true)
     public int analyzeTimeoutS = 43200;
 
     // insert timeout in second
-    @VariableMgr.VarAttr(name = INTERNAL_CACHE_HOT_SPOT_TIMEOUT, flag = VariableMgr.GLOBAL, needForward = true)
+    @VarAttrDef.VarAttr(name = INTERNAL_CACHE_HOT_SPOT_TIMEOUT, flag = VarAttrDef.GLOBAL, needForward = true)
     public int cacheHotSpotTimeoutS = 300;
 
     // The global max_execution_time value provides the default for the session value for new connections.
@@ -1124,50 +1124,50 @@ public class SessionVariable implements Serializable, Writable {
     // no MAX_EXECUTION_TIME(N) optimizer hint or for which N is 0.
     // https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html
     // So that it is == query timeout in doris
-    @VariableMgr.VarAttr(name = MAX_EXECUTION_TIME, checker = "checkMaxExecutionTimeMSValid",
+    @VarAttrDef.VarAttr(name = MAX_EXECUTION_TIME, checker = "checkMaxExecutionTimeMSValid",
                         setter = "setMaxExecutionTimeMS")
     public int maxExecutionTimeMS = 900000;
 
-    @VariableMgr.VarAttr(name = INSERT_TIMEOUT, needForward = true)
+    @VarAttrDef.VarAttr(name = INSERT_TIMEOUT, needForward = true)
     public int insertTimeoutS = 14400;
 
     // if true, need report to coordinator when plan fragment execute successfully.
-    @VariableMgr.VarAttr(name = ENABLE_PROFILE, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_PROFILE, needForward = true)
     public boolean enableProfile = false;
 
-    @VariableMgr.VarAttr(name = RPC_VERBOSE_PROFILE_MAX_INSTANCE_COUNT, needForward = true)
+    @VarAttrDef.VarAttr(name = RPC_VERBOSE_PROFILE_MAX_INSTANCE_COUNT, needForward = true)
     public int rpcVerboseProfileMaxInstanceCount = 5;
 
     // When enable_profile is true, profile of queries that costs more than autoProfileThresholdMs
     // will be stored to disk.
-    @VariableMgr.VarAttr(name = AUTO_PROFILE_THRESHOLD_MS, needForward = true)
+    @VarAttrDef.VarAttr(name = AUTO_PROFILE_THRESHOLD_MS, needForward = true)
     public int autoProfileThresholdMs = -1;
 
-    @VariableMgr.VarAttr(name = "runtime_filter_prune_for_external", fuzzy = true)
+    @VarAttrDef.VarAttr(name = "runtime_filter_prune_for_external", fuzzy = true)
     public boolean runtimeFilterPruneForExternal = false;
 
-    @VariableMgr.VarAttr(name = "runtime_filter_jump_threshold")
+    @VarAttrDef.VarAttr(name = "runtime_filter_jump_threshold")
     public int runtimeFilterJumpThreshold = 2;
 
     // using hashset instead of group by + count can improve performance
     //        but may cause rpc failed when cluster has less BE
     // Whether this switch is turned on depends on the BE number
-    @VariableMgr.VarAttr(name = ENABLE_SINGLE_DISTINCT_COLUMN_OPT)
+    @VarAttrDef.VarAttr(name = ENABLE_SINGLE_DISTINCT_COLUMN_OPT)
     public boolean enableSingleDistinctColumnOpt = false;
 
     // Set sqlMode to empty string
-    @VariableMgr.VarAttr(name = SQL_MODE, needForward = true, affectQueryResultInPlan = true)
+    @VarAttrDef.VarAttr(name = SQL_MODE, needForward = true, affectQueryResultInPlan = true)
     public long sqlMode = SqlModeHelper.MODE_ONLY_FULL_GROUP_BY;
 
-    @VariableMgr.VarAttr(name = WORKLOAD_VARIABLE, needForward = true)
+    @VarAttrDef.VarAttr(name = WORKLOAD_VARIABLE, needForward = true)
     public String workloadGroup = "";
 
-    @VariableMgr.VarAttr(name = BYPASS_WORKLOAD_GROUP, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = BYPASS_WORKLOAD_GROUP, needForward = true, description = {
             "查询是否绕开 WorkloadGroup 的限制,目前仅支持绕开查询排队的逻辑",
             "whether bypass workload group's limitation, currently only support bypass query queue"})
     public boolean bypassWorkloadGroup = false;
 
-    @VariableMgr.VarAttr(name = QUERY_SLOT_COUNT, needForward = true, checker = "checkQuerySlotCount",
+    @VarAttrDef.VarAttr(name = QUERY_SLOT_COUNT, needForward = true, checker = "checkQuerySlotCount",
             description = {
                 "每个查询占用的 slot 的数量,workload group 的 query slot 的总数等于设置的最大并发数",
                 "Number of slots occupied by each query, the total number of query slots "
@@ -1181,164 +1181,164 @@ public class SessionVariable implements Serializable, Writable {
         }
     }
 
-    @VariableMgr.VarAttr(name = MAX_COLUMN_READER_NUM)
+    @VarAttrDef.VarAttr(name = MAX_COLUMN_READER_NUM)
     public int maxColumnReaderNum = 20000;
 
-    @VariableMgr.VarAttr(name = RESOURCE_VARIABLE)
+    @VarAttrDef.VarAttr(name = RESOURCE_VARIABLE)
     public String resourceGroup = "";
 
     // this is used to make mysql client happy
     // autocommit is actually a boolean value, but @@autocommit is type of BIGINT.
     // So we need to set convertBoolToLongMethod to make "select @@autocommit" happy.
-    @VariableMgr.VarAttr(name = AUTO_COMMIT, convertBoolToLongMethod = "convertBoolToLong")
+    @VarAttrDef.VarAttr(name = AUTO_COMMIT, convertBoolToLongMethod = "convertBoolToLong")
     public boolean autoCommit = true;
 
     // this is used to make c3p0 library happy
-    @VariableMgr.VarAttr(name = TX_ISOLATION)
+    @VarAttrDef.VarAttr(name = TX_ISOLATION)
     public String txIsolation = "REPEATABLE-READ";
 
     // this is used to make mysql client happy
-    @VariableMgr.VarAttr(name = TX_READ_ONLY)
+    @VarAttrDef.VarAttr(name = TX_READ_ONLY)
     public boolean txReadonly = false;
 
     // this is used to make mysql client happy
-    @VariableMgr.VarAttr(name = TRANSACTION_READ_ONLY)
+    @VarAttrDef.VarAttr(name = TRANSACTION_READ_ONLY)
     public boolean transactionReadonly = false;
 
     // this is used to make mysql client happy
-    @VariableMgr.VarAttr(name = TRANSACTION_ISOLATION)
+    @VarAttrDef.VarAttr(name = TRANSACTION_ISOLATION)
     public String transactionIsolation = "REPEATABLE-READ";
 
     // this is used to make c3p0 library happy
-    @VariableMgr.VarAttr(name = CHARACTER_SET_CLIENT)
+    @VarAttrDef.VarAttr(name = CHARACTER_SET_CLIENT)
     public String charsetClient = "utf8mb4";
-    @VariableMgr.VarAttr(name = CHARACTER_SET_CONNNECTION)
+    @VarAttrDef.VarAttr(name = CHARACTER_SET_CONNNECTION)
     public String charsetConnection = "utf8mb4";
-    @VariableMgr.VarAttr(name = CHARACTER_SET_RESULTS)
+    @VarAttrDef.VarAttr(name = CHARACTER_SET_RESULTS)
     public String charsetResults = "utf8mb4";
-    @VariableMgr.VarAttr(name = CHARACTER_SET_SERVER)
+    @VarAttrDef.VarAttr(name = CHARACTER_SET_SERVER)
     public String charsetServer = "utf8mb4";
-    @VariableMgr.VarAttr(name = COLLATION_CONNECTION)
+    @VarAttrDef.VarAttr(name = COLLATION_CONNECTION)
     public String collationConnection = "utf8mb4_0900_bin";
-    @VariableMgr.VarAttr(name = COLLATION_DATABASE)
+    @VarAttrDef.VarAttr(name = COLLATION_DATABASE)
     public String collationDatabase = "utf8mb4_0900_bin";
 
-    @VariableMgr.VarAttr(name = COLLATION_SERVER)
+    @VarAttrDef.VarAttr(name = COLLATION_SERVER)
     public String collationServer = "utf8mb4_0900_bin";
 
     // this is used to make c3p0 library happy
-    @VariableMgr.VarAttr(name = SQL_AUTO_IS_NULL)
+    @VarAttrDef.VarAttr(name = SQL_AUTO_IS_NULL)
     public boolean sqlAutoIsNull = false;
 
-    @VariableMgr.VarAttr(name = SQL_SELECT_LIMIT, needForward = true, affectQueryResultInExecution = true)
+    @VarAttrDef.VarAttr(name = SQL_SELECT_LIMIT, needForward = true, affectQueryResultInExecution = true)
     private long sqlSelectLimit = Long.MAX_VALUE;
 
     // this is used to make c3p0 library happy
-    @VariableMgr.VarAttr(name = MAX_ALLOWED_PACKET)
+    @VarAttrDef.VarAttr(name = MAX_ALLOWED_PACKET)
     public int maxAllowedPacket = 16777216;
 
-    @VariableMgr.VarAttr(name = AUTO_INCREMENT_INCREMENT)
+    @VarAttrDef.VarAttr(name = AUTO_INCREMENT_INCREMENT)
     public int autoIncrementIncrement = 1;
 
     // this is used to make c3p0 library happy
-    @VariableMgr.VarAttr(name = QUERY_CACHE_TYPE)
+    @VarAttrDef.VarAttr(name = QUERY_CACHE_TYPE)
     public int queryCacheType = 0;
 
     // The number of seconds the server waits for activity on an interactive connection before closing it
-    @VariableMgr.VarAttr(name = INTERACTIVE_TIMTOUT)
+    @VarAttrDef.VarAttr(name = INTERACTIVE_TIMTOUT)
     public int interactiveTimeout = 3600;
 
     // The number of seconds the server waits for activity on a noninteractive connection before closing it.
-    @VariableMgr.VarAttr(name = WAIT_TIMEOUT)
+    @VarAttrDef.VarAttr(name = WAIT_TIMEOUT)
     public int waitTimeoutS = 28800;
 
     // The number of seconds to wait for a block to be written to a connection before aborting the write
-    @VariableMgr.VarAttr(name = NET_WRITE_TIMEOUT)
+    @VarAttrDef.VarAttr(name = NET_WRITE_TIMEOUT)
     public int netWriteTimeout = 600;
 
     // The number of seconds to wait for a block to be written to a connection before aborting the write
-    @VariableMgr.VarAttr(name = NET_READ_TIMEOUT)
+    @VarAttrDef.VarAttr(name = NET_READ_TIMEOUT)
     public int netReadTimeout = 600;
 
     // The current time zone
-    @VariableMgr.VarAttr(name = TIME_ZONE, needForward = true, affectQueryResultInExecution = true)
+    @VarAttrDef.VarAttr(name = TIME_ZONE, needForward = true, affectQueryResultInExecution = true)
     public String timeZone = TimeUtils.getSystemTimeZone().getID();
 
-    @VariableMgr.VarAttr(name = LC_TIME_NAMES, needForward = true, affectQueryResultInExecution = true,
+    @VarAttrDef.VarAttr(name = LC_TIME_NAMES, needForward = true, affectQueryResultInExecution = true,
             setter = "setLcTimeNames")
     public String lcTimeNames = "en_US";
 
-    @VariableMgr.VarAttr(name = PARALLEL_EXCHANGE_INSTANCE_NUM)
+    @VarAttrDef.VarAttr(name = PARALLEL_EXCHANGE_INSTANCE_NUM)
     public int exchangeInstanceParallel = 256;
 
-    @VariableMgr.VarAttr(name = SQL_SAFE_UPDATES)
+    @VarAttrDef.VarAttr(name = SQL_SAFE_UPDATES)
     public int sqlSafeUpdates = 0;
 
     // only
-    @VariableMgr.VarAttr(name = NET_BUFFER_LENGTH, flag = VariableMgr.READ_ONLY)
+    @VarAttrDef.VarAttr(name = NET_BUFFER_LENGTH, flag = VarAttrDef.READ_ONLY)
     public int netBufferLength = 16384;
 
-    @VariableMgr.VarAttr(name = HAVE_QUERY_CACHE, flag = VariableMgr.READ_ONLY)
+    @VarAttrDef.VarAttr(name = HAVE_QUERY_CACHE, flag = VarAttrDef.READ_ONLY)
     public boolean haveQueryCache = false;
 
     // 4096 minus 16 + 16 bytes padding that in padding pod array
-    @VariableMgr.VarAttr(name = BATCH_SIZE, fuzzy = true, checker = "checkBatchSize", needForward = true)
+    @VarAttrDef.VarAttr(name = BATCH_SIZE, fuzzy = true, checker = "checkBatchSize", needForward = true)
     public int batchSize = 8160;
 
     // 16352 + 16 + 16 = 16384
-    @VariableMgr.VarAttr(name = BROKER_LOAD_BATCH_SIZE, fuzzy = true, checker = "checkBatchSize")
+    @VarAttrDef.VarAttr(name = BROKER_LOAD_BATCH_SIZE, fuzzy = true, checker = "checkBatchSize")
     public int brokerLoadBatchSize = 16352;
 
-    @VariableMgr.VarAttr(name = DISABLE_STREAMING_PREAGGREGATIONS, fuzzy = true)
+    @VarAttrDef.VarAttr(name = DISABLE_STREAMING_PREAGGREGATIONS, fuzzy = true)
     public boolean disableStreamPreaggregations = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_DISTINCT_STREAMING_AGGREGATION, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_DISTINCT_STREAMING_AGGREGATION, fuzzy = true)
     public boolean enableDistinctStreamingAggregation = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_STREAMING_AGG_HASH_JOIN_FORCE_PASSTHROUGH, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_STREAMING_AGG_HASH_JOIN_FORCE_PASSTHROUGH, fuzzy = true)
     public boolean enableStreamingAggHashJoinForcePassthrough = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_DISTINCT_STREAMING_AGG_FORCE_PASSTHROUGH, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_DISTINCT_STREAMING_AGG_FORCE_PASSTHROUGH, fuzzy = true)
     public boolean enableDistinctStreamingAggForcePassthrough = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_BROADCAST_JOIN_FORCE_PASSTHROUGH, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_BROADCAST_JOIN_FORCE_PASSTHROUGH, fuzzy = true)
     public boolean enableBroadcastJoinForcePassthrough = false;
 
-    @VariableMgr.VarAttr(name = DISABLE_COLOCATE_PLAN)
+    @VarAttrDef.VarAttr(name = DISABLE_COLOCATE_PLAN)
     public boolean disableColocatePlan = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_BUCKET_SHUFFLE_JOIN, varType = VariableAnnotation.EXPERIMENTAL_ONLINE)
+    @VarAttrDef.VarAttr(name = ENABLE_BUCKET_SHUFFLE_JOIN, varType = VariableAnnotation.EXPERIMENTAL_ONLINE)
     public boolean enableBucketShuffleJoin = true;
 
     /**
      * explode function row count enlarge factor.
      */
-    @VariableMgr.VarAttr(name = GENERATE_STATS_FACTOR, checker = "checkGenerateStatsFactor",
+    @VarAttrDef.VarAttr(name = GENERATE_STATS_FACTOR, checker = "checkGenerateStatsFactor",
             setter = "setGenerateStatsFactor")
     public int generateStatsFactor = 5;
 
-    @VariableMgr.VarAttr(name = PREFER_JOIN_METHOD)
+    @VarAttrDef.VarAttr(name = PREFER_JOIN_METHOD)
     public String preferJoinMethod = "broadcast";
 
-    @VariableMgr.VarAttr(name = FRAGMENT_TRANSMISSION_COMPRESSION_CODEC)
+    @VarAttrDef.VarAttr(name = FRAGMENT_TRANSMISSION_COMPRESSION_CODEC)
     public String fragmentTransmissionCompressionCodec = "none";
 
     // whether sync load to other cluster
-    @VariableMgr.VarAttr(name = CLOUD_ENABLE_MULTI_CLUSTER_SYNC_LOAD, needForward = true)
+    @VarAttrDef.VarAttr(name = CLOUD_ENABLE_MULTI_CLUSTER_SYNC_LOAD, needForward = true)
     public static boolean cloudEnableMultiClusterSyncLoad = false;
 
     /*
      * the parallel exec instance num for one Fragment in one BE
      * 1 means disable this feature
      */
-    @VariableMgr.VarAttr(name = PARALLEL_FRAGMENT_EXEC_INSTANCE_NUM, needForward = true, fuzzy = false,
+    @VarAttrDef.VarAttr(name = PARALLEL_FRAGMENT_EXEC_INSTANCE_NUM, needForward = true, fuzzy = false,
                         setter = "setFragmentInstanceNum", varType = VariableAnnotation.DEPRECATED)
     public int parallelExecInstanceNum = 8;
 
-    @VariableMgr.VarAttr(name = COLOCATE_MAX_PARALLEL_NUM, needForward = true, fuzzy = false)
+    @VarAttrDef.VarAttr(name = COLOCATE_MAX_PARALLEL_NUM, needForward = true, fuzzy = false)
     public int colocateMaxParallelNum = 128;
 
-    @VariableMgr.VarAttr(name = PARALLEL_PIPELINE_TASK_NUM, fuzzy = true, needForward = true,
+    @VarAttrDef.VarAttr(name = PARALLEL_PIPELINE_TASK_NUM, fuzzy = true, needForward = true,
                         setter = "setPipelineTaskNum")
     public int parallelPipelineTaskNum = 0;
 
@@ -1351,19 +1351,19 @@ public class SessionVariable implements Serializable, Writable {
     }
 
     public static final String IGNORE_SPLIT_TYPE = "ignore_split_type";
-    @VariableMgr.VarAttr(name = IGNORE_SPLIT_TYPE,
+    @VarAttrDef.VarAttr(name = IGNORE_SPLIT_TYPE,
             checker = "checkIgnoreSplitType",
             options = {"NONE", "IGNORE_JNI", "IGNORE_NATIVE", "IGNORE_PAIMON_CPP"},
             description = {"忽略指定类型的 split", "Ignore splits of the specified type"})
     public String ignoreSplitType = IgnoreSplitType.NONE.toString();
 
     public static final String USE_CONSISTENT_HASHING_FOR_EXTERNAL_SCAN = "use_consistent_hash_for_external_scan";
-    @VariableMgr.VarAttr(name = USE_CONSISTENT_HASHING_FOR_EXTERNAL_SCAN,
+    @VarAttrDef.VarAttr(name = USE_CONSISTENT_HASHING_FOR_EXTERNAL_SCAN,
             description = {"对外表采用一致性 hash 的方式做 split 的分发",
                     "Use consistent hashing to split the appearance for external scan"})
     public boolean useConsistentHashForExternalScan = false;
 
-    @VariableMgr.VarAttr(name = PROFILE_LEVEL, fuzzy = false,
+    @VarAttrDef.VarAttr(name = PROFILE_LEVEL, fuzzy = false,
             setter = "setProfileLevel", checker = "checkProfileLevel",
             description = { "查询 profile 的级别,1 表示只收集 MergedProfile 级别的 Counter,2 表示打印详细信息,"
                             + "3 表示打开一些可能导致性能回退的 Counter", "The level of query profile, "
@@ -1371,10 +1371,10 @@ public class SessionVariable implements Serializable, Writable {
                             + " 3 means open some Counters that may cause performance degradation"})
     public int profileLevel = 1;
 
-    @VariableMgr.VarAttr(name = MAX_INSTANCE_NUM)
+    @VarAttrDef.VarAttr(name = MAX_INSTANCE_NUM)
     public int maxInstanceNum = 64;
 
-    @VariableMgr.VarAttr(name = DML_PLAN_RETRY_TIMES, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = DML_PLAN_RETRY_TIMES, needForward = true, description = {
             "写入规划的最大重试次数。为了避免死锁,写入规划时采用了分阶段加锁。当在两次加锁中间,表结构发生变更时,会尝试重新规划。"
                     + "此变量限制重新规划的最大尝试次数。",
             "Maximum retry attempts for write planning. To avoid deadlocks, "
@@ -1385,23 +1385,23 @@ public class SessionVariable implements Serializable, Writable {
     })
     public int dmlPlanRetryTimes = 3;
 
-    @VariableMgr.VarAttr(name = ENABLE_INSERT_STRICT, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_INSERT_STRICT, needForward = true)
     public boolean enableInsertStrict = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_INSERT_VALUE_AUTO_CAST, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_INSERT_VALUE_AUTO_CAST, needForward = true, description = {
             "INSERT VALUE 语句是否自动类型转换。当前只针对长字符串自动截短。默认开。",
             "INSERT VALUE statement whether to automatically type cast. Only use for truncate long string. "
                     + "ON by default."
     })
     public boolean enableInsertValueAutoCast = true;
 
-    @VariableMgr.VarAttr(name = INSERT_MAX_FILTER_RATIO, needForward = true)
+    @VarAttrDef.VarAttr(name = INSERT_MAX_FILTER_RATIO, needForward = true)
     public double insertMaxFilterRatio = 1.0;
 
-    @VariableMgr.VarAttr(name = ENABLE_ODBC_TRANSCATION)
+    @VarAttrDef.VarAttr(name = ENABLE_ODBC_TRANSCATION)
     public boolean enableOdbcTransaction = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_BINARY_SEARCH_FILTERING_PARTITIONS,
             fuzzy = true,
             description = {
@@ -1411,7 +1411,7 @@ public class SessionVariable implements Serializable, Writable {
     )
     public boolean enableBinarySearchFilteringPartitions = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = CACHE_SORTED_PARTITION_INTERVAL_SECOND,
             fuzzy = false,
             description = {
@@ -1422,7 +1422,7 @@ public class SessionVariable implements Serializable, Writable {
     )
     public int cacheSortedPartitionIntervalSecond = 10;
 
-    @VariableMgr.VarAttr(name = SKIP_PRUNE_PREDICATE, fuzzy = true,
+    @VarAttrDef.VarAttr(name = SKIP_PRUNE_PREDICATE, fuzzy = true,
             description = {
                     "是否跳过“在分区裁剪后删除恒真谓词”的优化。默认为 OFF(即执行此优化)。",
                     "Skips the removal of always-true predicates after partition pruning. "
@@ -1432,179 +1432,179 @@ public class SessionVariable implements Serializable, Writable {
     public boolean skipPrunePredicate = false;
 
 
-    @VariableMgr.VarAttr(name = ENABLE_SQL_CACHE, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_SQL_CACHE, fuzzy = true)
     public boolean enableSqlCache = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_HIVE_SQL_CACHE, fuzzy = false)
+    @VarAttrDef.VarAttr(name = ENABLE_HIVE_SQL_CACHE, fuzzy = false)
     public boolean enableHiveSqlCache = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_QUERY_CACHE, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_QUERY_CACHE, fuzzy = true)
     public boolean enableQueryCache = false;
 
-    @VarAttr(name = QUERY_CACHE_FORCE_REFRESH)
+    @VarAttrDef.VarAttr(name = QUERY_CACHE_FORCE_REFRESH)
     private boolean queryCacheForceRefresh = false;
 
-    @VarAttr(name = QUERY_CACHE_ENTRY_MAX_BYTES)
+    @VarAttrDef.VarAttr(name = QUERY_CACHE_ENTRY_MAX_BYTES)
     private long queryCacheEntryMaxBytes = 5242880;
 
-    @VarAttr(name = QUERY_CACHE_ENTRY_MAX_ROWS)
+    @VarAttrDef.VarAttr(name = QUERY_CACHE_ENTRY_MAX_ROWS)
     private long queryCacheEntryMaxRows = 500000;
 
-    @VariableMgr.VarAttr(name = ENABLE_CONDITION_CACHE)
+    @VarAttrDef.VarAttr(name = ENABLE_CONDITION_CACHE)
     public boolean enableConditionCache = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_LEFT_SEMI_DIRECT_RETURN_OPT)
+    @VarAttrDef.VarAttr(name = ENABLE_LEFT_SEMI_DIRECT_RETURN_OPT)
     public boolean enableLeftSemiDirectReturnOpt = true;
 
-    @VariableMgr.VarAttr(name = FORWARD_TO_MASTER)
+    @VarAttrDef.VarAttr(name = FORWARD_TO_MASTER)
     public boolean forwardToMaster = true;
 
-    @VariableMgr.VarAttr(name = USE_V2_ROLLUP)
+    @VarAttrDef.VarAttr(name = USE_V2_ROLLUP)
     public boolean useV2Rollup = false;
 
-    @VariableMgr.VarAttr(name = REWRITE_COUNT_DISTINCT_TO_BITMAP_HLL)
+    @VarAttrDef.VarAttr(name = REWRITE_COUNT_DISTINCT_TO_BITMAP_HLL)
     public boolean rewriteCountDistinct = true;
 
     // compatible with some mysql client connect, say DataGrip of JetBrains
-    @VariableMgr.VarAttr(name = EVENT_SCHEDULER)
+    @VarAttrDef.VarAttr(name = EVENT_SCHEDULER)
     public String eventScheduler = "OFF";
-    @VariableMgr.VarAttr(name = STORAGE_ENGINE)
+    @VarAttrDef.VarAttr(name = STORAGE_ENGINE)
     public String storageEngine = "olap";
-    @VariableMgr.VarAttr(name = DEFAULT_STORAGE_ENGINE)
+    @VarAttrDef.VarAttr(name = DEFAULT_STORAGE_ENGINE)
     public String defaultStorageEngine = "olap";
-    @VariableMgr.VarAttr(name = DEFAULT_TMP_STORAGE_ENGINE)
+    @VarAttrDef.VarAttr(name = DEFAULT_TMP_STORAGE_ENGINE)
     public String defaultTmpStorageEngine = "olap";
 
-    @VariableMgr.VarAttr(name = MAX_SCAN_KEY_NUM)
+    @VarAttrDef.VarAttr(name = MAX_SCAN_KEY_NUM)
     public int maxScanKeyNum = 48;
-    @VariableMgr.VarAttr(name = MAX_PUSHDOWN_CONDITIONS_PER_COLUMN)
+    @VarAttrDef.VarAttr(name = MAX_PUSHDOWN_CONDITIONS_PER_COLUMN)
     public int maxPushdownConditionsPerColumn = 1024;
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = SHOW_HIDDEN_COLUMNS,
-            flag = VariableMgr.SESSION_ONLY,
+            flag = VarAttrDef.SESSION_ONLY,
             needForward = true,
             affectQueryResultInPlan = true
     )
     public boolean showHiddenColumns = false;
 
-    @VariableMgr.VarAttr(name = ALLOW_PARTITION_COLUMN_NULLABLE, description = {
+    @VarAttrDef.VarAttr(name = ALLOW_PARTITION_COLUMN_NULLABLE, description = {
             "是否允许 NULLABLE 列作为 PARTITION 列。开启后,RANGE PARTITION 允许 NULLABLE PARTITION 列"
                     + "(LIST PARTITION 当前不支持)。默认开。",
             "Whether to allow NULLABLE columns as PARTITION columns. When ON, RANGE PARTITION allows "
                     + "NULLABLE PARTITION columns (LIST PARTITION is not supported currently). ON by default." })
     public boolean allowPartitionColumnNullable = true;
 
-    @VariableMgr.VarAttr(name = DELETE_WITHOUT_PARTITION, needForward = true)
+    @VarAttrDef.VarAttr(name = DELETE_WITHOUT_PARTITION, needForward = true)
     public boolean deleteWithoutPartition = false;
 
-    @VariableMgr.VarAttr(name = SEND_BATCH_PARALLELISM, needForward = true)
+    @VarAttrDef.VarAttr(name = SEND_BATCH_PARALLELISM, needForward = true)
     public int sendBatchParallelism = 1;
 
-    @VariableMgr.VarAttr(name = ENABLE_VARIANT_ACCESS_IN_ORIGINAL_PLANNER)
+    @VarAttrDef.VarAttr(name = ENABLE_VARIANT_ACCESS_IN_ORIGINAL_PLANNER)
     public boolean enableVariantAccessInOriginalPlanner = false;
 
-    @VariableMgr.VarAttr(name = EXTRACT_WIDE_RANGE_EXPR, needForward = true)
+    @VarAttrDef.VarAttr(name = EXTRACT_WIDE_RANGE_EXPR, needForward = true)
     public boolean extractWideRangeExpr = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_NEREIDS_DML, varType = VariableAnnotation.REMOVED)
+    @VarAttrDef.VarAttr(name = ENABLE_NEREIDS_DML, varType = VariableAnnotation.REMOVED)
     public boolean enableNereidsDML = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_NEREIDS_DML_WITH_PIPELINE,
+    @VarAttrDef.VarAttr(name = ENABLE_NEREIDS_DML_WITH_PIPELINE,
             varType = VariableAnnotation.REMOVED, description = { "在新优化器中,使用 pipeline 引擎执行 DML",
                     "execute DML with pipeline engine in Nereids" })
     public boolean enableNereidsDmlWithPipeline = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_STRICT_CONSISTENCY_DML, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_STRICT_CONSISTENCY_DML, needForward = true)
     public boolean enableStrictConsistencyDml = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_VECTORIZED_ENGINE, varType = VariableAnnotation.REMOVED)
+    @VarAttrDef.VarAttr(name = ENABLE_VECTORIZED_ENGINE, varType = VariableAnnotation.REMOVED)
     public boolean enableVectorizedEngine = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_PIPELINE_ENGINE, fuzzy = false, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_PIPELINE_ENGINE, fuzzy = false, needForward = true,
             varType = VariableAnnotation.REMOVED, setter = "setEnablePipelineEngine")
     private boolean enablePipelineEngine = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_PIPELINE_X_ENGINE, fuzzy = false, varType = VariableAnnotation.REMOVED,
+    @VarAttrDef.VarAttr(name = ENABLE_PIPELINE_X_ENGINE, fuzzy = false, varType = VariableAnnotation.REMOVED,
             setter = "setEnablePipelineXEngine")
     private boolean enablePipelineXEngine = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_SHARED_SCAN, fuzzy = false, varType = VariableAnnotation.EXPERIMENTAL,
+    @VarAttrDef.VarAttr(name = ENABLE_SHARED_SCAN, fuzzy = false, varType = VariableAnnotation.EXPERIMENTAL,
             needForward = true)
     private boolean enableSharedScan = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_PARALLEL_SCAN, fuzzy = true, varType = VariableAnnotation.EXPERIMENTAL,
+    @VarAttrDef.VarAttr(name = ENABLE_PARALLEL_SCAN, fuzzy = true, varType = VariableAnnotation.EXPERIMENTAL,
             needForward = true)
     private boolean enableParallelScan = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_AGGREGATE_FUNCTION_NULL_V2, fuzzy = true, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_AGGREGATE_FUNCTION_NULL_V2, fuzzy = true, needForward = true)
     private boolean enableAggregateFunctionNullV2 = true;
 
-    @VariableMgr.VarAttr(name = OPTIMIZE_INDEX_SCAN_PARALLELISM,
+    @VarAttrDef.VarAttr(name = OPTIMIZE_INDEX_SCAN_PARALLELISM,
             needForward = true,
             description = {"优化索引扫描时的 Scan 并行度,该优化目前只对 ann topn 查询生效",
                 "Optimize the Scan parallelism when indexing, this optimization only works for ann topn queries."})
     private boolean optimizeIndexScanParallelism = true;
 
-    @VariableMgr.VarAttr(name = PARALLEL_SCAN_MAX_SCANNERS_COUNT, fuzzy = true,
+    @VarAttrDef.VarAttr(name = PARALLEL_SCAN_MAX_SCANNERS_COUNT, fuzzy = true,
             varType = VariableAnnotation.EXPERIMENTAL, needForward = true)
     private int parallelScanMaxScannersCount = 0;
 
-    @VariableMgr.VarAttr(name = PARALLEL_SCAN_MIN_ROWS_PER_SCANNER, fuzzy = true,
+    @VarAttrDef.VarAttr(name = PARALLEL_SCAN_MIN_ROWS_PER_SCANNER, fuzzy = true,
             varType = VariableAnnotation.EXPERIMENTAL, needForward = true)
     private long parallelScanMinRowsPerScanner = 2097152; // 2M
 
-    @VariableMgr.VarAttr(name = IGNORE_STORAGE_DATA_DISTRIBUTION, fuzzy = false,
+    @VarAttrDef.VarAttr(name = IGNORE_STORAGE_DATA_DISTRIBUTION, fuzzy = false,
             varType = VariableAnnotation.EXPERIMENTAL, needForward = true)
     private boolean ignoreStorageDataDistribution = true;
 
-    @VariableMgr.VarAttr(name = USE_SERIAL_EXCHANGE, fuzzy = true,
+    @VarAttrDef.VarAttr(name = USE_SERIAL_EXCHANGE, fuzzy = true,
             varType = VariableAnnotation.EXPERIMENTAL, needForward = true)
     private boolean useSerialExchange = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_LOCAL_SHUFFLE, fuzzy = false, varType = VariableAnnotation.EXPERIMENTAL,
             description = {"是否在 pipelineX 引擎上开启 local shuffle 优化",
                     "Whether to enable local shuffle on pipelineX engine."}, needForward = true)
     private boolean enableLocalShuffle = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
                 name = FORCE_TO_LOCAL_SHUFFLE, fuzzy = false, varType = VariableAnnotation.EXPERIMENTAL,
                 description = {"是否在 pipelineX 引擎上强制开启 local shuffle 优化",
                         "Whether to force to local shuffle on pipelineX engine."})
     private boolean forceToLocalShuffle = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_LOCAL_MERGE_SORT)
+    @VarAttrDef.VarAttr(name = ENABLE_LOCAL_MERGE_SORT)
     private boolean enableLocalMergeSort = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_SHARED_EXCHANGE_SINK_BUFFER, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_SHARED_EXCHANGE_SINK_BUFFER, fuzzy = true)
     private boolean enableSharedExchangeSinkBuffer = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_AGG_STATE, fuzzy = false, varType = VariableAnnotation.EXPERIMENTAL,
+    @VarAttrDef.VarAttr(name = ENABLE_AGG_STATE, fuzzy = false, varType = VariableAnnotation.EXPERIMENTAL,
             needForward = true)
     public boolean enableAggState = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_PARALLEL_OUTFILE)
+    @VarAttrDef.VarAttr(name = ENABLE_PARALLEL_OUTFILE)
     public boolean enableParallelOutfile = false;
 
-    @VariableMgr.VarAttr(name = CPU_RESOURCE_LIMIT)
+    @VarAttrDef.VarAttr(name = CPU_RESOURCE_LIMIT)
     public int cpuResourceLimit = -1;
 
-    @VariableMgr.VarAttr(name = SQL_QUOTE_SHOW_CREATE)
+    @VarAttrDef.VarAttr(name = SQL_QUOTE_SHOW_CREATE)
     public boolean sqlQuoteShowCreate = true;
 
-    @VariableMgr.VarAttr(name = TRIM_TAILING_SPACES_FOR_EXTERNAL_TABLE_QUERY, needForward = true)
+    @VarAttrDef.VarAttr(name = TRIM_TAILING_SPACES_FOR_EXTERNAL_TABLE_QUERY, needForward = true)
     public boolean trimTailingSpacesForExternalTableQuery = false;
 
     // the maximum size in bytes for a table that will be broadcast to all be nodes
     // when performing a join, By setting this value to -1 broadcasting can be disabled.
     // Default value is 1Gto
-    @VariableMgr.VarAttr(name = AUTO_BROADCAST_JOIN_THRESHOLD)
+    @VarAttrDef.VarAttr(name = AUTO_BROADCAST_JOIN_THRESHOLD)
     public double autoBroadcastJoinThreshold = 0.8;
 
-    @VariableMgr.VarAttr(name = PARALLEL_PREPARE_THRESHOLD, fuzzy = true)
+    @VarAttrDef.VarAttr(name = PARALLEL_PREPARE_THRESHOLD, fuzzy = true)
     public int parallelPrepareThreshold = 32;
 
-    @VariableMgr.VarAttr(name = READ_HIVE_JSON_IN_ONE_COLUMN,
+    @VarAttrDef.VarAttr(name = READ_HIVE_JSON_IN_ONE_COLUMN,
             description = {"在读取 hive json 的时候,由于存在一些不支持的 json 格式,我们默认会报错。为了让用户使用体验更好,"
                     + "当该变量为 true 的时候,将一整行 json 读取到第一列中,用户可以自行选择对一整行 json 进行处理,例如 JSON_PARSE。"
                     + "需要表的第一列的数据类型为 string.",
@@ -1615,94 +1615,94 @@ public class SessionVariable implements Serializable, Writable {
                     + "be string."})
     private boolean readHiveJsonInOneColumn = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_COST_BASED_JOIN_REORDER)
+    @VarAttrDef.VarAttr(name = ENABLE_COST_BASED_JOIN_REORDER)
     private boolean enableJoinReorderBasedCost = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_FOLD_CONSTANT_BY_BE, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_FOLD_CONSTANT_BY_BE, fuzzy = true)
     public boolean enableFoldConstantByBe = false;
-    @VariableMgr.VarAttr(name = DEBUG_SKIP_FOLD_CONSTANT)
+    @VarAttrDef.VarAttr(name = DEBUG_SKIP_FOLD_CONSTANT)
     public boolean debugSkipFoldConstant = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_REWRITE_ELEMENT_AT_TO_SLOT, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_REWRITE_ELEMENT_AT_TO_SLOT, fuzzy = true)
     private boolean enableRewriteElementAtToSlot = true;
 
-    @VariableMgr.VarAttr(name = FORCE_SORT_ALGORITHM, needForward = true, description = { "强制指定 SortNode 的排序算法",
+    @VarAttrDef.VarAttr(name = FORCE_SORT_ALGORITHM, needForward = true, description = { "强制指定 SortNode 的排序算法",
             "Force the sort algorithm of SortNode to be specified" })
     public String forceSortAlgorithm = "";
 
-    @VariableMgr.VarAttr(name = FULL_SORT_MAX_BUFFERED_BYTES, needForward = true,
+    @VarAttrDef.VarAttr(name = FULL_SORT_MAX_BUFFERED_BYTES, needForward = true,
             setter = "setFullSortMaxBufferedBytes")
     public long fullSortMaxBufferedBytes = 64L * 1024L * 1024L;
 
-    @VariableMgr.VarAttr(name = "ignore_runtime_filter_error", needForward = true, description = { "在 rf 遇到错误的时候忽略该 rf",
+    @VarAttrDef.VarAttr(name = "ignore_runtime_filter_error", needForward = true, description = { "在 rf 遇到错误的时候忽略该 rf",
             "Ignore the rf when it encounters an error" })
     public boolean ignoreRuntimeFilterError = false;
 
 
-    @VariableMgr.VarAttr(name = RUNTIME_FILTER_MODE, needForward = true)
+    @VarAttrDef.VarAttr(name = RUNTIME_FILTER_MODE, needForward = true)
     private String runtimeFilterMode = "GLOBAL";
 
-    @VariableMgr.VarAttr(name = RUNTIME_BLOOM_FILTER_SIZE, needForward = true)
+    @VarAttrDef.VarAttr(name = RUNTIME_BLOOM_FILTER_SIZE, needForward = true)
     private int runtimeBloomFilterSize = 2097152;
 
-    @VariableMgr.VarAttr(name = RUNTIME_BLOOM_FILTER_MIN_SIZE, needForward = true)
+    @VarAttrDef.VarAttr(name = RUNTIME_BLOOM_FILTER_MIN_SIZE, needForward = true)
     private int runtimeBloomFilterMinSize = 1048576;
 
-    @VariableMgr.VarAttr(name = RUNTIME_BLOOM_FILTER_MAX_SIZE, needForward = true)
+    @VarAttrDef.VarAttr(name = RUNTIME_BLOOM_FILTER_MAX_SIZE, needForward = true)
     private int runtimeBloomFilterMaxSize = 67108864;
 
-    @VariableMgr.VarAttr(name = RUNTIME_FILTER_WAIT_TIME_MS, needForward = true)
+    @VarAttrDef.VarAttr(name = RUNTIME_FILTER_WAIT_TIME_MS, needForward = true)
     private int runtimeFilterWaitTimeMs = 1000;
 
-    @VariableMgr.VarAttr(name = runtime_filter_wait_infinitely, fuzzy = true, needForward = true)
+    @VarAttrDef.VarAttr(name = runtime_filter_wait_infinitely, fuzzy = true, needForward = true)
     private boolean runtimeFilterWaitInfinitely = false;
 
-    @VariableMgr.VarAttr(name = RUNTIME_FILTERS_MAX_NUM, needForward = true)
+    @VarAttrDef.VarAttr(name = RUNTIME_FILTERS_MAX_NUM, needForward = true)
     private int runtimeFiltersMaxNum = 10;
 
     // Set runtimeFilterType to IN_OR_BLOOM filter
-    @VariableMgr.VarAttr(name = RUNTIME_FILTER_TYPE, fuzzy = true, needForward = true)
+    @VarAttrDef.VarAttr(name = RUNTIME_FILTER_TYPE, fuzzy = true, needForward = true)
     private int runtimeFilterType = 12;
 
-    @VariableMgr.VarAttr(name = RUNTIME_FILTER_MAX_IN_NUM, needForward = true, fuzzy = true)
+    @VarAttrDef.VarAttr(name = RUNTIME_FILTER_MAX_IN_NUM, needForward = true, fuzzy = true)
     private int runtimeFilterMaxInNum = 40960;
 
-    @VariableMgr.VarAttr(name = ENABLE_SYNC_RUNTIME_FILTER_SIZE, needForward = true, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_SYNC_RUNTIME_FILTER_SIZE, needForward = true, fuzzy = true)
     private boolean enableSyncRuntimeFilterSize = true;
 
-    @VariableMgr.VarAttr(name = "runtime_filter_max_build_row_count", needForward = true, fuzzy = false)
+    @VarAttrDef.VarAttr(name = "runtime_filter_max_build_row_count", needForward = true, fuzzy = false)
     public long runtimeFilterMaxBuildRowCount = 64L * 1024L * 1024L;
 
-    @VariableMgr.VarAttr(name = ENABLE_PARALLEL_RESULT_SINK, needForward = true, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_PARALLEL_RESULT_SINK, needForward = true, fuzzy = true)
     private boolean enableParallelResultSink = true;
 
-    @VariableMgr.VarAttr(name = "sort_phase_num", fuzzy = true, needForward = true,
+    @VarAttrDef.VarAttr(name = "sort_phase_num", fuzzy = true, needForward = true,
             description = {"如设置为 1,则只生成 1 阶段 sort,设置为 2,则只生成 2 阶段 sort,设置其它值,优化器根据代价选择 sort 类型",
                     "set the number of sort phases 1 or 2. if set other value, let cbo decide the sort type"})
     public int sortPhaseNum = 0;
 
-    @VariableMgr.VarAttr(name = HIVE_TEXT_COMPRESSION, fuzzy = true, needForward = true)
+    @VarAttrDef.VarAttr(name = HIVE_TEXT_COMPRESSION, fuzzy = true, needForward = true)
     private String hiveTextCompression = "plain";
 
-    @VariableMgr.VarAttr(name = READ_CSV_EMPTY_LINE_AS_NULL, needForward = true,
+    @VarAttrDef.VarAttr(name = READ_CSV_EMPTY_LINE_AS_NULL, needForward = true,
             description = {"在读取 csv 文件时是否读取 csv 的空行为 null",
                     "Determine whether to read empty rows in CSV files as NULL when reading CSV files."})
     public boolean readCsvEmptyLineAsNull = false;
 
-    @VariableMgr.VarAttr(name = USE_RF_DEFAULT)
+    @VarAttrDef.VarAttr(name = USE_RF_DEFAULT)
     public boolean useRuntimeFilterDefaultSize = false;
 
-    @VariableMgr.VarAttr(name = "topn_lazy_materialization_threshold", needForward = true,
+    @VarAttrDef.VarAttr(name = "topn_lazy_materialization_threshold", needForward = true,
             fuzzy = false,
             varType = VariableAnnotation.EXPERIMENTAL)
     public int topNLazyMaterializationThreshold = 1024;
 
-    @VariableMgr.VarAttr(name = "topn_lazy_materialization_using_index", needForward = true,
+    @VarAttrDef.VarAttr(name = "topn_lazy_materialization_using_index", needForward = true,
             fuzzy = false,
             varType = VariableAnnotation.EXPERIMENTAL)
     public boolean topNLazyMaterializationUsingIndex = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_PRUNE_NESTED_COLUMN, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_PRUNE_NESTED_COLUMN, needForward = true,
             fuzzy = false,
             varType = VariableAnnotation.EXPERIMENTAL,
             description = {"是否裁剪 map/struct 类型", "Whether to prune the type of map/struct"}
@@ -1730,28 +1730,28 @@ public class SessionVariable implements Serializable, Writable {
         }
     }
 
-    @VariableMgr.VarAttr(name = DISABLE_INVERTED_INDEX_V1_FOR_VARIANT, needForward = true)
+    @VarAttrDef.VarAttr(name = DISABLE_INVERTED_INDEX_V1_FOR_VARIANT, needForward = true)
     private boolean disableInvertedIndexV1ForVaraint = true;
 
     @Deprecated
-    @VariableMgr.VarAttr(name = ENABLE_VARIANT_FLATTEN_NESTED, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_VARIANT_FLATTEN_NESTED, needForward = true)
     private boolean enableVariantFlattenNested = false;
 
     public int getBeNumberForTest() {
         return beNumberForTest;
     }
 
-    @VariableMgr.VarAttr(name = DESCRIBE_EXTEND_VARIANT_COLUMN, needForward = true)
+    @VarAttrDef.VarAttr(name = DESCRIBE_EXTEND_VARIANT_COLUMN, needForward = true)
     public boolean enableDescribeExtendVariantColumn = false;
 
-    @VariableMgr.VarAttr(name = PROFILLING)
+    @VarAttrDef.VarAttr(name = PROFILLING)
     public boolean profiling = false;
 
     public void setBeNumberForTest(int beNumberForTest) {
         this.beNumberForTest = beNumberForTest;
     }
 
-    @VariableMgr.VarAttr(name = BE_NUMBER_FOR_TEST)
+    @VarAttrDef.VarAttr(name = BE_NUMBER_FOR_TEST)
     private int beNumberForTest = -1;
 
     public double getCboCpuWeight() {
@@ -1778,25 +1778,25 @@ public class SessionVariable implements Serializable, Writable {
         this.cboNetWeight = cboNetWeight;
     }
 
-    @VariableMgr.VarAttr(name = "enable_init_join_order")
+    @VarAttrDef.VarAttr(name = "enable_init_join_order")
     public boolean enableInitJoinOrder = true;
 
-    @VariableMgr.VarAttr(name = CBO_CPU_WEIGHT)
+    @VarAttrDef.VarAttr(name = CBO_CPU_WEIGHT)
     private double cboCpuWeight = 1.0;
 
-    @VariableMgr.VarAttr(name = CBO_MEM_WEIGHT)
+    @VarAttrDef.VarAttr(name = CBO_MEM_WEIGHT)
     private double cboMemWeight = 1.0;
 
-    @VariableMgr.VarAttr(name = CBO_NET_WEIGHT)
+    @VarAttrDef.VarAttr(name = CBO_NET_WEIGHT)
     private double cboNetWeight = 1.5;
 
-    @VariableMgr.VarAttr(name = DISABLE_JOIN_REORDER)
+    @VarAttrDef.VarAttr(name = DISABLE_JOIN_REORDER)
     private boolean disableJoinReorder = false;
 
-    @VariableMgr.VarAttr(name = MAX_JOIN_NUMBER_OF_REORDER)
+    @VarAttrDef.VarAttr(name = MAX_JOIN_NUMBER_OF_REORDER)
     private int maxJoinNumberOfReorder = 63;
 
-    @VariableMgr.VarAttr(name = ENABLE_BUSHY_TREE, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_BUSHY_TREE, needForward = true)
     private boolean enableBushyTree = false;
 
     public int getMaxJoinNumBushyTree() {
@@ -1815,13 +1815,13 @@ public class SessionVariable implements Serializable, Writable {
         this.maxJoinNumberOfReorder = maxJoinNumberOfReorder;
     }
 
-    @VariableMgr.VarAttr(name = MAX_JOIN_NUMBER_BUSHY_TREE)
+    @VarAttrDef.VarAttr(name = MAX_JOIN_NUMBER_BUSHY_TREE)
     private int maxJoinNumBushyTree = 8;
 
-    @VariableMgr.VarAttr(name = ENABLE_PARTITION_TOPN)
+    @VarAttrDef.VarAttr(name = ENABLE_PARTITION_TOPN)
     private boolean enablePartitionTopN = true;
 
-    @VariableMgr.VarAttr(name = PARTITION_TOPN_MAX_PARTITIONS, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = PARTITION_TOPN_MAX_PARTITIONS, needForward = true, description = {
             "这个阈值决定了 partition_topn 计算时的最大分区数量,超过这个阈值后且输入总行数少于预估总量,剩余的数据将直接透传给下一个算子",
             "This threshold determines how many partitions will be allocated for window function get topn."
                     + " if this threshold is exceeded and input rows less than the estimated total rows, the remaining"
@@ -1829,7 +1829,7 @@ public class SessionVariable implements Serializable, Writable {
     })
     private int partitionTopNMaxPartitions = 1024;
 
-    @VariableMgr.VarAttr(name = PARTITION_TOPN_PER_PARTITION_ROWS, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = PARTITION_TOPN_PER_PARTITION_ROWS, needForward = true, description = {
             "这个数值用于 partition_topn 预估每个分区的行数,用来计算所有分区的预估数据总量,决定是否能透传下一个算子",
             "This value is used for partition_topn to estimate the number of rows in each partition, to calculate "
             + " the estimated total amount of data for all partitions, and to determine whether the next operator "
@@ -1837,31 +1837,31 @@ public class SessionVariable implements Serializable, Writable {
     })
     private int partitionTopNPerPartitionRows = 1000;
 
-    @VariableMgr.VarAttr(name = GLOBAL_PARTITION_TOPN_THRESHOLD)
+    @VarAttrDef.VarAttr(name = GLOBAL_PARTITION_TOPN_THRESHOLD)
     private double globalPartitionTopNThreshold = 100;
 
-    @VariableMgr.VarAttr(name = ENABLE_INFER_PREDICATE)
+    @VarAttrDef.VarAttr(name = ENABLE_INFER_PREDICATE)
     private boolean enableInferPredicate = true;
 
-    @VariableMgr.VarAttr(name = RETURN_OBJECT_DATA_AS_BINARY)
+    @VarAttrDef.VarAttr(name = RETURN_OBJECT_DATA_AS_BINARY)
     private boolean returnObjectDataAsBinary = false;
 
-    @VariableMgr.VarAttr(name = BLOCK_ENCRYPTION_MODE, affectQueryResultInPlan = true)
+    @VarAttrDef.VarAttr(name = BLOCK_ENCRYPTION_MODE, affectQueryResultInPlan = true)
     private String blockEncryptionMode = "";
 
-    @VariableMgr.VarAttr(name = ENABLE_PROJECTION)
+    @VarAttrDef.VarAttr(name = ENABLE_PROJECTION)
     private boolean enableProjection = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_SHORT_CIRCUIT_QUERY)
+    @VarAttrDef.VarAttr(name = ENABLE_SHORT_CIRCUIT_QUERY)
     private boolean enableShortCircuitQuery = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_SHORT_CIRCUIT_QUERY_ACCESS_COLUMN_STORE)
+    @VarAttrDef.VarAttr(name = ENABLE_SHORT_CIRCUIT_QUERY_ACCESS_COLUMN_STORE)
     private boolean enableShortCircuitQueryAcessColumnStore = true;
 
-    @VariableMgr.VarAttr(name = CHECK_OVERFLOW_FOR_DECIMAL, affectQueryResultInExecution = true)
+    @VarAttrDef.VarAttr(name = CHECK_OVERFLOW_FOR_DECIMAL, affectQueryResultInExecution = true)
     private boolean checkOverflowForDecimal = true;
 
-    @VariableMgr.VarAttr(name = DECIMAL_OVERFLOW_SCALE, needForward = true, affectQueryResultInPlan = true,
+    @VarAttrDef.VarAttr(name = DECIMAL_OVERFLOW_SCALE, needForward = true, affectQueryResultInPlan = true,
             description = {
                     "当 decimal 数值计算结果精度溢出时,计算结果最多可保留的小数位数", "When the precision of the result of"
                     + " a decimal numerical calculation overflows,"
@@ -1869,10 +1869,10 @@ public class SessionVariable implements Serializable, Writable {
     )
     public int decimalOverflowScale = 6;
 
-    @VariableMgr.VarAttr(name = ENABLE_DPHYP_OPTIMIZER)
+    @VarAttrDef.VarAttr(name = ENABLE_DPHYP_OPTIMIZER)
     public boolean enableDPHypOptimizer = false;
 
-    @VariableMgr.VarAttr(name = SHORT_CIRCUIT_EVALUATION, fuzzy = true, description = { "是否启用短路求值",
+    @VarAttrDef.VarAttr(name = SHORT_CIRCUIT_EVALUATION, fuzzy = true, description = { "是否启用短路求值",
             "Whether to enable short-circuit evaluation" })
     public boolean shortCircuitEvaluation = false;
 
@@ -1881,16 +1881,16 @@ public class SessionVariable implements Serializable, Writable {
      * It can allow us select different plans for the same SQL statement
      * and these plans can be used to evaluate the cost model.
      */
-    @VariableMgr.VarAttr(name = NTH_OPTIMIZED_PLAN)
+    @VarAttrDef.VarAttr(name = NTH_OPTIMIZED_PLAN)
     private int nthOptimizedPlan = 1;
 
-    @VariableMgr.VarAttr(name = REQUIRED_GROUP_IDS,
+    @VarAttrDef.VarAttr(name = REQUIRED_GROUP_IDS,
             description = {"指定优化器必须选择包含这些 Group ID 的物理计划(逗号分隔的整数列表)",
                     "Force the optimizer to choose a physical plan containing these Group IDs "
                     + "(comma-separated integer list)"})
     public String requiredGroupIds = "";
 
-    @VariableMgr.VarAttr(name = LIMIT_ROWS_FOR_SINGLE_INSTANCE,
+    @VarAttrDef.VarAttr(name = LIMIT_ROWS_FOR_SINGLE_INSTANCE,
             description = {"当一个 ScanNode 上没有过滤条件,且 limit 值小于这个阈值时,"
                     + "系统会将这个算子的并发度调整为 1,以减少简单查询的扇出",
                     "When a ScanNode has no filter conditions and the limit value is less than this threshold, "
@@ -1906,7 +1906,7 @@ public class SessionVariable implements Serializable, Writable {
         this.enableLeftZigZag = enableLeftZigZag;
     }
 
-    @VariableMgr.VarAttr(name = ENABLE_LEFT_ZIG_ZAG)
+    @VarAttrDef.VarAttr(name = ENABLE_LEFT_ZIG_ZAG)
     private boolean enableLeftZigZag = false;
 
     public boolean isEnableHboOptimization() {
@@ -1925,7 +1925,7 @@ public class SessionVariable implements Serializable, Writable {
         return hboSkewRatioThreshold;
     }
 
-    @VariableMgr.VarAttr(name = ENABLE_HBO_OPTIMIZATION)
+    @VarAttrDef.VarAttr(name = ENABLE_HBO_OPTIMIZATION)
     private boolean enableHboOptimization = false;
 
     public boolean isEnableHboInfoCollection() {
@@ -1936,19 +1936,19 @@ public class SessionVariable implements Serializable, Writable {
         return enableHboNonStrictMatchingMode;
     }
 
-    @VariableMgr.VarAttr(name = ENABLE_HBO_INFO_COLLECTION, flag = VariableMgr.GLOBAL)
+    @VarAttrDef.VarAttr(name = ENABLE_HBO_INFO_COLLECTION, flag = VarAttrDef.GLOBAL)
     private boolean enableHboInfoCollection = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_HBO_NONSTRICT_MATCHING_MODE)
+    @VarAttrDef.VarAttr(name = ENABLE_HBO_NONSTRICT_MATCHING_MODE)
     private boolean enableHboNonStrictMatchingMode = false;
 
-    @VariableMgr.VarAttr(name = HBO_RFSAFE_THRESHOLD, needForward = true)
+    @VarAttrDef.VarAttr(name = HBO_RFSAFE_THRESHOLD, needForward = true)
     private double hboRfSafeThreshold = 0.5;
 
-    @VariableMgr.VarAttr(name = HBO_ROW_MATCHING_THRESHOLD, needForward = true)
+    @VarAttrDef.VarAttr(name = HBO_ROW_MATCHING_THRESHOLD, needForward = true)
     private double hboRowMatchingThreshold = 0.1;
 
-    @VariableMgr.VarAttr(name = HBO_SKEW_RATIO_THRESHOLD, needForward = true)
+    @VarAttrDef.VarAttr(name = HBO_SKEW_RATIO_THRESHOLD, needForward = true)
     private int hboSkewRatioThreshold = 5;
 
     /**
@@ -1957,16 +1957,16 @@ public class SessionVariable implements Serializable, Writable {
      * the new optimizer is fully developed. I hope that day
      * would be coming soon.
      */
-    @VariableMgr.VarAttr(name = ENABLE_NEREIDS_PLANNER, needForward = true, varType = VariableAnnotation.REMOVED)
+    @VarAttrDef.VarAttr(name = ENABLE_NEREIDS_PLANNER, needForward = true, varType = VariableAnnotation.REMOVED)
     private boolean enableNereidsPlanner = true;
 
-    @VariableMgr.VarAttr(name = DISABLE_NEREIDS_RULES, needForward = true)
+    @VarAttrDef.VarAttr(name = DISABLE_NEREIDS_RULES, needForward = true)
     private String disableNereidsRules = "";
 
-    @VariableMgr.VarAttr(name = ENABLE_NEREIDS_RULES, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_NEREIDS_RULES, needForward = true)
     public String enableNereidsRules = "";
 
-    @VariableMgr.VarAttr(name = ENABLE_VISITOR_REWRITER_DEPTH_THRESHOLD, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_VISITOR_REWRITER_DEPTH_THRESHOLD, needForward = true, description = {
             "当查询计划的深度小于或等于这个阈值时,使用 visitor rewriter 去加速改写,否则使用 stack rewriter 去改写,"
                     + "防止 StackOverflowError",
             "When the depth of the query plan is less than or equal to this threshold, use visitor rewriter to "
@@ -1974,19 +1974,19 @@ public class SessionVariable implements Serializable, Writable {
     })
     public int enableVisitorRewriterDepthThreshold = 100;
 
-    @VariableMgr.VarAttr(name = DISABLE_NEREIDS_EXPRESSION_RULES, needForward = true,
+    @VarAttrDef.VarAttr(name = DISABLE_NEREIDS_EXPRESSION_RULES, needForward = true,
             setter = "setDisableNereidsExpressionRules")
     private String disableNereidsExpressionRules = "";
 
     private BitSet disableNereidsExpressionRuleSet = new BitSet();
 
-    @VariableMgr.VarAttr(name = "filter_cost_factor", needForward = true)
+    @VarAttrDef.VarAttr(name = "filter_cost_factor", needForward = true)
     public double filterCostFactor = 0.0001;
 
-    @VariableMgr.VarAttr(name = NEREIDS_STAR_SCHEMA_SUPPORT)
+    @VarAttrDef.VarAttr(name = NEREIDS_STAR_SCHEMA_SUPPORT)
     private boolean nereidsStarSchemaSupport = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_NEREIDS_DISTRIBUTE_PLANNER, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_NEREIDS_DISTRIBUTE_PLANNER, needForward = true,
             fuzzy = false, varType = VariableAnnotation.EXPERIMENTAL, description = {
                 "使用新的 nereids 的分布式规划器的开关,这个分布式规划器可以规划出一些更高效的查询计划,比如在某些情况下,"
                         + "可以把左表 shuffle 到右表去做 bucket shuffle join",
@@ -1997,40 +1997,40 @@ public class SessionVariable implements Serializable, Writable {
     )
     private boolean enableNereidsDistributePlanner = true;
 
-    @VariableMgr.VarAttr(name = REWRITE_OR_TO_IN_PREDICATE_THRESHOLD, fuzzy = true)
+    @VarAttrDef.VarAttr(name = REWRITE_OR_TO_IN_PREDICATE_THRESHOLD, fuzzy = true)
     private int rewriteOrToInPredicateThreshold = 2;
 
-    @VariableMgr.VarAttr(name = "push_topn_to_agg", fuzzy = false, needForward = true)
+    @VarAttrDef.VarAttr(name = "push_topn_to_agg", fuzzy = false, needForward = true)
     public boolean pushTopnToAgg = true;
 
-    @VariableMgr.VarAttr(name = NEREIDS_CBO_PENALTY_FACTOR, needForward = true)
+    @VarAttrDef.VarAttr(name = NEREIDS_CBO_PENALTY_FACTOR, needForward = true)
     private double nereidsCboPenaltyFactor = 0.7;
 
-    @VariableMgr.VarAttr(name = ENABLE_NEREIDS_TRACE)
+    @VarAttrDef.VarAttr(name = ENABLE_NEREIDS_TRACE)
     private boolean enableNereidsTrace = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_EXPR_TRACE)
+    @VarAttrDef.VarAttr(name = ENABLE_EXPR_TRACE)
     private boolean enableExprTrace = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_DPHYP_TRACE, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_DPHYP_TRACE, needForward = true)
     public boolean enableDpHypTrace = false;
 
-    @VariableMgr.VarAttr(name = BROADCAST_RIGHT_TABLE_SCALE_FACTOR)
+    @VarAttrDef.VarAttr(name = BROADCAST_RIGHT_TABLE_SCALE_FACTOR)
     private double broadcastRightTableScaleFactor = 0.0;
 
-    @VariableMgr.VarAttr(name = LEFT_SEMI_OR_ANTI_PROBE_FACTOR)
+    @VarAttrDef.VarAttr(name = LEFT_SEMI_OR_ANTI_PROBE_FACTOR)
     private double leftSemiOrAntiProbeFactor = 0.05;
 
-    @VariableMgr.VarAttr(name = BROADCAST_ROW_COUNT_LIMIT, needForward = true)
+    @VarAttrDef.VarAttr(name = BROADCAST_ROW_COUNT_LIMIT, needForward = true)
     private double broadcastRowCountLimit = 30_000_000;
 
-    @VariableMgr.VarAttr(name = BROADCAST_HASHTABLE_MEM_LIMIT_PERCENTAGE, needForward = true)
+    @VarAttrDef.VarAttr(name = BROADCAST_HASHTABLE_MEM_LIMIT_PERCENTAGE, needForward = true)
     private double broadcastHashtableMemLimitPercentage = 0.2;
 
-    @VariableMgr.VarAttr(name = ENABLE_RUNTIME_FILTER_PRUNE, needForward = true, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_RUNTIME_FILTER_PRUNE, needForward = true, fuzzy = true)
     public boolean enableRuntimeFilterPrune = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_RUNTIME_FILTER_PARTITION_PRUNE, needForward = true, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_RUNTIME_FILTER_PARTITION_PRUNE, needForward = true, fuzzy = true)
     public boolean enableRuntimeFilterPartitionPrune = true;
 
     /**
@@ -2038,18 +2038,18 @@ public class SessionVariable implements Serializable, Writable {
      * For example, trace_id can be passed to trace the query request sent by the user.
      * set session_context="trace_id:1234565678";
      */
-    @VariableMgr.VarAttr(name = SESSION_CONTEXT, needForward = true)
+    @VarAttrDef.VarAttr(name = SESSION_CONTEXT, needForward = true)
     public String sessionContext = "";
 
-    @VariableMgr.VarAttr(name = ENABLE_SINGLE_REPLICA_INSERT,
+    @VarAttrDef.VarAttr(name = ENABLE_SINGLE_REPLICA_INSERT,
             needForward = true, varType = VariableAnnotation.EXPERIMENTAL)
     public boolean enableSingleReplicaInsert = false;
 
-    @VariableMgr.VarAttr(name = SHUFFLED_AGG_NODE_IDS,
+    @VarAttrDef.VarAttr(name = SHUFFLED_AGG_NODE_IDS,
             needForward = true, varType = VariableAnnotation.EXPERIMENTAL)
     public String shuffledAggNodeIds = "";
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_FAST_ANALYZE_INSERT_INTO_VALUES, fuzzy = true,
             description = {
                     "跳过大部分的优化规则,快速分析 insert into values 语句",
@@ -2058,48 +2058,48 @@ public class SessionVariable implements Serializable, Writable {
     )
     private boolean enableFastAnalyzeInsertIntoValues = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_FUNCTION_PUSHDOWN, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_FUNCTION_PUSHDOWN, fuzzy = true)
     public boolean enableFunctionPushdown = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_EXT_FUNC_PRED_PUSHDOWN, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_EXT_FUNC_PRED_PUSHDOWN, needForward = true,
             description = {"启用外部表(如通过 ODBC 或 JDBC 访问的表)查询中谓词的函数下推",
                     "Enable function pushdown for predicates in queries to external tables "
                     + "(such as tables accessed via ODBC or JDBC)"})
     public boolean enableExtFuncPredPushdown = true;
 
-    @VariableMgr.VarAttr(name = FORBID_UNKNOWN_COLUMN_STATS)
+    @VarAttrDef.VarAttr(name = FORBID_UNKNOWN_COLUMN_STATS)
     public boolean forbidUnknownColStats = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_COMMON_EXPR_PUSHDOWN, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_COMMON_EXPR_PUSHDOWN, fuzzy = true)
     public boolean enableCommonExprPushdown = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_LOCAL_EXCHANGE, fuzzy = false, flag = VariableMgr.INVISIBLE,
+    @VarAttrDef.VarAttr(name = ENABLE_LOCAL_EXCHANGE, fuzzy = false, flag = VarAttrDef.INVISIBLE,
             varType = VariableAnnotation.DEPRECATED)
     public boolean enableLocalExchange = true;
 
     /**
      * For debug purpose, don't merge unique key and agg key when reading data.
      */
-    @VariableMgr.VarAttr(name = SKIP_STORAGE_ENGINE_MERGE, needForward = true,
+    @VarAttrDef.VarAttr(name = SKIP_STORAGE_ENGINE_MERGE, needForward = true,
             affectQueryResultInPlan = true, affectQueryResultInExecution = true)
     public boolean skipStorageEngineMerge = false;
 
     /**
      * For debug purpose, skip delete predicate when reading data.
      */
-    @VariableMgr.VarAttr(name = SKIP_DELETE_PREDICATE, needForward = true, affectQueryResultInExecution = true)
+    @VarAttrDef.VarAttr(name = SKIP_DELETE_PREDICATE, needForward = true, affectQueryResultInExecution = true)
     public boolean skipDeletePredicate = false;
 
     /**
      * For debug purpose, skip delete sign when reading data.
      */
-    @VariableMgr.VarAttr(name = SKIP_DELETE_SIGN, needForward = true, affectQueryResultInPlan = true)
+    @VarAttrDef.VarAttr(name = SKIP_DELETE_SIGN, needForward = true, affectQueryResultInPlan = true)
     public boolean skipDeleteSign = false;
 
     /**
      * For debug purpose, skip delete bitmap when reading data.
      */
-    @VariableMgr.VarAttr(name = SKIP_DELETE_BITMAP, needForward = true,
+    @VarAttrDef.VarAttr(name = SKIP_DELETE_BITMAP, needForward = true,
             affectQueryResultInPlan = true, affectQueryResultInExecution = true)
     public boolean skipDeleteBitmap = false;
 
@@ -2113,7 +2113,7 @@ public class SessionVariable implements Serializable, Writable {
     // You should only open it in the emergency scenarios mentioned above, only used for temporary recovery queries.
     // This variable conflicts with the use_fix_replica variable, when the use_fix_replica variable is not -1,
     // this variable will not work.
-    @VariableMgr.VarAttr(name = SKIP_MISSING_VERSION, affectQueryResultInPlan = true,
+    @VarAttrDef.VarAttr(name = SKIP_MISSING_VERSION, affectQueryResultInPlan = true,
             affectQueryResultInExecution = true)
     public boolean skipMissingVersion = false;
 
@@ -2122,48 +2122,48 @@ public class SessionVariable implements Serializable, Writable {
     // the table, if one of the tablet is damaged, the table will not be able to be select. If the user does not care
     // about the integrity of the data, they can use this variable to temporarily skip the bad tablet for querying and
     // load the remaining data into a new table.
-    @VariableMgr.VarAttr(name = SKIP_BAD_TABLET,  affectQueryResultInPlan = true,
+    @VarAttrDef.VarAttr(name = SKIP_BAD_TABLET,  affectQueryResultInPlan = true,
             affectQueryResultInExecution = true)
     public boolean skipBadTablet = false;
 
     // This variable is used to avoid FE fallback to the original parser. When we execute SQL in regression tests
     // for nereids, fallback will cause the Doris return the correct result although the syntax is unsupported
     // in nereids for some mistaken modification. You should set it on the
-    @VariableMgr.VarAttr(name = ENABLE_FALLBACK_TO_ORIGINAL_PLANNER, varType = VariableAnnotation.REMOVED)
+    @VarAttrDef.VarAttr(name = ENABLE_FALLBACK_TO_ORIGINAL_PLANNER, varType = VariableAnnotation.REMOVED)
     public boolean enableFallbackToOriginalPlanner = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_NEREIDS_TIMEOUT, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_NEREIDS_TIMEOUT, needForward = true)
     public boolean enableNereidsTimeout = true;
 
-    @VariableMgr.VarAttr(name = NEREIDS_TIMEOUT_SECOND, needForward = true)
+    @VarAttrDef.VarAttr(name = NEREIDS_TIMEOUT_SECOND, needForward = true)
     public int nereidsTimeoutSecond = 30;
 
-    @VariableMgr.VarAttr(name = ENABLE_PUSH_DOWN_NO_GROUP_AGG)
+    @VarAttrDef.VarAttr(name = ENABLE_PUSH_DOWN_NO_GROUP_AGG)
     public boolean enablePushDownNoGroupAgg = true;
 
     /**
      * The current statistics are only used for CBO test,
      * and are not available to users. (work in progress)
      */
-    @VariableMgr.VarAttr(name = ENABLE_CBO_STATISTICS)
+    @VarAttrDef.VarAttr(name = ENABLE_CBO_STATISTICS)
     public boolean enableCboStatistics = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_ELIMINATE_SORT_NODE)
+    @VarAttrDef.VarAttr(name = ENABLE_ELIMINATE_SORT_NODE)
     public boolean enableEliminateSortNode = true;
 
-    @VariableMgr.VarAttr(name = PARTITION_PRUNING_EXPAND_THRESHOLD, fuzzy = true)
+    @VarAttrDef.VarAttr(name = PARTITION_PRUNING_EXPAND_THRESHOLD, fuzzy = true)
     public int partitionPruningExpandThreshold = 10;
 
-    @VariableMgr.VarAttr(name = ENABLE_SHARE_HASH_TABLE_FOR_BROADCAST_JOIN, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_SHARE_HASH_TABLE_FOR_BROADCAST_JOIN, fuzzy = true)
     public boolean enableShareHashTableForBroadcastJoin = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_UNICODE_NAME_SUPPORT, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_UNICODE_NAME_SUPPORT, needForward = true)
     public boolean enableUnicodeNameSupport = true;
 
-    @VariableMgr.VarAttr(name = GROUP_CONCAT_MAX_LEN)
+    @VarAttrDef.VarAttr(name = GROUP_CONCAT_MAX_LEN)
     public long groupConcatMaxLen = 2147483646;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = USE_ONE_PHASE_AGG_FOR_GROUP_CONCAT_WITH_ORDER,
             needForward = true,
             fuzzy = true,
@@ -2177,39 +2177,39 @@ public class SessionVariable implements Serializable, Writable {
     // Whether enable two phase read optimization
     // 1. read related rowids along with necessary column data
     // 2. spawn fetch RPC to other nodes to get related data by sorted rowids
-    @VariableMgr.VarAttr(name = ENABLE_TWO_PHASE_READ_OPT, fuzzy = true)
+    @VarAttrDef.VarAttr(name = ENABLE_TWO_PHASE_READ_OPT, fuzzy = true)
     public boolean enableTwoPhaseReadOpt = true;
-    @VariableMgr.VarAttr(name = TOPN_OPT_LIMIT_THRESHOLD)
+    @VarAttrDef.VarAttr(name = TOPN_OPT_LIMIT_THRESHOLD)
     public long topnOptLimitThreshold = 1024;
-    @VariableMgr.VarAttr(name = TOPN_FILTER_RATIO)
+    @VarAttrDef.VarAttr(name = TOPN_FILTER_RATIO)
     public double topnFilterRatio = 0.5;
-    @VariableMgr.VarAttr(name = ENABLE_SNAPSHOT_POINT_QUERY)
+    @VarAttrDef.VarAttr(name = ENABLE_SNAPSHOT_POINT_QUERY)
     public boolean enableSnapshotPointQuery = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_SERVER_SIDE_PREPARED_STATEMENT, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_SERVER_SIDE_PREPARED_STATEMENT, needForward = true, description = {
             "是否启用开启服务端 prepared statement", "Set whether to enable server side prepared statement."})
     public boolean enableServeSidePreparedStatement = true;
 
-    @VariableMgr.VarAttr(name = MAX_PREPARED_STMT_COUNT,  flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = MAX_PREPARED_STMT_COUNT,  flag = VarAttrDef.GLOBAL,
             needForward = true, description = {
                 "服务端 prepared statement 最大个数", "the maximum prepared statements server holds."})
     public int maxPreparedStmtCount = 100000;
 
-    @VariableMgr.VarAttr(name = ENABLE_GROUP_COMMIT_FULL_PREPARE)
+    @VarAttrDef.VarAttr(name = ENABLE_GROUP_COMMIT_FULL_PREPARE)
     public boolean enableGroupCommitFullPrepare = true;
 
     // Default value is false, which means the group by and having clause
     // should first use column name not alias. According to mysql.
-    @VariableMgr.VarAttr(name = GROUP_BY_AND_HAVING_USE_ALIAS_FIRST, varType = VariableAnnotation.DEPRECATED)
+    @VarAttrDef.VarAttr(name = GROUP_BY_AND_HAVING_USE_ALIAS_FIRST, varType = VariableAnnotation.DEPRECATED)
     public boolean groupByAndHavingUseAliasFirst = false;
 
     // Whether disable block file cache. Block cache only works when FE's query options sets disableFileCache false
     // along with BE's config `enable_file_cache` true
-    @VariableMgr.VarAttr(name = DISABLE_FILE_CACHE, needForward = true)
+    @VarAttrDef.VarAttr(name = DISABLE_FILE_CACHE, needForward = true)
     public boolean disableFileCache = false;
 
     // Whether enable block file cache. Only take effect when BE config item enable_file_cache is true.
-    @VariableMgr.VarAttr(name = ENABLE_FILE_CACHE, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_FILE_CACHE, needForward = true, description = {
             "是否启用 file cache。该变量只有在 be.conf 中 enable_file_cache=true 时才有效,"
                     + "如果 be.conf 中 enable_file_cache=false,该 BE 节点的 file cache 处于禁用状态。",
             "Set wether to use file cache. This variable takes effect only if the BE config enable_file_cache=true. "
@@ -2217,51 +2217,51 @@ public class SessionVariable implements Serializable, Writable {
     public boolean enableFileCache = false;
 
     // Specify base path for file cache, or chose a random path.
-    @VariableMgr.VarAttr(name = FILE_CACHE_BASE_PATH, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = FILE_CACHE_BASE_PATH, needForward = true, description = {
             "指定 block file cache 在 BE 上的存储路径,默认 'random',随机选择 BE 配置的存储路径。",
             "Specify the storage path of the block file cache on BE, default 'random', "
                     + "and randomly select the storage path configured by BE."})
     public String fileCacheBasePath = "random";
 
     // Whether enable query with inverted index.
-    @VariableMgr.VarAttr(name = ENABLE_INVERTED_INDEX_QUERY, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_INVERTED_INDEX_QUERY, needForward = true, description = {
             "是否启用 inverted index query。", "Set whether to use inverted index query."})
     public boolean enableInvertedIndexQuery = true;
 
     // Whether enable query expr with inverted index.
-    @VariableMgr.VarAttr(name = ENABLE_COMMON_EXPR_PUSHDOWN_FOR_INVERTED_INDEX, fuzzy = true, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_COMMON_EXPR_PUSHDOWN_FOR_INVERTED_INDEX, fuzzy = true, needForward = true,
             description = {"是否启用表达式上使用 inverted index。", "Set whether to use inverted index query for expr."})
     public boolean enableCommonExpPushDownForInvertedIndex = true;
 
     // Whether enable pushdown count agg to scan node when using inverted index match.
-    @VariableMgr.VarAttr(name = ENABLE_PUSHDOWN_COUNT_ON_INDEX, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_PUSHDOWN_COUNT_ON_INDEX, needForward = true, description = {
             "是否启用 count_on_index pushdown。", "Set whether to pushdown count_on_index."})
     public boolean enablePushDownCountOnIndex = true;
 
     // Whether enable no need read data opt in segment_iterator.
-    @VariableMgr.VarAttr(name = ENABLE_NO_NEED_READ_DATA_OPT, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_NO_NEED_READ_DATA_OPT, needForward = true, description = {
             "是否启用 no_need_read_data opt。", "Set whether to enable no_need_read_data opt."})
     public boolean enableNoNeedReadDataOpt = true;
 
     // Whether enable pushdown minmax to scan node of unique table.
-    @VariableMgr.VarAttr(name = ENABLE_PUSHDOWN_MINMAX_ON_UNIQUE, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_PUSHDOWN_MINMAX_ON_UNIQUE, needForward = true, description = {
         "是否启用 pushdown minmax on unique table。", "Set whether to pushdown minmax on unique table."})
     public boolean enablePushDownMinMaxOnUnique = false;
 
     // Whether enable push down string type minmax to scan node.
-    @VariableMgr.VarAttr(name = ENABLE_PUSHDOWN_STRING_MINMAX, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_PUSHDOWN_STRING_MINMAX, needForward = true, description = {
         "是否启用 string 类型 min max 下推。", "Set whether to enable push down string type minmax."})
     public boolean enablePushDownStringMinMax = false;
 
     // Comma-separated list of MOR tables to enable value predicate pushdown.
-    @VariableMgr.VarAttr(name = ENABLE_MOR_VALUE_PREDICATE_PUSHDOWN_TABLES, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_MOR_VALUE_PREDICATE_PUSHDOWN_TABLES, needForward = true, description = {
         "指定启用MOR表value列谓词下推的表列表,格式:db1.tbl1,db2.tbl2 或 * 表示所有MOR表。",
         "Comma-separated list of MOR tables to enable value predicate pushdown. "
                 + "Format: db1.tbl1,db2.tbl2 or * for all MOR tables."})
     public String enableMorValuePredicatePushdownTables = "";
 
     // Comma-separated list of MOR tables to read as DUP (skip merge, skip delete sign filter).
-    @VariableMgr.VarAttr(name = READ_MOR_AS_DUP_TABLES, needForward = true,
+    @VarAttrDef.VarAttr(name = READ_MOR_AS_DUP_TABLES, needForward = true,
             affectQueryResultInPlan = true, description = {
                     "指定以DUP模式读取MOR表的表列表(跳过合并和删除标记过滤),格式:db1.tbl1,db2.tbl2 或 * 表示所有MOR表。",
                     "Comma-separated list of MOR tables to read as DUP (skip merge, skip delete sign filter). "
@@ -2269,33 +2269,33 @@ public class SessionVariable implements Serializable, Writable {
     public String readMorAsDupTables = "";
 
     // Whether drop table when create table as select insert data appear error.
-    @VariableMgr.VarAttr(name = DROP_TABLE_IF_CTAS_FAILED, needForward = true)
+    @VarAttrDef.VarAttr(name = DROP_TABLE_IF_CTAS_FAILED, needForward = true)
     public boolean dropTableIfCtasFailed = true;
 
-    @VariableMgr.VarAttr(name = MAX_TABLE_COUNT_USE_CASCADES_JOIN_REORDER, needForward = true)
+    @VarAttrDef.VarAttr(name = MAX_TABLE_COUNT_USE_CASCADES_JOIN_REORDER, needForward = true)
     public int maxTableCountUseCascadesJoinReorder = 10;
 
-    @VariableMgr.VarAttr(name = JOIN_REORDER_TIME_LIMIT, needForward = true)
+    @VarAttrDef.VarAttr(name = JOIN_REORDER_TIME_LIMIT, needForward = true)
     public long joinReorderTimeLimit = 1000;
 
     // If this is true, the result of `show roles` will return all user default role
-    @VariableMgr.VarAttr(name = SHOW_USER_DEFAULT_ROLE, needForward = true)
+    @VarAttrDef.VarAttr(name = SHOW_USER_DEFAULT_ROLE, needForward = true)
     public boolean showUserDefaultRole = false;
 
     // Default value is -1, which means not fix replica
-    @VariableMgr.VarAttr(name = USE_FIX_REPLICA, needForward = true)
+    @VarAttrDef.VarAttr(name = USE_FIX_REPLICA, needForward = true)
     public int useFixReplica = -1;
 
-    @VariableMgr.VarAttr(name = DUMP_NEREIDS_MEMO)
+    @VarAttrDef.VarAttr(name = DUMP_NEREIDS_MEMO)
     public boolean dumpNereidsMemo = false;
 
-    @VariableMgr.VarAttr(name = "memo_max_group_expression_size")
+    @VarAttrDef.VarAttr(name = "memo_max_group_expression_size")
     public int memoMaxGroupExpressionSize = 10000;
 
-    @VariableMgr.VarAttr(name = DPHYPER_LIMIT)
+    @VarAttrDef.VarAttr(name = DPHYPER_LIMIT)
     public int dphyperLimit = 1000;
 
-    @VariableMgr.VarAttr(name = "eager_aggregation_mode", needForward = true,
+    @VarAttrDef.VarAttr(name = "eager_aggregation_mode", needForward = true,
             description = {"0: 根据统计信息决定是使用eager aggregation,"
                     + "1: 强制使用 eager aggregation,"
                     + "-1: 禁止使用 eager aggregation",
@@ -2317,7 +2317,7 @@ public class SessionVariable implements Serializable, Writable {
         this.eagerAggregationMode = mode;
     }
 
-    @VariableMgr.VarAttr(name = "eager_aggregation_on_join", needForward = true)
+    @VarAttrDef.VarAttr(name = "eager_aggregation_on_join", needForward = true)
     public boolean eagerAggregationOnJoin = false;
 
     public static boolean isEagerAggregationOnJoin() {
@@ -2328,7 +2328,7 @@ public class SessionVariable implements Serializable, Writable {
         }
     }
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_PAGE_CACHE,
             description = {"控制是否启用 page cache。默认为 true。",
                 "Controls whether to use page cache. "
@@ -2336,30 +2336,30 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public boolean enablePageCache = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_PARQUET_FILE_PAGE_CACHE,
             description = {"控制是否启用 Parquet file page cache。默认为 true。",
                     "Controls whether to use Parquet file page cache. The default is true."},
             needForward = true)
     public boolean enableParquetFilePageCache = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_FOLD_NONDETERMINISTIC_FN)
+    @VarAttrDef.VarAttr(name = ENABLE_FOLD_NONDETERMINISTIC_FN)
     public boolean enableFoldNondeterministicFn = false;
 
-    @VariableMgr.VarAttr(name = TRACE_NEREIDS)
+    @VarAttrDef.VarAttr(name = TRACE_NEREIDS)
     public boolean traceNereids = false;
 
-    @VariableMgr.VarAttr(name = PLAN_NEREIDS_DUMP)
+    @VarAttrDef.VarAttr(name = PLAN_NEREIDS_DUMP)
     public boolean planNereidsDump = false;
 
     // If set to true, all query will be executed without returning result
-    @VariableMgr.VarAttr(name = DRY_RUN_QUERY, needForward = true)
+    @VarAttrDef.VarAttr(name = DRY_RUN_QUERY, needForward = true)
     public boolean dryRunQuery = false;
 
-    @VariableMgr.VarAttr(name = FILE_SPLIT_SIZE, needForward = true)
+    @VarAttrDef.VarAttr(name = FILE_SPLIT_SIZE, needForward = true)
     public long fileSplitSize = 0;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = MAX_INITIAL_FILE_SPLIT_SIZE,
             description = {"对于每个 table scan,最大文件分片初始大小。"
                     + "初始化使用 MAX_INITIAL_FILE_SPLIT_SIZE,一旦超过了 MAX_INITIAL_FILE_SPLIT_NUM,则使用 MAX_FILE_SPLIT_SIZE。",
@@ -2369,7 +2369,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public long maxInitialSplitSize = 32L * 1024L * 1024L;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = MAX_FILE_SPLIT_SIZE,
             description = {"对于每个 table scan,最大文件分片大小。"
                     + "初始化使用 MAX_INITIAL_FILE_SPLIT_SIZE,一旦超过了 MAX_INITIAL_FILE_SPLIT_NUM,则使用 MAX_FILE_SPLIT_SIZE。",
@@ -2379,7 +2379,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public long maxSplitSize = 64L * 1024L * 1024L;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = MAX_INITIAL_FILE_SPLIT_NUM,
             description = {"对于每个 table scan,最大文件分片初始数目。"
                     + "初始化使用 MAX_INITIAL_FILE_SPLIT_SIZE,一旦超过了 MAX_INITIAL_FILE_SPLIT_NUM,则使用 MAX_FILE_SPLIT_SIZE。",
@@ -2389,7 +2389,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public int maxInitialSplitNum = 200;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = MAX_FILE_SPLIT_NUM,
             description = {"在非 batch 模式下,每个 table scan 最大允许的 split 数量,防止产生过多 split 导致 OOM。",
                     "In non-batch mode, the maximum number of splits allowed per table scan to avoid OOM."},
@@ -2398,10 +2398,10 @@ public class SessionVariable implements Serializable, Writable {
 
     // Target file size for Iceberg write operations
     // Default 0 means use config::iceberg_sink_max_file_size
-    @VariableMgr.VarAttr(name = ICEBERG_WRITE_TARGET_FILE_SIZE_BYTES, needForward = true)
+    @VarAttrDef.VarAttr(name = ICEBERG_WRITE_TARGET_FILE_SIZE_BYTES, needForward = true)
     public long icebergWriteTargetFileSizeBytes = 0L;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = NUM_PARTITIONS_IN_BATCH_MODE,
             fuzzy = true,
             description = {"如果分区数量超过阈值,BE 将通过 batch 方式获取 scan ranges。作用于 Hive、Hudi、MaxCompute 表。",
@@ -2409,7 +2409,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public int numPartitionsInBatchMode = 1024;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = NUM_FILES_IN_BATCH_MODE,
             fuzzy = true,
             description = {"如果文件数量超过阈值,BE 将通过 batch 方式获取 scan ranges",
@@ -2417,14 +2417,14 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public int numFilesInBatchMode = 1024;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = FETCH_SPLITS_MAX_WAIT_TIME,
             description = {"batch 方式中 BE 获取 splits 的最大等待时间",
                     "The max wait time of getting splits in batch mode."},
             needForward = true)
     public long fetchSplitsMaxWaitTime = 1000;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_PARQUET_LAZY_MAT,
             fuzzy = true,
             description = {"控制 parquet reader 是否启用延迟物化技术。默认为 true。",
@@ -2433,7 +2433,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public boolean enableParquetLazyMat = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_ORC_LAZY_MAT,
             fuzzy = true,
             description = {"控制 orc reader 是否启用延迟物化技术。默认为 true。",
@@ -2442,7 +2442,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public boolean enableOrcLazyMat = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ORC_TINY_STRIPE_THRESHOLD_BYTES,
             fuzzy = true,
             description = {"在 orc 文件中如果一个 stripe 的字节大小小于`orc_tiny_stripe_threshold`,"
@@ -2458,7 +2458,7 @@ public class SessionVariable implements Serializable, Writable {
     public long orcTinyStripeThresholdBytes  = 8L * 1024L * 1024L;
 
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ORC_ONCE_MAX_READ_BYTES,
             fuzzy = true,
             description = {"在使用 tiny stripe 读取优化的时候,会对多个 tiny stripe 合并成一次 IO,"
@@ -2472,7 +2472,7 @@ public class SessionVariable implements Serializable, Writable {
     public long orcOnceMaxReadBytes = 8L * 1024L * 1024L;
 
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ORC_MAX_MERGE_DISTANCE_BYTES,
             fuzzy = true,
             description = {"在使用 tiny stripe 读取优化的时候,由于 tiny stripe 并不一定连续。"
@@ -2485,7 +2485,7 @@ public class SessionVariable implements Serializable, Writable {
     public long orcMaxMergeDistanceBytes = 1024L * 1024L;
 
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_PARQUET_FILTER_BY_MIN_MAX,
             fuzzy = true,
             description = {"控制 parquet reader 是否启用 min-max 值过滤。默认为 true。",
@@ -2494,7 +2494,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public boolean enableParquetFilterByMinMax = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_PARQUET_FILTER_BY_BLOOM_FILTER,
             fuzzy = true,
             description = {"控制 parquet reader 是否启用 bloom filter 过滤。默认为 true。",
@@ -2503,7 +2503,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public boolean enableParquetFilterByBloomFilter = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_ORC_FILTER_BY_MIN_MAX,
             description = {"控制 orc reader 是否启用 min-max 值过滤。默认为 true。",
                     "Controls whether to filter by min-max values in orc reader. "
@@ -2511,7 +2511,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public boolean enableOrcFilterByMinMax = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = CHECK_ORC_INIT_SARGS_SUCCESS,
             description = {"是否检查 orc init sargs 是否成功。默认为 false。",
                     "Whether to check whether orc init sargs is successful. "
@@ -2519,7 +2519,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public boolean checkOrcInitSargsSuccess = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = EXTERNAL_TABLE_ANALYZE_PART_NUM,
             description = {"收集外表统计信息行数时选取的采样分区数,默认 -1 表示全部分区",
                     "Number of sample partition for collecting external table line number, "
@@ -2527,19 +2527,19 @@ public class SessionVariable implements Serializable, Writable {
             needForward = false)
     public int externalTableAnalyzePartNum = -1;
 
-    @VariableMgr.VarAttr(name = INLINE_CTE_REFERENCED_THRESHOLD)
+    @VarAttrDef.VarAttr(name = INLINE_CTE_REFERENCED_THRESHOLD)
     public int inlineCTEReferencedThreshold = 1;
 
-    @VariableMgr.VarAttr(name = ENABLE_CTE_MATERIALIZE)
+    @VarAttrDef.VarAttr(name = ENABLE_CTE_MATERIALIZE)
     public boolean enableCTEMaterialize = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_ORDERED_SCAN_RANGE_LOCATIONS)
+    @VarAttrDef.VarAttr(name = ENABLE_ORDERED_SCAN_RANGE_LOCATIONS)
     public boolean enableOrderedScanRangeLocations = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_ANALYZE_COMPLEX_TYPE_COLUMN)
+    @VarAttrDef.VarAttr(name = ENABLE_ANALYZE_COMPLEX_TYPE_COLUMN)
     public boolean enableAnalyzeComplexTypeColumn = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_STRONG_CONSISTENCY, description = {"用以开启强一致读。Doris 默认支持同一个会话内的"
+    @VarAttrDef.VarAttr(name = ENABLE_STRONG_CONSISTENCY, description = {"用以开启强一致读。Doris 默认支持同一个会话内的"
             + "强一致性,即同一个会话内对数据的变更操作是实时可见的。如需要会话间的强一致读,则需将此变量设置为 true。",
             "Used to enable strong consistent reading. By default, Doris supports strong consistency "
                     + "within the same session, that is, changes to data within the same session are visible in "
@@ -2547,10 +2547,10 @@ public class SessionVariable implements Serializable, Writable {
     })
     public boolean enableStrongConsistencyRead = false;
 
-    @VariableMgr.VarAttr(name = PARALLEL_SYNC_ANALYZE_TASK_NUM)
+    @VarAttrDef.VarAttr(name = PARALLEL_SYNC_ANALYZE_TASK_NUM)
     public int parallelSyncAnalyzeTaskNum = 2;
 
-    @VariableMgr.VarAttr(name = TRUNCATE_CHAR_OR_VARCHAR_COLUMNS,
+    @VarAttrDef.VarAttr(name = TRUNCATE_CHAR_OR_VARCHAR_COLUMNS,
             description = {"是否按照表的 schema 来截断 char 或者 varchar 列。默认为 false。\n"
                     + "因为外表会存在表的 schema 中 char 或者 varchar 列的最大长度和底层 parquet 或者 orc 文件中的 schema 不一致"
                     + "的情况。此时开启改选项,会按照表的 schema 中的最大长度进行截断。",
@@ -2563,19 +2563,19 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public boolean truncateCharOrVarcharColumns = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_MEMTABLE_ON_SINK_NODE, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_MEMTABLE_ON_SINK_NODE, needForward = true)
     public boolean enableMemtableOnSinkNode = true;
 
-    @VariableMgr.VarAttr(name = LOAD_STREAM_PER_NODE)
+    @VarAttrDef.VarAttr(name = LOAD_STREAM_PER_NODE)
     public int loadStreamPerNode = 2;
 
-    @VariableMgr.VarAttr(name = GROUP_COMMIT, needForward = true)
+    @VarAttrDef.VarAttr(name = GROUP_COMMIT, needForward = true)
     public String groupCommit = "off_mode";
 
-    @VariableMgr.VarAttr(name = ENABLE_PREPARED_STMT_AUDIT_LOG, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_PREPARED_STMT_AUDIT_LOG, needForward = true)
     public boolean enablePreparedStmtAuditLog = false;
 
-    @VariableMgr.VarAttr(name = INVERTED_INDEX_CONJUNCTION_OPT_THRESHOLD,
+    @VarAttrDef.VarAttr(name = INVERTED_INDEX_CONJUNCTION_OPT_THRESHOLD,
             description = {"在 match_all 中求取多个倒排索引的交集时,如果最大的倒排索引中的总数是最小倒排索引中的总数的整数倍,"
                     + "则使用跳表来优化交集操作。",
                     "When intersecting multiple inverted indexes in match_all,"
@@ -2584,39 +2584,39 @@ public class SessionVariable implements Serializable, Writable {
                     + " use a skiplist to optimize the intersection."})
     public int invertedIndexConjunctionOptThreshold = 1000;
 
-    @VariableMgr.VarAttr(name = INVERTED_INDEX_MAX_EXPANSIONS,
+    @VarAttrDef.VarAttr(name = INVERTED_INDEX_MAX_EXPANSIONS,
             affectQueryResultInExecution = true,
             description = {"这个参数用来限制查询时扩展的词项(terms)的数量,以此来控制查询的性能",
                     "This parameter is used to limit the number of term expansions during a query,"
                     + " thereby controlling query performance"})
     public int invertedIndexMaxExpansions = 50;
 
-    @VariableMgr.VarAttr(name = INVERTED_INDEX_SKIP_THRESHOLD,
+    @VarAttrDef.VarAttr(name = INVERTED_INDEX_SKIP_THRESHOLD,
             description = {"在倒排索引中如果预估命中量占比总量超过百分比阈值,则跳过索引直接进行匹配。",
                     "In the inverted index,"
                             + " if the estimated hit ratio exceeds the percentage threshold of the total amount, "
                             + " then skip the index and proceed directly to matching."})
     public int invertedIndexSkipThreshold = 50;
 
-    @VariableMgr.VarAttr(name = INVERTED_INDEX_COMPATIBLE_READ,
+    @VarAttrDef.VarAttr(name = INVERTED_INDEX_COMPATIBLE_READ,
             description = {"兼容读取倒排索引,用于在 x86 和 arm 集群之间读取旧版本索引文件。",
                     "Compatible read for inverted index between x86 and arm, "
                             + "used to read old version index file from x86 in arm cluster"
                             + "or read old version index file from arm in x86 cluster"})
     public boolean invertedIndexCompatibleRead = false;
 
-    @VariableMgr.VarAttr(name = SQL_DIALECT, needForward = true, checker = "checkSqlDialect",
+    @VarAttrDef.VarAttr(name = SQL_DIALECT, needForward = true, checker = "checkSqlDialect",
             description = {"解析 sql 使用的方言", "The dialect used to parse sql."},
             affectQueryResultInPlan = true
     )
     public String sqlDialect = "doris";
 
-    @VariableMgr.VarAttr(name = RETRY_ORIGIN_SQL_ON_CONVERT_FAIL, needForward = true,
+    @VarAttrDef.VarAttr(name = RETRY_ORIGIN_SQL_ON_CONVERT_FAIL, needForward = true,
             description = {"当转换后的 SQL 解析失败时,是否重试原始 SQL",
                     "Enable retrying original SQL when converted SQL parsing fails."})
     public boolean retryOriginSqlOnConvertFail = false;
 
-    @VariableMgr.VarAttr(name = SERDE_DIALECT, needForward = true, checker = "checkSerdeDialect",
+    @VarAttrDef.VarAttr(name = SERDE_DIALECT, needForward = true, checker = "checkSerdeDialect",
             description = {"返回给 MySQL 客户端时各数据类型的输出格式方言",
                     "The output format dialect of each data type returned to the MySQL client."},
             options = {"doris", "presto", "trino"},
@@ -2624,67 +2624,67 @@ public class SessionVariable implements Serializable, Writable {
     )
     public String serdeDialect = "doris";
 
-    @VariableMgr.VarAttr(name = ENABLE_UNIQUE_KEY_PARTIAL_UPDATE, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_UNIQUE_KEY_PARTIAL_UPDATE, needForward = true)
     public boolean enableUniqueKeyPartialUpdate = false;
 
-    @VariableMgr.VarAttr(name = PARTIAL_UPDATE_NEW_KEY_BEHAVIOR, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = PARTIAL_UPDATE_NEW_KEY_BEHAVIOR, needForward = true, description = {
             "用于设置部分列更新中对于新插入的行的行为",
             "Used to set the behavior for newly inserted rows in partial update."
             }, checker = "checkPartialUpdateNewKeyBehavior", options = {"APPEND", "ERROR"})
     public String partialUpdateNewKeyPolicy = "APPEND";
 
-    @VariableMgr.VarAttr(name = ENABLE_AUTO_ANALYZE,
+    @VarAttrDef.VarAttr(name = ENABLE_AUTO_ANALYZE,
             description = {"该参数控制是否开启自动收集", "Set false to disable auto analyze"},
-            flag = VariableMgr.GLOBAL)
+            flag = VarAttrDef.GLOBAL)
     public volatile boolean enableAutoAnalyze = true;
 
-    @VariableMgr.VarAttr(name = FORCE_SAMPLE_ANALYZE, needForward = true,
+    @VarAttrDef.VarAttr(name = FORCE_SAMPLE_ANALYZE, needForward = true,
             description = {"是否将 full analyze 自动转换成 sample analyze", "Set true to force sample analyze"},
-            flag = VariableMgr.GLOBAL)
+            flag = VarAttrDef.GLOBAL)
     public boolean forceSampleAnalyze = Config.force_sample_analyze;
 
-    @VariableMgr.VarAttr(name = ENABLE_AUTO_ANALYZE_INTERNAL_CATALOG,
+    @VarAttrDef.VarAttr(name = ENABLE_AUTO_ANALYZE_INTERNAL_CATALOG,
             description = {"临时参数,收否自动收集所有内表", "Temp variable, enable to auto collect all OlapTable."},
-            flag = VariableMgr.GLOBAL)
+            flag = VarAttrDef.GLOBAL)
     public boolean enableAutoAnalyzeInternalCatalog = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_PARTITION_ANALYZE,
+    @VarAttrDef.VarAttr(name = ENABLE_PARTITION_ANALYZE,
             description = {"临时参数,收否收集分区级别统计信息", "Temp variable, enable to collect partition level statistics."},
-            flag = VariableMgr.GLOBAL)
+            flag = VarAttrDef.GLOBAL)
     public boolean enablePartitionAnalyze = false;
 
-    @VariableMgr.VarAttr(name = AUTO_ANALYZE_TABLE_WIDTH_THRESHOLD,
+    @VarAttrDef.VarAttr(name = AUTO_ANALYZE_TABLE_WIDTH_THRESHOLD,
             description = {"参与自动收集的最大表宽度,列数多于这个参数的表不参与自动收集",
                 "Maximum table width to enable auto analyze, "
                     + "table with more columns than this value will not be auto analyzed."},
-            flag = VariableMgr.GLOBAL)
+            flag = VarAttrDef.GLOBAL)
     public int autoAnalyzeTableWidthThreshold = 300;
 
-    @VariableMgr.VarAttr(name = AUTO_ANALYZE_START_TIME, needForward = true, checker = "checkAnalyzeTimeFormat",
+    @VarAttrDef.VarAttr(name = AUTO_ANALYZE_START_TIME, needForward = true, checker = "checkAnalyzeTimeFormat",
             description = {"该参数定义自动 ANALYZE 例程的开始时间",
                     "This parameter defines the start time for the automatic ANALYZE routine."},
-            flag = VariableMgr.GLOBAL)
+            flag = VarAttrDef.GLOBAL)
     public String autoAnalyzeStartTime = "00:00:00";
 
-    @VariableMgr.VarAttr(name = AUTO_ANALYZE_END_TIME, needForward = true, checker = "checkAnalyzeTimeFormat",
+    @VarAttrDef.VarAttr(name = AUTO_ANALYZE_END_TIME, needForward = true, checker = "checkAnalyzeTimeFormat",
             description = {"该参数定义自动 ANALYZE 例程的结束时间",
                     "This parameter defines the end time for the automatic ANALYZE routine."},
-            flag = VariableMgr.GLOBAL)
+            flag = VarAttrDef.GLOBAL)
     public String autoAnalyzeEndTime = "23:59:59";
 
-    @VariableMgr.VarAttr(name = IGNORE_RUNTIME_FILTER_IDS,
+    @VarAttrDef.VarAttr(name = IGNORE_RUNTIME_FILTER_IDS,
             description = {"在 IGNORE_RUNTIME_FILTER_IDS 列表中的 runtime filter 将不会被生成",
                     "the runtime filter id in IGNORE_RUNTIME_FILTER_IDS list will not be generated"})
 
     public String ignoreRuntimeFilterIds = "";
 
-    @VariableMgr.VarAttr(name = STATS_INSERT_MERGE_ITEM_COUNT, flag = VariableMgr.GLOBAL, description = {
+    @VarAttrDef.VarAttr(name = STATS_INSERT_MERGE_ITEM_COUNT, flag = VarAttrDef.GLOBAL, description = {
             "控制统计信息相关 INSERT 攒批数量", "Controls the batch size for stats INSERT merging."
     }
     )
     public int statsInsertMergeItemCount = 200;
 
-    @VariableMgr.VarAttr(name = HUGE_TABLE_DEFAULT_SAMPLE_ROWS, flag = VariableMgr.GLOBAL, description = {
+    @VarAttrDef.VarAttr(name = HUGE_TABLE_DEFAULT_SAMPLE_ROWS, flag = VarAttrDef.GLOBAL, description = {
             "定义开启开启大表自动 sample 后,对大表的采样比例",
             "This defines the number of sample percent for large tables when automatic sampling for"
                     + "large tables is enabled"
@@ -2693,7 +2693,7 @@ public class SessionVariable implements Serializable, Writable {
     public long hugeTableDefaultSampleRows = 4194304;
 
 
-    @VariableMgr.VarAttr(name = HUGE_TABLE_LOWER_BOUND_SIZE_IN_BYTES, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = HUGE_TABLE_LOWER_BOUND_SIZE_IN_BYTES, flag = VarAttrDef.GLOBAL,
             description = {
                     "大小超过该值的表将会自动通过采样收集统计信息",
                     "This defines the lower size bound for large tables. "
@@ -2702,7 +2702,7 @@ public class SessionVariable implements Serializable, Writable {
                             + "statistics through sampling"})
     public long hugeTableLowerBoundSizeInBytes = 0;
 
-    @VariableMgr.VarAttr(name = HUGE_TABLE_AUTO_ANALYZE_INTERVAL_IN_MILLIS, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = HUGE_TABLE_AUTO_ANALYZE_INTERVAL_IN_MILLIS, flag = VarAttrDef.GLOBAL,
             description = {"控制对大表的自动 ANALYZE 的最小时间间隔,"
                     + "在该时间间隔内大小超过 huge_table_lower_bound_size_in_bytes 的表仅 ANALYZE 一次",
                     "This controls the minimum time interval for automatic ANALYZE on large tables."
@@ -2710,13 +2710,13 @@ public class SessionVariable implements Serializable, Writable {
                             + "tables larger than huge_table_lower_bound_size_in_bytes are analyzed only once."})
     public long hugeTableAutoAnalyzeIntervalInMillis = TimeUnit.HOURS.toMillis(0);
 
-    @VariableMgr.VarAttr(name = EXTERNAL_TABLE_AUTO_ANALYZE_INTERVAL_IN_MILLIS, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = EXTERNAL_TABLE_AUTO_ANALYZE_INTERVAL_IN_MILLIS, flag = VarAttrDef.GLOBAL,
             description = {"控制对外表的自动 ANALYZE 的最小时间间隔,在该时间间隔内的外表仅 ANALYZE 一次",
                     "This controls the minimum time interval for automatic ANALYZE on external tables."
                         + "Within this interval, external tables are analyzed only once."})
     public long externalTableAutoAnalyzeIntervalInMillis = TimeUnit.HOURS.toMillis(24);
 
-    @VariableMgr.VarAttr(name = TABLE_STATS_HEALTH_THRESHOLD, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = TABLE_STATS_HEALTH_THRESHOLD, flag = VarAttrDef.GLOBAL,
             description = {"取值在 0-100 之间,当自上次统计信息收集操作之后"
                     + "数据更新量达到 (100 - table_stats_health_threshold)% ,认为该表的统计信息已过时",
                     "The value should be between 0 and 100. When the data update quantity "
@@ -2725,29 +2725,29 @@ public class SessionVariable implements Serializable, Writable {
                             + "considered outdated."})
     public int tableStatsHealthThreshold = 90;
 
-    @VariableMgr.VarAttr(name = PARTITION_SAMPLE_COUNT, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = PARTITION_SAMPLE_COUNT, flag = VarAttrDef.GLOBAL,
             description = {
                     "大分区表采样的分区数上限",
                     "The upper limit of the number of partitions for sampling large partitioned tables.\n"})
     public int partitionSampleCount = 30;
 
-    @VariableMgr.VarAttr(name = PARTITION_SAMPLE_ROW_COUNT, flag = VariableMgr.GLOBAL,
+    @VarAttrDef.VarAttr(name = PARTITION_SAMPLE_ROW_COUNT, flag = VarAttrDef.GLOBAL,
             description = {
                     "大分区表采样的行数上限",
                     "The upper limit of the number of rows for sampling large partitioned tables.\n"})
     public long partitionSampleRowCount = 3_000_000_000L;
 
-    @VariableMgr.VarAttr(name = FETCH_HIVE_ROW_COUNT_SYNC,
+    @VarAttrDef.VarAttr(name = FETCH_HIVE_ROW_COUNT_SYNC,
             fuzzy = true,
             description = {"同步获取 Hive 外表行数", "Fetch Hive external table row count synchronously"})
     public boolean fetchHiveRowCountSync = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_MATERIALIZED_VIEW_REWRITE, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_MATERIALIZED_VIEW_REWRITE, needForward = true,
             description = {"是否开启基于结构信息的物化视图透明改写",
                     "Whether to enable materialized view rewriting based on struct info"})
     public boolean enableMaterializedViewRewrite = true;
 
-    @VariableMgr.VarAttr(name = PRE_MATERIALIZED_VIEW_REWRITE_STRATEGY, needForward = true, fuzzy = true,
+    @VarAttrDef.VarAttr(name = PRE_MATERIALIZED_VIEW_REWRITE_STRATEGY, needForward = true, fuzzy = true,
             description = {"在 RBO 阶段基于结构信息的物化视图透明改写的策略,FORCE_IN_RBO:强制在 RBO 阶段透明改写,"
                     + "TRY_IN_RBO:如果在 NEED_PRE_REWRITE_RULE_TYPES 中的规则改写成功了,那么就会尝试在 RBO 阶段透明改写"
                     + "NOT_IN_RBO:不尝试在 RBO 阶段改写,只在 CBO 阶段改写",
@@ -2759,105 +2759,105 @@ public class SessionVariable implements Serializable, Writable {
             })
     public String preMaterializedViewRewriteStrategy = "TRY_IN_RBO";
 
-    @VariableMgr.VarAttr(name = ALLOW_MODIFY_MATERIALIZED_VIEW_DATA, needForward = true,
+    @VarAttrDef.VarAttr(name = ALLOW_MODIFY_MATERIALIZED_VIEW_DATA, needForward = true,
             description = {"是否允许修改物化视图的数据",
                     "Is it allowed to modify the data of the materialized view"})
     public boolean allowModifyMaterializedViewData = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_MATERIALIZED_VIEW_REWRITE_WHEN_BASE_TABLE_UNAWARENESS,
+    @VarAttrDef.VarAttr(name = ENABLE_MATERIALIZED_VIEW_REWRITE_WHEN_BASE_TABLE_UNAWARENESS,
             needForward = true,
             description = {"查询时,当物化视图存在无法实时感知数据的外表时,是否开启基于结构信息的物化视图透明改写",
                     ""})
     public boolean enableMaterializedViewRewriteWhenBaseTableUnawareness = false;
-    @VariableMgr.VarAttr(name = MATERIALIZED_VIEW_REWRITE_SUCCESS_CANDIDATE_NUM, needForward = true,
+    @VarAttrDef.VarAttr(name = MATERIALIZED_VIEW_REWRITE_SUCCESS_CANDIDATE_NUM, needForward = true,
             description = {"异步物化视图透明改写成功的结果集合,允许参与到 CBO 候选的最大数量",
                     "The max candidate num which participate in CBO when using asynchronous materialized views"})
     public int materializedViewRewriteSuccessCandidateNum = 3;
 
-    @VariableMgr.VarAttr(name = ENABLE_DML_MATERIALIZED_VIEW_REWRITE, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_DML_MATERIALIZED_VIEW_REWRITE, needForward = true,
             description = {"DML 时,是否开启基于结构信息的物化视图透明改写",
                     "Whether to enable materialized view rewriting based on struct info"})
     public boolean enableDmlMaterializedViewRewrite = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_DML_MATERIALIZED_VIEW_REWRITE_WHEN_BASE_TABLE_UNAWARENESS,
+    @VarAttrDef.VarAttr(name = ENABLE_DML_MATERIALIZED_VIEW_REWRITE_WHEN_BASE_TABLE_UNAWARENESS,
             needForward = true,
             description = {"DML 时,当物化视图存在无法实时感知数据的外表时,是否开启基于结构信息的物化视图透明改写",
                     ""})
     public boolean enableDmlMaterializedViewRewriteWhenBaseTableUnawareness = false;
 
-    @VariableMgr.VarAttr(name = MATERIALIZED_VIEW_RELATION_MAPPING_MAX_COUNT, needForward = true,
+    @VarAttrDef.VarAttr(name = MATERIALIZED_VIEW_RELATION_MAPPING_MAX_COUNT, needForward = true,
             description = {"透明改写过程中,relation mapping 最大允许数量,如果超过,进行截取",
                     "During transparent rewriting, relation mapping specifies the maximum allowed number. "
                             + "If the number exceeds the allowed number, the number is intercepted"})
     public int materializedViewRelationMappingMaxCount = 8;
 
-    @VariableMgr.VarAttr(name = ENABLE_MATERIALIZED_VIEW_UNION_REWRITE, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_MATERIALIZED_VIEW_UNION_REWRITE, needForward = true,
             description = {"当物化视图不足以提供查询的全部数据时,是否允许基表和物化视图 union 来响应查询",
                     "When the materialized view is not enough to provide all the data for the query, "
                             + "whether to allow the union of the base table and the materialized view to "
                             + "respond to the query"}, varType = VariableAnnotation.REMOVED)
     public boolean enableMaterializedViewUnionRewrite = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_MATERIALIZED_VIEW_NEST_REWRITE, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_MATERIALIZED_VIEW_NEST_REWRITE, needForward = true,
             description = {"是否允许嵌套物化视图改写",
                     "Whether enable materialized view nest rewrite"})
     public boolean enableMaterializedViewNestRewrite = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_SYNC_MV_COST_BASED_REWRITE, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_SYNC_MV_COST_BASED_REWRITE, needForward = true,
             description = {"是否允许基于代价改写同步物化视图",
                     "Whether enable cost based rewrite for sync mv"}, varType = VariableAnnotation.REMOVED)
     public boolean enableSyncMvCostBasedRewrite = true;
 
-    @VariableMgr.VarAttr(name = MATERIALIZED_VIEW_REWRITE_DURATION_THRESHOLD_MS, needForward = true,
+    @VarAttrDef.VarAttr(name = MATERIALIZED_VIEW_REWRITE_DURATION_THRESHOLD_MS, needForward = true,
             description = {"物化视图透明改写允许的最长耗时,超过此时长不再进行透明改写",
                     "The maximum duration allowed for transparent rewriting of materialized views; "
                             + "if this duration is exceeded, transparent rewriting will no longer be performed."})
     public long materializedViewRewriteDurationThresholdMs = 1000L;
 
-    @VariableMgr.VarAttr(name = CREATE_TABLE_PARTITION_MAX_NUM, needForward = true,
+    @VarAttrDef.VarAttr(name = CREATE_TABLE_PARTITION_MAX_NUM, needForward = true,
             description = {"建表时创建分区的最大数量",
                     "The maximum number of partitions created during table creation"})
     public int createTablePartitionMaxNum = 10000;
 
 
-    @VariableMgr.VarAttr(name = HIVE_PARQUET_USE_COLUMN_NAMES, affectQueryResultInExecution = true,
+    @VarAttrDef.VarAttr(name = HIVE_PARQUET_USE_COLUMN_NAMES, affectQueryResultInExecution = true,
             description = {"默认情况下按名称访问 Parquet 列。将此属性设置为“false”可按 Hive 表定义中的序号位置访问列。",
                     "Access Parquet columns by name by default. Set this property to `false` to access columns "
                             + "by their ordinal position in the Hive table definition."})
     public boolean hiveParquetUseColumnNames = true;
 
-    @VariableMgr.VarAttr(name = HIVE_ORC_USE_COLUMN_NAMES, affectQueryResultInExecution = true,
+    @VarAttrDef.VarAttr(name = HIVE_ORC_USE_COLUMN_NAMES, affectQueryResultInExecution = true,
             description = {"默认情况下按名称访问 Orc 列。将此属性设置为“false”可按 Hive 表定义中的序号位置访问列。",
                     "Access Parquet columns by name by default. Set this property to `false` to access columns "
                             + "by their ordinal position in the Hive table definition."})
     public boolean hiveOrcUseColumnNames = true;
 
-    @VariableMgr.VarAttr(name = KEEP_CARRIAGE_RETURN,
+    @VarAttrDef.VarAttr(name = KEEP_CARRIAGE_RETURN,
             description = {"在同时处理\r和\r\n作为 CSV 的行分隔符时,是否保留\r",
                     "When processing both \\n and \\r\\n as CSV line separators, should \\r be retained?"})
     public boolean keepCarriageReturn = false;
 
-    @VariableMgr.VarAttr(name = EXCHANGE_MULTI_BLOCKS_BYTE_SIZE,
+    @VarAttrDef.VarAttr(name = EXCHANGE_MULTI_BLOCKS_BYTE_SIZE,
             description = {"Enable exchange to send multiple blocks in one RPC. Default is 256KB. A negative"
                     + " value disables multi-block exchange."})
     public int exchangeMultiBlocksByteSize = 256 * 1024;
 
-    @VariableMgr.VarAttr(name = FORCE_JNI_SCANNER,
+    @VarAttrDef.VarAttr(name = FORCE_JNI_SCANNER,
             fuzzy = true,
             description = {"强制使用 jni 方式读取外表", "Force the use of jni mode to read external table"})
     private boolean forceJniScanner = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_PAIMON_CPP_READER,
+    @VarAttrDef.VarAttr(name = ENABLE_PAIMON_CPP_READER,
             fuzzy = true,
             description = {"Paimon 非原生文件读取使用 paimon-cpp", "Use paimon-cpp for non-native Paimon reads"})
     private boolean enablePaimonCppReader = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_COUNT_PUSH_DOWN_FOR_EXTERNAL_TABLE,
+    @VarAttrDef.VarAttr(name = ENABLE_COUNT_PUSH_DOWN_FOR_EXTERNAL_TABLE,
             fuzzy = true,
             description = {"对外表启用 count(*) 下推优化", "enable count(*) pushdown optimization for external table"})
     private boolean enableCountPushDownForExternalTable = true;
 
-    @VariableMgr.VarAttr(name = MINIMUM_OPERATOR_MEMORY_REQUIRED_KB, needForward = true,
+    @VarAttrDef.VarAttr(name = MINIMUM_OPERATOR_MEMORY_REQUIRED_KB, needForward = true,
             description = {"一个算子运行需要的最小的内存大小",
                     "The minimum memory required to be used by an operator, if not meet, the operator will not run"})
     public int minimumOperatorMemoryRequiredKB = 32000;
@@ -2867,14 +2867,14 @@ public class SessionVariable implements Serializable, Writable {
     public static final String ENABLE_EXTERNAL_TABLE_BATCH_MODE = "enable_external_table_batch_mode";
 
     public static final String ENABLE_MC_LIMIT_SPLIT_OPTIMIZATION = "enable_mc_limit_split_optimization";
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_EXTERNAL_TABLE_BATCH_MODE,
             fuzzy = true,
             description = {"使能外表的 batch mode 功能", "Enable the batch mode function of the external table."},
             needForward = true)
     public boolean enableExternalTableBatchMode = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_MC_LIMIT_SPLIT_OPTIMIZATION,
             fuzzy = true,
             description = {"开启 MaxCompute 表 LIMIT 查询的 split 优化。当查询仅包含分区等值条件且带有 LIMIT 时,"
@@ -2885,7 +2885,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public boolean enableMcLimitSplitOptimization = false;
 
-    @VariableMgr.VarAttr(name = SKEW_REWRITE_AGG_BUCKET_NUM, needForward = true,
+    @VarAttrDef.VarAttr(name = SKEW_REWRITE_AGG_BUCKET_NUM, needForward = true,
             description = {"bucketNum 参数控制 count(distinct) 倾斜优化的数据分布。决定不同值在 worker 间的分配方式,"
                     + "值越大越能处理极端倾斜但增加 shuffle 开销,值越小网络开销越低但可能无法完全解决倾斜。",
                     "The bucketNum parameter controls data distribution for skew optimization "
@@ -2896,29 +2896,29 @@ public class SessionVariable implements Serializable, Writable {
             }, checker = "checkSkewRewriteAggBucketNum")
     public int skewRewriteAggBucketNum = 1024;
 
-    @VariableMgr.VarAttr(name = AGG_SHUFFLE_USE_PARENT_KEY, description = {
+    @VarAttrDef.VarAttr(name = AGG_SHUFFLE_USE_PARENT_KEY, description = {
             "在聚合算子进行 shuffle 时,是否使用父节点的分组键进行 shuffle",
             "Whether to use the parent node's grouping key for shuffling during the aggregation operator"
     }, needForward = false)
     public boolean aggShuffleUseParentKey = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_PREFER_CACHED_ROWSET, needForward = false,
+    @VarAttrDef.VarAttr(name = ENABLE_PREFER_CACHED_ROWSET, needForward = false,
             description = {"是否启用 prefer cached rowset 功能",
                     "Whether to enable prefer cached rowset feature"})
     public boolean enablePreferCachedRowset = false;
 
-    @VariableMgr.VarAttr(name = QUERY_FRESHNESS_TOLERANCE_MS, needForward = false)
+    @VarAttrDef.VarAttr(name = QUERY_FRESHNESS_TOLERANCE_MS, needForward = false)
     public long queryFreshnessToleranceMs = -1;
 
     public void setSkewRewriteAggBucketNum(int num) {
         this.skewRewriteAggBucketNum = num;
     }
 
-    @VariableMgr.VarAttr(name = ENABLE_STRICT_CAST,
+    @VarAttrDef.VarAttr(name = ENABLE_STRICT_CAST,
             description = {"cast 使用严格模式", "Use strict mode for cast"}, affectQueryResultInPlan = true)
     public boolean enableStrictCast = false;
 
-    @VariableMgr.VarAttr(name = MULTI_DISTINCT_STRATEGY, description = {"用于控制在包含多个 DISTINCT 函数的 SQL 查询中所采用的"
+    @VarAttrDef.VarAttr(name = MULTI_DISTINCT_STRATEGY, description = {"用于控制在包含多个 DISTINCT 函数的 SQL 查询中所采用的"
             + "执行策略。默认值为 0,表示由系统自动选择最优策略;设为 1 表示强制使用 MultiDistinct 方式处理;"
             + "设为 2 表示强制采用 CTE 拆分方式执行。",
             "Used to control the execution strategy used in SQL queries containing multiple DISTINCT "
@@ -2928,7 +2928,7 @@ public class SessionVariable implements Serializable, Writable {
             checker = "checkMultiDistinctStrategy")
     public int multiDistinctStrategy = 0;
 
-    @VariableMgr.VarAttr(name = AGG_PHASE, description = {"用于控制聚合查询的执行阶段划分策略。默认值为 0,"
+    @VarAttrDef.VarAttr(name = AGG_PHASE, description = {"用于控制聚合查询的执行阶段划分策略。默认值为 0,"
             + "表示由系统自动选择最优执行阶段;设为 1 至 4 之间的值则表示强制指定使用对应 1 至 4 阶段进行聚合计算。",
             "Controls the execution phase strategy for aggregate queries. The default value is 0,"
                     + "which means the system automatically selects the optimal execution phase. Setting this value"
@@ -2937,12 +2937,12 @@ public class SessionVariable implements Serializable, Writable {
     public int aggPhase = 0;
 
 
-    @VariableMgr.VarAttr(name = MERGE_IO_READ_SLICE_SIZE_BYTES, description = {
+    @VarAttrDef.VarAttr(name = MERGE_IO_READ_SLICE_SIZE_BYTES, description = {
             "调整 READ_SLICE_SIZE 大小,降低 Merge IO 读放大影响",
             "Make the READ_SLICE_SIZE variable configurable to reduce the impact caused by read amplification."})
     public int mergeReadSliceSizeBytes = 8388608;
 
-    @VariableMgr.VarAttr(name = FILE_CACHE_QUERY_LIMIT_PERCENT, needForward = true,
+    @VarAttrDef.VarAttr(name = FILE_CACHE_QUERY_LIMIT_PERCENT, needForward = true,
             checker = "checkFileCacheQueryLimitPercent",
             description = {"限制用户的单个查询能使用的 FILE_CACHE 比例 "
                     + "(用户设置,取值范围 1 到 Config.file_cache_query_limit_max_percent)。",
@@ -3070,17 +3070,17 @@ public class SessionVariable implements Serializable, Writable {
         this.ignoreShapePlanNodes = ignoreShapePlanNodes;
     }
 
-    @VariableMgr.VarAttr(name = IGNORE_SHAPE_NODE,
+    @VarAttrDef.VarAttr(name = IGNORE_SHAPE_NODE,
             description = {"'explain shape plan' 命令中忽略的 PlanNode 类型",
                     "the plan node type which is ignored in 'explain shape plan' command"})
     public String ignoreShapePlanNodes = "";
 
-    @VariableMgr.VarAttr(name = DETAIL_SHAPE_NODES, needForward = true, setter = "setDetailShapePlanNodes",
+    @VarAttrDef.VarAttr(name = DETAIL_SHAPE_NODES, needForward = true, setter = "setDetailShapePlanNodes",
             description = {"'explain shape plan' 命令中显示详细信息的 PlanNode 类型",
                     "the plan node type show detail in 'explain shape plan' command"})
     public String detailShapePlanNodes = "";
 
-    @VariableMgr.VarAttr(name = ENABLE_EXPLAIN_NONE, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_EXPLAIN_NONE, needForward = true, description = {
             "执行 explain 命令,但不打印 explain 结果",
             "execute explain command and return nothing"
     })
@@ -3098,27 +3098,27 @@ public class SessionVariable implements Serializable, Writable {
         this.detailShapePlanNodes = detailShapePlanNodes;
     }
 
-    @VariableMgr.VarAttr(name = ENABLE_DECIMAL256, needForward = true, description = { "控制是否在计算过程中使用 Decimal256 类型",
+    @VarAttrDef.VarAttr(name = ENABLE_DECIMAL256, needForward = true, description = { "控制是否在计算过程中使用 Decimal256 类型",
             "Set to true to enable Decimal256 type" }, affectQueryResultInPlan = true)
     public boolean enableDecimal256 = false;
 
-    @VariableMgr.VarAttr(name = FALLBACK_OTHER_REPLICA_WHEN_FIXED_CORRUPT, needForward = true,
+    @VarAttrDef.VarAttr(name = FALLBACK_OTHER_REPLICA_WHEN_FIXED_CORRUPT, needForward = true,
             description = { "当开启 use_fix_replica 时遇到故障,是否漂移到其他健康的副本",
                 "use other health replica when the use_fix_replica meet error" })
     public boolean fallbackOtherReplicaWhenFixedCorrupt = false;
 
     public static final String FE_DEBUG = "fe_debug";
-    @VariableMgr.VarAttr(name = FE_DEBUG, needForward = true, fuzzy = true,
+    @VarAttrDef.VarAttr(name = FE_DEBUG, needForward = true, fuzzy = true,
             description = {"when set true, FE will throw exceptions instead swallow them. This is used for test",
                     "when set true, FE will throw exceptions instead swallow them. This is used for test"})
     public boolean feDebug = false;
 
-    @VariableMgr.VarAttr(name = FETCH_ALL_FE_FOR_SYSTEM_TABLE,
+    @VarAttrDef.VarAttr(name = FETCH_ALL_FE_FOR_SYSTEM_TABLE,
             description = {"When the variable is true, some system tables retrieve data from all fe",
                     "当变量为 true 时,部分系统表从所有 fe 获取数据"})
     public boolean fetchAllFeForSystemTable = true;
 
-    @VariableMgr.VarAttr(name = MAX_MSG_SIZE_OF_RESULT_RECEIVER,
+    @VarAttrDef.VarAttr(name = MAX_MSG_SIZE_OF_RESULT_RECEIVER,
             description = {"Max message size during result deserialization, change this if you meet error"
                     + " like \"MaxMessageSize reached\"",
                     "用于控制结果反序列化时 thrift 字段的最大值,当遇到类似\"MaxMessageSize reached\"这样的错误时可以考虑修改该参数"})
@@ -3126,28 +3126,28 @@ public class SessionVariable implements Serializable, Writable {
 
 
     // CLOUD_VARIABLES_BEGIN
-    @VariableMgr.VarAttr(name = CLOUD_CLUSTER, alias = {COMPUTE_GROUP})
+    @VarAttrDef.VarAttr(name = CLOUD_CLUSTER, alias = {COMPUTE_GROUP})
     public String cloudCluster = "";
-    @VariableMgr.VarAttr(name = DISABLE_EMPTY_PARTITION_PRUNE)
+    @VarAttrDef.VarAttr(name = DISABLE_EMPTY_PARTITION_PRUNE)
     public boolean disableEmptyPartitionPrune = false;
-    @VariableMgr.VarAttr(name = CLOUD_FORCE_SYNC_TABLET_STATS, needForward = true)
+    @VarAttrDef.VarAttr(name = CLOUD_FORCE_SYNC_TABLET_STATS, needForward = true)
     public boolean cloudForceSyncTabletStats = false;
-    @VariableMgr.VarAttr(name = CLOUD_PARTITION_VERSION_CACHE_TTL_MS)
+    @VarAttrDef.VarAttr(name = CLOUD_PARTITION_VERSION_CACHE_TTL_MS)
     public long cloudPartitionVersionCacheTtlMs = Long.MAX_VALUE;
-    @VariableMgr.VarAttr(name = CLOUD_TABLE_VERSION_CACHE_TTL_MS)
+    @VarAttrDef.VarAttr(name = CLOUD_TABLE_VERSION_CACHE_TTL_MS)
     public long cloudTableVersionCacheTtlMs = Long.MAX_VALUE;
-    @VariableMgr.VarAttr(name = CLOUD_FORCE_SYNC_VERSION, needForward = true)
+    @VarAttrDef.VarAttr(name = CLOUD_FORCE_SYNC_VERSION, needForward = true)
     public boolean cloudForceSyncVersion = false;
     // CLOUD_VARIABLES_END
 
     // fetch remote schema rpc timeout
-    @VariableMgr.VarAttr(name = FETCH_REMOTE_SCHEMA_TIMEOUT_SECONDS, fuzzy = true)
+    @VarAttrDef.VarAttr(name = FETCH_REMOTE_SCHEMA_TIMEOUT_SECONDS, fuzzy = true)
     public long fetchRemoteSchemaTimeoutSeconds = 120;
     // max tablet count for fetch remote schema
-    @VariableMgr.VarAttr(name = MAX_FETCH_REMOTE_TABLET_COUNT, fuzzy = true)
+    @VarAttrDef.VarAttr(name = MAX_FETCH_REMOTE_TABLET_COUNT, fuzzy = true)
     public int maxFetchRemoteTabletCount = 512;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = "enable_compress_materialize",
             description = {"控制是否启用 compress materialize。",
                     "enable compress-materialize. "},
@@ -3156,7 +3156,7 @@ public class SessionVariable implements Serializable, Writable {
     )
     public boolean enableCompressMaterialize = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = DATA_QUEUE_MAX_BLOCKS,
             description = {"DataQueue 中每个子队列允许最大的 block 个数",
                     "Max blocks in DataQueue."},
@@ -3164,7 +3164,7 @@ public class SessionVariable implements Serializable, Writable {
     public long dataQueueMaxBlocks = 1;
 
     // for spill to disk
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_SPILL,
             description = {"控制是否启用查询算子落盘。默认为 false。",
                     "Controls whether to enable spill to disk for query. "
@@ -3172,7 +3172,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true, fuzzy = true)
     public boolean enableSpill = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_FORCE_SPILL,
             description = {"控制是否开启强制落盘(即使在内存足够的情况),默认为 false。",
                     "Controls whether enable force spill."
@@ -3181,7 +3181,7 @@ public class SessionVariable implements Serializable, Writable {
     )
     public boolean enableForceSpill = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_RESERVE_MEMORY,
             description = {"控制是否启用分配内存前先 reverve memory 的功能。默认为 true。",
                     "Controls whether to enable reserve memory before allocating memory. "
@@ -3189,10 +3189,10 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true, fuzzy = true)
     public boolean enableReserveMemory = true;
 
-    @VariableMgr.VarAttr(name = SPILL_MIN_REVOCABLE_MEM, fuzzy = true)
+    @VarAttrDef.VarAttr(name = SPILL_MIN_REVOCABLE_MEM, fuzzy = true)
     public long spillMinRevocableMem = 4 * 1024 * 1024;
 
-    @VariableMgr.VarAttr(name = SPILL_BUFFER_SIZE_BYTES, fuzzy = true, needForward = true,
+    @VarAttrDef.VarAttr(name = SPILL_BUFFER_SIZE_BYTES, fuzzy = true, needForward = true,
             description = {"落盘时写 block 的最大大小(字节)。如果一个 block 超过该阈值,会按此大小拆分后再写入磁盘。"
                     + "同时也控制 merge sort 阶段每个文件的读 buffer 大小。默认 8MB。",
                 "Maximum block size for spill writes (in bytes). Blocks larger than this threshold are "
@@ -3200,44 +3200,44 @@ public class SessionVariable implements Serializable, Writable {
                     + "Default is 8MB."})
     public long spillBufferSizeBytes = 8L * 1024L * 1024L;
 
-    @VariableMgr.VarAttr(name = SPILL_AGGREGATION_PARTITION_COUNT, fuzzy = true)
+    @VarAttrDef.VarAttr(name = SPILL_AGGREGATION_PARTITION_COUNT, fuzzy = true)
     public int spillAggregationPartitionCount = 4;
 
-    @VariableMgr.VarAttr(name = LOW_MEMORY_MODE_BUFFER_LIMIT, fuzzy = false)
+    @VarAttrDef.VarAttr(name = LOW_MEMORY_MODE_BUFFER_LIMIT, fuzzy = false)
     public long lowMemoryModeBufferLimit = 33554432;
 
     // The memory limit of streaming agg when spilling is enabled
     // NOTE: streaming agg operator will not spill to disk.
-    @VariableMgr.VarAttr(name = SPILL_STREAMING_AGG_MEM_LIMIT, fuzzy = false)
+    @VarAttrDef.VarAttr(name = SPILL_STREAMING_AGG_MEM_LIMIT, fuzzy = false)
     public long spillStreamingAggMemLimit = 268435456; //256MB
 
-    @VariableMgr.VarAttr(name = SPILL_HASH_JOIN_PARTITION_COUNT, fuzzy = true)
+    @VarAttrDef.VarAttr(name = SPILL_HASH_JOIN_PARTITION_COUNT, fuzzy = true)
     public int spillHashJoinPartitionCount = 4;
 
-    @VariableMgr.VarAttr(name = SPILL_REPARTITION_MAX_DEPTH, fuzzy = true, needForward = true,
+    @VarAttrDef.VarAttr(name = SPILL_REPARTITION_MAX_DEPTH, fuzzy = true, needForward = true,
             description = {"重分区的最大递归深度,超过该深度不再继续重分区,\n默认值为 8",
                 "Maximum depth for repartition recursion. When exceeded, repartitioning will stop. Default is 8."})
     public int spillRepartitionMaxDepth = 8;
 
-    @VariableMgr.VarAttr(name = SPILL_JOIN_BUILD_SINK_MEM_LIMIT_BYTES, fuzzy = true, needForward = true,
+    @VarAttrDef.VarAttr(name = SPILL_JOIN_BUILD_SINK_MEM_LIMIT_BYTES, fuzzy = true, needForward = true,
             description = {"一旦触发 spill 后,join build sink 的 revocable memory 超过该阈值就主动落盘(字节)。默认 64MB。",
                 "After spill is triggered, join build sink will proactively spill when revocable memory "
                     + "exceeds this threshold (in bytes). Default is 64MB."})
     public long spillJoinBuildSinkMemLimitBytes = 64L * 1024L * 1024L;
 
-    @VariableMgr.VarAttr(name = SPILL_AGGREGATION_SINK_MEM_LIMIT_BYTES, fuzzy = true, needForward = true,
+    @VarAttrDef.VarAttr(name = SPILL_AGGREGATION_SINK_MEM_LIMIT_BYTES, fuzzy = true, needForward = true,
             description = {"一旦触发 spill 后,aggregation sink 的 revocable memory 超过该阈值就主动落盘(字节)。默认 64MB。",
                 "After spill is triggered, aggregation sink will proactively spill when revocable memory "
                     + "exceeds this threshold (in bytes). Default is 64GB."})
     public long spillAggregationSinkMemLimitBytes = 64L * 1024L * 1024L * 1024L;
 
-    @VariableMgr.VarAttr(name = SPILL_SORT_SINK_MEM_LIMIT_BYTES, fuzzy = true, needForward = true,
+    @VarAttrDef.VarAttr(name = SPILL_SORT_SINK_MEM_LIMIT_BYTES, fuzzy = true, needForward = true,
             description = {"一旦触发 spill 后,sort sink 的 revocable memory 超过该阈值就主动落盘(字节)。默认 64MB。",
                 "After spill is triggered, sort sink will proactively spill when revocable memory "
                     + "exceeds this threshold (in bytes). Default is 64MB."})
     public long spillSortSinkMemLimitBytes = 64L * 1024L * 1024L;
 
-    @VariableMgr.VarAttr(name = SPILL_SORT_MERGE_MEM_LIMIT_BYTES, fuzzy = true, needForward = true,
+    @VarAttrDef.VarAttr(name = SPILL_SORT_MERGE_MEM_LIMIT_BYTES, fuzzy = true, needForward = true,
             description = {"一旦触发 spill 后,sort merge 阶段可用的总内存大小(字节)。"
                     + "该值除以 spill_buffer_size_bytes 即为可并行读取合并的文件数。默认 64MB。",
                 "After spill is triggered, total memory budget for the sort merge phase (in bytes). "
@@ -3245,10 +3245,10 @@ public class SessionVariable implements Serializable, Writable {
                     + "in parallel. Default is 64MB."})
     public long spillSortMergeMemLimitBytes = 64L * 1024L * 1024L;
 
-    @VariableMgr.VarAttr(name = SPILL_REVOCABLE_MEMORY_HIGH_WATERMARK_PERCENT, fuzzy = true)
+    @VarAttrDef.VarAttr(name = SPILL_REVOCABLE_MEMORY_HIGH_WATERMARK_PERCENT, fuzzy = true)
     public int spillRevocableMemoryHighWatermarkPercent = -1;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = DUMP_HEAP_PROFILE_WHEN_MEM_LIMIT_EXCEEDED,
             description = {"查询因为内存不足被 Cancel 时,是否 Dump heap profile 到日志文件。默认为 false。",
                     "Whether to dump heap profile to log file when query is canceled becuase of memory not enough. "
@@ -3256,11 +3256,11 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true)
     public boolean dumpHeapProfileWhenMemLimitExceeded = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_FUZZY_BLOCKABLE_TASK, fuzzy = true)
     public boolean enableFuzzyBlockableTask = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_USE_HYBRID_SORT,
             description = {"是否启用混合排序,动态选择 PdqSort 和 TimSort 以适应数据模式。默认为 true。",
                     "Enable hybrid sorting: dynamically selects between PdqSort and TimSort "
@@ -3269,7 +3269,7 @@ public class SessionVariable implements Serializable, Writable {
             needForward = true, fuzzy = true)
     public boolean enableUseHybridSort = true;
 
-    @VariableMgr.VarAttr(name = USE_MAX_LENGTH_OF_VARCHAR_IN_CTAS, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = USE_MAX_LENGTH_OF_VARCHAR_IN_CTAS, needForward = true, description = {
             "在 CTAS 中,如果 CHAR / VARCHAR 列不来自于源表,是否是将这一列的长度设置为 MAX,即 65533。默认为 true。",
             "In CTAS (Create Table As Select), if CHAR/VARCHAR columns do not originate from the source table,"
                     + " whether to set the length of such a column to MAX, which is 65533. The default is true."
@@ -3278,53 +3278,53 @@ public class SessionVariable implements Serializable, Writable {
 
     // Whether enable segment cache. Segment cache only works when FE's query options sets enableSegmentCache true
     // along with BE's config `disable_segment_cache` false
-    @VariableMgr.VarAttr(name = ENABLE_SEGMENT_CACHE, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_SEGMENT_CACHE, needForward = true)
     public boolean enableSegmentCache = true;
 
     /**
      * When enabling shard scroll, FE will plan scan ranges by shards of ES indices.
      * Otherwise, FE will plan a single query to ES.
      */
-    @VariableMgr.VarAttr(name = ENABLE_ES_PARALLEL_SCROLL, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_ES_PARALLEL_SCROLL, description = {
         "ES catalog 是否开启 shard 级别并发的 scroll 请求,默认开启。",
         "Whether to enable shard-level parallel scroll requests for ES catalog, enabled by default."
     })
     public boolean enableESParallelScroll = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_MATCH_WITHOUT_INVERTED_INDEX, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_MATCH_WITHOUT_INVERTED_INDEX, description = {
         "开启无索引 match 查询功能,建议正式环境保持开启",
         "Enable no-index match query functionality."
                 + " it is recommended to keep this enabled in the production environment."
     })
     public boolean enableMatchWithoutInvertedIndex = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_FALLBACK_ON_MISSING_INVERTED_INDEX, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_FALLBACK_ON_MISSING_INVERTED_INDEX, description = {
         "开启后在没有找到索引的情况下直接查询报错,建议正式环境保持开启",
         "After enabling, it will directly query and report an error if no index is found."
                 + " It is recommended to keep this enabled in the production environment."
     })
     public boolean enableFallbackOnMissingInvertedIndex = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_INVERTED_INDEX_SEARCHER_CACHE, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_INVERTED_INDEX_SEARCHER_CACHE, description = {
         "开启后会缓存倒排索引 searcher",
         "Enabling this will cache the inverted index searcher."
     })
     public boolean enableInvertedIndexSearcherCache = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_INVERTED_INDEX_QUERY_CACHE, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_INVERTED_INDEX_QUERY_CACHE, description = {
         "开启后会缓存倒排索引查询结果",
         "Enabling this will cache the results of inverted index queries."
     })
     public boolean enableInvertedIndexQueryCache = true;
 
-    @VariableMgr.VarAttr(name = IN_LIST_VALUE_COUNT_THRESHOLD, description = {
+    @VarAttrDef.VarAttr(name = IN_LIST_VALUE_COUNT_THRESHOLD, description = {
         "in 条件 value 数量大于这个 threshold 后将不会走 fast_execute",
         "When the number of values in the IN condition exceeds this threshold,"
                 + " fast_execute will not be used."
     }, affectQueryResultInExecution = true)
     public int inListValueCountThreshold = 10;
 
-    @VariableMgr.VarAttr(name = ENABLE_ADAPTIVE_PIPELINE_TASK_SERIAL_READ_ON_LIMIT, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_ADAPTIVE_PIPELINE_TASK_SERIAL_READ_ON_LIMIT, needForward = true, description = {
         "开启后将会允许自动调整 pipeline task 的并发数。当 scan 节点没有过滤条件,且 limit 参数小于"
             + "adaptive_pipeline_task_serial_read_on_limit 中指定的行数时,scanner 的并行度将会被设置为 1",
         "When enabled, the pipeline task concurrency will be adjusted automatically. When the scan node has no filter "
@@ -3333,33 +3333,33 @@ public class SessionVariable implements Serializable, Writable {
     })
     public boolean enableAdaptivePipelineTaskSerialReadOnLimit = true;
 
-    @VariableMgr.VarAttr(name = ADAPTIVE_PIPELINE_TASK_SERIAL_READ_ON_LIMIT, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ADAPTIVE_PIPELINE_TASK_SERIAL_READ_ON_LIMIT, needForward = true, description = {
         "当 enable_adaptive_pipeline_task_serial_read_on_limit 开启时,scanner 的并行度将会被设置为 1 的行数阈值",
             "When enable_adaptive_pipeline_task_serial_read_on_limit is enabled, "
             + "the number of rows at which the parallelism of the scan will be set to 1."
     })
     public int adaptivePipelineTaskSerialReadOnLimit = 10000;
 
-    @VariableMgr.VarAttr(name = ENABLE_PHRASE_QUERY_SEQUENYIAL_OPT, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_PHRASE_QUERY_SEQUENYIAL_OPT, needForward = true, description = {
         "开启顺序短语查询对连词的优化",
         "enable optimization for conjunctions in sequential phrase queries"
     })
     public boolean enablePhraseQuerySequentialOpt = true;
 
-    @VariableMgr.VarAttr(name = "enable_adjust_conjunct_order_by_cost", needForward = true)
+    @VarAttrDef.VarAttr(name = "enable_adjust_conjunct_order_by_cost", needForward = true)
     public boolean enableAdjustConjunctOrderByCost = true;
 
-    @VariableMgr.VarAttr(name = REQUIRE_SEQUENCE_IN_INSERT, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = REQUIRE_SEQUENCE_IN_INSERT, needForward = true, description = {
             "该变量用于控制,使用了 sequence 列的 unique key 表,insert into 操作是否要求必须提供每一行的 sequence 列的值",
             "This variable controls whether the INSERT INTO operation on unique key tables with a sequence"
                     + " column requires a sequence column to be provided for each row"
     })
     public boolean requireSequenceInInsert = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_COOLDOWN_REPLICA_AFFINITY, needForward = true)
+    @VarAttrDef.VarAttr(name = ENABLE_COOLDOWN_REPLICA_AFFINITY, needForward = true)
     public boolean enableCooldownReplicaAffinity = true;
 
-    @VariableMgr.VarAttr(name = ENABLE_AUTO_CREATE_WHEN_OVERWRITE, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_AUTO_CREATE_WHEN_OVERWRITE, needForward = true, description = {
         "开启后对自动分区表的 insert overwrite 操作会对没有找到分区的插入数据按自动分区规则创建分区,默认关闭",
         "The insert overwrite operation on an auto-partitioned table will create partitions for inserted data"
                 + " for which no partition is found according to the auto-partitioning rules, which is turned off"
@@ -3367,14 +3367,14 @@ public class SessionVariable implements Serializable, Writable {
     })
     public boolean enableAutoCreateWhenOverwrite = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_TEXT_VALIDATE_UTF8, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_TEXT_VALIDATE_UTF8, needForward = true, description = {
             "对于 text 类型的文件读取,是否开启 utf8 编码检查。非 utf8 字符会显示成乱码。",
             "For text type file reading, whether to enable utf8 encoding check."
                     + "non-utf8 characters will be displayed as garbled characters."
     })
     public boolean enableTextValidateUtf8 = true;
 
-    @VariableMgr.VarAttr(name = SKIP_CHECKING_ACID_VERSION_FILE, needForward = true, affectQueryResultInPlan = true,
+    @VarAttrDef.VarAttr(name = SKIP_CHECKING_ACID_VERSION_FILE, needForward = true, affectQueryResultInPlan = true,
             description = {
                 "跳过检查 transactional hive 版本文件 '_orc_acid_version.'",
                 "Skip checking transactional hive version file '_orc_acid_version.'"
@@ -3382,7 +3382,7 @@ public class SessionVariable implements Serializable, Writable {
     )
     public boolean skipCheckingAcidVersionFile = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_SQL_CONVERTOR_FEATURES, needForward = true,
+    @VarAttrDef.VarAttr(name = ENABLE_SQL_CONVERTOR_FEATURES, needForward = true,
             checker = "checkSqlConvertorFeatures",
             description = {
                     "开启 SQL 转换器的指定功能。多个功能使用逗号分隔",
@@ -3394,34 +3394,34 @@ public class SessionVariable implements Serializable, Writable {
     // which throughs reducing rpc call from follower node to meta service to improve query performance
     // for getting version is memory operation in master node,
     // but it will slightly increase the pressure on the FE master.
-    @VariableMgr.VarAttr(name = ENABLE_SCHEMA_SCAN_FROM_MASTER_FE, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_SCHEMA_SCAN_FROM_MASTER_FE, description = {
             "在 follower 节点查询时,是否允许从 master 节点扫描 information_schema.tables 的结果",
             "Whether to allow scanning information_schema.tables from the master node"
     })
     public boolean enableSchemaScanFromMasterFe = true;
 
-    @VariableMgr.VarAttr(name = SHOW_COLUMN_COMMENT_IN_DESCRIBE, needForward = true,
+    @VarAttrDef.VarAttr(name = SHOW_COLUMN_COMMENT_IN_DESCRIBE, needForward = true,
             description = {
                     "是否在 DESCRIBE TABLE 语句中显示列注释",
                     "whether to show column comments in DESCRIBE TABLE statement"
             })
     public boolean showColumnCommentInDescribe = false;
 
-    @VariableMgr.VarAttr(name = SQL_CONVERTOR_CONFIG, needForward = true,
+    @VarAttrDef.VarAttr(name = SQL_CONVERTOR_CONFIG, needForward = true,
             description = {
                     "SQL 转换器的相关配置,使用 Json 格式。以 {} 为根元素。",
                     "SQL convertor config, use Json format. The root element is {}"
             })
     public String sqlConvertorConfig = "{}";
 
-    @VariableMgr.VarAttr(name = PREFER_UDF_OVER_BUILTIN, needForward = true,
+    @VarAttrDef.VarAttr(name = PREFER_UDF_OVER_BUILTIN, needForward = true,
             description = {
                     "是否优先查找 UDF 而不是内置函数",
                     "Whether to prefer UDF over builtin functions"
             })
     public boolean preferUdfOverBuiltin = false;
 
-    @VariableMgr.VarAttr(name = SKEW_REWRITE_JOIN_SALT_EXPLODE_FACTOR, description = {
+    @VarAttrDef.VarAttr(name = SKEW_REWRITE_JOIN_SALT_EXPLODE_FACTOR, description = {
             "join 加盐优化的扩展因子,对指定的倾斜值,join 倾斜侧生成 0 到 ExplodeFactor - 1 的随机值,"
                     + "join 扩展侧复制为 ExplodeFactor 个副本,使 hash shuffle 之后计算负载均匀分布。"
                     + "可以配置为 0-65535 中的数字:0 代表根据集群中 be 的数量和 cpu 核数自适应,1-65535 中的数量代表扩展倍数",
@@ -3434,7 +3434,7 @@ public class SessionVariable implements Serializable, Writable {
     }, checker = "checkSkewRewriteJoinSaltExplodeFactor")
     public int skewRewriteJoinSaltExplodeFactor = 0;
 
-    @VariableMgr.VarAttr(name = DEFAULT_AI_RESOURCE, needForward = true,
+    @VarAttrDef.VarAttr(name = DEFAULT_AI_RESOURCE, needForward = true,
             description = {
                     "当函数参数未指定 AI Resource 时,系统将默认使用此变量定义的 Resource。",
                     "Defines the default AI resource to be used when no specific AI resource is specified "
@@ -3450,7 +3450,7 @@ public class SessionVariable implements Serializable, Writable {
         return enableESParallelScroll;
     }
 
-    @VariableMgr.VarAttr(name = ENABLE_ADD_INDEX_FOR_NEW_DATA, needForward = true, description = {
+    @VarAttrDef.VarAttr(name = ENABLE_ADD_INDEX_FOR_NEW_DATA, needForward = true, description = {
             "是否启用仅对新数据生效的索引添加模式,开启时新建索引只对后续写入的数据生效,关闭时对全部数据重建索引",
             "Whether to enable add index mode that only affects new data, "
                     + "when enabled new indexes only affect subsequently written data, "
@@ -3458,27 +3458,27 @@ public class SessionVariable implements Serializable, Writable {
     })
     public boolean enableAddIndexForNewData = false;
 
-    @VariableMgr.VarAttr(name = HNSW_EF_SEARCH, needForward = true,
+    @VarAttrDef.VarAttr(name = HNSW_EF_SEARCH, needForward = true,
             description = {"HNSW 索引的 EF 搜索参数,控制搜索的精度和速度",
                     "HNSW index EF search parameter, controls the precision and speed of the search"})
     public int hnswEFSearch = 32;
 
-    @VariableMgr.VarAttr(name = HNSW_CHECK_RELATIVE_DISTANCE, needForward = true,
+    @VarAttrDef.VarAttr(name = HNSW_CHECK_RELATIVE_DISTANCE, needForward = true,
             description = {"是否启用相对距离检查机制,以提升 HNSW 搜索的准确性",
                     "Enable relative distance checking to improve HNSW search accuracy"})
     public boolean hnswCheckRelativeDistance = true;
 
-    @VariableMgr.VarAttr(name = HNSW_BOUNDED_QUEUE, needForward = true,
+    @VarAttrDef.VarAttr(name = HNSW_BOUNDED_QUEUE, needForward = true,
             description = {"是否使用有界优先队列来优化 HNSW 的搜索性能",
                     "Whether to use a bounded priority queue to optimize HNSW search performance"})
     public boolean hnswBoundedQueue = true;
 
-    @VariableMgr.VarAttr(name = IVF_NPROBE, needForward = true,
+    @VarAttrDef.VarAttr(name = IVF_NPROBE, needForward = true,
             description = {"IVF 索引的 nprobe 参数,控制搜索时访问的聚类数量",
                     "IVF index nprobe parameter, controls the number of clusters to search"})
     public int ivfNprobe = 32;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = DEFAULT_VARIANT_MAX_SUBCOLUMNS_COUNT,
             needForward = true,
             checker = "checkDefaultVariantMaxSubcolumnsCount",
@@ -3486,7 +3486,7 @@ public class SessionVariable implements Serializable, Writable {
     )
     public int defaultVariantMaxSubcolumnsCount = 2048;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = ENABLE_VARIANT_SCHEMA_AUTO_CAST,
             needForward = true,
             affectQueryResultInExecution = true,
@@ -3498,39 +3498,39 @@ public class SessionVariable implements Serializable, Writable {
     )
     public boolean enableVariantSchemaAutoCast = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = DEFAULT_VARIANT_ENABLE_TYPED_PATHS_TO_SPARSE,
             needForward = true,
             fuzzy = true
     )
     public boolean defaultEnableTypedPathsToSparse = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = DEFAULT_VARIANT_MAX_SPARSE_COLUMN_STATISTICS_SIZE,
             needForward = true,
             fuzzy = true
     )
     public int defaultVariantMaxSparseColumnStatisticsSize = 10000;
 
-    @VariableMgr.VarAttr(name = ENABLE_EXTENDED_REGEX, needForward = true, affectQueryResultInExecution = true,
+    @VarAttrDef.VarAttr(name = ENABLE_EXTENDED_REGEX, needForward = true, affectQueryResultInExecution = true,
             description = {"是否启用扩展的正则表达式,支持如 look-around 类的零宽断言",
                     "Enable extended regular expressions, support look-around zero-width assertions"})
     public boolean enableExtendedRegex = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = DEFAULT_VARIANT_SPARSE_HASH_SHARD_COUNT,
             needForward = true,
             fuzzy = true
     )
     public int defaultVariantSparseHashShardCount = 0;
 
-    @VariableMgr.VarAttr(name = CLOUD_PARTITIONS_TABLE_USE_CACHED_VISIBLE_VERSION, needForward = false,
+    @VarAttrDef.VarAttr(name = CLOUD_PARTITIONS_TABLE_USE_CACHED_VISIBLE_VERSION, needForward = false,
             description = {"partitions系统表的visible_version列在cloud模式是否使用cached",
                     "Whether cache is used for the visible_version column"
                              + "in the partitions system table on cloud mode"})
     public boolean cloudPartitionsTableUseCachedVisibleVersion = true;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = DEFAULT_VARIANT_ENABLE_DOC_MODE,
             needForward = true,
             fuzzy = true
@@ -3538,28 +3538,28 @@ public class SessionVariable implements Serializable, Writable {
     public boolean defaultVariantEnableDocMode = false;
 
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = DEFAULT_VARIANT_DOC_MATERIALIZATION_MIN_ROWS,
             needForward = true,
             fuzzy = true
     )
     public long defaultVariantDocMaterializationMinRows = 0L;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = DEFAULT_VARIANT_DOC_HASH_SHARD_COUNT,
             needForward = true,
             fuzzy = true
     )
     public int defaultVariantDocHashShardCount = 64;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = DEFAULT_VARIANT_ENABLE_NESTED_GROUP,
             needForward = true,
             fuzzy = true
     )
     public boolean defaultVariantEnableNestedGroup = false;
 
-    @VariableMgr.VarAttr(
+    @VarAttrDef.VarAttr(
             name = "use_v3_storage_format",
             fuzzy = true,
             description = {
@@ -3568,11 +3568,11 @@ public class SessionVariable implements Serializable, Writable {
     )
     public boolean useV3StorageFormat = false;
 
-    @VariableMgr.VarAttr(name = DECOMPOSE_REPEAT_SHUFFLE_INDEX_IN_MAX_GROUP)
+    @VarAttrDef.VarAttr(name = DECOMPOSE_REPEAT_SHUFFLE_INDEX_IN_MAX_GROUP)
     public int decomposeRepeatShuffleIndexInMaxGroup = -1;
 
     public static final String IGNORE_ICEBERG_DANGLING_DELETE = "ignore_iceberg_dangling_delete";
-    @VariableMgr.VarAttr(name = IGNORE_ICEBERG_DANGLING_DELETE,
+    @VarAttrDef.VarAttr(name = IGNORE_ICEBERG_DANGLING_DELETE,
             description = {"是否忽略 Iceberg 表中 dangling delete 文件对 COUNT(*) 统计信息的影响。"
                     + "默认为 true,COUNT(*) 会直接从元信息中获取行数,性能更好,但是如果有 dangling delete,结果可能是不准确的。"
                     + "设置为 false 时,COUNT(*) 会扫描数据文件以排除 dangling delete 文件的影响。",
@@ -3584,7 +3584,7 @@ public class SessionVariable implements Serializable, Writable {
                             + "to exclude the impact of dangling delete files."})
     public boolean ignoreIcebergDanglingDelete = false;
 
-    @VariableMgr.VarAttr(name = ENABLE_ICEBERG_MERGE_PARTITIONING,
+    @VarAttrDef.VarAttr(name = ENABLE_ICEBERG_MERGE_PARTITIONING,
             description = {"是否启用 Iceberg UPDATE/DELETE 合并写入的双分支分发(INSERT 按分区列,DELETE 按 row_id)。",
                     "Enable merge partitioning for Iceberg UPDATE/DELETE (INSERT by partition columns, "
                             + "DELETE by row_id)."})
@@ -3809,7 +3809,7 @@ public class SessionVariable implements Serializable, Writable {
      * all except event_1, event_2, ..., event_n -> use all events excluding the event_1~n
      * event_1, event_2, ..., event_n -> use event_1~n
      */
-    @VariableMgr.VarAttr(name = NEREIDS_TRACE_EVENT_MODE, checker = "checkNereidsTraceEventMode")
+    @VarAttrDef.VarAttr(name = NEREIDS_TRACE_EVENT_MODE, checker = "checkNereidsTraceEventMode")
     public String nereidsTraceEventMode = "all";
 
     private Set<Class<? extends Event>> parsedNereidsEventMode = EventSwitchParser.parse(Lists.newArrayList("all"));
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/VariableMgr.java b/fe/fe-core/src/main/java/org/apache/doris/qe/VariableMgr.java
index b13dcfc0223..dc55ddf12f5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/VariableMgr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/VariableMgr.java
@@ -54,8 +54,6 @@ import org.json.simple.JSONValue;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Collections;
@@ -105,18 +103,6 @@ import javax.annotation.Nullable;
 public class VariableMgr {
     private static final Logger LOG = LogManager.getLogger(VariableMgr.class);
 
-    // variable have this flag means that every session have a copy of this variable,
-    // and can modify its own variable.
-    public static final int SESSION = 1;
-    // Variables with this flag have only one instance in one process.
-    public static final int GLOBAL = 2;
-    // Variables with this flag only exist in each session.
-    public static final int SESSION_ONLY = 4;
-    // Variables with this flag can only be read.
-    public static final int READ_ONLY = 8;
-    // Variables with this flag can not be seen with `SHOW VARIABLES` statement.
-    public static final int INVISIBLE = 16;
-
     // Map variable name to variable context which have enough information to change variable value.
     // This map contains info of all session and global variables.
     private static ImmutableMap<String, VarContext> ctxByVarName;
@@ -160,7 +146,7 @@ public class VariableMgr {
 
         Field field = sessionVariableField.getField();
         field.setAccessible(true);
-        VarAttr attr = field.getAnnotation(VarAttr.class);
+        VarAttrDef.VarAttr attr = field.getAnnotation(VarAttrDef.VarAttr.class);
 
         if (VariableVarConverters.hasConverter(attr.name())) {
             value = VariableVarConverters.encode(attr.name(), value).toString();
@@ -275,13 +261,13 @@ public class VariableMgr {
     // But in some case, we do not want to set the query state and need to ignore that error.
     // Set setVarForNonMasterFE() is an example.
     private static void checkUpdate(SetVar setVar, int flag) throws DdlException {
-        if ((flag & READ_ONLY) != 0) {
+        if ((flag & VarAttrDef.READ_ONLY) != 0) {
             throw new DdlException(ErrorCode.ERR_VARIABLE_IS_READONLY.formatErrorMsg(setVar.getVariable()));
         }
-        if (setVar.getType() == SetType.GLOBAL && (flag & SESSION_ONLY) != 0) {
+        if (setVar.getType() == SetType.GLOBAL && (flag & VarAttrDef.SESSION_ONLY) != 0) {
             throw new DdlException(ErrorCode.ERR_LOCAL_VARIABLE.formatErrorMsg(setVar.getVariable()));
         }
-        if (setVar.getType() != SetType.GLOBAL && (flag & GLOBAL) != 0) {
+        if (setVar.getType() != SetType.GLOBAL && (flag & VarAttrDef.GLOBAL) != 0) {
             throw new DdlException(ErrorCode.ERR_GLOBAL_VARIABLE.formatErrorMsg(setVar.getVariable()));
         }
     }
@@ -367,7 +353,7 @@ public class VariableMgr {
             return null;
         }
         // for non-matched prefix, report an error
-        VariableAnnotation varType = ctx.getField().getAnnotation(VarAttr.class).varType();
+        VariableAnnotation varType = ctx.getField().getAnnotation(VarAttrDef.VarAttr.class).varType();
         if (hasExpPrefix && (!name.startsWith(varType.getPrefix())
                 || varType == VariableAnnotation.NONE)) {
             return null;
@@ -378,7 +364,7 @@ public class VariableMgr {
     private static void setVarInternal(SessionVariable sessionVariable, SetVar setVar, VarContext ctx)
             throws DdlException {
         // To modify to default value.
-        VarAttr attr = ctx.getField().getAnnotation(VarAttr.class);
+        VarAttrDef.VarAttr attr = ctx.getField().getAnnotation(VarAttrDef.VarAttr.class);
         String value;
         // If value is null, this is `set variable = DEFAULT`
         if (setVar.getResult() != null) {
@@ -536,7 +522,7 @@ public class VariableMgr {
     }
 
     private static void fillValue(Object obj, Field field, VariableExpr desc) {
-        VarAttr attr = field.getAnnotation(VarAttr.class);
+        VarAttrDef.VarAttr attr = field.getAnnotation(VarAttrDef.VarAttr.class);
         if (!Strings.isNullOrEmpty(attr.convertBoolToLongMethod())) {
             try {
                 Preconditions.checkArgument(obj instanceof SessionVariable);
@@ -638,7 +624,7 @@ public class VariableMgr {
     }
 
     private static Literal getLiteral(Object obj, Field field) {
-        VarAttr attr = field.getAnnotation(VarAttr.class);
+        VarAttrDef.VarAttr attr = field.getAnnotation(VarAttrDef.VarAttr.class);
         if (!Strings.isNullOrEmpty(attr.convertBoolToLongMethod())) {
             try {
                 Preconditions.checkArgument(obj instanceof SessionVariable);
@@ -716,7 +702,7 @@ public class VariableMgr {
         Map<String, VarContext> result = Maps.newHashMap();
         for (Map.Entry<String, VarContext> entry : ctxByVarName.entrySet()) {
             VarContext varContext = entry.getValue();
-            VarAttr varAttr = varContext.getField().getAnnotation(VarAttr.class);
+            VarAttrDef.VarAttr varAttr = varContext.getField().getAnnotation(VarAttrDef.VarAttr.class);
             result.put(varAttr.varType().getPrefix() + entry.getKey(), varContext);
         }
         return ImmutableMap.copyOf(result);
@@ -759,13 +745,13 @@ public class VariableMgr {
         rlock.lock();
         try {
             for (Map.Entry<String, VarContext> entry : ctxByDisplayVarName.entrySet()) {
-                VarAttr varAttr = entry.getValue().getField().getAnnotation(VarAttr.class);
+                VarAttrDef.VarAttr varAttr = entry.getValue().getField().getAnnotation(VarAttrDef.VarAttr.class);
                 // not show removed variables
                 if (VariableAnnotation.REMOVED.equals(varAttr.varType())) {
                     continue;
                 }
                 // not show invisible variables
-                if ((VariableMgr.INVISIBLE & varAttr.flag()) != 0) {
+                if ((VarAttrDef.INVISIBLE & varAttr.flag()) != 0) {
                     continue;
                 }
                 // Filter variable not match to the regex.
@@ -842,13 +828,13 @@ public class VariableMgr {
         try {
             for (Map.Entry<String, VarContext> entry : ctxByDisplayVarName.entrySet()) {
                 VarContext ctx = entry.getValue();
-                VarAttr varAttr = ctx.getField().getAnnotation(VarAttr.class);
+                VarAttrDef.VarAttr varAttr = ctx.getField().getAnnotation(VarAttrDef.VarAttr.class);
                 // not show removed variables
                 if (VariableAnnotation.REMOVED.equals(varAttr.varType())) {
                     continue;
                 }
                 // not show invisible variables
-                if ((VariableMgr.INVISIBLE & varAttr.flag()) != 0) {
+                if ((VarAttrDef.INVISIBLE & varAttr.flag()) != 0) {
                     continue;
                 }
                 List<String> row = Lists.newArrayList();
@@ -880,53 +866,6 @@ public class VariableMgr {
         return changedRows;
     }
 
-    @Retention(RetentionPolicy.RUNTIME)
-    public @interface VarAttr {
-        // Name in show variables and set statement;
-        String name();
-
-        String[] alias() default {};
-
-        int flag() default 0;
-
-        // TODO(zhaochun): min and max is not used.
-        String minValue() default "0";
-
-        String maxValue() default "0";
-
-        // the function name that check the VarAttr before setting it to sessionVariable
-        // only support check function: 0 argument and 0 return value, if an error occurs, throw an exception.
-        // the checker function should be: public void checker(String value), value is the input string.
-        String checker() default "";
-
-        // could specify the setter method for a variable, not depend on reflect mechanism
-        String setter() default "";
-
-        // Set to true if the variables need to be forwarded along with forward statement.
-        boolean needForward() default false;
-
-        // Set to true if this variable is fuzzy
-        boolean fuzzy() default false;
-
-        VariableAnnotation varType() default VariableAnnotation.NONE;
-
-        // description for this config item.
-        // There should be 2 elements in the array.
-        // The first element is the description in Chinese.
-        // The second element is the description in English.
-        String[] description() default {"待补充", "TODO"};
-
-        // Enum options for this config item, if it has.
-        String[] options() default {};
-
-        String convertBoolToLongMethod() default "";
-        // If the variable affects the outcome, set it to true.
-        // If this value is true, it will ignore needForward and enforce forwarding.
-        boolean affectQueryResultInPlan() default false;
-
-        boolean affectQueryResultInExecution() default false;
-    }
-
     public static class VarContext {
         private Field field;
         private Object obj;
@@ -975,13 +914,13 @@ public class VariableMgr {
         ImmutableSortedMap.Builder<String, VarContext> builder =
                 ImmutableSortedMap.orderedBy(String.CASE_INSENSITIVE_ORDER);
         for (Field field : SessionVariable.class.getDeclaredFields()) {
-            VarAttr attr = field.getAnnotation(VarAttr.class);
+            VarAttrDef.VarAttr attr = field.getAnnotation(VarAttrDef.VarAttr.class);
             if (attr == null) {
                 continue;
             }
 
             field.setAccessible(true);
-            VarContext varContext = new VarContext(field, sessionVariable, SESSION | attr.flag(),
+            VarContext varContext = new VarContext(field, sessionVariable, VarAttrDef.SESSION | attr.flag(),
                     getValue(sessionVariable, field));
 
             // 1. Register the primary name.
@@ -995,13 +934,14 @@ public class VariableMgr {
 
         // Variables only exist in global environment.
         for (Field field : GlobalVariable.class.getDeclaredFields()) {
-            VarAttr attr = field.getAnnotation(VarAttr.class);
+            VarAttrDef.VarAttr attr = field.getAnnotation(VarAttrDef.VarAttr.class);
             if (attr == null) {
                 continue;
             }
 
             field.setAccessible(true);
-            builder.put(attr.name(), new VarContext(field, null, GLOBAL | attr.flag(), getValue(null, field)));
+            builder.put(attr.name(),
+                    new VarContext(field, null, VarAttrDef.GLOBAL | attr.flag(), getValue(null, field)));
         }
         return builder;
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisManager.java b/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisManager.java
index 228ebd3f51c..14558fb3a8b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisManager.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/AnalysisManager.java
@@ -44,6 +44,7 @@ import org.apache.doris.datasource.CatalogIf;
 import org.apache.doris.datasource.InternalCatalog;
 import org.apache.doris.datasource.hive.HMSExternalTable;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.metric.MetricRepo;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.nereids.trees.expressions.Slot;
@@ -254,8 +255,8 @@ public class AnalysisManager implements Writable {
             if (table instanceof View) {
                 continue;
             }
-            TableNameInfo tableNameInfo = new TableNameInfo(db.getCatalog().getName(),
-                    db.getFullName(), table.getName());
+            TableNameInfo tableNameInfo = TableNameInfoUtils.fromCatalogDb(db.getCatalog(),
+                    db, table);
             // columnNames null means to add all visible columns.
             // Will get all the visible columns in analyzeTableOp.check()
             AnalyzeTableCommand command = new AnalyzeTableCommand(analyzeProperties, tableNameInfo,
diff --git a/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsJobAppender.java b/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsJobAppender.java
index 4559182a2bb..c502565252a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsJobAppender.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/StatisticsJobAppender.java
@@ -28,6 +28,7 @@ import org.apache.doris.common.Pair;
 import org.apache.doris.common.util.MasterDaemon;
 import org.apache.doris.datasource.InternalCatalog;
 import org.apache.doris.info.TableNameInfo;
+import org.apache.doris.info.TableNameInfoUtils;
 import org.apache.doris.statistics.util.StatisticsUtil;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -126,8 +127,8 @@ public class StatisticsJobAppender extends MasterDaemon {
             if (columnIndexPairs.isEmpty()) {
                 continue;
             }
-            TableNameInfo tableName = new TableNameInfo(table.getDatabase().getCatalog().getName(),
-                    table.getDatabase().getFullName(), table.getName());
+            TableNameInfo tableName = TableNameInfoUtils.fromCatalogDb(table.getDatabase().getCatalog(),
+                    table.getDatabase(), table);
             synchronized (jobs) {
                 // If job map reach the upper limit, stop putting new jobs.
                 if (!jobs.containsKey(tableName) && jobs.size() >= JOB_MAP_SIZE) {
@@ -176,8 +177,8 @@ public class StatisticsJobAppender extends MasterDaemon {
                 Set<String> columns = t.getSchemaAllIndexes(false).stream()
                         .filter(c -> !StatisticsUtil.isUnsupportedType(c.getType()))
                         .map(Column::getName).collect(Collectors.toSet());
-                TableNameInfo tableName = new TableNameInfo(t.getDatabase().getCatalog().getName(),
-                        t.getDatabase().getFullName(), t.getName());
+                TableNameInfo tableName = TableNameInfoUtils.fromCatalogDb(t.getDatabase().getCatalog(),
+                        t.getDatabase(), t);
                 boolean appended = false;
                 long version = Config.isCloudMode() ? 0 : StatisticsUtil.getOlapTableVersion((OlapTable) t);
                 for (Pair<String, String> p : t.getColumnIndexPairs(columns)) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/task/AlterInvertedIndexTask.java b/fe/fe-core/src/main/java/org/apache/doris/task/AlterInvertedIndexTask.java
index d9dd503a6ea..7f3eb7df618 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/task/AlterInvertedIndexTask.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/task/AlterInvertedIndexTask.java
@@ -18,6 +18,7 @@
 package org.apache.doris.task;
 
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ColumnToThrift;
 import org.apache.doris.catalog.Index;
 import org.apache.doris.thrift.TAlterInvertedIndexReq;
 import org.apache.doris.thrift.TColumn;
@@ -123,7 +124,7 @@ public class AlterInvertedIndexTask extends AgentTask {
         if (schemaColumns != null) {
             List<TColumn> columns = new ArrayList<TColumn>();
             for (Column column : schemaColumns) {
-                columns.add(column.toThrift());
+                columns.add(ColumnToThrift.toThrift(column));
             }
             req.setColumns(columns);
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/task/AlterReplicaTask.java b/fe/fe-core/src/main/java/org/apache/doris/task/AlterReplicaTask.java
index 5a497467f7a..3298b1c8f3e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/task/AlterReplicaTask.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/task/AlterReplicaTask.java
@@ -23,6 +23,7 @@ import org.apache.doris.analysis.Expr;
 import org.apache.doris.analysis.ExprToThriftVisitor;
 import org.apache.doris.analysis.SlotRef;
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ColumnToThrift;
 import org.apache.doris.common.Config;
 import org.apache.doris.thrift.TAlterMaterializedViewParam;
 import org.apache.doris.thrift.TAlterTabletReqV2;
@@ -181,7 +182,7 @@ public class AlterReplicaTask extends AgentTask {
             if (value == null) {
                 List<TColumn> columns = new ArrayList<TColumn>();
                 for (Column column : baseSchemaColumns) {
-                    columns.add(column.toThrift());
+                    columns.add(ColumnToThrift.toThrift(column));
                 }
                 objectPool.put(baseSchemaColumns, columns);
                 req.setColumns(columns);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/task/CreateReplicaTask.java b/fe/fe-core/src/main/java/org/apache/doris/task/CreateReplicaTask.java
index 1d03b7bfe9b..8c03cda8a41 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/task/CreateReplicaTask.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/task/CreateReplicaTask.java
@@ -20,6 +20,7 @@ package org.apache.doris.task;
 import org.apache.doris.analysis.DataSortInfo;
 import org.apache.doris.catalog.BinlogConfig;
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.ColumnToThrift;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.Index;
 import org.apache.doris.catalog.KeysType;
@@ -318,7 +319,7 @@ public class CreateReplicaTask extends AgentTask {
             tColumns = new ArrayList<>();
             for (int i = 0; i < columns.size(); i++) {
                 Column column = columns.get(i);
-                TColumn tColumn = column.toThrift();
+                TColumn tColumn = ColumnToThrift.toThrift(column);
                 // is bloom filter column
                 if (bfColumns != null && bfColumns.contains(column.getName())) {
                     tColumn.setIsBloomFilterColumn(true);
diff --git a/fe/fe-core/src/test/java/org/apache/doris/info/TableNameInfoUtilsTest.java b/fe/fe-core/src/test/java/org/apache/doris/info/TableNameInfoUtilsTest.java
new file mode 100644
index 00000000000..ea7bd33ccad
--- /dev/null
+++ b/fe/fe-core/src/test/java/org/apache/doris/info/TableNameInfoUtilsTest.java
@@ -0,0 +1,181 @@
+// 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.info;
+
+import org.apache.doris.catalog.Database;
+import org.apache.doris.catalog.DatabaseIf;
+import org.apache.doris.catalog.NameSpaceContext;
+import org.apache.doris.catalog.TableIf;
+import org.apache.doris.datasource.CatalogIf;
+
+import mockit.Expectations;
+import mockit.Mocked;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TableNameInfoUtilsTest {
+
+    @Test
+    public void testFromDbWithCatalog(@Mocked Database db, @Mocked CatalogIf catalog) {
+        new Expectations() {
+            {
+                db.getCatalog();
+                result = catalog;
+                catalog.getName();
+                result = "test_catalog";
+                db.getFullName();
+                result = "test_db";
+            }
+        };
+
+        TableNameInfo info = TableNameInfoUtils.fromDb(db, "test_table");
+        Assertions.assertEquals("test_catalog", info.getCtl());
+        Assertions.assertEquals("test_db", info.getDb());
+        Assertions.assertEquals("test_table", info.getTbl());
+    }
+
+    @Test
+    public void testFromDbWithNullCatalog(@Mocked Database db) {
+        new Expectations() {
+            {
+                db.getCatalog();
+                result = null;
+                db.getFullName();
+                result = "test_db";
+            }
+        };
+
+        TableNameInfo info = TableNameInfoUtils.fromDb(db, "test_table");
+        Assertions.assertEquals(NameSpaceContext.INTERNAL_CATALOG_NAME, info.getCtl());
+        Assertions.assertEquals("test_db", info.getDb());
+        Assertions.assertEquals("test_table", info.getTbl());
+    }
+
+    @Test
+    public void testFromCatalogDbWithString(@Mocked CatalogIf catalog, @Mocked DatabaseIf db) {
+        new Expectations() {
+            {
+                catalog.getName();
+                result = "my_catalog";
+                db.getFullName();
+                result = "my_db";
+            }
+        };
+
+        TableNameInfo info = TableNameInfoUtils.fromCatalogDb(catalog, db, "my_table");
+        Assertions.assertEquals("my_catalog", info.getCtl());
+        Assertions.assertEquals("my_db", info.getDb());
+        Assertions.assertEquals("my_table", info.getTbl());
+    }
+
+    @Test
+    public void testFromCatalogDbWithTableIf(@Mocked CatalogIf catalog, @Mocked DatabaseIf db,
+            @Mocked TableIf table) {
+        new Expectations() {
+            {
+                catalog.getName();
+                result = "cat1";
+                db.getFullName();
+                result = "db1";
+                table.getName();
+                result = "tbl1";
+            }
+        };
+
+        TableNameInfo info = TableNameInfoUtils.fromCatalogDb(catalog, db, table);
+        Assertions.assertEquals("cat1", info.getCtl());
+        Assertions.assertEquals("db1", info.getDb());
+        Assertions.assertEquals("tbl1", info.getTbl());
+    }
+
+    @Test
+    public void testFromTableOrNullWithDbAndCatalog(@Mocked TableIf table, @Mocked DatabaseIf db,
+            @Mocked CatalogIf catalog) {
+        new Expectations() {
+            {
+                table.getDatabase();
+                result = db;
+                db.getCatalog();
+                result = catalog;
+                catalog.getName();
+                result = "ext_catalog";
+                db.getFullName();
+                result = "ext_db";
+                table.getName();
+                result = "ext_table";
+            }
+        };
+
+        TableNameInfo info = TableNameInfoUtils.fromTableOrNull(table);
+        Assertions.assertNotNull(info);
+        Assertions.assertEquals("ext_catalog", info.getCtl());
+        Assertions.assertEquals("ext_db", info.getDb());
+        Assertions.assertEquals("ext_table", info.getTbl());
+    }
+
+    @Test
+    public void testFromTableOrNullWithNullDb(@Mocked TableIf table) {
+        new Expectations() {
+            {
+                table.getName();
+                result = "some_table";
+                table.getDatabase();
+                result = null;
+            }
+        };
+
+        TableNameInfo info = TableNameInfoUtils.fromTableOrNull(table);
+        Assertions.assertNull(info);
+    }
+
+    @Test
+    public void testFromTableOrNullWithNullCatalog(@Mocked TableIf table, @Mocked DatabaseIf db) {
+        new Expectations() {
+            {
+                table.getName();
+                result = "internal_table";
+                table.getDatabase();
+                result = db;
+                db.getCatalog();
+                result = null;
+            }
+        };
+
+        TableNameInfo info = TableNameInfoUtils.fromTableOrNull(table);
+        Assertions.assertNull(info);
+    }
+
+    @Test
+    public void testFromTableOrNullWithNullTable() {
+        TableNameInfo info = TableNameInfoUtils.fromTableOrNull(null);
+        Assertions.assertNull(info);
+    }
+
+    @Test
+    public void testFromTableOrNullWithEmptyName(@Mocked TableIf table) {
+        new Expectations() {
+            {
+                table.getName();
+                result = "";
+            }
+        };
+
+        TableNameInfo info = TableNameInfoUtils.fromTableOrNull(table);
+        Assertions.assertNull(info);
+    }
+}
diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/ConstraintTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/ConstraintTest.java
index 6cb5bc83863..2b6c6c02dbd 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/ConstraintTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/ConstraintTest.java
@@ -19,6 +19,7 @@ package org.apache.doris.nereids.trees.plans;
 
 import org.apache.doris.catalog.Column;
 import org.apache.doris.catalog.Env;
+import org.apache.doris.catalog.TableIf;
 import org.apache.doris.catalog.constraint.Constraint;
 import org.apache.doris.catalog.constraint.ConstraintManager;
 import org.apache.doris.catalog.constraint.ForeignKeyConstraint;
@@ -31,6 +32,7 @@ import org.apache.doris.nereids.trees.plans.commands.AddConstraintCommand;
 import org.apache.doris.nereids.trees.plans.commands.DropConstraintCommand;
 import org.apache.doris.nereids.util.PlanChecker;
 import org.apache.doris.nereids.util.PlanPatternMatchSupported;
+import org.apache.doris.qe.GlobalVariable;
 import org.apache.doris.utframe.TestWithFeService;
 
 import com.google.common.collect.Sets;
@@ -45,6 +47,15 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
         return Env.getCurrentEnv().getConstraintManager();
     }
 
+    private TableNameInfo tableNameInfoOf(TableIf table) {
+        String tblName = table.getName();
+        if (GlobalVariable.isStoredTableNamesLowerCase()) {
+            tblName = tblName.toLowerCase();
+        }
+        return new TableNameInfo(
+                table.getDatabase().getCatalog().getName(), table.getDatabase().getFullName(), tblName);
+    }
+
     @Override
     public void runBeforeAll() throws Exception {
         createDatabase("test");
@@ -84,7 +95,7 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
                 "alter table t1 add constraint pk primary key (k1)");
         addCommand.run(connectContext, null);
         PlanChecker.from(connectContext).parse("select * from t1").analyze().matches(logicalOlapScan().when(o -> {
-            TableNameInfo tni = new TableNameInfo(o.getTable());
+            TableNameInfo tni = tableNameInfoOf(o.getTable());
             Constraint c = getConstraintMgr().getConstraint(tni, "pk");
             if (c instanceof PrimaryKeyConstraint) {
                 Set<String> columns = ((PrimaryKeyConstraint) c).getPrimaryKeyNames();
@@ -98,7 +109,7 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
         dropCommand.run(connectContext, null);
         PlanChecker.from(connectContext).parse("select * from t1").analyze().matches(
                 logicalOlapScan().when(o -> getConstraintMgr()
-                        .getConstraints(new TableNameInfo(o.getTable())).isEmpty()));
+                        .getConstraints(tableNameInfoOf(o.getTable())).isEmpty()));
     }
 
     @Test
@@ -107,7 +118,7 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
                 "alter table t1 add constraint un unique (k1)");
         command.run(connectContext, null);
         PlanChecker.from(connectContext).parse("select * from t1").analyze().matches(logicalOlapScan().when(o -> {
-            TableNameInfo tni = new TableNameInfo(o.getTable());
+            TableNameInfo tni = tableNameInfoOf(o.getTable());
             Constraint c = getConstraintMgr().getConstraint(tni, "un");
             if (c instanceof UniqueConstraint) {
                 Set<String> columns = ((UniqueConstraint) c).getUniqueColumnNames();
@@ -121,7 +132,7 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
         dropCommand.run(connectContext, null);
         PlanChecker.from(connectContext).parse("select * from t1").analyze().matches(
                 logicalOlapScan().when(o -> getConstraintMgr()
-                        .getConstraints(new TableNameInfo(o.getTable())).isEmpty()));
+                        .getConstraints(tableNameInfoOf(o.getTable())).isEmpty()));
     }
 
     @Test
@@ -141,7 +152,7 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
                 null);
 
         PlanChecker.from(connectContext).parse("select * from t1").analyze().matches(logicalOlapScan().when(o -> {
-            TableNameInfo tni = new TableNameInfo(o.getTable());
+            TableNameInfo tni = tableNameInfoOf(o.getTable());
             Constraint c = getConstraintMgr().getConstraint(tni, "fk");
             if (c instanceof ForeignKeyConstraint) {
                 ForeignKeyConstraint f = (ForeignKeyConstraint) c;
@@ -155,7 +166,7 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
         }));
 
         PlanChecker.from(connectContext).parse("select * from t2").analyze().matches(logicalOlapScan().when(o -> {
-            TableNameInfo tni = new TableNameInfo(o.getTable());
+            TableNameInfo tni = tableNameInfoOf(o.getTable());
             Constraint c = getConstraintMgr().getConstraint(tni, "pk");
             if (c instanceof PrimaryKeyConstraint) {
                 Set<String> columnNames = ((PrimaryKeyConstraint) c).getPrimaryKeyNames();
@@ -174,7 +185,7 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
         dropCommand.run(connectContext, null);
         PlanChecker.from(connectContext).parse("select * from t1").analyze().matches(
                 logicalOlapScan().when(o -> getConstraintMgr()
-                        .getConstraints(new TableNameInfo(o.getTable())).isEmpty()));
+                        .getConstraints(tableNameInfoOf(o.getTable())).isEmpty()));
         // drop pk and fk referenced it also should be dropped
         ((AddConstraintCommand) new NereidsParser().parseSingle(
                 "alter table t1 add constraint fk foreign key (k1, k2) references t2(k1, k2)")).run(connectContext,
@@ -184,10 +195,10 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
 
         PlanChecker.from(connectContext).parse("select * from t1").analyze().matches(
                 logicalOlapScan().when(o -> getConstraintMgr()
-                        .getConstraints(new TableNameInfo(o.getTable())).isEmpty()));
+                        .getConstraints(tableNameInfoOf(o.getTable())).isEmpty()));
         PlanChecker.from(connectContext).parse("select * from t2").analyze().matches(
                 logicalOlapScan().when(o -> getConstraintMgr()
-                        .getConstraints(new TableNameInfo(o.getTable())).isEmpty()));
+                        .getConstraints(tableNameInfoOf(o.getTable())).isEmpty()));
     }
 
     @Test
@@ -198,7 +209,7 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
 
         PlanChecker.from(connectContext).parse("select * from t2").analyze().matches(
                 logicalOlapScan().when(o -> getConstraintMgr()
-                        .getConstraints(new TableNameInfo(o.getTable())).isEmpty()));
+                        .getConstraints(tableNameInfoOf(o.getTable())).isEmpty()));
 
         addConstraint("alter table t1 add constraint pk primary key (k1)");
         addConstraint("alter table t1 add constraint fk foreign key (k1) references t1(k1)");
@@ -207,13 +218,13 @@ class ConstraintTest extends TestWithFeService implements PlanPatternMatchSuppor
         dropConstraint("alter table t1 drop constraint pk");
         PlanChecker.from(connectContext).parse("select * from t1").analyze().matches(
                 logicalOlapScan().when(o -> getConstraintMgr()
-                        .getConstraints(new TableNameInfo(o.getTable())).isEmpty()));
+                        .getConstraints(tableNameInfoOf(o.getTable())).isEmpty()));
         PlanChecker.from(connectContext).parse("select * from t2").analyze().matches(
                 logicalOlapScan().when(o -> getConstraintMgr()
-                        .getConstraints(new TableNameInfo(o.getTable())).isEmpty()));
+                        .getConstraints(tableNameInfoOf(o.getTable())).isEmpty()));
         PlanChecker.from(connectContext).parse("select * from t3").analyze().matches(
                 logicalOlapScan().when(o -> getConstraintMgr()
-                        .getConstraints(new TableNameInfo(o.getTable())).isEmpty()));
+                        .getConstraints(tableNameInfoOf(o.getTable())).isEmpty()));
     }
 
     @Test
diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/CreateTableCommandTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/CreateTableCommandTest.java
index 4cae5e946ab..3530f353619 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/CreateTableCommandTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/CreateTableCommandTest.java
@@ -18,6 +18,7 @@
 package org.apache.doris.nereids.trees.plans;
 
 import org.apache.doris.analysis.Expr;
+import org.apache.doris.analysis.ExprToExprNameVisitor;
 import org.apache.doris.analysis.FunctionCallExpr;
 import org.apache.doris.analysis.PartitionDesc;
 import org.apache.doris.analysis.SinglePartitionDesc;
@@ -789,41 +790,41 @@ public class CreateTableCommandTest extends TestWithFeService {
 
         Expr expr0 = partitionFields2.get(0);
         Assertions.assertInstanceOf(SlotRef.class, expr0);
-        Assertions.assertEquals("val", expr0.getExprName());
+        Assertions.assertEquals("val", expr0.accept(ExprToExprNameVisitor.INSTANCE, null));
 
         Expr expr1 = partitionFields2.get(1);
         Assertions.assertInstanceOf(FunctionCallExpr.class, expr1);
         List<Expr> params1 = ((FunctionCallExpr) expr1).getParams().exprs();
-        Assertions.assertEquals("bucket", expr1.getExprName());
+        Assertions.assertEquals("bucket", expr1.accept(ExprToExprNameVisitor.INSTANCE, null));
         Assertions.assertEquals(2, params1.size());
         Assertions.assertInstanceOf(StringLiteral.class, params1.get(0));
         Assertions.assertEquals("2", params1.get(0).getStringValue());
         Assertions.assertInstanceOf(SlotRef.class, params1.get(1));
-        Assertions.assertEquals("id", params1.get(1).getExprName());
+        Assertions.assertEquals("id", params1.get(1).accept(ExprToExprNameVisitor.INSTANCE, null));
 
         Expr expr2 = partitionFields2.get(2);
         Assertions.assertInstanceOf(SlotRef.class, expr2);
-        Assertions.assertEquals("par", expr2.getExprName());
+        Assertions.assertEquals("par", expr2.accept(ExprToExprNameVisitor.INSTANCE, null));
 
         Expr expr3 = partitionFields2.get(3);
         Assertions.assertInstanceOf(FunctionCallExpr.class, expr3);
         List<Expr> params3 = ((FunctionCallExpr) expr3).getParams().exprs();
-        Assertions.assertEquals("day", expr3.getExprName());
+        Assertions.assertEquals("day", expr3.accept(ExprToExprNameVisitor.INSTANCE, null));
         Assertions.assertEquals(1, params3.size());
         Assertions.assertInstanceOf(SlotRef.class, params3.get(0));
-        Assertions.assertEquals("ts", params3.get(0).getExprName());
+        Assertions.assertEquals("ts", params3.get(0).accept(ExprToExprNameVisitor.INSTANCE, null));
 
         Expr expr4 = partitionFields2.get(4);
         Assertions.assertInstanceOf(FunctionCallExpr.class, expr4);
         List<Expr> params4 = ((FunctionCallExpr) expr4).getParams().exprs();
-        Assertions.assertEquals("efg", expr4.getExprName());
+        Assertions.assertEquals("efg", expr4.accept(ExprToExprNameVisitor.INSTANCE, null));
         Assertions.assertEquals(3, params4.size());
         Assertions.assertInstanceOf(SlotRef.class, params4.get(0));
-        Assertions.assertEquals("a", params4.get(0).getExprName());
+        Assertions.assertEquals("a", params4.get(0).accept(ExprToExprNameVisitor.INSTANCE, null));
         Assertions.assertInstanceOf(SlotRef.class, params4.get(1));
-        Assertions.assertEquals("b", params4.get(1).getExprName());
+        Assertions.assertEquals("b", params4.get(1).accept(ExprToExprNameVisitor.INSTANCE, null));
         Assertions.assertInstanceOf(SlotRef.class, params4.get(2));
-        Assertions.assertEquals("c", params4.get(2).getExprName());
+        Assertions.assertEquals("c", params4.get(2).accept(ExprToExprNameVisitor.INSTANCE, null));
 
         Assertions.assertEquals(
                 "PARTITION BY LIST(`val`, bucket('2', `id`), `par`, day(`ts`), efg(`a`, `b`, `c`))\n(\n\n)",
diff --git a/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java b/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java
index 25fd823abb3..cdccf17f247 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java
@@ -46,7 +46,7 @@ public class SessionVariablesTest extends TestWithFeService {
         sessionVariable = new SessionVariable();
         Field[] fields = SessionVariable.class.getDeclaredFields();
         for (Field f : fields) {
-            VariableMgr.VarAttr varAttr = f.getAnnotation(VariableMgr.VarAttr.class);
+            VarAttrDef.VarAttr varAttr = f.getAnnotation(VarAttrDef.VarAttr.class);
             if (varAttr == null || !(varAttr.needForward() || varAttr.affectQueryResultInPlan()
                     || varAttr.affectQueryResultInExecution())) {
                 continue;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/VirtualSlotRef.java b/fe/fe-type/src/main/java/org/apache/doris/catalog/PatternType.java
similarity index 58%
copy from fe/fe-core/src/main/java/org/apache/doris/analysis/VirtualSlotRef.java
copy to fe/fe-type/src/main/java/org/apache/doris/catalog/PatternType.java
index e31bef9ca6f..e427e7a8c22 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/VirtualSlotRef.java
+++ b/fe/fe-type/src/main/java/org/apache/doris/catalog/PatternType.java
@@ -15,32 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.analysis;
-
-import java.util.Map;
-import java.util.Set;
+package org.apache.doris.catalog;
 
 /**
- * It like a SlotRef except that it is not a real column exist in table.
+ * Pattern type for variant column field matching.
+ * Decoupled from thrift TPatternType to avoid thrift dependency.
  */
-@Deprecated
-public class VirtualSlotRef extends SlotRef {
-
-    protected VirtualSlotRef(VirtualSlotRef other) {
-        super(other);
-    }
-
-    @Override
-    public void getTableIdToColumnNames(Map<Long, Set<String>> tableIdToColumnNames) {
-    }
-
-    @Override
-    public Expr clone() {
-        return new VirtualSlotRef(this);
-    }
-
-    @Override
-    public String getExprName() {
-        return super.getExprName();
-    }
+public enum PatternType {
+    MATCH_NAME,
+    MATCH_NAME_GLOB;
 }
diff --git a/fe/fe-type/src/main/java/org/apache/doris/catalog/VariantField.java b/fe/fe-type/src/main/java/org/apache/doris/catalog/VariantField.java
index adb99c52cf0..5ccff65291b 100644
--- a/fe/fe-type/src/main/java/org/apache/doris/catalog/VariantField.java
+++ b/fe/fe-type/src/main/java/org/apache/doris/catalog/VariantField.java
@@ -17,7 +17,6 @@
 
 package org.apache.doris.catalog;
 
-import org.apache.doris.thrift.TPatternType;
 import org.apache.doris.thrift.TTypeDesc;
 import org.apache.doris.thrift.TTypeNode;
 
@@ -36,9 +35,9 @@ public class VariantField {
     protected final String comment;
 
     @SerializedName(value = "fpt")
-    protected final TPatternType patternType;
+    protected final PatternType patternType;
 
-    public VariantField(String pattern, Type type, String comment, TPatternType patternType) {
+    public VariantField(String pattern, Type type, String comment, PatternType patternType) {
         this.pattern = pattern;
         this.type = type;
         this.comment = comment;
@@ -47,7 +46,7 @@ public class VariantField {
 
     // default MATCH_GLOB
     public VariantField(String pattern, Type type, String comment) {
-        this(pattern, type, comment, TPatternType.MATCH_NAME_GLOB);
+        this(pattern, type, comment, PatternType.MATCH_NAME_GLOB);
     }
 
     public Type getType() {
@@ -62,13 +61,13 @@ public class VariantField {
         return comment;
     }
 
-    public TPatternType getPatternType() {
+    public PatternType getPatternType() {
         return patternType;
     }
 
     public String toSql(int depth) {
         StringBuilder sb = new StringBuilder();
-        if (patternType == TPatternType.MATCH_NAME) {
+        if (patternType == PatternType.MATCH_NAME) {
             sb.append(patternType.toString()).append(" ");
         }
 
diff --git a/gensrc/script/Makefile b/gensrc/script/Makefile
index a7d766f5db1..1d79be7e017 100644
--- a/gensrc/script/Makefile
+++ b/gensrc/script/Makefile
@@ -18,7 +18,7 @@
 # generate files with python
 
 BUILD_DIR = ${CURDIR}/../build/
-FE_TARGET_DIR = ${CURDIR}/../../fe/fe-core/target/generated-sources/build
+FE_TARGET_DIR = ${CURDIR}/../../fe/fe-common/target/generated-sources/build
 
 # Prerequisites on the right side of '|' is only order
 all: gen_version
diff --git a/gensrc/script/gen_build_version.sh b/gensrc/script/gen_build_version.sh
index d8d67ddd01d..8e438948ee2 100755
--- a/gensrc/script/gen_build_version.sh
+++ b/gensrc/script/gen_build_version.sh
@@ -60,7 +60,7 @@ if [[ -z "${DORIS_HOME}" ]]; then
 fi
 
 if [[ -z "${DORIS_TEST_BINARY_DIR}" ]]; then
-    if [[ -e "${DORIS_HOME}/fe/fe-core/target/generated-sources/build/org/apache/doris/common/Version.java" && -e "${DORIS_HOME}/gensrc/build/gen_cpp/version.h" && -e "${DORIS_HOME}/gensrc/build/gen_cpp/cloud_version.h" ]]; then
+    if [[ -e "${DORIS_HOME}/fe/fe-common/target/generated-sources/build/org/apache/doris/common/Version.java" && -e "${DORIS_HOME}/gensrc/build/gen_cpp/version.h" && -e "${DORIS_HOME}/gensrc/build/gen_cpp/cloud_version.h" ]]; then
         exit
     fi
 fi
@@ -101,7 +101,7 @@ java_version_str="$("${java_cmd}" -fullversion 2>&1 | sed -e 's/"/\\"/g')"
 echo "get java cmd: ${java_cmd}"
 echo "get java version: ${java_version_str}"
 
-VERSION_PACKAGE="${DORIS_HOME}/fe/fe-core/target/generated-sources/build/org/apache/doris/common"
+VERSION_PACKAGE="${DORIS_HOME}/fe/fe-common/target/generated-sources/build/org/apache/doris/common"
 mkdir -p "${VERSION_PACKAGE}"
 cat >"${VERSION_PACKAGE}/Version.java" <<EOF
 // Licensed to the Apache Software Foundation (ASF) under one


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org