This is an automated email from the ASF dual-hosted git repository.
lijibing 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 feaf0e27dcc [fix](cast)Check cast overflow for complex type cast.
(#55434)
feaf0e27dcc is described below
commit feaf0e27dcc9e6fdc5a5e1ad43037796289c8549
Author: James <[email protected]>
AuthorDate: Fri Sep 12 10:58:09 2025 +0800
[fix](cast)Check cast overflow for complex type cast. (#55434)
Check cast overflow for complex type cast. Before, only checked
PrimitiveType overflow.
---
.../trees/expressions/literal/ArrayLiteral.java | 2 +-
.../nereids/trees/expressions/literal/Literal.java | 23 ++++++----
.../trees/expressions/literal/MapLiteral.java | 4 +-
.../trees/expressions/literal/StructLiteral.java | 2 +-
.../expressions/literal/IntegerLiteralTest.java | 22 ++++++++-
.../expressions/literal/LargeIntLiteralTest.java | 50 +++++++++++++++++++++
.../nested_types/query/sql/nested_with_join.out | Bin 1020 -> 1024 bytes
.../outfile/csv/test_outfile_csv_map_type.out | Bin 13169 -> 13059 bytes
.../parquet/test_outfile_parquet_map_type.out | Bin 12974 -> 12302 bytes
.../data/export_p0/test_outfile_orc_map_type.out | Bin 13416 -> 13292 bytes
.../nereids_function_p0/scalar_function/Array1.out | Bin 34349519 -> 34343181
bytes
regression-test/data/query_p0/cast/test_cast.out | Bin 1214 -> 1412 bytes
.../parquet/test_outfile_parquet_map_type.groovy | 19 ++++----
.../suites/query_p0/cast/test_cast.groovy | 20 +++++++++
14 files changed, 118 insertions(+), 24 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ArrayLiteral.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ArrayLiteral.java
index 85af76061e0..57c4bba82e6 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ArrayLiteral.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/ArrayLiteral.java
@@ -110,7 +110,7 @@ public class ArrayLiteral extends Literal implements
ComparableLiteral {
} else if (targetType instanceof ArrayType) {
// we should pass dataType to constructor because arguments maybe
empty
return new ArrayLiteral(items.stream()
- .map(i -> i.uncheckedCastWithFallback(((ArrayType)
targetType).getItemType()))
+ .map(i -> i.checkedCastWithFallback(((ArrayType)
targetType).getItemType()))
.map(Literal.class::cast)
.collect(ImmutableList.toImmutableList()), targetType);
} else {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
index 81882c4d120..cacccf343e1 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
@@ -48,6 +48,7 @@ import org.apache.doris.nereids.types.TimeV2Type;
import org.apache.doris.nereids.types.TinyIntType;
import org.apache.doris.nereids.types.VarcharType;
import org.apache.doris.nereids.types.coercion.IntegralType;
+import org.apache.doris.qe.SessionVariable;
import com.google.common.collect.ImmutableList;
import org.apache.log4j.Logger;
@@ -312,27 +313,31 @@ public abstract class Literal extends Expression
implements LeafExpression {
throw new AnalysisException("cannot cast " + desc + " from type " +
this.dataType + " to type " + targetType);
}
+ /**
+ * Fall back to old cast logic when new cast not covered yet.
+ */
public Expression checkedCastWithFallback(DataType targetType) {
try {
return checkedCastTo(targetType);
- } catch (Exception e) {
+ } catch (CastException c) {
+ if (SessionVariable.enableStrictCast()) {
+ throw c;
+ } else {
+ return new NullLiteral(dataType);
+ }
+ } catch (Throwable t) {
return deprecatingCheckedCastTo(targetType);
}
}
- public Expression uncheckedCastWithFallback(DataType targetType) {
- try {
- return uncheckedCastTo(targetType);
- } catch (Exception e) {
- return deprecatingUncheckedCastTo(targetType);
- }
- }
-
/**
* literal expr compare.
*/
@Override
public Expression checkedCastTo(DataType targetType) throws
AnalysisException {
+ if (this instanceof NullLiteral) {
+ return new NullLiteral(targetType);
+ }
if (getDataType().isNumericType()) {
String desc = getStringValue();
if (numericOverflow(desc, targetType)) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MapLiteral.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MapLiteral.java
index d408cf22803..f82df3ad42d 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MapLiteral.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MapLiteral.java
@@ -72,10 +72,10 @@ public class MapLiteral extends Literal {
return new MapLiteral(
map.entrySet().stream()
.collect(ImmutableMap.toImmutableMap(
- entry -> (Literal)
entry.getKey().uncheckedCastWithFallback(((MapType) targetType)
+ entry -> (Literal)
entry.getKey().checkedCastWithFallback(((MapType) targetType)
.getKeyType()),
entry -> (Literal) entry.getValue()
-
.uncheckedCastWithFallback(((MapType) targetType).getValueType())
+
.checkedCastWithFallback(((MapType) targetType).getValueType())
)),
targetType
);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StructLiteral.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StructLiteral.java
index c9d844b280a..2fb1f4c753d 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StructLiteral.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StructLiteral.java
@@ -79,7 +79,7 @@ public class StructLiteral extends Literal {
ImmutableList.Builder<Literal> newLiterals =
ImmutableList.builder();
for (int i = 0; i < fields.size(); i++) {
newLiterals.add((Literal) fields.get(i)
- .uncheckedCastWithFallback(((StructType)
targetType).getFields().get(i).getDataType()));
+ .checkedCastWithFallback(((StructType)
targetType).getFields().get(i).getDataType()));
}
return new StructLiteral(newLiterals.build(), targetType);
} else {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java
index 3f42bae214b..177070da71c 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/IntegerLiteralTest.java
@@ -17,6 +17,7 @@
package org.apache.doris.nereids.trees.expressions.literal;
+import org.apache.doris.nereids.exceptions.CastException;
import org.apache.doris.nereids.trees.expressions.Expression;
import
org.apache.doris.nereids.trees.expressions.literal.format.IntegerChecker;
import org.apache.doris.nereids.types.BooleanType;
@@ -24,6 +25,8 @@ import org.apache.doris.nereids.types.DateTimeV2Type;
import org.apache.doris.nereids.types.DateType;
import org.apache.doris.nereids.types.DoubleType;
import org.apache.doris.nereids.types.FloatType;
+import org.apache.doris.nereids.types.SmallIntType;
+import org.apache.doris.nereids.types.TinyIntType;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -78,8 +81,25 @@ public class IntegerLiteralTest {
d1 = new IntegerLiteral(-3);
Assertions.assertTrue(((BooleanLiteral)
d1.uncheckedCastTo(BooleanType.INSTANCE)).getValue());
+ // To integer like
+ d1 = new IntegerLiteral(127);
+ Expression expression = d1.uncheckedCastTo(TinyIntType.INSTANCE);
+ Assertions.assertInstanceOf(TinyIntLiteral.class, expression);
+ Assertions.assertEquals(127, (int) ((TinyIntLiteral)
expression).getValue());
+ d1 = new IntegerLiteral(128);
+ IntegerLiteral finalD = d1;
+ Assertions.assertThrows(CastException.class, () ->
finalD.checkedCastTo(TinyIntType.INSTANCE));
+ d1 = new IntegerLiteral(32767);
+ expression = d1.uncheckedCastTo(SmallIntType.INSTANCE);
+ Assertions.assertInstanceOf(SmallIntLiteral.class, expression);
+ Assertions.assertEquals(32767, (int) ((SmallIntLiteral)
expression).getValue());
+ d1 = new IntegerLiteral(32768);
+ IntegerLiteral finalD1 = d1;
+ Assertions.assertThrows(CastException.class, () ->
finalD1.checkedCastTo(SmallIntType.INSTANCE));
+
// To float
- Expression expression = d1.uncheckedCastTo(FloatType.INSTANCE);
+ d1 = new IntegerLiteral(-3);
+ expression = d1.uncheckedCastTo(FloatType.INSTANCE);
Assertions.assertInstanceOf(FloatLiteral.class, expression);
Assertions.assertEquals((float) -3, ((FloatLiteral)
expression).getValue());
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/LargeIntLiteralTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/LargeIntLiteralTest.java
new file mode 100644
index 00000000000..17d9cedcc51
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/LargeIntLiteralTest.java
@@ -0,0 +1,50 @@
+// 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.nereids.trees.expressions.literal;
+
+import org.apache.doris.nereids.exceptions.CastException;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.types.BigIntType;
+import org.apache.doris.nereids.types.TinyIntType;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigInteger;
+
+public class LargeIntLiteralTest {
+ @Test
+ void testUncheckedCastTo() {
+ // To integer like
+ LargeIntLiteral d1 = new LargeIntLiteral(new BigInteger("127"));
+ Expression expression = d1.uncheckedCastTo(TinyIntType.INSTANCE);
+ Assertions.assertInstanceOf(TinyIntLiteral.class, expression);
+ Assertions.assertEquals(127, (int) ((TinyIntLiteral)
expression).getValue());
+ d1 = new LargeIntLiteral(new BigInteger("128"));
+ LargeIntLiteral finalD = d1;
+ Assertions.assertThrows(CastException.class, () ->
finalD.checkedCastTo(TinyIntType.INSTANCE));
+
+ d1 = new LargeIntLiteral(new BigInteger("9223372036854775807"));
+ expression = d1.uncheckedCastTo(BigIntType.INSTANCE);
+ Assertions.assertInstanceOf(BigIntLiteral.class, expression);
+ Assertions.assertEquals(9223372036854775807L, (long) ((BigIntLiteral)
expression).getValue());
+ d1 = new LargeIntLiteral(new BigInteger("9223372036854775808"));
+ LargeIntLiteral finalD1 = d1;
+ Assertions.assertThrows(CastException.class, () ->
finalD1.checkedCastTo(BigIntType.INSTANCE));
+ }
+}
diff --git
a/regression-test/data/datatype_p0/nested_types/query/sql/nested_with_join.out
b/regression-test/data/datatype_p0/nested_types/query/sql/nested_with_join.out
index 8487429c301..4ec79a3b898 100644
Binary files
a/regression-test/data/datatype_p0/nested_types/query/sql/nested_with_join.out
and
b/regression-test/data/datatype_p0/nested_types/query/sql/nested_with_join.out
differ
diff --git
a/regression-test/data/export_p0/outfile/csv/test_outfile_csv_map_type.out
b/regression-test/data/export_p0/outfile/csv/test_outfile_csv_map_type.out
index 28f5e9799b5..0884b649f97 100644
Binary files
a/regression-test/data/export_p0/outfile/csv/test_outfile_csv_map_type.out and
b/regression-test/data/export_p0/outfile/csv/test_outfile_csv_map_type.out
differ
diff --git
a/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_map_type.out
b/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_map_type.out
index 86b0395afd0..f210bf62460 100644
Binary files
a/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_map_type.out
and
b/regression-test/data/export_p0/outfile/parquet/test_outfile_parquet_map_type.out
differ
diff --git a/regression-test/data/export_p0/test_outfile_orc_map_type.out
b/regression-test/data/export_p0/test_outfile_orc_map_type.out
index e6fe430dc97..8be209ffa6b 100644
Binary files a/regression-test/data/export_p0/test_outfile_orc_map_type.out and
b/regression-test/data/export_p0/test_outfile_orc_map_type.out differ
diff --git
a/regression-test/data/nereids_function_p0/scalar_function/Array1.out
b/regression-test/data/nereids_function_p0/scalar_function/Array1.out
index 6ac01b39ef3..e45d8616bee 100644
Binary files
a/regression-test/data/nereids_function_p0/scalar_function/Array1.out and
b/regression-test/data/nereids_function_p0/scalar_function/Array1.out differ
diff --git a/regression-test/data/query_p0/cast/test_cast.out
b/regression-test/data/query_p0/cast/test_cast.out
index c6d84582b2a..1d6ebd63cb8 100644
Binary files a/regression-test/data/query_p0/cast/test_cast.out and
b/regression-test/data/query_p0/cast/test_cast.out differ
diff --git
a/regression-test/suites/export_p0/outfile/parquet/test_outfile_parquet_map_type.groovy
b/regression-test/suites/export_p0/outfile/parquet/test_outfile_parquet_map_type.groovy
index 31592967e2b..dd48a8a2c88 100644
---
a/regression-test/suites/export_p0/outfile/parquet/test_outfile_parquet_map_type.groovy
+++
b/regression-test/suites/export_p0/outfile/parquet/test_outfile_parquet_map_type.groovy
@@ -385,16 +385,15 @@ suite("test_outfile_parquet_map_type", "p0") {
// test base data
qt_select_base10 """ SELECT * FROM ${export_table_name} t ORDER BY
user_id; """
- def outfile_url = outfile_to_S3()
-
- qt_select_load10 """ SELECT * FROM S3 (
- "uri" =
"http://${bucket}.${s3_endpoint}${outfile_url.substring(5 + bucket.length(),
outfile_url.length() - 1)}0.parquet",
- "ACCESS_KEY"= "${ak}",
- "SECRET_KEY" = "${sk}",
- "format" = "parquet",
- "region" = "${region}"
- );
- """
+// def outfile_url = outfile_to_S3()
+// qt_select_load10 """ SELECT * FROM S3 (
+// "uri" =
"http://${bucket}.${s3_endpoint}${outfile_url.substring(5 + bucket.length(),
outfile_url.length() - 1)}0.parquet",
+// "ACCESS_KEY"= "${ak}",
+// "SECRET_KEY" = "${sk}",
+// "format" = "parquet",
+// "region" = "${region}"
+// );
+// """
} finally {
}
diff --git a/regression-test/suites/query_p0/cast/test_cast.groovy
b/regression-test/suites/query_p0/cast/test_cast.groovy
index 2f3d72b7cac..af166a2e58e 100644
--- a/regression-test/suites/query_p0/cast/test_cast.groovy
+++ b/regression-test/suites/query_p0/cast/test_cast.groovy
@@ -222,4 +222,24 @@ suite('test_cast', "arrow_flight_sql") {
cast(cast(170141183460469231731687303715884105728.0 as float) as
largeint) v1, cast(cast(170141183460469231731687303715884105727.0 as float) as
largeint) v2,
cast(cast(-170141183460469231731687303715884105728.0 as float) as
largeint) v3, cast(cast(-170141183460469231731687303715884105729.0 as float) as
largeint) v4;
"""
+
+ qt_int_array_to_smallint_array """
+ select cast([32768, 1, 7777777] as array<smallint>);
+ """
+
+ qt_int_array_to_decimal_array2 """
+ select cast([32768, 1, 7777777] as array<decimal(6, 1)>);
+ """
+
+ qt_map_to_map1 """
+ select cast(map(1, 10) as map<int, int>);
+ """
+
+ qt_map_to_map2 """
+ select cast(map(123456789011, 10) as map<int, int>);
+ """
+
+ qt_map_to_map3 """
+ select cast(map(123456789011, 123456789011) as map<int, int>);
+ """
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]