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

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


The following commit(s) were added to refs/heads/master by this push:
     new 0b9b1be1f14 [fix](function) Fix from_second functions overflow and 
wrong result (#28685)
0b9b1be1f14 is described below

commit 0b9b1be1f146d2f24767e3abfbf230019721bdbc
Author: zclllyybb <[email protected]>
AuthorDate: Fri Dec 22 10:22:49 2023 +0800

    [fix](function) Fix from_second functions overflow and wrong result (#28685)
---
 be/src/exec/es/es_scroll_parser.cpp                |  14 +-
 be/src/runtime/runtime_state.h                     |   1 +
 be/src/vec/functions/date_time_transforms.h        |   4 +-
 be/src/vec/functions/function_convert_tz.h         |  13 +-
 .../function_date_or_datetime_computation.h        | 144 +++++++++------------
 be/src/vec/runtime/vdatetime_value.cpp             |  30 +++--
 be/src/vec/runtime/vdatetime_value.h               |  17 +--
 .../date-time-functions/from-second.md             |  56 ++++----
 docs/sidebars.json                                 |   1 +
 .../date-time-functions/from-second.md             |  52 ++++----
 .../test_from_millisecond_microsecond.out          |  33 +++--
 .../test_from_millisecond_microsecond.groovy       |   5 +
 12 files changed, 174 insertions(+), 196 deletions(-)

diff --git a/be/src/exec/es/es_scroll_parser.cpp 
b/be/src/exec/es/es_scroll_parser.cpp
index d7b16f656c3..726e86ea74f 100644
--- a/be/src/exec/es/es_scroll_parser.cpp
+++ b/be/src/exec/es/es_scroll_parser.cpp
@@ -222,7 +222,8 @@ Status get_date_value_int(const rapidjson::Value& col, 
PrimitiveType type, bool
             if (ok) {
                 // The local time zone can change by session variable 
`time_zone`
                 // We should use the user specified time zone, not the actual 
system local time zone.
-                success = 
dt_val.from_unixtime(std::chrono::system_clock::to_time_t(tp), time_zone);
+                success = true;
+                dt_val.from_unixtime(std::chrono::system_clock::to_time_t(tp), 
time_zone);
             }
         } else if (str_length == 19) {
             // YYYY-MM-DDTHH:MM:SS
@@ -231,8 +232,8 @@ Status get_date_value_int(const rapidjson::Value& col, 
PrimitiveType type, bool
                 const bool ok =
                         cctz::parse("%Y-%m-%dT%H:%M:%S", str_date, 
cctz::utc_time_zone(), &tp);
                 if (ok) {
-                    success = 
dt_val.from_unixtime(std::chrono::system_clock::to_time_t(tp),
-                                                   time_zone);
+                    success = true;
+                    
dt_val.from_unixtime(std::chrono::system_clock::to_time_t(tp), time_zone);
                 }
             } else {
                 // YYYY-MM-DD HH:MM:SS
@@ -243,7 +244,8 @@ Status get_date_value_int(const rapidjson::Value& col, 
PrimitiveType type, bool
             // string long like "1677895728000"
             int64_t time_long = std::atol(str_date.c_str());
             if (time_long > 0) {
-                success = dt_val.from_unixtime(time_long / 1000, time_zone);
+                success = true;
+                dt_val.from_unixtime(time_long / 1000, time_zone);
             }
         } else {
             // YYYY-MM-DD or others
@@ -255,9 +257,7 @@ Status get_date_value_int(const rapidjson::Value& col, 
PrimitiveType type, bool
         }
 
     } else {
-        if (!dt_val.from_unixtime(col.GetInt64() / 1000, time_zone)) {
-            RETURN_ERROR_IF_CAST_FORMAT_ERROR(col, type);
-        }
+        dt_val.from_unixtime(col.GetInt64() / 1000, time_zone);
     }
     if constexpr (is_datetime_v1) {
         if (type == TYPE_DATE) {
diff --git a/be/src/runtime/runtime_state.h b/be/src/runtime/runtime_state.h
index a4524d846fb..989655a36c7 100644
--- a/be/src/runtime/runtime_state.h
+++ b/be/src/runtime/runtime_state.h
@@ -132,6 +132,7 @@ public:
     TQueryType::type query_type() const { return _query_options.query_type; }
     int64_t timestamp_ms() const { return _timestamp_ms; }
     int32_t nano_seconds() const { return _nano_seconds; }
+    // if possible, use timezone_obj() rather than timezone()
     const std::string& timezone() const { return _timezone; }
     const cctz::time_zone& timezone_obj() const { return _timezone_obj; }
     const std::string& user() const { return _user; }
diff --git a/be/src/vec/functions/date_time_transforms.h 
b/be/src/vec/functions/date_time_transforms.h
index 877a66e002a..a513f9f154d 100644
--- a/be/src/vec/functions/date_time_transforms.h
+++ b/be/src/vec/functions/date_time_transforms.h
@@ -222,10 +222,10 @@ struct FromUnixTimeImpl {
     static inline auto execute(FromType val, StringRef format, 
ColumnString::Chars& res_data,
                                size_t& offset, const cctz::time_zone& 
time_zone) {
         DateType dt;
-        if (format.size > 128 || val < 0 || val > TIMESTAMP_VALID_MAX ||
-            !dt.from_unixtime(val, time_zone)) {
+        if (format.size > 128 || val < 0 || val > TIMESTAMP_VALID_MAX) {
             return std::pair {offset, true};
         }
+        dt.from_unixtime(val, time_zone);
 
         char buf[128];
         if (!dt.to_format_string(format.data, format.size, buf)) {
diff --git a/be/src/vec/functions/function_convert_tz.h 
b/be/src/vec/functions/function_convert_tz.h
index c8957122abe..bfd261640c1 100644
--- a/be/src/vec/functions/function_convert_tz.h
+++ b/be/src/vec/functions/function_convert_tz.h
@@ -201,12 +201,7 @@ private:
                 result_column->insert_default();
                 return;
             }
-
-            if (!ts_value2.from_unixtime(timestamp, to_tz)) {
-                result_null_map[index_now] = true;
-                result_column->insert_default();
-                return;
-            }
+            ts_value2.from_unixtime(timestamp, to_tz);
         } else {
             int64_t timestamp;
             if (!ts_value.unix_timestamp(&timestamp, from_tz)) {
@@ -215,11 +210,7 @@ private:
                 return;
             }
 
-            if (!ts_value2.from_unixtime(timestamp, to_tz)) {
-                result_null_map[index_now] = true;
-                result_column->insert_default();
-                return;
-            }
+            ts_value2.from_unixtime(timestamp, to_tz);
         }
 
         result_column->insert(binary_cast<ReturnDateValueType, 
ReturnNativeType>(ts_value2));
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 87d3fa8268b..383fb10e34a 100644
--- a/be/src/vec/functions/function_date_or_datetime_computation.h
+++ b/be/src/vec/functions/function_date_or_datetime_computation.h
@@ -918,34 +918,30 @@ struct CurrentDateTimeImpl {
         DateValueType dtv;
         bool use_const;
         if constexpr (WithPrecision) {
-            if (const ColumnConst* const_column = 
check_and_get_column<ColumnConst>(
+            if (const auto* const_column = check_and_get_column<ColumnConst>(
                         block.get_by_position(arguments[0]).column)) {
                 int scale = const_column->get_int(0);
-                if (dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
-                                      context->state()->nano_seconds(),
-                                      context->state()->timezone_obj(), 
scale)) {
-                    if constexpr (std::is_same_v<DateValueType, 
VecDateTimeValue>) {
-                        
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
-                    }
-                    auto date_packed_int = binary_cast<DateValueType, 
NativeType>(dtv);
-                    col_to->insert_data(
-                            const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)), 0);
-
-                } else {
-                    auto invalid_val = 0;
-                    col_to->insert_data(
-                            const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)), 0);
+                dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
+                                  context->state()->nano_seconds(),
+                                  context->state()->timezone_obj(), scale);
+                if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) 
{
+                    
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
                 }
+                auto date_packed_int = binary_cast<DateValueType, 
NativeType>(dtv);
+                col_to->insert_data(
+                        const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)), 0);
+
                 use_const = true;
-            } else if (const ColumnNullable* nullable_column = 
check_and_get_column<ColumnNullable>(
+            } else if (const auto* nullable_column = 
check_and_get_column<ColumnNullable>(
                                block.get_by_position(arguments[0]).column)) {
                 const auto& null_map = nullable_column->get_null_map_data();
                 const auto& nested_column = 
nullable_column->get_nested_column_ptr();
                 for (int i = 0; i < input_rows_count; i++) {
-                    if (!null_map[i] && 
dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
-                                                          
context->state()->nano_seconds(),
-                                                          
context->state()->timezone_obj(),
-                                                          
nested_column->get64(i))) {
+                    if (!null_map[i]) {
+                        dtv.from_unixtime(context->state()->timestamp_ms() / 
1000,
+                                          context->state()->nano_seconds(),
+                                          context->state()->timezone_obj(),
+                                          nested_column->get64(i));
                         if constexpr (std::is_same_v<DateValueType, 
VecDateTimeValue>) {
                             
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
                         }
@@ -963,38 +959,27 @@ struct CurrentDateTimeImpl {
             } else {
                 auto& int_column = block.get_by_position(arguments[0]).column;
                 for (int i = 0; i < input_rows_count; i++) {
-                    if (dtv.from_unixtime(context->state()->timestamp_ms() / 
1000,
-                                          context->state()->nano_seconds(),
-                                          context->state()->timezone_obj(), 
int_column->get64(i))) {
-                        if constexpr (std::is_same_v<DateValueType, 
VecDateTimeValue>) {
-                            
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
-                        }
-                        auto date_packed_int = binary_cast<DateValueType, 
NativeType>(dtv);
-                        col_to->insert_data(
-                                const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)),
-                                0);
-                    } else {
-                        auto invalid_val = 0;
-                        col_to->insert_data(
-                                const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)), 0);
+                    dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
+                                      context->state()->nano_seconds(),
+                                      context->state()->timezone_obj(), 
int_column->get64(i));
+                    if constexpr (std::is_same_v<DateValueType, 
VecDateTimeValue>) {
+                        
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
                     }
+                    auto date_packed_int = binary_cast<DateValueType, 
NativeType>(dtv);
+                    col_to->insert_data(
+                            const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)), 0);
                 }
                 use_const = false;
             }
         } else {
-            if (dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
-                                  context->state()->timezone_obj())) {
-                if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) 
{
-                    
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
-                }
-                auto date_packed_int = binary_cast<DateValueType, 
NativeType>(dtv);
-                col_to->insert_data(
-                        const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)), 0);
-            } else {
-                auto invalid_val = 0;
-                col_to->insert_data(const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)),
-                                    0);
+            dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
+                              context->state()->timezone_obj());
+            if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
+                
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
             }
