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

yiguolei 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 1eb427f19eb [fix](fe) Reject dotted VARIANT column names in ALTER 
TABLE (#69088)
1eb427f19eb is described below

commit 1eb427f19ebf7667a2c828857b7b7cc98c30dbfb
Author: lihangyu <[email protected]>
AuthorDate: Mon Oct 19 12:37:56 2026 +0800

    [fix](fe) Reject dotted VARIANT column names in ALTER TABLE (#69088)
    
    ### What problem does this PR solve?
    
    Related PR: #69077 (branch-4.1 backport)
    
    Problem Summary: CREATE TABLE rejected top-level VARIANT column names
    containing a dot, but ALTER TABLE ADD COLUMN could persist the same
    invalid schema. Move the restriction into shared column-definition
    validation so CREATE, single/batch ADD, and MODIFY enforce it
    consistently. Reject RENAME to a dotted VARIANT name before changing
    metadata, while preserving edit-log replay and nested-field semantics.
    
    Update both existing CREATE regression controls to match the shared
    VARIANT naming error, and assert the CREATE error in the FE SQL unit
    test. The previous generic CREATE-only expectation caused
    sql_create_time_range_table to fail even though the DDL was correctly
    rejected.
    
    ### Release note
    
    Reject ALTER TABLE operations that introduce a top-level VARIANT column
    name containing a dot.
    
    ### Check List (For Author)
    
    - Test:
    - FE SQL unit test: `./run-fe-ut.sh --run
    org.apache.doris.alter.VariantColumnNameTest` — passed (1 test, 0
    failures/errors; full wrapper exit 0 after FE packaging).
    - Master FE build and Checkstyle: `DISABLE_BUILD_UI=ON ./build.sh --fe
    --exclude-obs-dependencies` — passed; exclude OBS to avoid dependency
    repository validation stalls.
    - On both master and branch-4.1, run `sql_create_time_range_table` under
    `ddl_p0` and `test_variant_column_name` under `variant_p0/schema_change`
    with `run-regression-test.sh`: all four focused suite runs passed, 0
    failures/skips. Each runtime used its branch's built FE and a prebuilt
    ASAN BE (326d74e175b); no BE source changed.
      - Branch-4.1 FE Checkstyle and `git diff --check`: passed.
    - Behavior changed: Yes; reject previously accepted invalid VARIANT
    column names. Dotted names of other types remain supported.
    - Does this need documentation: Yes;
    https://github.com/apache/doris-website/pull/4307
    
    Metadata / compatibility review: reject invalid names before catalog
    mutation; RENAME retains its write lock and replay behavior. Both local
    and cloud tables use the shared FE validation; no protocol or metadata
    format changes.
---
 .../main/java/org/apache/doris/catalog/Env.java    |  8 +++
 .../plans/commands/info/ColumnDefinition.java      |  4 ++
 .../trees/plans/commands/info/CreateTableInfo.java |  7 ---
 .../apache/doris/alter/VariantColumnNameTest.java  | 71 ++++++++++++++++++++++
 .../suites/ddl_p0/test_create_table.groovy         |  4 +-
 .../schema_change/test_variant_column_name.groovy  | 40 ++++++++++++
 6 files changed, 125 insertions(+), 9 deletions(-)

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 426ec84bab4..46a11792b6f 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
@@ -6241,6 +6241,14 @@ public class Env {
         try {
             String colName = renameColumnOp.getColName();
             String newColName = renameColumnOp.getNewColName();
+            Column column = table.getColumn(colName);
+            if (column == null) {
+                throw new DdlException("Column[" + colName + "] does not 
exists");
+            }
+            if (column.getType().isVariantType() && newColName.indexOf('.') != 
-1) {
+                throw new DdlException(
+                        "Cannot use `VARIANT` type column named with a `.` 
character: " + newColName);
+            }
             Map<Long, Integer> indexIdToSchemaVersion = new HashMap<Long, 
Integer>();
             renameColumn(db, table, colName, newColName, 
indexIdToSchemaVersion, false);
         } finally {
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 f7a6969d2ba..dd250ab9f6e 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
@@ -428,6 +428,10 @@ public class ColumnDefinition {
         } catch (Exception e) {
             throw new AnalysisException(e.getMessage(), e);
         }
+        if (!nestedColumn && type.isVariantType() && name.indexOf('.') != -1) {
+            throw new AnalysisException(
+                    "Cannot use `VARIANT` type column named with a `.` 
character: " + name);
+        }
         type.validateDataType();
         type = updateCharacterTypeLength(type);
         if (!isSystemGeneratedTable && isOlap && keysType != KeysType.AGG_KEYS 
&& isAggregateTableOnlyType()
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
index 4eeadf708e0..c7a44f1835d 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
@@ -486,13 +486,6 @@ public class CreateTableInfo {
             if (columnDef.getType().isVarBinaryType()) {
                 throw new AnalysisException("doris do not support varbinary 
create table, could use it by catalog");
             }
-            if (columnDef.getType().isVariantType()) {
-                if (columnNameUpperCase.indexOf('.') != -1) {
-                    throw new AnalysisException(
-                        "Disable to create table of `VARIANT` type column 
named with a `.` character: "
-                                + columnNameUpperCase);
-                }
-            }
             if (columnDef.getType().isDateType() && Config.disable_datev1) {
                 throw new AnalysisException(
                         "Disable to create table with `DATE` type columns, 
please use `DATEV2`.");
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/alter/VariantColumnNameTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/alter/VariantColumnNameTest.java
new file mode 100644
index 00000000000..18943131d83
--- /dev/null
+++ b/fe/fe-core/src/test/java/org/apache/doris/alter/VariantColumnNameTest.java
@@ -0,0 +1,71 @@
+// 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.alter;
+
+import org.apache.doris.catalog.Env;
+import org.apache.doris.catalog.OlapTable;
+import org.apache.doris.utframe.TestWithFeService;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class VariantColumnNameTest extends TestWithFeService {
+    @Override
+    protected void runBeforeAll() throws Exception {
+        createDatabase("variant_column_name");
+        connectContext.setDatabase("variant_column_name");
+    }
+
+    @Test
+    public void testRejectDottedVariantColumnNames() throws Exception {
+        createTable("CREATE TABLE variant_column_name.t (k INT, v VARIANT, 
`s.x` STRING) "
+                + "DUPLICATE KEY(k) DISTRIBUTED BY HASH(k) BUCKETS 1 "
+                + "PROPERTIES ('replication_num'='1')");
+        OlapTable table = (OlapTable) Env.getCurrentInternalCatalog()
+                
.getDbOrMetaException("variant_column_name").getTableOrMetaException("t");
+        String[] statements = {
+                "ALTER TABLE t ADD COLUMN `v.x` VARIANT",
+                "ALTER TABLE t ADD COLUMN (good VARIANT, `v.x` VARIANT)",
+                "ALTER TABLE t MODIFY COLUMN `s.x` VARIANT",
+                "ALTER TABLE t RENAME COLUMN v `v.x`"
+        };
+        for (String statement : statements) {
+            Exception error = Assertions.assertThrows(Exception.class, () -> 
alterTableSync(statement));
+            Assertions.assertTrue(error.getMessage().contains(
+                    "`VARIANT` type column named with a `.` character"), 
error.getMessage());
+            Assertions.assertEquals(3, table.getBaseSchema().size());
+            Assertions.assertNull(table.getColumn("v.x"));
+            Assertions.assertNull(table.getColumn("good"));
+            
Assertions.assertTrue(table.getColumn("s.x").getType().isStringType());
+            Assertions.assertNotNull(table.getColumn("v"));
+        }
+        Exception createError = Assertions.assertThrows(Exception.class, () -> 
createTable(
+                "CREATE TABLE bad (k INT, `v.x` VARIANT) DUPLICATE KEY(k) "
+                        + "DISTRIBUTED BY HASH(k) BUCKETS 1 PROPERTIES 
('replication_num'='1')"));
+        Assertions.assertTrue(createError.getMessage().contains(
+                "`VARIANT` type column named with a `.` character"), 
createError.getMessage());
+        alterTableSync("ALTER TABLE t ADD COLUMN good VARIANT");
+        
Assertions.assertTrue(table.getColumn("good").getType().isVariantType());
+        alterTableSync("ALTER TABLE t RENAME COLUMN good renamed");
+        
Assertions.assertTrue(table.getColumn("renamed").getType().isVariantType());
+        alterTableSync("ALTER TABLE t ADD COLUMN `other.x` STRING");
+        Assertions.assertNotNull(table.getColumn("other.x"));
+        alterTableSync("ALTER TABLE t RENAME COLUMN `other.x` `other.y`");
+        Assertions.assertNotNull(table.getColumn("other.y"));
+    }
+}
diff --git a/regression-test/suites/ddl_p0/test_create_table.groovy 
b/regression-test/suites/ddl_p0/test_create_table.groovy
index 03de74bc289..4c5f9387ca6 100644
--- a/regression-test/suites/ddl_p0/test_create_table.groovy
+++ b/regression-test/suites/ddl_p0/test_create_table.groovy
@@ -58,7 +58,7 @@ suite("sql_create_time_range_table") {
             DISTRIBUTED BY HASH(`k`) BUCKETS 1
             PROPERTIES ( "replication_num" = "1");
         """
-        exception "Disable to create table"
+        exception "`VARIANT` type column named with a `.` character"
     }
 
     // DDL/DML return 1 row and 1 column, the only value is update row count
@@ -86,6 +86,6 @@ suite("sql_create_time_range_table") {
             DISTRIBUTED BY HASH(`k`) BUCKETS 1
             PROPERTIES ( "replication_num" = "1");
         """
-        exception "Disable to create table"
+        exception "`VARIANT` type column named with a `.` character"
     }
 }
diff --git 
a/regression-test/suites/variant_p0/schema_change/test_variant_column_name.groovy
 
b/regression-test/suites/variant_p0/schema_change/test_variant_column_name.groovy
new file mode 100644
index 00000000000..f5d4302c2fa
--- /dev/null
+++ 
b/regression-test/suites/variant_p0/schema_change/test_variant_column_name.groovy
@@ -0,0 +1,40 @@
+// 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.
+
+suite("test_variant_column_name", "variant_type") {
+    sql "DROP TABLE IF EXISTS test_variant_column_name"
+    sql """CREATE TABLE test_variant_column_name (
+        k INT, v VARIANT, `s.x` STRING
+    ) DUPLICATE KEY(k) DISTRIBUTED BY HASH(k) BUCKETS 1
+    PROPERTIES ('replication_num'='1')"""
+
+    [
+        "ALTER TABLE test_variant_column_name ADD COLUMN `v.x` VARIANT",
+        "ALTER TABLE test_variant_column_name ADD COLUMN (good VARIANT, `v.x` 
VARIANT)",
+        "ALTER TABLE test_variant_column_name MODIFY COLUMN `s.x` VARIANT",
+        "ALTER TABLE test_variant_column_name RENAME COLUMN v `v.x`"
+    ].each { statement ->
+        test {
+            sql statement
+            exception "`VARIANT` type column named with a `.` character"
+        }
+    }
+    sql "ALTER TABLE test_variant_column_name ADD COLUMN good VARIANT"
+    sql "ALTER TABLE test_variant_column_name RENAME COLUMN good renamed"
+    sql "ALTER TABLE test_variant_column_name ADD COLUMN `other.x` STRING"
+    sql "ALTER TABLE test_variant_column_name RENAME COLUMN `other.x` 
`other.y`"
+}


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

Reply via email to