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]

Reply via email to