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
The following commit(s) were added to refs/heads/branch-1.2-lts by this push:
new eb22e5e8d7 Fixed datetime-diff overflow bug. (#17141)
eb22e5e8d7 is described below
commit eb22e5e8d73728670aea699e1be56f9ac3e37639
Author: ZhaoChangle <[email protected]>
AuthorDate: Sun Feb 26 21:25:07 2023 +0800
Fixed datetime-diff overflow bug. (#17141)
cherry-pick #16935
---
.../function_date_or_datetime_computation.h | 8 +++-
be/src/vec/runtime/vdatetime_value.cpp | 12 +----
be/src/vec/runtime/vdatetime_value.h | 55 ++++++++++------------
.../datetime_functions/test_time_diff.out | 19 ++++++++
.../datetime_functions/test_time_diff.groovy | 25 ++++++++++
5 files changed, 78 insertions(+), 41 deletions(-)
diff --git a/be/src/vec/functions/function_date_or_datetime_computation.h
b/be/src/vec/functions/function_date_or_datetime_computation.h
index d98f47248e..c60263f758 100644
--- a/be/src/vec/functions/function_date_or_datetime_computation.h
+++ b/be/src/vec/functions/function_date_or_datetime_computation.h
@@ -17,6 +17,8 @@
#pragma once
+#include <cstdint>
+
#include "common/logging.h"
#include "fmt/format.h"
#include "runtime/datetime_value.h"
@@ -238,7 +240,8 @@ struct SubtractYearsImpl :
SubtractIntervalImpl<AddYearsImpl<DateType>, DateType
using ReturnType = RETURN_TYPE;
\
static constexpr auto name = #FN_NAME;
\
static constexpr auto is_nullable = false;
\
- static inline Int32 execute(const ArgType1& t0, const ArgType2& t1,
bool& is_null) { \
+ static inline ReturnType::FieldType execute(const ArgType1& t0, const
ArgType2& t1, \
+ bool& is_null) {
\
const auto& ts0 = reinterpret_cast<const DateValueType1&>(t0);
\
const auto& ts1 = reinterpret_cast<const DateValueType2&>(t1);
\
is_null = !ts0.is_valid_date() || !ts1.is_valid_date();
\
@@ -275,7 +278,8 @@ TIME_DIFF_FUNCTION_IMPL(SecondsDiffImpl, seconds_diff,
SECOND);
using ReturnType = DataTypeInt32;
\
static constexpr auto name = #NAME;
\
static constexpr auto is_nullable = false;
\
- static inline int64_t execute(const ArgType& t0, const Int32 mode,
bool& is_null) { \
+ static inline ReturnType::FieldType execute(const ArgType& t0, const
Int32 mode, \
+ bool& is_null) {
\
const auto& ts0 = reinterpret_cast<const DateValueType&>(t0);
\
is_null = !ts0.is_valid_date();
\
return ts0.FUNCTION;
\
diff --git a/be/src/vec/runtime/vdatetime_value.cpp
b/be/src/vec/runtime/vdatetime_value.cpp
index 378ed79556..d5086ab6b0 100644
--- a/be/src/vec/runtime/vdatetime_value.cpp
+++ b/be/src/vec/runtime/vdatetime_value.cpp
@@ -1529,14 +1529,6 @@ bool VecDateTimeValue::from_date_format_str(const char*
format, int format_len,
return check_range_and_set_time(year, month, day, hour, minute, second,
_type);
}
-template <typename T>
-int64_t VecDateTimeValue::second_diff(const DateV2Value<T>& rhs) const {
- int day_diff = daynr() - rhs.daynr();
- int time_diff = (hour() * 3600 + minute() * 60 + second()) -
- (rhs.hour() * 3600 + rhs.minute() * 60 + rhs.second());
- return day_diff * 3600 * 24 + time_diff;
-}
-
template <TimeUnit unit>
bool VecDateTimeValue::date_add_interval(const TimeInterval& interval) {
if (!is_valid_date()) return false;
@@ -3346,9 +3338,9 @@ template void
VecDateTimeValue::create_from_date_v2<DateV2ValueType>(
template void VecDateTimeValue::create_from_date_v2<DateTimeV2ValueType>(
DateV2Value<DateTimeV2ValueType>& value, TimeType type);
-template int64_t VecDateTimeValue::second_diff<DateV2ValueType>(
+template int64_t VecDateTimeValue::second_diff<DateV2Value<DateV2ValueType>>(
const DateV2Value<DateV2ValueType>& rhs) const;
-template int64_t VecDateTimeValue::second_diff<DateTimeV2ValueType>(
+template int64_t
VecDateTimeValue::second_diff<DateV2Value<DateTimeV2ValueType>>(
const DateV2Value<DateTimeV2ValueType>& rhs) const;
#define DELARE_DATE_ADD_INTERVAL(DateValueType1, DateValueType2)
\
diff --git a/be/src/vec/runtime/vdatetime_value.h
b/be/src/vec/runtime/vdatetime_value.h
index dd8c12cec2..0db31dae20 100644
--- a/be/src/vec/runtime/vdatetime_value.h
+++ b/be/src/vec/runtime/vdatetime_value.h
@@ -21,6 +21,7 @@
#include <stdint.h>
#include <chrono>
+#include <climits>
#include <cstddef>
#include <iostream>
@@ -142,6 +143,10 @@ const int TIME_MAX_SECOND = 59;
const int TIME_MAX_VALUE = 10000 * TIME_MAX_HOUR + 100 * TIME_MAX_MINUTE +
TIME_MAX_SECOND;
const int TIME_MAX_VALUE_SECONDS = 3600 * TIME_MAX_HOUR + 60 * TIME_MAX_MINUTE
+ TIME_MAX_SECOND;
+constexpr int HOUR_PER_DAY = 24;
+constexpr int64_t SECOND_PER_HOUR = 3600;
+constexpr int64_t SECOND_PER_MINUTE = 60;
+
constexpr size_t const_length(const char* str) {
return (str == nullptr || *str == 0) ? 0 : const_length(str + 1) + 1;
}
@@ -384,7 +389,7 @@ public:
return true;
};
- uint64_t daynr() const { return calc_daynr(_year, _month, _day); }
+ int32_t daynr() const { return calc_daynr(_year, _month, _day); }
int year() const { return _year; }
int month() const { return _month; }
@@ -395,6 +400,9 @@ public:
int minute() const { return _minute; }
int second() const { return _second; }
int neg() const { return _neg; }
+ int64_t time_part_to_seconds() const {
+ return _hour * SECOND_PER_HOUR + _minute * SECOND_PER_MINUTE + _second;
+ }
bool check_loss_accuracy_cast_to_date() {
auto loss_accuracy = _hour != 0 || _minute != 0 || _second != 0;
@@ -608,20 +616,14 @@ public:
return _s_max_datetime_value;
}
- int64_t second_diff(const VecDateTimeValue& rhs) const {
- int day_diff = daynr() - rhs.daynr();
- int time_diff = (hour() * 3600 + minute() * 60 + second()) -
- (rhs.hour() * 3600 + rhs.minute() * 60 + rhs.second());
- return day_diff * 3600 * 24 + time_diff;
+ template <typename T>
+ int64_t time_part_diff(const T& rhs) const {
+ return time_part_to_seconds() - rhs.time_part_to_seconds();
}
template <typename T>
- int64_t second_diff(const DateV2Value<T>& rhs) const;
-
- int64_t time_part_diff(const VecDateTimeValue& rhs) const {
- int time_diff = (hour() * 3600 + minute() * 60 + second()) -
- (rhs.hour() * 3600 + rhs.minute() * 60 + rhs.second());
- return time_diff;
+ int64_t second_diff(const T& rhs) const {
+ return (daynr() - rhs.daynr()) * SECOND_PER_HOUR * HOUR_PER_DAY +
time_part_diff(rhs);
}
void set_type(int type);
@@ -728,8 +730,7 @@ template <typename T>
class DateV2Value {
public:
static constexpr bool is_datetime = std::is_same_v<T, DateTimeV2ValueType>;
- using underlying_value =
- std::conditional_t<std::is_same_v<T, DateTimeV2ValueType>,
uint64_t, uint32_t>;
+ using underlying_value = std::conditional_t<is_datetime, uint64_t,
uint32_t>;
// Constructor
DateV2Value<T>() : date_v2_value_(0, 0, 0, 0, 0, 0, 0) {}
@@ -838,7 +839,7 @@ public:
return true;
};
- uint32_t daynr() const {
+ int32_t daynr() const {
return calc_daynr(date_v2_value_.year_, date_v2_value_.month_,
date_v2_value_.day_);
}
@@ -874,6 +875,10 @@ public:
}
}
+ int64_t time_part_to_seconds() const {
+ return hour() * SECOND_PER_HOUR + minute() * SECOND_PER_MINUTE +
second();
+ }
+
uint16_t year() const { return date_v2_value_.year_; }
uint8_t month() const { return date_v2_value_.month_; }
int quarter() const { return (date_v2_value_.month_ - 1) / 3 + 1; }
@@ -1063,23 +1068,15 @@ public:
}
}
+ //only calculate the diff of dd:mm:ss
template <typename RHS>
- int64_t second_diff(const DateV2Value<RHS>& rhs) const {
- int day_diff = daynr() - rhs.daynr();
- return day_diff * 3600 * 24 + (hour() * 3600 + minute() * 60 +
second()) -
- (rhs.hour() * 3600 + rhs.minute() * 60 + rhs.second());
+ int64_t time_part_diff(const RHS& rhs) const {
+ return time_part_to_seconds() - rhs.time_part_to_seconds();
}
- int64_t second_diff(const VecDateTimeValue& rhs) const {
- int day_diff = daynr() - rhs.daynr();
- return day_diff * 3600 * 24 + (hour() * 3600 + minute() * 60 +
second()) -
- (rhs.hour() * 3600 + rhs.minute() * 60 + rhs.second());
- };
-
- int64_t time_part_diff(const VecDateTimeValue& rhs) const {
- int time_diff = (hour() * 3600 + minute() * 60 + second()) -
- (rhs.hour() * 3600 + rhs.minute() * 60 + rhs.second());
- return time_diff;
+ template <typename RHS>
+ int64_t second_diff(const RHS& rhs) const {
+ return (daynr() - rhs.daynr()) * SECOND_PER_HOUR * HOUR_PER_DAY +
time_part_diff(rhs);
}
bool can_cast_to_date_without_loss_accuracy() {
diff --git
a/regression-test/data/query_p0/sql_functions/datetime_functions/test_time_diff.out
b/regression-test/data/query_p0/sql_functions/datetime_functions/test_time_diff.out
new file mode 100644
index 0000000000..972698e802
--- /dev/null
+++
b/regression-test/data/query_p0/sql_functions/datetime_functions/test_time_diff.out
@@ -0,0 +1,19 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !sql --
+36270723
+
+-- !sql --
+35745123
+
+-- !sql --
+63093603
+
+-- !sql --
+62412288
+
+-- !sql --
+34711459380
+
+-- !sql --
+63113904000
+
diff --git
a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_time_diff.groovy
b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_time_diff.groovy
new file mode 100644
index 0000000000..bd159f2892
--- /dev/null
+++
b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_time_diff.groovy
@@ -0,0 +1,25 @@
+// 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_time_diff") {
+ qt_sql """SELECT minutes_diff('2020-02-02 15:30:00', '1951-02-16
15:27:00'); """
+ qt_sql """SELECT minutes_diff('2020-02-02 15:30:00', '1952-02-16
15:27:00'); """
+ qt_sql """SELECT minutes_diff('2020-02-02 15:30:00', '1900-02-16
15:27:00'); """
+ qt_sql """SELECT hours_diff('9020-02-02 15:30:00', '1900-02-16 15:27:00');
"""
+ qt_sql """SELECT seconds_diff('3000-02-02 15:30:00', '1900-02-16
15:27:00'); """
+ qt_sql """SELECT seconds_diff('3000-01-01 00:00:00', '1000-01-01
00:00:00'); """
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]