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

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


The following commit(s) were added to refs/heads/branch-4.2 by this push:
     new 2c0dfb21ced branch-4.2: [fix](fe) Reject complex types 
(ARRAY/MAP/STRUCT) as MAP key types #63621 (#70037)
2c0dfb21ced is described below

commit 2c0dfb21ceddfe341fe3c5675d02bfb0522613cf
Author: morrySnow <[email protected]>
AuthorDate: Tue Nov 3 17:19:06 2026 +0800

    branch-4.2: [fix](fe) Reject complex types (ARRAY/MAP/STRUCT) as MAP key 
types #63621 (#70037)
    
    picked from master #63621
---
 .../org/apache/doris/nereids/types/DataType.java   |  7 +++-
 .../trees/plans/CreateTableCommandTest.java        | 24 ++++++++++++++
 .../string_len/test_string_len_complex.out         |  7 ----
 .../test_complex_disallowed_subtypes.groovy        | 33 +++++++++++++++++++
 .../string_len/test_string_len_complex.groovy      | 38 ----------------------
 .../show/test_nested_complex_switch.groovy         | 17 ----------
 6 files changed, 63 insertions(+), 63 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
index d3bcd607fc3..782e7462471 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
@@ -949,7 +949,12 @@ public abstract class DataType {
             if (catalogType.isMapType()) {
                 org.apache.doris.catalog.MapType mt =
                         (org.apache.doris.catalog.MapType) catalogType;
-                validateNestedType(catalogType, mt.getKeyType());
+                Type mapKeyType = mt.getKeyType();
+                if (mapKeyType.isComplexType()) {
+                    throw new AnalysisException(
+                            "MAP key type must be a primitive type but get " + 
mapKeyType.toSql());
+                }
+                validateNestedType(catalogType, mapKeyType);
                 validateNestedType(catalogType, mt.getValueType());
             }
             if (catalogType.isStructType()) {
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 2ec8b39aa57..eb49d9790ae 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
@@ -709,6 +709,30 @@ public class CreateTableCommandTest extends 
TestWithFeService {
                         + "distributed by hash(k1) buckets 1 
properties('replication_num' = '1');"));
     }
 
+    @Test
+    public void testCreateTableWithComplexMapKey() {
+        // MAP<ARRAY<INT>, INT> should be rejected - array key
+        checkThrow(AnalysisException.class, "MAP key type must be a primitive 
type",
+                () -> createTable("create table test.test_map_array_key(k1 
INT, k2 Map<Array<int>, int>) "
+                        + "duplicate key (k1) distributed by hash(k1) buckets 
1 "
+                        + "properties('replication_num' = '1');"));
+        // MAP<MAP<INT, INT>, INT> should be rejected - map key
+        checkThrow(AnalysisException.class, "MAP key type must be a primitive 
type",
+                () -> createTable("create table test.test_map_map_key(k1 INT, 
k2 Map<Map<int,int>, int>) "
+                        + "duplicate key (k1) distributed by hash(k1) buckets 
1 "
+                        + "properties('replication_num' = '1');"));
+        // MAP<STRUCT<f1:INT>, INT> should be rejected - struct key
+        checkThrow(AnalysisException.class, "MAP key type must be a primitive 
type",
+                () -> createTable("create table test.test_map_struct_key(k1 
INT, k2 Map<Struct<f1:int>, int>) "
+                        + "duplicate key (k1) distributed by hash(k1) buckets 
1 "
+                        + "properties('replication_num' = '1');"));
+        // MAP<STRING, ARRAY<INT>> should still be accepted - complex value 
type is OK
+        Assertions.assertDoesNotThrow(
+                () -> createTable("create table test.test_map_complex_value(k1 
INT, k2 Map<String, Array<int>>) "
+                        + "duplicate key (k1) distributed by hash(k1) buckets 
1 "
+                        + "properties('replication_num' = '1');"));
+    }
+
     @Test
     public void testCreateTableWithStructType() {
         Assertions.assertDoesNotThrow(
diff --git 
a/regression-test/data/datatype_p0/nested_types/string_len/test_string_len_complex.out
 
b/regression-test/data/datatype_p0/nested_types/string_len/test_string_len_complex.out
index acc8e888691..d09fc1f00f6 100644
--- 
a/regression-test/data/datatype_p0/nested_types/string_len/test_string_len_complex.out
+++ 
b/regression-test/data/datatype_p0/nested_types/string_len/test_string_len_complex.out
@@ -34,10 +34,3 @@
 
 -- !sql_map_all2 --
 
--- !sql_map_all3 --
-1      {{"01234567891":"12345678901"}:{"11234567891":"12345678901"}, 
{"01234567892":"12345678902"}:{"11234567892":"12345678902"}}
-2      {{"01234567891":"22345678901"}:{"11234567891":"22345678901"}, 
{"01234567892":"22345678902"}:{"11234567892":"22345678902"}}
-3      {{"01234567891":"32345678901"}:{"11234567891":"32345678901"}, 
{"01234567892":"32345678902"}:{"11234567892":"32345678902"}}
-
--- !sql_map_all4 --
-
diff --git 
a/regression-test/suites/datatype_p0/complex_types/test_complex_disallowed_subtypes.groovy
 
b/regression-test/suites/datatype_p0/complex_types/test_complex_disallowed_subtypes.groovy
index 36d261e9d0a..684c1084f83 100644
--- 
a/regression-test/suites/datatype_p0/complex_types/test_complex_disallowed_subtypes.groovy
+++ 
b/regression-test/suites/datatype_p0/complex_types/test_complex_disallowed_subtypes.groovy
@@ -64,6 +64,31 @@ suite("test_complex_disallowed_subtypes") {
         exception "unsupported sub-type"
     }
 
+    // ---- DORIS-25583: MAP key must not be a complex type (MAP/ARRAY/STRUCT) 
----
+
+    sql "DROP TABLE IF EXISTS t_complex_map_key_1"
+    sql "DROP TABLE IF EXISTS t_complex_map_key_2"
+    sql "DROP TABLE IF EXISTS t_complex_map_key_3"
+    sql "DROP TABLE IF EXISTS t_complex_map_key_valid"
+
+    test {
+        // MAP<ARRAY<INT>, INT>
+        sql "CREATE TABLE t_complex_map_key_1 (k INT, v MAP<ARRAY<INT>,INT>) 
DUPLICATE KEY(k) DISTRIBUTED BY HASH(k) BUCKETS 1 
PROPERTIES('replication_num'='1')"
+        exception "MAP key type must be a primitive type"
+    }
+
+    test {
+        // MAP<MAP<STRING,INT>, INT>
+        sql "CREATE TABLE t_complex_map_key_2 (k INT, v 
MAP<MAP<STRING,INT>,INT>) DUPLICATE KEY(k) DISTRIBUTED BY HASH(k) BUCKETS 1 
PROPERTIES('replication_num'='1')"
+        exception "MAP key type must be a primitive type"
+    }
+
+    test {
+        // MAP<STRUCT<a:INT>, INT>
+        sql "CREATE TABLE t_complex_map_key_3 (k INT, v 
MAP<STRUCT<a:INT>,INT>) DUPLICATE KEY(k) DISTRIBUTED BY HASH(k) BUCKETS 1 
PROPERTIES('replication_num'='1')"
+        exception "MAP key type must be a primitive type"
+    }
+
     // ---- valid deep nesting must still be accepted ----
 
     sql """
@@ -73,5 +98,13 @@ suite("test_complex_disallowed_subtypes") {
         PROPERTIES('replication_num'='1')
     """
 