+            auto date_packed_int = binary_cast<DateValueType, NativeType>(dtv);
+            col_to->insert_data(const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)),
+                                0);
             use_const = true;
         }
 
@@ -1017,31 +1002,21 @@ struct CurrentDateImpl {
         auto col_to = ColumnVector<NativeType>::create();
         if constexpr (std::is_same_v<DateType, DataTypeDateV2>) {
             DateV2Value<DateV2ValueType> dtv;
-            if (dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
-                                  context->state()->timezone_obj())) {
-                auto date_packed_int = 
binary_cast<DateV2Value<DateV2ValueType>, uint32_t>(
-                        
*reinterpret_cast<DateV2Value<DateV2ValueType>*>(&dtv));
-                col_to->insert_data(
-                        const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)), 0);
-            } else {
-                auto invalid_val = 0;
-                col_to->insert_data(const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)),
-                                    0);
-            }
+            dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
+                              context->state()->timezone_obj());
+            auto date_packed_int = binary_cast<DateV2Value<DateV2ValueType>, 
uint32_t>(
+                    *reinterpret_cast<DateV2Value<DateV2ValueType>*>(&dtv));
+            col_to->insert_data(const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)),
+                                0);
         } else {
             VecDateTimeValue dtv;
-            if (dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
-                                  context->state()->timezone_obj())) {
-                reinterpret_cast<VecDateTimeValue*>(&dtv)->set_type(TIME_DATE);
-                auto date_packed_int = binary_cast<doris::VecDateTimeValue, 
int64_t>(
-                        *reinterpret_cast<VecDateTimeValue*>(&dtv));
-                col_to->insert_data(
-                        const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)), 0);
-            } else {
-                auto invalid_val = 0;
-                col_to->insert_data(const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)),
-                                    0);
-            }
+            dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
+                              context->state()->timezone_obj());
+            reinterpret_cast<VecDateTimeValue*>(&dtv)->set_type(TIME_DATE);
+            auto date_packed_int = binary_cast<doris::VecDateTimeValue, 
int64_t>(
+                    *reinterpret_cast<VecDateTimeValue*>(&dtv));
+            col_to->insert_data(const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)),
+                                0);
         }
         block.get_by_position(result).column =
                 ColumnConst::create(std::move(col_to), input_rows_count);
