linrrzqqq commented on code in PR #57253:
URL: https://github.com/apache/doris/pull/57253#discussion_r2471729057
##########
be/src/vec/functions/function_date_or_datetime_computation.h:
##########
@@ -125,6 +126,88 @@ ADD_TIME_FUNCTION_IMPL(AddWeeksImpl, weeks_add, WEEK);
ADD_TIME_FUNCTION_IMPL(AddMonthsImpl, months_add, MONTH);
ADD_TIME_FUNCTION_IMPL(AddYearsImpl, years_add, YEAR);
+template <PrimitiveType PType>
+struct AddDaySecondImpl {
+ static constexpr PrimitiveType ArgPType = PType;
+ static constexpr PrimitiveType ReturnType = PType;
+ static constexpr PrimitiveType IntervalPType = PrimitiveType ::TYPE_STRING;
+ using InputNativeType = typename PrimitiveTypeTraits<PType>::DataType
::FieldType;
+ using ReturnNativeType = InputNativeType;
+ using IntervalDataType = typename
PrimitiveTypeTraits<IntervalPType>::DataType;
+ using IntervalNativeType = IntervalDataType::FieldType; // string
+ using ConvertedType = typename
PrimitiveTypeTraits<TYPE_BIGINT>::DataType::FieldType;
+
+ static constexpr auto name = "day_second_add";
+ static constexpr auto is_nullable = false;
+
+ static inline ReturnNativeType execute(const InputNativeType& t,
IntervalNativeType delta) {
+ long seconds = parse_time_string_to_seconds(delta);
+ return date_time_add<TimeUnit::SECOND, PType, ConvertedType>(t,
seconds);
+ }
+
+ static DataTypes get_variadic_argument_types() {
+ return {std ::make_shared<typename
PrimitiveTypeTraits<PType>::DataType>(),
+ std ::make_shared<typename
PrimitiveTypeTraits<IntervalPType>::DataType>()};
+ }
+
+ static long parse_time_string_to_seconds(IntervalNativeType time_str_ref) {
+ auto time_str = StringRef {time_str_ref.data(),
time_str_ref.length()}.trim();
+ // string format: "d h:m:s"
+ size_t space_pos = time_str.find_first_of(' ');
+ if (space_pos == std::string::npos) {
+ throw Exception(ErrorCode::INVALID_ARGUMENT,
+ "Invalid time format, missing space in '{}'",
+ std::string_view {time_str.data, time_str.size});
+ }
+ // day
+ StringRef days_sub = time_str.substring(0, space_pos).trim();
+ StringParser::ParseResult success;
+ int days = StringParser::string_to_int_internal<int32_t,
true>(days_sub.data, days_sub.size,
+
&success);
+ if (success != StringParser::PARSE_SUCCESS) {
+ throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid days format
in '{}'",
+ std::string_view {time_str.data, time_str.size});
+ }
+ // hour:minute:second
+ StringRef time_hour_str = time_str.substring(space_pos + 1);
+ size_t colon1 = time_hour_str.find_first_of(':');
+ if (colon1 == std::string::npos) {
+ throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid time format,
missing ':' in '{}'",
+ std::string_view {time_str.data, time_str.size});
+ }
+ size_t colon2_rel = time_hour_str.substring(colon1 +
1).find_first_of(':');
+ size_t colon2 =
+ (colon2_rel != std::string::npos) ? colon1 + 1 + colon2_rel :
std::string::npos;
+ if (colon2 == std::string::npos) {
+ throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid time format,
missing ':' in '{}'",
+ std::string_view {time_str.data, time_str.size});
+ }
+ StringRef hours_sub = time_hour_str.substring(0, colon1).trim();
+ int hours = StringParser::string_to_int_internal<int32_t,
true>(hours_sub.data,
+
hours_sub.size, &success);
+ if (success != StringParser::PARSE_SUCCESS) {
+ throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid hours format
in '{}'",
+ std::string_view {time_str.data, time_str.size});
+ }
+ StringRef minutes_sub = time_hour_str.substring(colon1 + 1, colon2 -
colon1 - 1).trim();
+ int minutes = StringParser::string_to_int_internal<int32_t, true>(
+ minutes_sub.data, minutes_sub.size, &success);
+ if (success != StringParser::PARSE_SUCCESS) {
+ throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid minutes
format in '{}'",
+ std::string_view {time_str.data, time_str.size});
+ }
+ StringRef seconds_sub = time_hour_str.substring(colon2 + 1).trim();
+ int seconds = StringParser::string_to_int_internal<int32_t, true>(
+ seconds_sub.data, seconds_sub.size, &success);
+ if (success != StringParser::PARSE_SUCCESS) {
+ throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid seconds
format in '{}'",
+ std::string_view {time_str.data, time_str.size});
+ }
+
+ return days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds;
Review Comment:
seems that you extract each part separately here, I wonder if this will
cause some issues when dealing with negative numbers. In MySQL, day_second is
treated as a whole, with its positive or negative value determined by the DAY
value, for example:
```text
mysql> select date_add("2025-10-29", INTERVAL "-1 1:1:1" DAY_SECOND);
+--------------------------------------------------------+
| date_add("2025-10-29", INTERVAL "-1 1:1:1" DAY_SECOND) |
+--------------------------------------------------------+
| 2025-10-27 22:58:59 |
+--------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select date_add("2025-10-29", INTERVAL "-1 1:-1:1" DAY_SECOND);
+---------------------------------------------------------+
| date_add("2025-10-29", INTERVAL "-1 1:-1:1" DAY_SECOND) |
+---------------------------------------------------------+
| 2025-10-27 22:58:59 |
+---------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select date_add("2025-10-29", INTERVAL "1 -1:1:1" DAY_SECOND);
+--------------------------------------------------------+
| date_add("2025-10-29", INTERVAL "1 -1:1:1" DAY_SECOND) |
+--------------------------------------------------------+
| 2025-10-30 01:01:01 |
+--------------------------------------------------------+
1 row in set (0.00 sec)
```
Please confirm this point, and better add some regression tests and
supplement the corresponding results in `.out` file.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]