+    sql """
+        CREATE TABLE t_complex_map_key_valid (k INT, v MAP<STRING, ARRAY<INT>>)
+        DUPLICATE KEY(k)
+        DISTRIBUTED BY HASH(k) BUCKETS 1
+        PROPERTIES('replication_num'='1')
+    """
+
     sql "DROP TABLE IF EXISTS t_complex_valid"
+    sql "DROP TABLE IF EXISTS t_complex_map_key_valid"
 }
diff --git 
a/regression-test/suites/datatype_p0/nested_types/string_len/test_string_len_complex.groovy
 
b/regression-test/suites/datatype_p0/nested_types/string_len/test_string_len_complex.groovy
index 07b63914fa9..1e8ff5e4c46 100644
--- 
a/regression-test/suites/datatype_p0/nested_types/string_len/test_string_len_complex.groovy
+++ 
b/regression-test/suites/datatype_p0/nested_types/string_len/test_string_len_complex.groovy
@@ -200,42 +200,4 @@ suite("test_string_len_complex") {
     }
     qt_sql_map_all2 """ select * from test_string_len_map_one_level order by 
id; """
 
-    // test map two level
-    def create_table_map_two_level = {
-        sql """ DROP TABLE IF EXISTS test_string_len_map_two_level """
-        sql """
-            CREATE TABLE `test_string_len_map_two_level` (
-              `id` int(11),
-              `info` map<map<char(11), char(11)>, map<char(11), char(11)>>
-            ) PROPERTIES ("replication_num" = "1");
-        """
-    }
-
-    create_table_map_two_level()
-    sql """
-    set enable_insert_strict = false;
-    set enable_strict_cast = false;
-    """
-    sql """
-    insert into test_string_len_map_two_level values (1, { 
{'01234567891':'12345678901'}:{'11234567891':'12345678901'}, 
{'01234567892':'12345678902'}:{'11234567892':'12345678902'} } ), 
-    (2, { {'01234567891':'22345678901'}:{'11234567891':'22345678901'}, 
{'01234567892':'22345678902'}:{'11234567892':'22345678902'} } ), 
-    (3, { {'01234567891':'32345678901'}:{'11234567891':'32345678901'}, 
{'01234567892':'32345678902x'}:{'11234567892':'32345678902x'} } );
-    """
-    qt_sql_map_all3 """ select * from test_string_len_map_two_level order by 
id; """
-
-    create_table_map_two_level()
-    sql """
-    set enable_insert_strict = true;
-    set enable_strict_cast = true;
-    """
-    test {
-        sql """
-        insert into test_string_len_map_two_level values (1, { 
{'01234567891':'12345678901'}:{'11234567891':'12345678901'}, 
{'01234567892':'12345678902'}:{'11234567892':'12345678902'} } ), 
-        (2, { {'01234567891':'22345678901'}:{'11234567891':'22345678901'}, 
{'01234567892':'22345678902'}:{'11234567892':'22345678902'} } ), 
-        (3, { {'01234567891':'32345678901'}:{'11234567891':'32345678901'}, 
{'01234567892':'32345678902x'}:{'11234567892':'32345678902x'} } );
-        """
-        exception "Insert has filtered data in strict mode"
-    }
-    qt_sql_map_all4 """ select * from test_string_len_map_two_level order by 
id; """
-
 }
