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