@@ -1057,15 +1032,11 @@ struct CurrentTimeImpl {
                           size_t result, size_t input_rows_count) {
         auto col_to = ColumnVector<Float64>::create();
         VecDateTimeValue dtv;
-        if (dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
-                              context->state()->timezone_obj())) {
-            double time = dtv.hour() * 3600l + dtv.minute() * 60l + 
dtv.second();
-            time *= (1000 * 1000);
-            col_to->insert_data(const_cast<const 
char*>(reinterpret_cast<char*>(&time)), 0);
-        } else {
-            auto invalid_val = 0;
-            col_to->insert_data(const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)), 0);
-        }
+        dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
+                          context->state()->timezone_obj());
+        double time = dtv.hour() * 3600l + dtv.minute() * 60l + dtv.second();
+        time *= (1000 * 1000);
+        col_to->insert_data(const_cast<const 
char*>(reinterpret_cast<char*>(&time)), 0);
         block.get_by_position(result).column =
                 ColumnConst::create(std::move(col_to), input_rows_count);
         return Status::OK();
@@ -1144,15 +1115,28 @@ struct TimestampToDateTime : IFunction {
         auto null_vector = ColumnVector<UInt8>::create();
         res_col->get_data().resize_fill(input_rows_count, 0);
         null_vector->get_data().resize_fill(input_rows_count, false);
+
         NullMap& null_map = null_vector->get_data();
         auto& res_data = res_col->get_data();
         const cctz::time_zone& time_zone = context->state()->timezone_obj();
+
         for (int i = 0; i < input_rows_count; ++i) {
             Int64 value = column_data.get_element(i);
+            if (value < 0) {
+                null_map[i] = true;
+                continue;
+            }
+
             auto& dt = 
reinterpret_cast<DateV2Value<DateTimeV2ValueType>&>(res_data[i]);
-            null_map[i] = !dt.from_unixtime(value / Impl::ratio, time_zone);
-            dt.set_microsecond((value % Impl::ratio) * ratio_to_micro);
+            dt.from_unixtime(value / Impl::ratio, time_zone);
+
+            if (dt.is_valid_date()) [[likely]] {
+                dt.set_microsecond((value % Impl::ratio) * ratio_to_micro);
+            } else {
+                null_map[i] = true;
+            }
         }
+
         block.get_by_position(result).column =
                 ColumnNullable::create(std::move(res_col), 
std::move(null_vector));
         return Status::OK();
diff --git a/be/src/vec/runtime/vdatetime_value.cpp 
b/be/src/vec/runtime/vdatetime_value.cpp
index b177164b9ef..f625631ace9 100644
--- a/be/src/vec/runtime/vdatetime_value.cpp
+++ b/be/src/vec/runtime/vdatetime_value.cpp
@@ -1731,10 +1731,11 @@ bool VecDateTimeValue::from_unixtime(int64_t timestamp, 
const std::string& timez
     if (!TimezoneUtils::find_cctz_time_zone(timezone, ctz)) {
         return false;
     }
-    return from_unixtime(timestamp, ctz);
+    from_unixtime(timestamp, ctz);
+    return true;
 }
 
-bool VecDateTimeValue::from_unixtime(int64_t timestamp, const cctz::time_zone& 
ctz) {
+void VecDateTimeValue::from_unixtime(int64_t timestamp, const cctz::time_zone& 
ctz) {
     static const cctz::time_point<cctz::sys_seconds> epoch =
             std::chrono::time_point_cast<cctz::sys_seconds>(
                     std::chrono::system_clock::from_time_t(0));
@@ -1742,6 +1743,8 @@ bool VecDateTimeValue::from_unixtime(int64_t timestamp, 
const cctz::time_zone& c
 
     const auto tp = cctz::convert(t, ctz);
 
+    // there's no overflow check since it's hot path
+
     _neg = 0;
     _type = TIME_DATETIME;
     _year = tp.year();
@@ -1750,8 +1753,6 @@ bool VecDateTimeValue::from_unixtime(int64_t timestamp, 
const cctz::time_zone& c
     _hour = tp.hour();
     _minute = tp.minute();
     _second = tp.second();
-
-    return true;
 }
 
 const char* VecDateTimeValue::month_name() const {
@@ -3202,20 +3203,21 @@ bool DateV2Value<T>::from_unixtime(int64_t timestamp, 
const std::string& timezon
     if (!TimezoneUtils::find_cctz_time_zone(timezone, ctz)) {
         return false;
     }
-    return from_unixtime(timestamp, ctz);
+    from_unixtime(timestamp, ctz);
+    return true;
 }
 
 template <typename T>
-bool DateV2Value<T>::from_unixtime(int64_t timestamp, const cctz::time_zone& 
ctz) {
+void DateV2Value<T>::from_unixtime(int64_t timestamp, const cctz::time_zone& 
ctz) {
     static const cctz::time_point<cctz::sys_seconds> epoch =
             std::chrono::time_point_cast<cctz::sys_seconds>(
                     std::chrono::system_clock::from_time_t(0));
     cctz::time_point<cctz::sys_seconds> t = epoch + cctz::seconds(timestamp);
-
     const auto tp = cctz::convert(t, ctz);
 
+    // there's no overflow check since it's hot path
+
     set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), 
tp.second(), 0);
-    return true;
 }
 
 template <typename T>
@@ -3225,11 +3227,12 @@ bool DateV2Value<T>::from_unixtime(std::pair<int64_t, 
int64_t> timestamp,
     if (!TimezoneUtils::find_cctz_time_zone(timezone, ctz)) {
         return false;
     }
-    return from_unixtime(timestamp, ctz);
+    from_unixtime(timestamp, ctz);
+    return true;
 }
 
 template <typename T>
-bool DateV2Value<T>::from_unixtime(std::pair<int64_t, int64_t> timestamp,
+void DateV2Value<T>::from_unixtime(std::pair<int64_t, int64_t> timestamp,
                                    const cctz::time_zone& ctz) {
     static const cctz::time_point<cctz::sys_seconds> epoch =
             std::chrono::time_point_cast<cctz::sys_seconds>(
@@ -3240,7 +3243,6 @@ bool DateV2Value<T>::from_unixtime(std::pair<int64_t, 
int64_t> timestamp,
 
     set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), 
tp.second(),
              timestamp.second);
-    return true;
 }
 
 template <typename T>
@@ -3250,11 +3252,12 @@ bool DateV2Value<T>::from_unixtime(int64_t timestamp, 
int32_t nano_seconds,
     if (!TimezoneUtils::find_cctz_time_zone(timezone, ctz)) {
         return false;
     }
-    return from_unixtime(timestamp, nano_seconds, ctz, scale);
+    from_unixtime(timestamp, nano_seconds, ctz, scale);
+    return true;
 }
 
 template <typename T>
-bool DateV2Value<T>::from_unixtime(int64_t timestamp, int32_t nano_seconds,
+void DateV2Value<T>::from_unixtime(int64_t timestamp, int32_t nano_seconds,
                                    const cctz::time_zone& ctz, int scale) {
     static const cctz::time_point<cctz::sys_seconds> epoch =
             std::chrono::time_point_cast<cctz::sys_seconds>(
@@ -3269,7 +3272,6 @@ bool DateV2Value<T>::from_unixtime(int64_t timestamp, 
int32_t nano_seconds,
 
     set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), 
tp.second(),
              nano_seconds / int_exp10(9 - scale) * int_exp10(6 - scale));
-    return true;
 }
 
 template <typename T>
diff --git a/be/src/vec/runtime/vdatetime_value.h 
b/be/src/vec/runtime/vdatetime_value.h
index 6fe7104ecdb..1999c230809 100644
--- a/be/src/vec/runtime/vdatetime_value.h
+++ b/be/src/vec/runtime/vdatetime_value.h
@@ -508,9 +508,10 @@ public:
     bool unix_timestamp(int64_t* timestamp, const cctz::time_zone& ctz) const;
 
     //construct datetime_value from timestamp and timezone
-    //timestamp is an internal timestamp value representing seconds since 
'1970-01-01 00:00:00' UTC
+    //timestamp is an internal timestamp value representing seconds since 
'1970-01-01 00:00:00' UTC. negative avaliable.
+    //we don't do any check in it because it's hot path. any usage want ensure 
the time legality should check itself.
     bool from_unixtime(int64_t, const std::string& timezone);
-    bool from_unixtime(int64_t, const cctz::time_zone& ctz);
+    void from_unixtime(int64_t, const cctz::time_zone& ctz);
 
     bool operator==(const VecDateTimeValue& other) const {
         // NOTE: This is not same with MySQL.
@@ -970,14 +971,14 @@ public:
     bool unix_timestamp(std::pair<int64_t, int64_t>* timestamp, const 
cctz::time_zone& ctz) const;
 
     //construct datetime_value from timestamp and timezone
-    //timestamp is an internal timestamp value representing seconds since 
'1970-01-01 00:00:00' UTC
+    //timestamp is an internal timestamp value representing seconds since 
'1970-01-01 00:00:00' UTC. negative avaliable.
+    //we don't do any check in it because it's hot path. any usage want ensure 
the time legality should check itself.
     bool from_unixtime(int64_t, const std::string& timezone);
-    bool from_unixtime(int64_t, const cctz::time_zone& ctz);
+    void from_unixtime(int64_t, const cctz::time_zone& ctz);
     bool from_unixtime(std::pair<int64_t, int64_t>, const std::string& 
timezone);
-    bool from_unixtime(std::pair<int64_t, int64_t>, const cctz::time_zone& 
ctz);
-
-    bool from_unixtime(int64_t, int32_t, const std::string& timezone, const 
int scale);
-    bool from_unixtime(int64_t, int32_t, const cctz::time_zone& ctz, int 
scale);
+    void from_unixtime(std::pair<int64_t, int64_t>, const cctz::time_zone& 
ctz);
+    bool from_unixtime(int64_t, int32_t, const std::string& timezone, int 
scale);
+    void from_unixtime(int64_t, int32_t, const cctz::time_zone& ctz, int 
scale);
 
     bool operator==(const DateV2Value<T>& other) const {
         // NOTE: This is not same with MySQL.
diff --git 
a/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/from-second.md 
b/docs/en/docs/sql-manual/sql-functions/date-time-functions/from-second.md
similarity index 54%
copy from 
docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/from-second.md
copy to docs/en/docs/sql-manual/sql-functions/date-time-functions/from-second.md
index 601cb4a7071..bcbf92521ad 100644
--- 
a/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/from-second.md
+++ b/docs/en/docs/sql-manual/sql-functions/date-time-functions/from-second.md
@@ -1,7 +1,7 @@
 ---
 {
     "title": "FROM_SECOND",
-    "language": "zh-CN"
+    "language": "en"
 }
 ---
 
@@ -26,40 +26,25 @@ under the License.
 
 ## from_second
 ### description
-#### Syntax
+#### syntax
 
 `DATETIME FROM_SECOND(BIGINT unix_timestamp)`
 `DATETIME FROM_MILLISECOND(BIGINT unix_timestamp)`
 `DATETIME FROM_MICROSECOND(BIGINT unix_timestamp)`
 
-将时间戳转化为对应的 DATETIME
-
-传入的是整型,返回的是DATETIME类型
-
+Converts a timestamp to its DATETIME represent, with argument as an integer 
and returned as a DATETIME type. Returns `NULL` if `unix_timestamp < 0` or if 
the function result is greater than `9999-12-31 23:59:59.999999`.
 
 ### example
 
 ```
-mysql> select from_microsecond(0);
-+----------------------------+
-| from_microsecond(0)        |
-+----------------------------+
-| 1970-01-01 08:00:00.000000 |
-+----------------------------+
-
-mysql> select from_microsecond(12345678);
-+----------------------------+
-| from_microsecond(12345678) |
-+----------------------------+
-| 1970-01-01 08:00:12.345678 |
-+----------------------------+
+mysql> set time_zone='Asia/Shanghai';
 
-mysql> select from_millisecond(0);
-+-------------------------+
-| from_millisecond(0)     |
-+-------------------------+
-| 1970-01-01 08:00:00.000 |
-+-------------------------+
+mysql> select from_second(-1);
++---------------------------+
+| from_second(-1)           |
++---------------------------+
+| NULL                      |
++---------------------------+
 
 mysql> select from_millisecond(12345678);
 +----------------------------+
@@ -68,14 +53,21 @@ mysql> select from_millisecond(12345678);
 | 1970-01-01 11:25:45.678    |
 +----------------------------+
 
-mysql> select from_second(21474836470);
-+--------------------------+
-| from_second(21474836470) |
-+--------------------------+
-| 2650-07-06 16:21:10      |
-+--------------------------+
+mysql> select from_microsecond(253402271999999999);
++--------------------------------------+
+| from_microsecond(253402271999999999) |
++--------------------------------------+
+| 9999-12-31 23:59:59.999999           |
++--------------------------------------+
+
+mysql> select from_microsecond(253402272000000000);
++--------------------------------------+
+| from_microsecond(253402272000000000) |
++--------------------------------------+
+| NULL                                 |
++--------------------------------------+
 ```
 
 ### keywords
 
-    FROM_SECOND
+    FROM_SECOND,FROM,SECOND,MILLISECOND,MICROSECOND
diff --git a/docs/sidebars.json b/docs/sidebars.json
index 0ba8f71b499..da910610f08 100644
--- a/docs/sidebars.json
+++ b/docs/sidebars.json
@@ -347,6 +347,7 @@
                                 
"sql-manual/sql-functions/date-time-functions/from-days",
                                 
"sql-manual/sql-functions/date-time-functions/last-day",
                                 
"sql-manual/sql-functions/date-time-functions/to-monday",
+                                
"sql-manual/sql-functions/date-time-functions/from-second",
                                 
"sql-manual/sql-functions/date-time-functions/from-unixtime",
                                 
"sql-manual/sql-functions/date-time-functions/unix-timestamp",
                                 
"sql-manual/sql-functions/date-time-functions/utc-timestamp",
diff --git 
a/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/from-second.md 
b/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/from-second.md
index 601cb4a7071..df3c031966b 100644
--- 
a/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/from-second.md
+++ 
b/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/from-second.md
@@ -32,34 +32,19 @@ under the License.
 `DATETIME FROM_MILLISECOND(BIGINT unix_timestamp)`
 `DATETIME FROM_MICROSECOND(BIGINT unix_timestamp)`
 
-将时间戳转化为对应的 DATETIME
-
-传入的是整型,返回的是DATETIME类型
-
+将时间戳转化为对应的 DATETIME,传入的是整型,返回的是DATETIME类型。若`unix_timestamp < 0` 或函数结果大于 
`9999-12-31 23:59:59.999999`,则返回`NULL`。
 
 ### example
 
 ```
-mysql> select from_microsecond(0);
-+----------------------------+
-| from_microsecond(0)        |
-+----------------------------+
-| 1970-01-01 08:00:00.000000 |
-+----------------------------+
-
-mysql> select from_microsecond(12345678);
-+----------------------------+
-| from_microsecond(12345678) |
-+----------------------------+
-| 1970-01-01 08:00:12.345678 |
-+----------------------------+
+mysql> set time_zone='Asia/Shanghai';
 
-mysql> select from_millisecond(0);
-+-------------------------+
-| from_millisecond(0)     |
-+-------------------------+
-| 1970-01-01 08:00:00.000 |
-+-------------------------+
+mysql> select from_second(-1);
++---------------------------+
+| from_second(-1)           |
++---------------------------+
+| NULL                      |
++---------------------------+
 
 mysql> select from_millisecond(12345678);
 +----------------------------+
@@ -68,14 +53,21 @@ mysql> select from_millisecond(12345678);
 | 1970-01-01 11:25:45.678    |
 +----------------------------+
 
-mysql> select from_second(21474836470);
-+--------------------------+
-| from_second(21474836470) |
-+--------------------------+
-| 2650-07-06 16:21:10      |
-+--------------------------+
+mysql> select from_microsecond(253402271999999999);
++--------------------------------------+
+| from_microsecond(253402271999999999) |
++--------------------------------------+
+| 9999-12-31 23:59:59.999999           |
++--------------------------------------+
+
+mysql> select from_microsecond(253402272000000000);
++--------------------------------------+
+| from_microsecond(253402272000000000) |
++--------------------------------------+
+| NULL                                 |
++--------------------------------------+
 ```
 
 ### keywords
 
-    FROM_SECOND
+    FROM_SECOND,FROM,SECOND,MILLISECOND,MICROSECOND
diff --git 
a/regression-test/data/correctness/test_from_millisecond_microsecond.out 
b/regression-test/data/correctness/test_from_millisecond_microsecond.out
index 2dc7f81a74d..b4f5d9623f6 100644
--- a/regression-test/data/correctness/test_from_millisecond_microsecond.out
+++ b/regression-test/data/correctness/test_from_millisecond_microsecond.out
@@ -15,9 +15,9 @@
 3001-01-19 07:59:59    3001-01-19T07:59:59     \N      3001-01-19T08:00        
2650-07-06 16:21:10     2650-07-06T16:21:10
 
 -- !select4 --
-1919810114514          1919810114514
-89417891234789         488885820389
-1235817896941          1235817896941
+1919810114514  \N      \N
+89417891234789 \N      \N
+1235817896941  \N      \N
 \N     \N      \N
 
 -- !select5 --
@@ -48,9 +48,9 @@
 2038-01-19 11:14:07    2038-01-19T11:14:07     2038-01-19 11:14:08     
2038-01-19T11:14:08     2650-07-06 16:21:10     2650-07-06T16:21:10
 
 -- !select10 --
-1919810114514          1919810114514
-89417891234789         488885820389
-1235817896941          1235817896941
+1919810114514  \N      \N
+89417891234789 \N      \N
+1235817896941  \N      \N
 \N     \N      \N
 
 -- !select11 --
@@ -99,9 +99,9 @@
 3001-01-19 07:59:59    3001-01-19T07:59:59     \N      3001-01-19T08:00        
2650-07-06 16:21:10     2650-07-06T16:21:10
 
 -- !select4 --
-1919810114514          1919810114514
-89417891234789         488885820389
-1235817896941          1235817896941
+1919810114514  \N      \N
+89417891234789 \N      \N
+1235817896941  \N      \N
 \N     \N      \N
 
 -- !select5 --
@@ -132,9 +132,9 @@
 2038-01-19 11:14:07    2038-01-19T11:14:07     2038-01-19 11:14:08     
2038-01-19T11:14:08     2650-07-06 16:21:10     2650-07-06T16:21:10
 
 -- !select10 --
-1919810114514          1919810114514
-89417891234789         488885820389
-1235817896941          1235817896941
+1919810114514  \N      \N
+89417891234789 \N      \N
+1235817896941  \N      \N
 \N     \N      \N
 
 -- !select11 --
@@ -159,3 +159,12 @@
 2      1672502400      1672502400123   1672502400123000
 3      1672502400      1672502400123   1672502400123456
 
+-- !sql --
+\N
+
+-- !sql --
+9999-12-31T23:59:59.999999
+
+-- !sql --
+\N
+
diff --git 
a/regression-test/suites/correctness/test_from_millisecond_microsecond.groovy 
b/regression-test/suites/correctness/test_from_millisecond_microsecond.groovy
index 39b5ab9c89d..3e5548f0ac6 100644
--- 
a/regression-test/suites/correctness/test_from_millisecond_microsecond.groovy
+++ 
b/regression-test/suites/correctness/test_from_millisecond_microsecond.groovy
@@ -320,4 +320,9 @@ suite("test_from_millisecond_microsecond") {
         from millimicro
         order by id;
     """ 
+
+    sql " set time_zone='Asia/Shanghai' "
+    qt_sql " select from_second(-1) "
+    qt_sql " select from_microsecond(253402271999999999) "
+    qt_sql " select from_microsecond(253402272000000000) "
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to