This is an automated email from the ASF dual-hosted git repository. xuyang 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 0a450d96a5 [Fix] fix `cast(array<not_null> as array<>)` causes be core dump (#11649) 0a450d96a5 is described below commit 0a450d96a529b6a746f94aa98f44f1e1f00423ef Author: xy720 <22125576+xy...@users.noreply.github.com> AuthorDate: Wed Aug 24 22:51:30 2022 +0800 [Fix] fix `cast(array<not_null> as array<>)` causes be core dump (#11649) --- .../java/org/apache/doris/analysis/CastExpr.java | 36 +++++++++------- .../array_functions/test_cast_array_function.out | 24 +++++++++++ .../test_cast_array_function.groovy | 49 ++++++++++++++++++++++ .../test_cast_array_functions_by_literal.groovy | 46 +------------------- 4 files changed, 95 insertions(+), 60 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java index 7950c04db4..cca5e50d52 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java @@ -20,6 +20,7 @@ package org.apache.doris.analysis; +import org.apache.doris.catalog.ArrayType; import org.apache.doris.catalog.Env; import org.apache.doris.catalog.Function; import org.apache.doris.catalog.FunctionSet; @@ -29,7 +30,6 @@ import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.Pair; -import org.apache.doris.common.util.VectorizedUtil; import org.apache.doris.qe.ConnectContext; import org.apache.doris.thrift.TExpr; import org.apache.doris.thrift.TExprNode; @@ -270,15 +270,28 @@ public class CastExpr extends Expr { // this cast may result in loss of precision, but the user requested it if (childType.matchesType(type)) { - // For types which has precision and scale, we also need to check quality between precisions and scales - if (!PrimitiveType.typeWithPrecision.contains( - type.getPrimitiveType()) || ((((ScalarType) type).decimalPrecision() - == ((ScalarType) childType).decimalPrecision()) && (((ScalarType) type).decimalScale() - == ((ScalarType) childType).decimalScale()))) { + if (PrimitiveType.typeWithPrecision.contains(type.getPrimitiveType())) { + // For types which has precision and scale, we also need to check quality between precisions and scales + if ((((ScalarType) type).decimalPrecision() + == ((ScalarType) childType).decimalPrecision()) && (((ScalarType) type).decimalScale() + == ((ScalarType) childType).decimalScale())) { + noOp = true; + } + } else if (type.isArrayType()) { + // For types array, we also need to check contains null for case like + // cast(array<not_null(int)> as array<int>) + if (((ArrayType) type).getContainsNull() == ((ArrayType) childType).getContainsNull()) { + noOp = true; + } + } else { noOp = true; - return; } } + + if (noOp) { + return; + } + // select stmt will make BE coredump when its castExpr is like cast(int as array<>), // it is necessary to check if it is castable before creating fn. // char type will fail in canCastTo, so for compatibility, only the cast of array type is checked here. @@ -301,17 +314,10 @@ public class CastExpr extends Expr { searchDesc, Function.CompareMode.IS_IDENTICAL); } } else if (type.isArrayType()) { - if (VectorizedUtil.isVectorized()) { - // Vec engine don't need a scala cast function, but we still create one to pass the check. - fn = ScalarFunction.createBuiltin("CAST", type, Lists.newArrayList(), false, - "", null, null, true); - } else if (childType.isVarchar()) { - // only support varchar cast to array for origin exec engine. - fn = ScalarFunction.createBuiltin(getFnName(Type.ARRAY), + fn = ScalarFunction.createBuiltin(getFnName(Type.ARRAY), type, Function.NullableMode.ALWAYS_NULLABLE, Lists.newArrayList(Type.VARCHAR), false, "doris::CastFunctions::cast_to_array_val", null, null, true); - } } if (fn == null) { diff --git a/regression-test/data/query_p0/sql_functions/array_functions/test_cast_array_function.out b/regression-test/data/query_p0/sql_functions/array_functions/test_cast_array_function.out new file mode 100644 index 0000000000..7c3874ea69 --- /dev/null +++ b/regression-test/data/query_p0/sql_functions/array_functions/test_cast_array_function.out @@ -0,0 +1,24 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !select -- +1 [1, 2, 3] ['a', 'b', ''] +2 [4] ['1', '2', '3'] +3 [10000] ['2022-08-10', '2022-08-11'] +4 [] [] + +-- !select -- +1 ['1', '2', '3'] [NULL, NULL, NULL] +2 ['4'] [1, 2, 3] +3 ['10000'] [NULL, NULL] +4 [] [] + +-- !select -- +1 [1.3, 2.14] [1.3, 2.14] +2 [5] [5] +3 [1] [1] +4 \N \N + +-- !select -- +1 [1, 2, 3] [NULL, NULL, NULL] +2 [4] [NULL, NULL, NULL] +3 [16] [2022-08-10, 2022-08-11] +4 [] [] diff --git a/regression-test/suites/query_p0/sql_functions/array_functions/test_cast_array_function.groovy b/regression-test/suites/query_p0/sql_functions/array_functions/test_cast_array_function.groovy new file mode 100644 index 0000000000..94b8a9ea1b --- /dev/null +++ b/regression-test/suites/query_p0/sql_functions/array_functions/test_cast_array_function.groovy @@ -0,0 +1,49 @@ +// 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_array_function", "query") { + def tableName = "tbl_test_cast_array_function" + // open enable_array_type + sql "ADMIN SET FRONTEND CONFIG ('enable_array_type' = 'true')" + // array functions only supported in vectorized engine + sql """ set enable_vectorized_engine = true """ + + sql """DROP TABLE IF EXISTS ${tableName}""" + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + `k1` int(11) NULL COMMENT "", + `k2` ARRAY<int(11)> NOT NULL COMMENT "", + `k3` ARRAY<VARCHAR(20)> NULL COMMENT "", + `k4` ARRAY<decimal(27,9)> NULL COMMENT "" + ) ENGINE=OLAP + DUPLICATE KEY(`k1`) + DISTRIBUTED BY HASH(`k1`) BUCKETS 1 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1", + "storage_format" = "V2" + ) + """ + sql """ INSERT INTO ${tableName} VALUES(1, [1, 2, 3], ["a", "b", ""], [1.3, 2.14]) """ + sql """ INSERT INTO ${tableName} VALUES(2, [4], ["1", "2", "3"], [5]) """ + sql """ INSERT INTO ${tableName} VALUES(3, [10000], ["2022-08-10", "2022-08-11"], [1]) """ + sql """ INSERT INTO ${tableName} VALUES(4, [], [], NULL) """ + + qt_select "SELECT k1, cast(k2 as array<int>), cast(k3 as array<varchar>)FROM ${tableName} ORDER BY k1" + qt_select "SELECT k1, cast(k2 as array<varchar>), cast(k3 as array<int>) FROM ${tableName} ORDER BY k1" + qt_select "SELECT k1, cast(k4 as array<float>), cast(k4 as array<double>) FROM ${tableName} ORDER BY k1" + qt_select "SELECT k1, cast(k2 as array<tinyint>), cast(k3 as array<date>) FROM ${tableName} ORDER BY k1" +} diff --git a/regression-test/suites/query_p0/sql_functions/array_functions/test_cast_array_functions_by_literal.groovy b/regression-test/suites/query_p0/sql_functions/array_functions/test_cast_array_functions_by_literal.groovy index cc00a56b76..349560a5aa 100644 --- a/regression-test/suites/query_p0/sql_functions/array_functions/test_cast_array_functions_by_literal.groovy +++ b/regression-test/suites/query_p0/sql_functions/array_functions/test_cast_array_functions_by_literal.groovy @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -suite("test_cast_array_functions") { +suite("test_cast_array_functions_by_literal") { // open enable_array_type sql "ADMIN SET FRONTEND CONFIG ('enable_array_type' = 'true')" // array functions only supported in vectorized engine @@ -190,48 +190,4 @@ suite("test_cast_array_functions") { // check exception message contains exception "errCode = 2," } - - // ========== cast array to array =========== - test { - sql "select cast(['x'] as array<int>)" - // check exception message contains - exception "errCode = 2," - } - - test { - sql "select cast([0] as array<int>)" - // check exception message contains - exception "errCode = 2," - } - - test { - sql "select cast(['1'] as array<tinyint>)" - // check exception message contains - exception "errCode = 2," - } - - test { - sql "select cast(['100'] as array<smallint>)" - // check exception message contains - exception "errCode = 2," - } - - test { - sql "select cast([999.999] as array<double>)" - // check exception message contains - exception "errCode = 2," - } - - test { - sql "select cast([1] as array<char>)" - // check exception message contains - exception "errCode = 2," - } - - test { - sql "select cast([1] as array<varchar>)" - // check exception message contains - exception "errCode = 2," - } - } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org