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

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


The following commit(s) were added to refs/heads/branch-2.1 by this push:
     new f7e844b1f2e branch-2.1: [Enhancement] reject schema change on hidden 
columns (#53… (#55387)
f7e844b1f2e is described below

commit f7e844b1f2e7f002a5a78506aff44d7ef057f122
Author: csding <[email protected]>
AuthorDate: Wed Sep 3 19:52:59 2025 +0800

    branch-2.1: [Enhancement] reject schema change on hidden columns (#53… 
(#55387)
    
    Issue Number: close https://github.com/apache/doris/issues/53019
    
    picked from #53376
    
    ### What problem does this PR solve?
    
    Issue Number: close #xxx
    
    Related PR: #xxx
    
    Problem Summary:
    
    ### Release note
    
    None
    
    ### Check List (For Author)
    
    - Test <!-- At least one of them must be included. -->
        - [ ] Regression test
        - [ ] Unit Test
        - [ ] Manual test (add detailed scripts or steps below)
        - [ ] No need to test or manual test. Explain why:
    - [ ] This is a refactor/code format and no logic has been changed.
            - [ ] Previous test can cover this change.
            - [ ] No code files have been changed.
            - [ ] Other reason <!-- Add your reason?  -->
    
    - Behavior changed:
        - [ ] No.
        - [ ] Yes. <!-- Explain the behavior change -->
    
    - Does this need documentation?
        - [ ] No.
    - [ ] Yes. <!-- Add document PR link here. eg:
    https://github.com/apache/doris-website/pull/1214 -->
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label <!-- Add branch pick label that this PR
    should merge into -->
---
 .../java/org/apache/doris/analysis/ColumnDef.java  | 47 +++++++++---
 .../main/java/org/apache/doris/catalog/Column.java |  1 +
 .../java/org/apache/doris/common/FeNameFormat.java | 24 +++++--
 .../plans/commands/info/ColumnDefinition.java      | 84 ++++++++++++++++++----
 4 files changed, 128 insertions(+), 28 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java
index 17986662058..4312f706ee3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java
@@ -185,6 +185,12 @@ public class ColumnDef {
     private String comment;
     private boolean visible;
     private int clusterKeyId = -1;
+    // if add hidden column, must set enableAddHiddenColumn true
+    private boolean enableAddHiddenColumn = false;
+
+    public void setEnableAddHiddenColumn(boolean enableAddHiddenColumn) {
+        this.enableAddHiddenColumn = enableAddHiddenColumn;
+    }
 
     public ColumnDef(String name, TypeDef typeDef) {
         this(name, typeDef, false, null, false, -1, DefaultValue.NOT_SET, "");
@@ -219,40 +225,59 @@ public class ColumnDef {
     }
 
     public static ColumnDef newDeleteSignColumnDef() {
-        return new ColumnDef(Column.DELETE_SIGN, 
TypeDef.create(PrimitiveType.TINYINT), false, null, false,
+        ColumnDef columnDef = new ColumnDef(Column.DELETE_SIGN, 
TypeDef.create(PrimitiveType.TINYINT),
+                false, null, false,
                 -1, new ColumnDef.DefaultValue(true, "0"), "doris delete flag 
hidden column", false);
+        columnDef.setEnableAddHiddenColumn(true);
+        return columnDef;
     }
 
     public static ColumnDef newDeleteSignColumnDef(AggregateType 
aggregateType) {
-        return new ColumnDef(Column.DELETE_SIGN, 
TypeDef.create(PrimitiveType.TINYINT), false, aggregateType, false,
+        ColumnDef columnDef = new ColumnDef(Column.DELETE_SIGN, 
TypeDef.create(PrimitiveType.TINYINT),
+                false, aggregateType, false,
                 -1, new ColumnDef.DefaultValue(true, "0"), "doris delete flag 
hidden column", false);
+        columnDef.setEnableAddHiddenColumn(true);
+        return columnDef;
     }
 
     public static ColumnDef newSequenceColumnDef(Type type) {
-        return new ColumnDef(Column.SEQUENCE_COL, new TypeDef(type), false, 
null, true,
+        ColumnDef columnDef = new ColumnDef(Column.SEQUENCE_COL, new 
TypeDef(type),
+                false, null, true,
                 -1, DefaultValue.NULL_DEFAULT_VALUE, "sequence column hidden 
column", false);
+        columnDef.setEnableAddHiddenColumn(true);
+        return columnDef;
     }
 
     public static ColumnDef newSequenceColumnDef(Type type, AggregateType 
aggregateType) {
-        return new ColumnDef(Column.SEQUENCE_COL, new TypeDef(type), false,
+        ColumnDef columnDef = new ColumnDef(Column.SEQUENCE_COL, new 
TypeDef(type), false,
                 aggregateType, true, -1, DefaultValue.NULL_DEFAULT_VALUE,
                 "sequence column hidden column", false);
+        columnDef.setEnableAddHiddenColumn(true);
+        return columnDef;
     }
 
     public static ColumnDef newRowStoreColumnDef(AggregateType aggregateType) {
-        return new ColumnDef(Column.ROW_STORE_COL, 
TypeDef.create(PrimitiveType.STRING), false,
+        ColumnDef columnDef = new ColumnDef(Column.ROW_STORE_COL, 
TypeDef.create(PrimitiveType.STRING), false,
                 aggregateType, false, -1,
                 new ColumnDef.DefaultValue(true, ""), "doris row store hidden 
column", false);
+        columnDef.setEnableAddHiddenColumn(true);
+        return columnDef;
     }
 
     public static ColumnDef newVersionColumnDef() {
-        return new ColumnDef(Column.VERSION_COL, 
TypeDef.create(PrimitiveType.BIGINT), false, null, false, -1,
+        ColumnDef columnDef = new ColumnDef(Column.VERSION_COL, 
TypeDef.create(PrimitiveType.BIGINT),
+                false, null, false, -1,
                 new ColumnDef.DefaultValue(true, "0"), "doris version hidden 
column", false);
+        columnDef.setEnableAddHiddenColumn(true);
+        return columnDef;
     }
 
     public static ColumnDef newVersionColumnDef(AggregateType aggregateType) {
-        return new ColumnDef(Column.VERSION_COL, 
TypeDef.create(PrimitiveType.BIGINT), false, aggregateType, false,
+        ColumnDef columnDef = new ColumnDef(Column.VERSION_COL, 
TypeDef.create(PrimitiveType.BIGINT),
+                false, aggregateType, false,
                 -1, new ColumnDef.DefaultValue(true, "0"), "doris version 
hidden column", false);
+        columnDef.setEnableAddHiddenColumn(true);
+        return columnDef;
     }
 
     public boolean isAllowNull() {
@@ -311,7 +336,13 @@ public class ColumnDef {
         if (name == null || typeDef == null) {
             throw new AnalysisException("No column name or column type in 
column definition.");
         }
-        FeNameFormat.checkColumnName(name);
+        // if enableAddHiddenColumn is true, can add hidden column.
+        // So does not check if the column name starts with __DORIS_
+        if (enableAddHiddenColumn) {
+            FeNameFormat.checkColumnNameBypassHiddenColumn(name);
+        } else {
+            FeNameFormat.checkColumnName(name);
+        }
 
         typeDef.analyze(null);
 
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 903b7569e60..a99c348810b 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
@@ -55,6 +55,7 @@ import java.util.Set;
  */
 public class Column implements Writable, GsonPostProcessable {
     private static final Logger LOG = LogManager.getLogger(Column.class);
+    public static final String HIDDEN_COLUMN_PREFIX = "__DORIS_";
     // NOTE: you should name hidden column start with '__DORIS_' 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     public static final String DELETE_SIGN = "__DORIS_DELETE_SIGN__";
     public static final String WHERE_SIGN = "__DORIS_WHERE_SIGN__";
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java
index 03600cc3e3b..68855e71c1f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java
@@ -19,6 +19,7 @@ package org.apache.doris.common;
 
 import org.apache.doris.alter.SchemaChangeHandler;
 import org.apache.doris.analysis.CreateMaterializedViewStmt;
+import org.apache.doris.catalog.Column;
 import org.apache.doris.datasource.InternalCatalog;
 import org.apache.doris.mysql.privilege.Role;
 import org.apache.doris.mysql.privilege.RoleManager;
@@ -85,18 +86,29 @@ public class FeNameFormat {
     }
 
     public static void checkColumnName(String columnName) throws 
AnalysisException {
+        // if need check another column name prefix, add in 
`checkColumnNameBypassHiddenColumn`
+        checkColumnNameBypassHiddenColumn(columnName);
+        checkColumnNamePrefix(columnName, Column.HIDDEN_COLUMN_PREFIX);
+    }
+
+    public static void checkColumnNameBypassHiddenColumn(String columnName) 
throws AnalysisException {
         if (Strings.isNullOrEmpty(columnName) || 
!columnName.matches(getColumnNameRegex())) {
             
ErrorReport.reportAnalysisException(ErrorCode.ERR_WRONG_COLUMN_NAME,
                     columnName, getColumnNameRegex());
         }
-        if (columnName.startsWith(SchemaChangeHandler.SHADOW_NAME_PREFIX)) {
-            
ErrorReport.reportAnalysisException(ErrorCode.ERR_WRONG_COLUMN_NAME,
-                    columnName, getColumnNameRegex());
+        checkColumnNamePrefix(columnName, 
SchemaChangeHandler.SHADOW_NAME_PREFIX);
+        checkColumnNamePrefix(columnName, 
CreateMaterializedViewStmt.MATERIALIZED_VIEW_NAME_PREFIX);
+        checkColumnNamePrefix(columnName, 
CreateMaterializedViewStmt.MATERIALIZED_VIEW_AGGREGATE_NAME_PREFIX);
+    }
+
+    private static void checkColumnNamePrefix(String columnName, String 
prefix) throws AnalysisException {
+        int prefixLength = prefix.length();
+        if (columnName.length() < prefixLength) {
+            return;
         }
-        if 
(columnName.startsWith(CreateMaterializedViewStmt.MATERIALIZED_VIEW_NAME_PREFIX)
-                || 
columnName.startsWith(CreateMaterializedViewStmt.MATERIALIZED_VIEW_AGGREGATE_NAME_PREFIX))
 {
+        if (columnName.substring(0, prefixLength).equalsIgnoreCase(prefix)) {
             throw new AnalysisException(
-                    "Incorrect column name " + columnName + ", column name 
can't start with 'mv_'/'mva_'");
+                "Incorrect column name " + columnName + ", column name can't 
start with '" + prefix + "'");
         }
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
index 36140b3b821..28a0b7bdd93 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
@@ -65,6 +65,8 @@ public class ColumnDefinition {
     private boolean aggTypeImplicit = false;
     private long autoIncInitValue = -1;
     private int clusterKeyId = -1;
+    // if add hidden column, must set enableAddHiddenColumn true
+    private boolean enableAddHiddenColumn = false;
 
     public ColumnDefinition(String name, DataType type, boolean isKey, 
AggregateType aggType, boolean isNullable,
             Optional<DefaultValue> defaultValue, String comment) {
@@ -131,6 +133,10 @@ public class ColumnDefinition {
         return aggType;
     }
 
+    public void setEnableAddHiddenColumn(boolean enableAddHiddenColumn) {
+        this.enableAddHiddenColumn = enableAddHiddenColumn;
+    }
+
     public void setAggType(AggregateType aggType) {
         this.aggType = aggType;
     }
@@ -180,7 +186,13 @@ public class ColumnDefinition {
      */
     public void validate(boolean isOlap, Set<String> keysSet, boolean 
isEnableMergeOnWrite, KeysType keysType) {
         try {
-            FeNameFormat.checkColumnName(name);
+            // if enableAddHiddenColumn is true, can add hidden column.
+            // So does not check if the column name starts with __DORIS_
+            if (enableAddHiddenColumn) {
+                FeNameFormat.checkColumnNameBypassHiddenColumn(name);
+            } else {
+                FeNameFormat.checkColumnName(name);
+            }
         } catch (Exception e) {
             throw new AnalysisException(e.getMessage(), e);
         }
@@ -639,35 +651,79 @@ public class ColumnDefinition {
         return column;
     }
 
-    // hidden column
+    /**
+     * add hidden column
+     */
     public static ColumnDefinition newDeleteSignColumnDefinition() {
-        return new ColumnDefinition(Column.DELETE_SIGN, TinyIntType.INSTANCE, 
false, null, false,
-                Optional.of(new DefaultValue(DefaultValue.ZERO_NUMBER)), 
"doris delete flag hidden column", false);
+        ColumnDefinition columnDefinition = new 
ColumnDefinition(Column.DELETE_SIGN, TinyIntType.INSTANCE, false, null,
+                false, Optional.of(new DefaultValue(DefaultValue.ZERO_NUMBER)),
+                "doris delete flag hidden column", false);
+        columnDefinition.setEnableAddHiddenColumn(true);
+
+        return columnDefinition;
     }
 
+    /**
+     * add hidden column
+     */
     public static ColumnDefinition newDeleteSignColumnDefinition(AggregateType 
aggregateType) {
-        return new ColumnDefinition(Column.DELETE_SIGN, TinyIntType.INSTANCE, 
false, aggregateType, false,
-                Optional.of(new DefaultValue(DefaultValue.ZERO_NUMBER)), 
"doris delete flag hidden column", false);
+        ColumnDefinition columnDefinition = new 
ColumnDefinition(Column.DELETE_SIGN, TinyIntType.INSTANCE, false,
+                        aggregateType, false, Optional.of(new 
DefaultValue(DefaultValue.ZERO_NUMBER)),
+                "doris delete flag hidden column", false);
+        columnDefinition.setEnableAddHiddenColumn(true);
+
+        return columnDefinition;
     }
 
+    /**
+     * add hidden column
+     */
     public static ColumnDefinition newSequenceColumnDefinition(DataType type) {
-        return new ColumnDefinition(Column.SEQUENCE_COL, type, false, null, 
true,
-                Optional.empty(), "sequence column hidden column", false);
+        ColumnDefinition columnDefinition = new 
ColumnDefinition(Column.SEQUENCE_COL, type, false, null,
+                true, Optional.empty(),
+                "sequence column hidden column", false);
+        columnDefinition.setEnableAddHiddenColumn(true);
+
+        return columnDefinition;
     }
 
+    /**
+     * add hidden column
+     */
     public static ColumnDefinition newSequenceColumnDefinition(DataType type, 
AggregateType aggregateType) {
-        return new ColumnDefinition(Column.SEQUENCE_COL, type, false, 
aggregateType, true,
-                Optional.empty(), "sequence column hidden column", false);
+        ColumnDefinition columnDefinition = new 
ColumnDefinition(Column.SEQUENCE_COL, type, false, aggregateType,
+                true, Optional.empty(),
+                "sequence column hidden column", false);
+        columnDefinition.setEnableAddHiddenColumn(true);
+
+        return columnDefinition;
     }
 
+    /**
+     * add hidden column
+     */
     public static ColumnDefinition newRowStoreColumnDefinition(AggregateType 
aggregateType) {
-        return new ColumnDefinition(Column.ROW_STORE_COL, StringType.INSTANCE, 
false, aggregateType, false,
-                Optional.of(new DefaultValue("")), "doris row store hidden 
column", false);
+        ColumnDefinition columnDefinition = new 
ColumnDefinition(Column.ROW_STORE_COL, StringType.INSTANCE, false,
+                        aggregateType, false, Optional.of(new 
DefaultValue("")),
+                "doris row store hidden column", false);
+        columnDefinition.setEnableAddHiddenColumn(true);
+
+        return columnDefinition;
     }
 
+    /**
+     * add hidden column
+     */
     public static ColumnDefinition newVersionColumnDefinition(AggregateType 
aggregateType) {
-        return new ColumnDefinition(Column.VERSION_COL, BigIntType.INSTANCE, 
false, aggregateType, false,
-                Optional.of(new DefaultValue(DefaultValue.ZERO_NUMBER)), 
"doris version hidden column", false);
+        ColumnDefinition columnDefinition = new 
ColumnDefinition(Column.VERSION_COL, BigIntType.INSTANCE, false,
+                    aggregateType, false, Optional.of(new 
DefaultValue(DefaultValue.ZERO_NUMBER)),
+                "doris version hidden column", false);
+        columnDefinition.setEnableAddHiddenColumn(true);
+
+        return columnDefinition;
     }
 
+    public long getAutoIncInitValue() {
+        return autoIncInitValue;
+    }
 }


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

Reply via email to