This is an automated email from the ASF dual-hosted git repository. yiguolei 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 11f32d9ebd3 [fix](datetime) fix hour 24 on be (#31304) (#31393) 11f32d9ebd3 is described below commit 11f32d9ebd3c7c9c50e2f7c5c0f6bd53a0cec4e9 Author: zhiqiang <seuhezhiqi...@163.com> AuthorDate: Mon Feb 26 16:43:42 2024 +0800 [fix](datetime) fix hour 24 on be (#31304) (#31393) --- be/src/vec/runtime/vdatetime_value.cpp | 2 +- .../expression/rules/DateFunctionRewrite.java | 9 +- .../trees/expressions/literal/DateV2Literal.java | 31 ++++++- .../datatype_p0/datetimev2/test_curdate_fold.out | 57 ++++++++++++ .../datatype_p0/datetimev2/test_invalid_hour.out | 14 +++ .../datetimev2/test_curdate_fold.groovy | 102 +++++++++++++++++++++ .../datetimev2/test_invalid_hour.groovy | 89 ++++++++++++++++++ 7 files changed, 297 insertions(+), 7 deletions(-) diff --git a/be/src/vec/runtime/vdatetime_value.cpp b/be/src/vec/runtime/vdatetime_value.cpp index 35abba4d004..04f374a5ec4 100644 --- a/be/src/vec/runtime/vdatetime_value.cpp +++ b/be/src/vec/runtime/vdatetime_value.cpp @@ -1921,7 +1921,7 @@ template <typename T> bool DateV2Value<T>::is_invalid(uint32_t year, uint32_t month, uint32_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t microsecond, bool only_time_part) { - if (hour > 24 || minute >= 60 || second >= 60 || microsecond > 999999) { + if (hour >= 24 || minute >= 60 || second >= 60 || microsecond > 999999) { return true; } if (only_time_part) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java index 09f9b311f49..e80022b0ba9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/DateFunctionRewrite.java @@ -58,8 +58,10 @@ public class DateFunctionRewrite extends AbstractExpressionRewriteRule { // V2 if (equalTo.left().child(0).getDataType() instanceof DateTimeV2Type && equalTo.right() instanceof DateV2Literal) { - DateTimeV2Literal lowerBound = ((DateV2Literal) equalTo.right()).toBeginOfTheDay(); - DateTimeV2Literal upperBound = ((DateV2Literal) equalTo.right()).toEndOfTheDay(); + DateTimeV2Literal lowerBound = ((DateV2Literal) equalTo.right()).toBeginOfTheDay( + (DateTimeV2Type) equalTo.left().child(0).getDataType()); + DateTimeV2Literal upperBound = ((DateV2Literal) equalTo.right()).toEndOfTheDay( + (DateTimeV2Type) equalTo.left().child(0).getDataType()); Expression newLeft = equalTo.left().child(0); return new And(new GreaterThanEqual(newLeft, lowerBound), new LessThanEqual(newLeft, upperBound)); @@ -142,7 +144,8 @@ public class DateFunctionRewrite extends AbstractExpressionRewriteRule { // V2 if (lessThanEqual.left().child(0).getDataType() instanceof DateTimeV2Type && lessThanEqual.right() instanceof DateV2Literal) { - DateTimeV2Literal newLiteral = ((DateV2Literal) lessThanEqual.right()).toEndOfTheDay(); + DateTimeV2Literal newLiteral = ((DateV2Literal) lessThanEqual.right()).toEndOfTheDay( + (DateTimeV2Type) lessThanEqual.left().child(0).getDataType()); return new LessThanEqual(lessThanEqual.left().child(0), newLiteral); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java index 9a25a5241c9..f522265f161 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateV2Literal.java @@ -22,6 +22,7 @@ import org.apache.doris.catalog.Type; import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; import org.apache.doris.nereids.types.DateV2Type; import org.apache.doris.nereids.util.DateUtils; import org.apache.doris.nereids.util.StandardDateFormat; @@ -78,18 +79,42 @@ public class DateV2Literal extends DateLiteral { /** * 2020-01-01 - * @return 2020-01-01 24:00:00 + * @return 2020-01-01 00:00:00 */ public DateTimeV2Literal toBeginOfTheDay() { - return new DateTimeV2Literal(year, month, day, 0, 0, 0); + return toBeginOfTheDay(DateTimeV2Type.SYSTEM_DEFAULT); } /** * 2020-01-01 * @return 2020-01-01 00:00:00 */ + public DateTimeV2Literal toBeginOfTheDay(DateTimeV2Type dateType) { + return new DateTimeV2Literal(dateType, year, month, day, 0, 0, 0, 000000); + } + + /** + * 2020-01-01 + * @return 2020-01-01 23:59:59 + */ public DateTimeV2Literal toEndOfTheDay() { - return new DateTimeV2Literal(year, month, day, 24, 0, 0); + return toEndOfTheDay(DateTimeV2Type.SYSTEM_DEFAULT); + } + + /** + * 2020-01-01 + * @return 2020-01-01 23:59:59.9[scale] + */ + public DateTimeV2Literal toEndOfTheDay(DateTimeV2Type dateType) { + long microSecond = 0; + // eg. scale == 4 -> 999900 + for (int i = 0; i < 6; ++i) { + microSecond *= 10; + if (i < dateType.getScale()) { + microSecond += 9; + } + } + return new DateTimeV2Literal(dateType, year, month, day, 23, 59, 59, microSecond); } /** diff --git a/regression-test/data/datatype_p0/datetimev2/test_curdate_fold.out b/regression-test/data/datatype_p0/datetimev2/test_curdate_fold.out new file mode 100644 index 00000000000..d9ef4ab6de0 --- /dev/null +++ b/regression-test/data/datatype_p0/datetimev2/test_curdate_fold.out @@ -0,0 +1,57 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !sql0 -- +0 +1 + +-- !sql1 -- +0 +1 + +-- !sql2 -- +0 +1 + +-- !sql3 -- +0 +1 + +-- !sql4 -- +0 +1 + +-- !sql5 -- +0 +1 + +-- !sql6 -- +0 +1 + +-- !sql7 -- +0 +1 + +-- !sql8 -- +0 +1 + +-- !sql9 -- +0 +1 + +-- !sql10 -- +0 +1 + +-- !sql11 -- +0 +1 + +-- !sql12 -- +0 +1 + +-- !sql13 -- +0 +1 + diff --git a/regression-test/data/datatype_p0/datetimev2/test_invalid_hour.out b/regression-test/data/datatype_p0/datetimev2/test_invalid_hour.out new file mode 100644 index 00000000000..6a036dfeef2 --- /dev/null +++ b/regression-test/data/datatype_p0/datetimev2/test_invalid_hour.out @@ -0,0 +1,14 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !sql -- +\N + +-- !sql -- +\N + +-- !sql -- +1 2023-12-12 24:00:00 \N \N +2 2023-12-12 23:00:00 2023-12-12T23:00 2023-12-12T23:00 + +-- !sql -- +1 2023-12-12 23:00:00 2023-12-12T23:00 2023-12-12T23:00 + diff --git a/regression-test/suites/datatype_p0/datetimev2/test_curdate_fold.groovy b/regression-test/suites/datatype_p0/datetimev2/test_curdate_fold.groovy new file mode 100644 index 00000000000..d95c854d35c --- /dev/null +++ b/regression-test/suites/datatype_p0/datetimev2/test_curdate_fold.groovy @@ -0,0 +1,102 @@ + +// 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_curdate_fold") { + def tbName = "test_curdate_fold" + + sql "DROP TABLE IF EXISTS test_curdate_fold" + sql """ + CREATE TABLE IF NOT EXISTS test_curdate_fold ( + `rowid` int, + `dt0` datetime, + `dt1` datetime(1), + `dt2` datetime(2), + `dt3` datetime(3), + `dt4` datetime(4), + `dt5` datetime(5), + `dt6` datetime(6) + ) + UNIQUE KEY(`rowid`) + DISTRIBUTED BY HASH(`rowid`) BUCKETS 5 properties("replication_num" = "1"); + """ + sql """ + INSERT INTO test_curdate_fold (rowid, dt0, dt1, dt2, dt3, dt4, dt5, dt6) + SELECT 0, + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "23:59:59"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "23:59:59.9"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "23:59:59.99"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "23:59:59.999"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "23:59:59.9999"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "23:59:59.99999"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "23:59:59.999999"); + """ + sql """ + INSERT INTO test_curdate_fold (rowid, dt0, dt1, dt2, dt3, dt4, dt5, dt6) + SELECT 1, + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "00:00:00"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "00:00:00.0"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "00:00:00.00"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "00:00:00.000"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "00:00:00.0000"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "00:00:00.00000"), + CONCAT(CAST(DATE(CURRENT_TIMESTAMP()) AS STRING), " ", "00:00:00.000000"); + """ + + qt_sql0 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt0) <= curDate() ORDER BY rowid; + """ + qt_sql1 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt1) <= curDate() ORDER BY rowid; + """ + qt_sql2 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt2) <= curDate() ORDER BY rowid; + """ + qt_sql3 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt3) <= curDate() ORDER BY rowid; + """ + qt_sql4 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt4) <= curDate() ORDER BY rowid; + """ + qt_sql5 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt5) <= curDate() ORDER BY rowid; + """ + qt_sql6 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt6) <= curDate() ORDER BY rowid; + """ + qt_sql7 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt0) = curDate() ORDER BY rowid; + """ + qt_sql8 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt1) = curDate() ORDER BY rowid; + """ + qt_sql9 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt2) = curDate() ORDER BY rowid; + """ + qt_sql10 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt3) = curDate() ORDER BY rowid; + """ + qt_sql11 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt4) = curDate() ORDER BY rowid; + """ + qt_sql12 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt5) = curDate() ORDER BY rowid; + """ + qt_sql13 """ + SELECT rowid FROM test_curdate_fold WHERE Date(dt6) = curDate() ORDER BY rowid; + """ +} diff --git a/regression-test/suites/datatype_p0/datetimev2/test_invalid_hour.groovy b/regression-test/suites/datatype_p0/datetimev2/test_invalid_hour.groovy new file mode 100644 index 00000000000..e72f0dc6cba --- /dev/null +++ b/regression-test/suites/datatype_p0/datetimev2/test_invalid_hour.groovy @@ -0,0 +1,89 @@ +// 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_invalid_hour") { + qt_sql """ + select cast("2024-02-02 24:23:12" as DateTime); + """ + qt_sql """ + select cast(concat("2024-02-02", ' ', "24:23:12") as DateTime); + """ + sql "drop table if exists test_invalid_hour_null" + sql "drop table if exists test_invalid_hour_not_null" + sql """ + create table test_invalid_hour_null ( + `rowid` int, + `str` varchar, + `dt` datetime null + ) ENGINE=OLAP + UNIQUE KEY(`rowid`) + COMMENT "OLAP" + DISTRIBUTED BY HASH(`rowid`) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1", + "colocate_with" = "lineitem_orders", + "enable_unique_key_merge_on_write" = "true" + ); + """ + + sql """ + create table test_invalid_hour_not_null ( + `rowid` int, + `str` varchar, + `dt` datetime not null + ) ENGINE=OLAP + UNIQUE KEY(`rowid`) + COMMENT "OLAP" + DISTRIBUTED BY HASH(`rowid`) BUCKETS 3 + PROPERTIES ( + "replication_num" = "1", + "colocate_with" = "lineitem_orders", + "enable_unique_key_merge_on_write" = "true" + ); + """ + + sql """ + insert into test_invalid_hour_null values + (1, "2023-12-12 24:00:00", "2023-12-12 24:00:00"), + (2, "2023-12-12 23:00:00", "2023-12-12 23:00:00") + """ + + sql """ + insert into test_invalid_hour_not_null values + (1, "2023-12-12 23:00:00", "2023-12-12 23:00:00") + """ + + try { + sql """ set enable_insert_strict = true; """ + + sql """ + insert into test_invalid_hour_not_null values + (2, "2023-12-12 24:00:00", "2023-12-12 24:00:00") + """ + } catch (Exception e) { + logger.info("exception: " + e) + assertTrue(e.toString().contains("Insert has filtered data in strict mode")) + } + + qt_sql """ + select *, cast(str as Datetime) from test_invalid_hour_null order by rowid; + """ + + qt_sql """ + select *, cast(str as Datetime) from test_invalid_hour_not_null order by rowid; + """ +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org