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

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


The following commit(s) were added to refs/heads/branch-2.0 by this push:
     new 557693c8a9f [FIX](complextype) fxi array nested struct literal #26270 
(#26778)
557693c8a9f is described below

commit 557693c8a9f38314bc96467e3745a83a63416b2d
Author: amory <wangqian...@selectdb.com>
AuthorDate: Fri Nov 10 22:18:26 2023 +0800

    [FIX](complextype) fxi array nested struct literal #26270 (#26778)
---
 be/src/olap/rowset/segment_v2/column_reader.cpp    |  1 +
 .../java/org/apache/doris/catalog/ArrayType.java   | 10 ++++
 .../java/org/apache/doris/catalog/MapType.java     | 15 ++++++
 .../java/org/apache/doris/catalog/StructType.java  | 24 +++++++++
 .../main/java/org/apache/doris/catalog/Type.java   | 27 ++++------
 .../cast_function/test_cast_map_function.out       | 48 -----------------
 .../cast_function/test_cast_map_function.groovy    | 60 ----------------------
 7 files changed, 60 insertions(+), 125 deletions(-)

diff --git a/be/src/olap/rowset/segment_v2/column_reader.cpp 
b/be/src/olap/rowset/segment_v2/column_reader.cpp
index d9a074e2904..3d1e89de2ed 100644
--- a/be/src/olap/rowset/segment_v2/column_reader.cpp
+++ b/be/src/olap/rowset/segment_v2/column_reader.cpp
@@ -87,6 +87,7 @@ Status ColumnReader::create(const ColumnReaderOptions& opts, 
const ColumnMetaPB&
         case FieldType::OLAP_FIELD_TYPE_STRUCT: {
             // not support empty struct
             DCHECK(meta.children_columns_size() >= 1);
+            num_rows = meta.children_columns(0).num_rows();
             // create struct column reader
             std::unique_ptr<ColumnReader> struct_reader(
                     new ColumnReader(opts, meta, num_rows, file_reader));
diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java
index 477d278bf8a..b820cda7a44 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java
@@ -163,6 +163,16 @@ public class ArrayType extends Type {
         return Type.canCastTo(type.getItemType(), targetType.getItemType());
     }
 
+    public static Type getAssignmentCompatibleType(ArrayType t1, ArrayType t2, 
boolean strict) {
+        Type itemCompatibleType = 
Type.getAssignmentCompatibleType(t1.getItemType(), t2.getItemType(), strict);
+
+        if (itemCompatibleType.isInvalid()) {
+            return ScalarType.INVALID;
+        }
+
+        return new ArrayType(itemCompatibleType, t1.getContainsNull() || 
t2.getContainsNull());
+    }
+
     @Override
     public void toThrift(TTypeDesc container) {
         TTypeNode node = new TTypeNode();
diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java
index 691c4d7e04d..06dba8c2fb0 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java
@@ -198,6 +198,21 @@ public class MapType extends Type {
             || targetType.getValueType().isStringType() && 
type.getValueType().isStringType());
     }
 
+    public static Type getAssignmentCompatibleType(MapType t1, MapType t2, 
boolean strict) {
+        Type keyCompatibleType = 
Type.getAssignmentCompatibleType(t1.getKeyType(), t2.getKeyType(), strict);
+        if (keyCompatibleType.isInvalid()) {
+            return ScalarType.INVALID;
+        }
+        Type valCompatibleType = 
Type.getAssignmentCompatibleType(t1.getValueType(), t2.getValueType(), strict);
+        if (valCompatibleType.isInvalid()) {
+            return ScalarType.INVALID;
+        }
+
+        return new MapType(keyCompatibleType, valCompatibleType,
+            t1.getIsKeyContainsNull() || t2.getIsKeyContainsNull(),
+            t1.getIsValueContainsNull() || t2.getIsValueContainsNull());
+    }
+
     @Override
     public boolean supportSubType(Type subType) {
         for (Type supportedType : Type.getMapSubTypes()) {
diff --git 
a/fe/fe-common/src/main/java/org/apache/doris/catalog/StructType.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/StructType.java
index 0a058ae5406..1d6be19d28e 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/StructType.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/StructType.java
@@ -29,6 +29,7 @@ import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.gson.annotations.SerializedName;
+import org.apache.commons.lang3.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -110,6 +111,29 @@ public class StructType extends Type {
         return true;
     }
 
+    public static Type getAssignmentCompatibleType(StructType t1, StructType 
t2, boolean strict) {
+        ArrayList<StructField> fieldsLeft = t1.getFields();
+        ArrayList<StructField> fieldsRight = t2.getFields();
+        ArrayList<StructField> fieldsRes = new ArrayList<>();
+
+        for (int i = 0; i < t1.getFields().size(); ++i) {
+            StructField leftField = fieldsLeft.get(i);
+            StructField rightField = fieldsRight.get(i);
+            Type itemCompatibleType = 
Type.getAssignmentCompatibleType(leftField.getType(), rightField.getType(),
+                    strict);
+            if (itemCompatibleType.isInvalid()) {
+                return ScalarType.INVALID;
+            }
+            fieldsRes.add(new 
StructField(StringUtils.isEmpty(leftField.getName()) ? rightField.getName()
+                    : leftField.getName(),
+                    itemCompatibleType, 
StringUtils.isEmpty(leftField.getComment()) ? rightField.getComment()
+                    : leftField.getComment(), leftField.getContainsNull() || 
rightField.getContainsNull()));
+
+        }
+
+        return new StructType(fieldsRes);
+    }
+
     @Override
     public boolean isSupported() {
         for (StructField f : fields) {
diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
index fe2c132b9df..b32b29c18fe 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
@@ -746,19 +746,14 @@ public abstract class Type {
         }
 
         if (t1.isArrayType() && t2.isArrayType()) {
-            ArrayType arrayType1 = (ArrayType) t1;
-            ArrayType arrayType2 = (ArrayType) t2;
-            Type itemCompatibleType = 
Type.getAssignmentCompatibleType(arrayType1.getItemType(),
-                    arrayType2.getItemType(), strict);
-
-            if (itemCompatibleType.isInvalid()) {
-                return itemCompatibleType;
-            }
-
-            return new ArrayType(itemCompatibleType, 
arrayType1.getContainsNull() || arrayType2.getContainsNull());
-        } else if (t1.isArrayType() && t2.isNull()) {
+            return ArrayType.getAssignmentCompatibleType((ArrayType) t1, 
(ArrayType) t2, strict);
+        } else if (t1.isMapType() && t2.isMapType()) {
+            return MapType.getAssignmentCompatibleType((MapType) t1, (MapType) 
t2, strict);
+        } else if (t1.isStructType() && t2.isStructType()) {
+            return StructType.getAssignmentCompatibleType((StructType) t1, 
(StructType) t2, strict);
+        } else if (t1.isComplexType() && t2.isNull()) {
             return t1;
-        } else if (t1.isNull() && t2.isArrayType()) {
+        } else if (t1.isNull() && t2.isComplexType()) {
             return t2;
         }
 
@@ -1963,17 +1958,15 @@ public abstract class Type {
             } else if (type2.isArrayType()) {
                 // For types array, we also need to check contains null for 
case like
                 // cast(array<not_null(int)> as array<int>)
-                if (!((ArrayType) type2).getContainsNull() == ((ArrayType) 
type1).getContainsNull()) {
+                if (((ArrayType) type2).getContainsNull() != ((ArrayType) 
type1).getContainsNull()) {
                     return false;
                 }
                 return matchExactType(((ArrayType) type2).getItemType(), 
((ArrayType) type1).getItemType());
             } else if (type2.isMapType()) {
-                // For types array, we also need to check contains null for 
case like
-                // cast(array<not_null(int)> as array<int>)
-                if (!((MapType) type2).getIsKeyContainsNull() == ((MapType) 
type1).getIsKeyContainsNull()) {
+                if (((MapType) type2).getIsKeyContainsNull() != ((MapType) 
type1).getIsKeyContainsNull()) {
                     return false;
                 }
-                if (!((MapType) type2).getIsValueContainsNull() == ((MapType) 
type1).getIsValueContainsNull()) {
+                if (((MapType) type2).getIsValueContainsNull() != ((MapType) 
type1).getIsValueContainsNull()) {
                     return false;
                 }
                 return matchExactType(((MapType) type2).getKeyType(), 
((MapType) type1).getKeyType())
diff --git 
a/regression-test/data/nereids_function_p0/cast_function/test_cast_map_function.out
 
b/regression-test/data/nereids_function_p0/cast_function/test_cast_map_function.out
deleted file mode 100644
index c9da5a1c286..00000000000
--- 
a/regression-test/data/nereids_function_p0/cast_function/test_cast_map_function.out
+++ /dev/null
@@ -1,48 +0,0 @@
--- This file is automatically generated. You should know what you did if you 
want to edit this
--- !select --
-1      {"aa":1, "b":2, "1234567":77}
-2      {"b":12, "123":7777}
-
--- !select --
-{}
-
--- !select --
-{}
-
--- !sql1 --
-\N
-
--- !sql2 --
-{"":NULL}
-
--- !sql3 --
-{"1":2}
-
--- !sql4 --
-{"aa":1, "b":2, "1234567":77}
-{"b":12, "123":7777}
-
--- !sql5 --
-{"aa":1, "b":2, "1234567":77}
-{"b":12, "123":7777}
-
--- !sql6 --
-{"aa":1, "b":2, "1234567":77}
-{"b":12, "123":97}
-
--- !sql7 --
-{"aa":"1", "b":"2", "1234567":"77"}
-{"b":"12", "123":"7777"}
-
--- !sql8 --
-{NULL:"1", NULL:"2", 1234567:"77"}
-{NULL:"12", 123:"7777"}
-
--- !sql9 --
-{NULL:1, NULL:2, 1234567:77}
-{NULL:12, 123:7777}
-
--- !sql10 --
-{NULL:NULL, NULL:NULL, 1234567:NULL}
-{NULL:NULL, 123:NULL}
-
diff --git 
a/regression-test/suites/nereids_function_p0/cast_function/test_cast_map_function.groovy
 
b/regression-test/suites/nereids_function_p0/cast_function/test_cast_map_function.groovy
deleted file mode 100644
index e3a4ccdaecc..00000000000
--- 
a/regression-test/suites/nereids_function_p0/cast_function/test_cast_map_function.groovy
+++ /dev/null
@@ -1,60 +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.
-
-suite("test_cast_map_function", "query") {
-    sql """ set enable_nereids_planner = true; """
-    sql """ set enable_fallback_to_original_planner=false; """ 
-    def tableName = "tbl_test_cast_map_function_nereids"
-
-    sql """DROP TABLE IF EXISTS ${tableName}"""
-    sql """
-            CREATE TABLE IF NOT EXISTS ${tableName} (
-              `k1` int(11) NULL COMMENT "",
-              `k2` Map<char(7), int(11)> NOT NULL COMMENT "",
-            ) ENGINE=OLAP
-            DUPLICATE KEY(`k1`)
-            DISTRIBUTED BY HASH(`k1`) BUCKETS 1
-            PROPERTIES (
-            "replication_allocation" = "tag.location.default: 1",
-            "storage_format" = "V2"
-            )
-        """
-    // insert into with implicit cast
-    sql """ INSERT INTO ${tableName} VALUES(1, {"aa": 1, "b": 2, "1234567": 
77}) """
-    sql """ INSERT INTO ${tableName} VALUES(2, {"b":12, "123":7777}) """
-
-    qt_select """ select * from ${tableName} order by k1; """
-
-    qt_select " select cast({} as MAP<INT,INT>);"
-    qt_select " select cast(map() as MAP<INT,INT>); "
-    qt_sql1 "select cast(NULL as MAP<string,int>)"
-
-    // literal NONSTRICT_SUPERTYPE_OF cast
-    qt_sql2 "select cast({'':''} as MAP<String,INT>);"
-    qt_sql3 "select cast({1:2} as MAP<String,INT>);"
-
-    // select SUPERTYPE_OF cast
-    qt_sql4 "select cast(k2 as map<varchar, bigint>) from ${tableName} order 
by k1;"
-
-    // select NONSTRICT_SUPERTYPE_OF cast , this behavior is same with nested 
scala type
-    qt_sql5 "select cast(k2 as map<char(2), smallint>) from ${tableName} order 
by k1;"
-    qt_sql6 "select cast(k2 as map<char(1), tinyint>) from ${tableName} order 
by k1;"
-    qt_sql7 "select cast(k2 as map<char, string>) from ${tableName} order by 
k1;"
-    qt_sql8 "select cast(k2 as map<int, string>) from ${tableName} order by 
k1;"
-    qt_sql9 "select cast(k2 as map<largeint, decimal>) from ${tableName} order 
by k1;"
-    qt_sql10 "select cast(k2 as map<double, datetime>) from ${tableName} order 
by k1;"
-}


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

Reply via email to