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 2020/10/27 04:52:55 UTC

[incubator-doris] branch master updated: [Bug] Fix some date functions to make their result same as MySQL (#4786)

This is an automated email from the ASF dual-hosted git repository.

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git


The following commit(s) were added to refs/heads/master by this push:
     new bfdb15c  [Bug] Fix some date functions to make their result same as MySQL (#4786)
bfdb15c is described below

commit bfdb15c730443ddc7eb0487a4439c939c35c1a51
Author: Mingyu Chen <mo...@gmail.com>
AuthorDate: Tue Oct 27 12:52:44 2020 +0800

    [Bug] Fix some date functions to make their result same as MySQL (#4786)
    
    dayofweek, dayofmonth, dayofyear, weekofyear, timediff
    
    Also fix ut compilation problem
---
 be/src/exprs/timestamp_functions.cpp               |  21 +++-
 be/src/runtime/datetime_value.h                    |   6 +-
 be/test/exprs/timestamp_functions_test.cpp         | 127 +++++++++++++++++++++
 be/test/olap/cumulative_compaction_policy_test.cpp |   6 +-
 docs/en/installing/compilation.md                  |   6 +
 docs/zh-CN/installing/compilation.md               |   6 +
 .../apache/doris/analysis/FunctionCallExpr.java    |   3 +-
 7 files changed, 165 insertions(+), 10 deletions(-)

diff --git a/be/src/exprs/timestamp_functions.cpp b/be/src/exprs/timestamp_functions.cpp
index 79faee0..9c64e60 100644
--- a/be/src/exprs/timestamp_functions.cpp
+++ b/be/src/exprs/timestamp_functions.cpp
@@ -120,13 +120,17 @@ IntVal TimestampFunctions::month(
     const DateTimeValue& ts_value = DateTimeValue::from_datetime_val(ts_val);
     return IntVal(ts_value.month());
 }
+
 IntVal TimestampFunctions::day_of_week(
         FunctionContext* context, const DateTimeVal& ts_val) {
     if (ts_val.is_null) {
         return IntVal::null();
     }
     const DateTimeValue& ts_value = DateTimeValue::from_datetime_val(ts_val);
-    return IntVal((ts_value.weekday() + 1 ) % 7 + 1);
+    if (ts_value.is_valid_date()) {
+        return IntVal((ts_value.weekday() + 1 ) % 7 + 1);
+    }
+    return IntVal::null();
 }
 
 IntVal TimestampFunctions::day_of_month(
@@ -144,7 +148,10 @@ IntVal TimestampFunctions::day_of_year(
         return IntVal::null();
     }
     const DateTimeValue& ts_value = DateTimeValue::from_datetime_val(ts_val);
-    return IntVal(ts_value.day_of_year());
+    if (ts_value.is_valid_date()) {
+        return IntVal(ts_value.day_of_year());
+    }
+    return IntVal::null();
 }
 
 IntVal TimestampFunctions::week_of_year(
@@ -153,7 +160,10 @@ IntVal TimestampFunctions::week_of_year(
         return IntVal::null();
     }
     const DateTimeValue& ts_value = DateTimeValue::from_datetime_val(ts_val);
-    return IntVal(ts_value.week(mysql_week_mode(3)));
+    if (ts_value.is_valid_date()) {
+        return IntVal(ts_value.week(mysql_week_mode(3)));
+    }
+    return IntVal::null();
 }
 
 IntVal TimestampFunctions::hour(
@@ -673,7 +683,10 @@ DoubleVal TimestampFunctions::time_diff(
 
     const DateTimeValue& ts_value1 = DateTimeValue::from_datetime_val(ts_val1);
     const DateTimeValue& ts_value2 = DateTimeValue::from_datetime_val(ts_val2);
-    return DoubleVal(ts_value1.second_diff(ts_value2));
+    if (ts_value1.is_valid_date() && ts_value2.is_valid_date()) {
+        return DoubleVal(ts_value1.second_diff(ts_value2));
+    }
+    return DoubleVal::null();
 }
 
 IntVal TimestampFunctions::date_diff(
diff --git a/be/src/runtime/datetime_value.h b/be/src/runtime/datetime_value.h
index e8e80d7..37fa461 100644
--- a/be/src/runtime/datetime_value.h
+++ b/be/src/runtime/datetime_value.h
@@ -462,6 +462,10 @@ public:
 
     void set_type(int type);
 
+    bool is_valid_date() const {
+        return !check_range() && !check_date() && _month > 0 && _day > 0;
+    }
+
 private:
     // Used to make sure sizeof DateTimeValue
     friend class UnusedClass;
@@ -502,7 +506,7 @@ private:
         return _neg ? -tmp : tmp;
     }
 
-    // Check whether value of field is valid.
+    // Return true if range or date is invalid
     bool check_range() const;
     bool check_date() const;
 
diff --git a/be/test/exprs/timestamp_functions_test.cpp b/be/test/exprs/timestamp_functions_test.cpp
index 09e7637..6a43070 100644
--- a/be/test/exprs/timestamp_functions_test.cpp
+++ b/be/test/exprs/timestamp_functions_test.cpp
@@ -72,6 +72,107 @@ TEST_F(TimestampFunctionsTest, day_of_week_test) {
     tv.type = TIME_DATETIME;
 
     ASSERT_EQ(7, TimestampFunctions::day_of_week(context, tv).val);
+
+    // 2020-00-01 00:00:00
+    DateTimeValue dtv2(20200001000000);
+    dtv2.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv2;
+    dtv2.to_datetime_val(&tv2);
+    ASSERT_EQ(true, TimestampFunctions::day_of_week(context, tv2).is_null);
+
+    // 2020-01-00 00:00:00
+    DateTimeValue dtv3(20200100000000);
+    dtv3.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv3;
+    dtv3.to_datetime_val(&tv3);
+    ASSERT_EQ(true, TimestampFunctions::day_of_week(context, tv3).is_null);
+
+    delete context;
+}
+
+TEST_F(TimestampFunctionsTest, day_of_month_test) {
+    doris_udf::FunctionContext *context = new doris_udf::FunctionContext();
+
+    // 2020-00-01 00:00:00
+    DateTimeValue dtv1(20200001000000);
+    dtv1.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv1;
+    dtv1.to_datetime_val(&tv1);
+    ASSERT_EQ(false, TimestampFunctions::day_of_month(context, tv1).is_null);
+    ASSERT_EQ(1, TimestampFunctions::day_of_month(context, tv1).val);
+
+    // 2020-01-00 00:00:00
+    DateTimeValue dtv2(20200100000000);
+    dtv2.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv2;
+    dtv2.to_datetime_val(&tv2);
+    ASSERT_EQ(false, TimestampFunctions::day_of_month(context, tv2).is_null);
+    ASSERT_EQ(0, TimestampFunctions::day_of_month(context, tv2).val);
+
+    // 2020-02-29 00:00:00
+    DateTimeValue dtv3(20200229000000);
+    dtv3.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv3;
+    dtv3.to_datetime_val(&tv3);
+    ASSERT_EQ(false, TimestampFunctions::day_of_month(context, tv3).is_null);
+    ASSERT_EQ(29, TimestampFunctions::day_of_month(context, tv3).val);
+
+    delete context;
+}
+
+TEST_F(TimestampFunctionsTest, day_of_year_test) {
+    doris_udf::FunctionContext *context = new doris_udf::FunctionContext();
+
+    // 2020-00-01 00:00:00
+    DateTimeValue dtv1(20200001000000);
+    dtv1.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv1;
+    dtv1.to_datetime_val(&tv1);
+    ASSERT_EQ(true, TimestampFunctions::day_of_year(context, tv1).is_null);
+
+    // 2020-01-00 00:00:00
+    DateTimeValue dtv2(20200100000000);
+    dtv2.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv2;
+    dtv2.to_datetime_val(&tv2);
+    ASSERT_EQ(true, TimestampFunctions::day_of_year(context, tv2).is_null);
+
+    // 2020-02-29 00:00:00
+    DateTimeValue dtv3(20200229000000);
+    dtv3.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv3;
+    dtv3.to_datetime_val(&tv3);
+    ASSERT_EQ(false, TimestampFunctions::day_of_year(context, tv3).is_null);
+    ASSERT_EQ(60, TimestampFunctions::day_of_year(context, tv3).val);
+
+    delete context;
+}
+
+TEST_F(TimestampFunctionsTest, week_of_year_test) {
+    doris_udf::FunctionContext *context = new doris_udf::FunctionContext();
+
+    // 2020-00-01 00:00:00
+    DateTimeValue dtv1(20200001000000);
+    dtv1.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv1;
+    dtv1.to_datetime_val(&tv1);
+    ASSERT_EQ(true, TimestampFunctions::week_of_year(context, tv1).is_null);
+
+    // 2020-01-00 00:00:00
+    DateTimeValue dtv2(20200100000000);
+    dtv2.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv2;
+    dtv2.to_datetime_val(&tv2);
+    ASSERT_EQ(true, TimestampFunctions::week_of_year(context, tv2).is_null);
+
+    // 2020-02-29 00:00:00
+    DateTimeValue dtv3(20200229000000);
+    dtv3.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv3;
+    dtv3.to_datetime_val(&tv3);
+    ASSERT_EQ(false, TimestampFunctions::week_of_year(context, tv3).is_null);
+    ASSERT_EQ(9, TimestampFunctions::week_of_year(context, tv3).val);
+
     delete context;
 }
 
@@ -87,6 +188,32 @@ TEST_F(TimestampFunctionsTest, time_diff_test) {
     dt2.to_datetime_val(&tv2);
     
     ASSERT_EQ(-3662, TimestampFunctions::time_diff(ctx, tv1, tv2).val);
+
+    // invalid
+    DateTimeValue dt3(20190018120000);
+    dt3.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv3;
+    dt3.to_datetime_val(&tv3);
+    
+    DateTimeValue dt4(20190718130102);
+    dt4.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv4;
+    dt4.to_datetime_val(&tv4);
+    
+    ASSERT_EQ(true, TimestampFunctions::time_diff(ctx, tv3, tv4).is_null);
+
+    // invalid
+    DateTimeValue dt5(20190718120000);
+    dt5.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv5;
+    dt5.to_datetime_val(&tv5);
+    
+    DateTimeValue dt6(20190700130102);
+    dt6.set_type(TIME_DATETIME);
+    doris_udf::DateTimeVal tv6;
+    dt6.to_datetime_val(&tv6);
+    
+    ASSERT_EQ(true, TimestampFunctions::time_diff(ctx, tv5, tv6).is_null);
 }
 
 TEST_F(TimestampFunctionsTest, now) {
diff --git a/be/test/olap/cumulative_compaction_policy_test.cpp b/be/test/olap/cumulative_compaction_policy_test.cpp
index ca80100..4d5d0d1 100644
--- a/be/test/olap/cumulative_compaction_policy_test.cpp
+++ b/be/test/olap/cumulative_compaction_policy_test.cpp
@@ -1052,20 +1052,20 @@ TEST_F(TestSizeBasedCumulativeCompactionPolicy, _pick_missing_version_cumulative
     rowsets.push_back(_tablet->get_rowset_by_version({4, 4}));
     std::shared_ptr<MemTracker> mem_tracker(new MemTracker());
     CumulativeCompaction compaction(_tablet, "label", mem_tracker);
-    compaction.find_longest_consecutive_version(&rowsets);
+    compaction.find_longest_consecutive_version(&rowsets, nullptr);
     ASSERT_EQ(3, rowsets.size());
     ASSERT_EQ(2, rowsets[2]->end_version());
 
     // no miss version
     std::vector<RowsetSharedPtr> rowsets2;
     rowsets2.push_back(_tablet->get_rowset_by_version({0, 0}));
-    compaction.find_longest_consecutive_version(&rowsets2);
+    compaction.find_longest_consecutive_version(&rowsets2, nullptr);
     ASSERT_EQ(1, rowsets2.size());
     ASSERT_EQ(0, rowsets[0]->end_version());
 
     // no version
     std::vector<RowsetSharedPtr> rowsets3;
-    compaction.find_longest_consecutive_version(&rowsets3);
+    compaction.find_longest_consecutive_version(&rowsets3, nullptr);
     ASSERT_EQ(0, rowsets3.size());
 }
 }
diff --git a/docs/en/installing/compilation.md b/docs/en/installing/compilation.md
index 94bd5f9..3cb7c5a 100644
--- a/docs/en/installing/compilation.md
+++ b/docs/en/installing/compilation.md
@@ -107,6 +107,12 @@ You can try to compile Doris directly in your own Linux environment.
     $ sh build.sh
     ```
 	After compilation, the output file is in the `output/` directory.
+
+## FAQ
+
+1. `Could not transfer artifact net.sourceforge.czt.dev:cup-maven-plugin:pom:1.6-cdh from/to xxx`
+
+    If you encounter the above error, please refer to [PR #4769](https://github.com/apache/incubator-doris/pull/4769/files) to modify the cloudera-related repo configuration in `fe/pom.xml`.
 	
 ## Special statement
 
diff --git a/docs/zh-CN/installing/compilation.md b/docs/zh-CN/installing/compilation.md
index 0df6b0e..bb66839 100644
--- a/docs/zh-CN/installing/compilation.md
+++ b/docs/zh-CN/installing/compilation.md
@@ -109,6 +109,12 @@ under the License.
     
     编译完成后,产出文件在 `output/` 目录中。
 
+## 常见问题
+
+1. `Could not transfer artifact net.sourceforge.czt.dev:cup-maven-plugin:pom:1.6-cdh from/to xxx`
+
+    如遇到上述错误,请参照 [PR #4769](https://github.com/apache/incubator-doris/pull/4769/files) 修改 `fe/pom.xml` 中 cloudera 相关的仓库配置。
+
 ## 特别声明
 
 自 0.13 版本开始,默认的编译产出中将取消对 [1] 和 [2] 两个第三方库的依赖。这两个第三方库为 [GNU General Public License V3](https://www.gnu.org/licenses/gpl-3.0.en.html) 协议。该协议与 [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) 协议不兼容,因此默认不出现在 Apache 发布版本中。
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
index d43178d..074d4f7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
@@ -604,9 +604,8 @@ public class FunctionCallExpr extends Expr {
             }
         }
 
-        if (fn.getFunctionName().getFunction().equals("time_diff")) {
+        if (fn.getFunctionName().getFunction().equals("timediff")) {
             fn.getReturnType().getPrimitiveType().setTimeType();
-            return;
         }
 
         if (isAggregateFunction()) {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org