You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2023/01/31 15:39:15 UTC
[doris] 17/20: [Bug](date) Fix invalid date (#16205)
This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch branch-1.2-lts
in repository https://gitbox.apache.org/repos/asf/doris.git
commit b13500f4dbbdf276897956a1904c872745779d82
Author: Gabriel <ga...@gmail.com>
AuthorDate: Tue Jan 31 10:08:44 2023 +0800
[Bug](date) Fix invalid date (#16205)
Issue Number: close #15777
---
be/src/vec/exprs/vliteral.cpp | 28 ++++++++++------
.../org/apache/doris/analysis/DateLiteral.java | 18 +++++++++--
.../apache/doris/analysis/ExpressionFunctions.java | 13 +++++++-
.../org/apache/doris/analysis/StringLiteral.java | 5 +++
.../data/datatype_p0/date/test_invalid_date.out | 7 ++++
.../datatype_p0/date/test_invalid_date.groovy | 37 ++++++++++++++++++++++
6 files changed, 95 insertions(+), 13 deletions(-)
diff --git a/be/src/vec/exprs/vliteral.cpp b/be/src/vec/exprs/vliteral.cpp
index 27324e5c0a..f78118ab0f 100644
--- a/be/src/vec/exprs/vliteral.cpp
+++ b/be/src/vec/exprs/vliteral.cpp
@@ -93,28 +93,36 @@ void VLiteral::init(const TExprNode& node) {
}
case TYPE_DATE: {
VecDateTimeValue value;
- value.from_date_str(node.date_literal.value.c_str(), node.date_literal.value.size());
- value.cast_to_date();
- field = Int64(*reinterpret_cast<__int64_t*>(&value));
+ if (value.from_date_str(node.date_literal.value.c_str(),
+ node.date_literal.value.size())) {
+ value.cast_to_date();
+ field = Int64(*reinterpret_cast<__int64_t*>(&value));
+ }
break;
}
case TYPE_DATEV2: {
DateV2Value<DateV2ValueType> value;
- value.from_date_str(node.date_literal.value.c_str(), node.date_literal.value.size());
- field = value.to_date_int_val();
+ if (value.from_date_str(node.date_literal.value.c_str(),
+ node.date_literal.value.size())) {
+ field = value.to_date_int_val();
+ }
break;
}
case TYPE_DATETIMEV2: {
DateV2Value<DateTimeV2ValueType> value;
- value.from_date_str(node.date_literal.value.c_str(), node.date_literal.value.size());
- field = value.to_date_int_val();
+ if (value.from_date_str(node.date_literal.value.c_str(),
+ node.date_literal.value.size())) {
+ field = value.to_date_int_val();
+ }
break;
}
case TYPE_DATETIME: {
VecDateTimeValue value;
- value.from_date_str(node.date_literal.value.c_str(), node.date_literal.value.size());
- value.to_datetime();
- field = Int64(*reinterpret_cast<__int64_t*>(&value));
+ if (value.from_date_str(node.date_literal.value.c_str(),
+ node.date_literal.value.size())) {
+ value.to_datetime();
+ field = Int64(*reinterpret_cast<__int64_t*>(&value));
+ }
break;
}
case TYPE_STRING:
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java
index a87811bcfe..d7615151f1 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java
@@ -627,6 +627,13 @@ public class DateLiteral extends LiteralExpr {
}
msg.node_type = TExprNodeType.DATE_LITERAL;
msg.date_literal = new TDateLiteral(getStringValue());
+ try {
+ checkValueValid();
+ } catch (AnalysisException e) {
+ // If date value is invalid, set this to null
+ msg.node_type = TExprNodeType.NULL_LITERAL;
+ msg.setIsNullable(true);
+ }
}
@Override
@@ -775,6 +782,11 @@ public class DateLiteral extends LiteralExpr {
}
}
+ private boolean isLeapYear() {
+ return ((year % 4) == 0) && ((year % 100 != 0) || ((year % 400) == 0 && year > 0));
+ }
+
+ // Validation check should be same as DateV2Value<T>::is_invalid in BE
@Override
public void checkValueValid() throws AnalysisException {
if (year < 0 || year > 9999) {
@@ -783,8 +795,10 @@ public class DateLiteral extends LiteralExpr {
if (month < 1 || month > 12) {
throw new AnalysisException("DateLiteral has invalid month value: " + month);
}
- if (day < 1 || day > 31) {
- throw new AnalysisException("DateLiteral has invalid day value: " + day);
+ if (day < 1 || day > DAYS_IN_MONTH[(int) month]) {
+ if (!(month == 2 && day == 29 && isLeapYear())) {
+ throw new AnalysisException("DateLiteral has invalid day value: " + day);
+ }
}
if (type.isDatetimeV2() || type.isDatetime()) {
if (hour < 0 || hour > 24) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java
index 02c7b26b25..e7dae9617b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java
@@ -98,7 +98,18 @@ public enum ExpressionFunctions {
FEFunctionInvoker invoker = getFunction(signature);
if (invoker != null) {
try {
- return invoker.invoke(constExpr.getChildrenWithoutCast());
+ if (fn.getReturnType().isDateType()) {
+ Expr dateLiteral = invoker.invoke(constExpr.getChildrenWithoutCast());
+ Preconditions.checkArgument(dateLiteral instanceof DateLiteral);
+ try {
+ ((DateLiteral) dateLiteral).checkValueValid();
+ } catch (AnalysisException e) {
+ return NullLiteral.create(dateLiteral.getType());
+ }
+ return dateLiteral;
+ } else {
+ return invoker.invoke(constExpr.getChildrenWithoutCast());
+ }
} catch (AnalysisException e) {
LOG.debug("failed to invoke", e);
return constExpr;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java
index 1094ca6564..62038dec27 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java
@@ -193,6 +193,11 @@ public class StringLiteral extends LiteralExpr {
throw e;
}
}
+ try {
+ newLiteral.checkValueValid();
+ } catch (AnalysisException e) {
+ return NullLiteral.create(newLiteral.getType());
+ }
return newLiteral;
}
diff --git a/regression-test/data/datatype_p0/date/test_invalid_date.out b/regression-test/data/datatype_p0/date/test_invalid_date.out
new file mode 100644
index 0000000000..80b3c3963d
--- /dev/null
+++ b/regression-test/data/datatype_p0/date/test_invalid_date.out
@@ -0,0 +1,7 @@
+-- This file is automatically generated. You should know what you did if you want to edit this
+-- !sql1 --
+\N
+
+-- !sql2 --
+\N
+
diff --git a/regression-test/suites/datatype_p0/date/test_invalid_date.groovy b/regression-test/suites/datatype_p0/date/test_invalid_date.groovy
new file mode 100644
index 0000000000..6b683d90b6
--- /dev/null
+++ b/regression-test/suites/datatype_p0/date/test_invalid_date.groovy
@@ -0,0 +1,37 @@
+
+// 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_date") {
+ def tbName = "test_invalid_date"
+ sql "DROP TABLE IF EXISTS ${tbName}"
+ sql """
+ CREATE TABLE IF NOT EXISTS ${tbName} (
+ c0 int,
+ c1 char(10),
+ c2 date,
+ c3 datev2
+ )
+ UNIQUE KEY(c0)
+ DISTRIBUTED BY HASH(c0) BUCKETS 5 properties("replication_num" = "1");
+ """
+ sql "insert into ${tbName} values(1, 'test1', '2000-01-01', '2000-01-01')"
+
+ qt_sql1 "select str_to_date('202301', '%Y%m');"
+ qt_sql2 "select str_to_date('202301', '%Y%m') from ${tbName}"
+ sql "DROP TABLE ${tbName}"
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org