\ No newline at end of file
diff --git 
a/regression-test/suites/query_p0/show/test_nested_complex_switch.groovy 
b/regression-test/suites/query_p0/show/test_nested_complex_switch.groovy
index 9b06a00eb42..e0175f3147a 100644
--- a/regression-test/suites/query_p0/show/test_nested_complex_switch.groovy
+++ b/regression-test/suites/query_p0/show/test_nested_complex_switch.groovy
@@ -35,19 +35,6 @@ suite("test_nested_complex_switch", "query") {
                                          "storage_format" = "V2",
                                          "disable_auto_compaction" = "false"
                                          )"""
-    def sql_m_a = """CREATE TABLE IF NOT EXISTS ${testTable_m} (
-                          `k1` INT(11) NULL,
-                          `k2` MAP<ARRAY<INT>, STRING>
-                        ) ENGINE=OLAP
-                        DUPLICATE KEY(`k1`)
-                        COMMENT 'OLAP'
-                        DISTRIBUTED BY HASH(`k1`) BUCKETS 1
-                        PROPERTIES (
-                        "replication_allocation" = "tag.location.default: 1",
-                        "in_memory" = "false",
-                        "storage_format" = "V2",
-                        "disable_auto_compaction" = "false"
-                        )"""
 
     def sql_m_m = """CREATE TABLE IF NOT EXISTS ${testTable_m} (
                           `k1` INT(11) NULL,
@@ -145,10 +132,6 @@ suite("test_nested_complex_switch", "query") {
             sql sql_m_s
         }
 
-        test {
-            sql sql_m_a
-        }
-
         test {
             sql sql_m_m
         }


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

Reply via email to