Mryange commented on code in PR #53869:
URL: https://github.com/apache/doris/pull/53869#discussion_r2235347127


##########
be/src/vec/functions/cast/cast_to_basic_number_common.h:
##########
@@ -17,18 +17,314 @@
 
 #pragma once
 
+#include <limits>
 #include <type_traits>
 
 #include "cast_base.h"
 #include "common/status.h"
+#include "runtime/define_primitive_type.h"
 #include "runtime/primitive_type.h"
+#include "vec/core/types.h"
 #include "vec/data_types/data_type_decimal.h"
 #include "vec/data_types/data_type_number.h"
 #include "vec/data_types/data_type_string.h"
 
 namespace doris::vectorized {
 #include "common/compile_check_begin.h"
 
+template <typename CppT>
+static inline constexpr const char* int_type_name = std::is_same_v<CppT, 
vectorized::UInt8> ? "bool"
+                                                    : std::is_same_v<CppT, 
int8_t>     ? "tinyint"
+                                                    : std::is_same_v<CppT, 
int16_t>    ? "smallint"
+                                                    : std::is_same_v<CppT, 
int32_t>    ? "int"
+                                                    : std::is_same_v<CppT, 
int64_t>    ? "bigint"
+                                                    : std::is_same_v<CppT, 
__int128_t> ? "largeint"
+                                                                               
        : "unknown";
+
+template <typename CppT>
+constexpr bool IsCppTypeInt =
+        std::is_same_v<CppT, 
PrimitiveTypeTraits<TYPE_TINYINT>::ColumnItemType> ||
+        std::is_same_v<CppT, 
PrimitiveTypeTraits<TYPE_SMALLINT>::ColumnItemType> ||
+        std::is_same_v<CppT, PrimitiveTypeTraits<TYPE_INT>::ColumnItemType> ||
+        std::is_same_v<CppT, PrimitiveTypeTraits<TYPE_BIGINT>::ColumnItemType> 
||
+        std::is_same_v<CppT, 
PrimitiveTypeTraits<TYPE_LARGEINT>::ColumnItemType>;
+
+template <typename CppT>
+constexpr bool IsCppTypeFloat =
+        std::is_same_v<CppT, PrimitiveTypeTraits<TYPE_FLOAT>::ColumnItemType> 
||
+        std::is_same_v<CppT, PrimitiveTypeTraits<TYPE_DOUBLE>::ColumnItemType>;
+
+template <typename CppT>
+constexpr bool IsCppTypeNumberOrTime =
+        std::is_same_v<CppT, 
PrimitiveTypeTraits<TYPE_BOOLEAN>::ColumnItemType> ||
+        IsCppTypeInt<CppT> || IsCppTypeFloat<CppT> ||
+        std::is_same_v<CppT, PrimitiveTypeTraits<TYPE_TIMEV2>::ColumnItemType>;
+
+// cast to int, may overflow if:
+// 1. from wider int to narrower int
+// 2. from float/double to int
+// 3. from time to tinyint, smallint and int
+template <typename FromCppT, typename ToCppT>
+constexpr bool CastToIntFromWiderInt = IsCppTypeInt<FromCppT> && 
IsCppTypeInt<ToCppT> &&
+                                       sizeof(FromCppT) > sizeof(ToCppT);
+
+template <typename FromCppT, typename ToCppT>
+constexpr bool CastToIntFromTimeMayOverflow =
+        std::is_same_v<FromCppT, 
PrimitiveTypeTraits<TYPE_TIMEV2>::ColumnItemType> &&
+        (std::is_same_v<FromCppT, 
PrimitiveTypeTraits<TYPE_INT>::ColumnItemType> ||
+         std::is_same_v<FromCppT, 
PrimitiveTypeTraits<TYPE_SMALLINT>::ColumnItemType> ||
+         std::is_same_v<FromCppT, 
PrimitiveTypeTraits<TYPE_TINYINT>::ColumnItemType>);
+
+template <typename FromCppT, typename ToCppT>
+constexpr bool CastToIntCppTypeMayOverflow =
+        CastToIntFromWiderInt<FromCppT, ToCppT> || IsCppTypeFloat<FromCppT> ||
+        CastToIntFromTimeMayOverflow<FromCppT, ToCppT>;
+
+template <typename CppT>
+constexpr static bool IntAllowCastFromDate =
+        std::is_same_v<CppT, PrimitiveTypeTraits<TYPE_INT>::ColumnItemType> ||
+        std::is_same_v<CppT, PrimitiveTypeTraits<TYPE_BIGINT>::ColumnItemType> 
||
+        std::is_same_v<CppT, 
PrimitiveTypeTraits<TYPE_LARGEINT>::ColumnItemType>;
+
+template <typename CppT>
+constexpr static bool IntAllowCastFromDatetime =
+        std::is_same_v<CppT, PrimitiveTypeTraits<TYPE_BIGINT>::ColumnItemType> 
||
+        std::is_same_v<CppT, 
PrimitiveTypeTraits<TYPE_LARGEINT>::ColumnItemType>;
+
+template <typename CppT>
+constexpr bool IsCppTypeDate = std::is_same_v<CppT, 
PrimitiveTypeTraits<TYPE_DATE>::CppType> ||
+                               std::is_same_v<CppT, 
PrimitiveTypeTraits<TYPE_DATEV2>::CppType>;
+
+template <typename CppT>
+constexpr bool IsCppTypeDateTime =
+        std::is_same_v<CppT, PrimitiveTypeTraits<TYPE_DATETIME>::CppType> ||
+        std::is_same_v<CppT, PrimitiveTypeTraits<TYPE_DATETIMEV2>::CppType>;
+struct CastToInt {
+    template <typename ToCppT>
+        requires(IsCppTypeInt<ToCppT>)
+    static inline bool from_string(const StringRef& from, ToCppT& to, 
CastParameters& params) {
+        return std::visit(
+                [&](auto is_strict_mode) {
+                    if constexpr (is_strict_mode) {
+                        return try_read_int_text<ToCppT, true>(to, from);
+                    } else {
+                        return try_read_int_text<ToCppT, false>(to, from);
+                    }
+                },
+                vectorized::make_bool_variant(params.is_strict));
+    }
+
+    template <typename FromCppT, typename ToCppT>
+        requires(IsCppTypeInt<ToCppT> &&
+                 std::is_same_v<FromCppT, 
PrimitiveTypeTraits<TYPE_BOOLEAN>::ColumnItemType>)
+    static inline bool from_bool(FromCppT from, ToCppT& to, CastParameters& 
params) {
+        CastUtil::static_cast_set(to, from);
+        return true;
+    }
+
+    // from wider int to narrower int, may overflow
+    template <typename FromCppT, typename ToCppT>
+        requires(IsCppTypeInt<ToCppT> && IsCppTypeInt<FromCppT> &&
+                 CastToIntFromWiderInt<FromCppT, ToCppT>)
+    static inline bool from_int(FromCppT from, ToCppT& to, CastParameters& 
params) {
+        constexpr auto min_to_value = std::numeric_limits<ToCppT>::min();
+        constexpr auto max_to_value = std::numeric_limits<ToCppT>::max();
+        return std::visit(
+                [&](auto is_strict_cast) {
+                    if (from < min_to_value || from > max_to_value) {
+                        // overflow
+                        if constexpr (is_strict_cast) {
+                            params.status = Status::InternalError(
+                                    fmt::format("Value {} out of range for 
type {}", from,
+                                                int_type_name<ToCppT>));
+                        }
+                        return false;
+                    }
+                    CastUtil::static_cast_set(to, from);
+                    return true;
+                },
+                make_bool_variant(params.is_strict));
+    }
+
+    // from narrower int to wider int, no overflow
+    template <typename FromCppT, typename ToCppT>
+        requires(IsCppTypeInt<ToCppT> && IsCppTypeInt<FromCppT> &&
+                 !CastToIntFromWiderInt<FromCppT, ToCppT>)
+    static inline bool from_int(FromCppT from, ToCppT& to, CastParameters& 
params) {
+        CastUtil::static_cast_set(to, from);
+        return true;
+    }
+
+    // from float/double to int, may overflow
+    template <typename FromCppT, typename ToCppT>
+        requires(IsCppTypeInt<ToCppT> && IsCppTypeFloat<FromCppT>)
+    static inline bool from_float(FromCppT from, ToCppT& to, CastParameters& 
params) {
+        constexpr auto min_to_value = std::numeric_limits<ToCppT>::min();
+        constexpr auto max_to_value = std::numeric_limits<ToCppT>::max();
+        return std::visit(
+                [&](auto is_strict_cast) {
+                    if (std::isinf(from) || std::isnan(from)) {
+                        if constexpr (is_strict_cast) {
+                            params.status = Status::InternalError(
+                                    fmt::format("Value {} out of range for 
type {}", from,
+                                                int_type_name<ToCppT>));
+                        }
+                        return false;
+                    }
+                    auto truncated_value = std::trunc(from);
+                    if (truncated_value < min_to_value ||
+                        truncated_value > static_cast<double>(max_to_value)) {
+                        // overflow
+                        if constexpr (is_strict_cast) {
+                            params.status = Status::InternalError(
+                                    fmt::format("Value {} out of range for 
type {}", from,
+                                                int_type_name<ToCppT>));
+                        }
+                        return false;
+                    }
+                    CastUtil::static_cast_set(to, from);
+                    return true;
+                },
+                make_bool_variant(params.is_strict));
+    }
+
+    // from decimal to int, may overflow
+    template <typename FromCppT, typename ToCppT, bool narrow_integral>
+        requires(IsCppTypeInt<ToCppT> && IsDecimalNumber<FromCppT>)
+    static inline bool from_decimal(FromCppT from, UInt32 from_scale,
+                                    const FromCppT::NativeType& 
scale_multiplier, ToCppT& to,
+                                    CastParameters& params) {
+        constexpr auto min_result = std::numeric_limits<ToCppT>::lowest();
+        constexpr auto max_result = std::numeric_limits<ToCppT>::max();
+        auto tmp = from.value / scale_multiplier;
+        if constexpr (narrow_integral) {
+            if (tmp < min_result || tmp > max_result) {
+                params.status = Status::Error(
+                        ErrorCode::ARITHMETIC_OVERFLOW_ERRROR,
+                        fmt::format("Arithmetic overflow when converting "
+                                    "value {} from type {} to type {}",
+                                    decimal_to_string(from.value, from_scale),
+                                    type_to_string(FromCppT::PType), 
int_type_name<ToCppT>));
+                return false;
+            }
+        }
+        to = static_cast<ToCppT>(tmp);
+        return true;
+    }
+
+    // cast from date and datetime to int
+    template <typename FromCppT, typename ToCppT>
+        requires((IsCppTypeDate<FromCppT> && IntAllowCastFromDate<ToCppT>) ||
+                 (IsCppTypeDateTime<FromCppT> && 
IntAllowCastFromDatetime<ToCppT>))
+    static inline bool from_datetime(FromCppT from, ToCppT& to, 
CastParameters& params) {
+        CastUtil::static_cast_set(to, from.to_int64());
+        return true;
+    }
+
+    // from time to bigint and largeint, will not overflow
+    template <typename FromCppT, typename ToCppT>
+        requires(std::is_same_v<ToCppT, 
PrimitiveTypeTraits<TYPE_BIGINT>::CppType> ||
+                 std::is_same_v<ToCppT, 
PrimitiveTypeTraits<TYPE_LARGEINT>::CppType>)
+    static inline bool from_time(FromCppT from, ToCppT& to, CastParameters& 
params) {
+        CastUtil::static_cast_set(to, from);
+        return true;
+    }
+
+    // from time to tinyint, smallint and int, may overflow
+    template <typename FromCppT, typename ToCppT>
+        requires(std::is_same_v<ToCppT, 
PrimitiveTypeTraits<TYPE_TINYINT>::CppType> ||
+                 std::is_same_v<ToCppT, 
PrimitiveTypeTraits<TYPE_SMALLINT>::CppType> ||
+                 std::is_same_v<ToCppT, 
PrimitiveTypeTraits<TYPE_INT>::CppType>)
+    static inline bool from_time(FromCppT from, ToCppT& to, CastParameters& 
params) {
+        constexpr auto min_to_value = std::numeric_limits<ToCppT>::min();
+        constexpr auto max_to_value = std::numeric_limits<ToCppT>::max();
+        return std::visit(
+                [&](auto is_strict_cast) {
+                    if (from < min_to_value || from > max_to_value) {
+                        // overflow
+                        if constexpr (is_strict_cast) {
+                            params.status = Status::InternalError(
+                                    fmt::format("Value {} out of range for 
type {}", from,
+                                                int_type_name<ToCppT>));
+                        }
+                        return false;
+                    }
+                    CastUtil::static_cast_set(to, from);
+                    return true;
+                },
+                make_bool_variant(params.is_strict));
+        return true;
+    }
+};
+
+struct CastToFloat {
+    template <typename ToCppT>
+        requires(IsCppTypeFloat<ToCppT>)
+    static inline bool from_string(const StringRef& from, ToCppT& to, 
CastParameters& params) {
+        return std::visit(
+                [&](auto is_strict_mode) {
+                    if constexpr (is_strict_mode) {
+                        return try_read_float_text(to, from);

Review Comment:
   这两个函数没有区别吧



-- 
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: commits-unsubscr...@doris.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


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

Reply via email to