| // 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. |
| |
| #pragma once |
| #include <cstddef> |
| #include <cstdint> |
| |
| #include "core/block/block.h" |
| #include "core/call_on_type_index.h" |
| #include "core/data_type/data_type.h" |
| #include "core/data_type/data_type_array.h" |
| #include "core/data_type/data_type_bitmap.h" |
| #include "core/data_type/data_type_date.h" |
| #include "core/data_type/data_type_date_or_datetime_v2.h" |
| #include "core/data_type/data_type_date_time.h" |
| #include "core/data_type/data_type_decimal.h" |
| #include "core/data_type/data_type_hll.h" |
| #include "core/data_type/data_type_ipv4.h" |
| #include "core/data_type/data_type_ipv6.h" |
| #include "core/data_type/data_type_jsonb.h" |
| #include "core/data_type/data_type_map.h" |
| #include "core/data_type/data_type_nullable.h" |
| #include "core/data_type/data_type_number.h" |
| #include "core/data_type/data_type_string.h" |
| #include "core/data_type/data_type_struct.h" |
| #include "core/data_type/data_type_time.h" |
| #include "exprs/function/cast/cast_parameters.h" |
| #include "exprs/function/function.h" |
| #include "exprs/function/function_helpers.h" |
| #include "util/io_helper.h" |
| |
| namespace doris { |
| |
| enum class DatelikeParseMode { |
| NON_STRICT, |
| STRICT, |
| }; |
| |
| constexpr bool is_datelike_parse_strict(DatelikeParseMode parse_mode) { |
| return parse_mode == DatelikeParseMode::STRICT; |
| } |
| |
| enum class DatelikeTargetType { |
| DATE, |
| DATE_TIME, |
| }; |
| |
| constexpr bool is_datelike_target_datetime(DatelikeTargetType target_type) { |
| return target_type == DatelikeTargetType::DATE_TIME; |
| } |
| |
| struct NameCast { |
| static constexpr auto name = "CAST"; |
| }; |
| |
| namespace CastUtil { |
| // `static_cast_set` is introduced to wrap `static_cast` and handle special cases. |
| // Doris uses `uint8` to represent boolean values internally. |
| // Directly `static_cast` to `uint8` can result in non-0/1 values, |
| // To address this, `static_cast_set` performs an additional check: |
| // For `uint8` types, it explicitly uses `static_cast<bool>` to ensure |
| // the result is either 0 or 1. |
| template <typename FromFieldType, typename ToFieldType> |
| void static_cast_set(ToFieldType& to, const FromFieldType& from) { |
| // uint8_t now use as boolean in doris |
| if constexpr (std::is_same_v<uint8_t, ToFieldType>) { |
| to = static_cast<bool>(from); |
| } else { |
| to = static_cast<ToFieldType>(from); |
| } |
| } |
| |
| template <typename T> |
| constexpr static bool IsPureDigitType = |
| IsDataTypeInt<T> || IsDataTypeFloat<T> || IsDataTypeDecimal<T>; |
| |
| // IsDataTypeNumber include integer, float and boolean. |
| template <typename T> |
| constexpr static bool IsBaseCastToType = |
| IsDataTypeNumber<T> || IsDataTypeDecimal<T> || IsDatelikeTypes<T> || IsIPType<T>; |
| |
| template <typename T> |
| constexpr static bool IsBaseCastFromType = IsBaseCastToType<T> || IsStringType<T>; |
| |
| } // namespace CastUtil |
| |
| namespace CastWrapper { |
| |
| using WrapperType = std::function<Status(FunctionContext*, Block&, const ColumnNumbers&, uint32_t, |
| size_t, const NullMap::value_type*)>; |
| |
| using ElementWrappers = std::vector<WrapperType>; |
| |
| WrapperType create_unsupport_wrapper(const String error_msg); |
| |
| WrapperType create_unsupport_wrapper(const String from_type_name, const String to_type_name); |
| //// Generic conversion of any type to String. |
| |
| Status cast_from_generic_to_jsonb(FunctionContext* context, Block& block, |
| const ColumnNumbers& arguments, uint32_t result, |
| size_t input_rows_count, |
| const NullMap::value_type* null_map = nullptr); |
| |
| // string to bitmap or hll object |
| Status cast_from_string_to_generic(FunctionContext* context, Block& block, |
| const ColumnNumbers& arguments, uint32_t result, |
| size_t input_rows_count, |
| const NullMap::value_type* null_map = nullptr); |
| |
| Status cast_from_string_to_complex_type(FunctionContext* context, Block& block, |
| const ColumnNumbers& arguments, uint32_t result, |
| size_t input_rows_count, |
| const NullMap::value_type* null_map = nullptr); |
| |
| Status cast_from_string_to_complex_type_strict_mode(FunctionContext* context, Block& block, |
| const ColumnNumbers& arguments, uint32_t result, |
| size_t input_rows_count, |
| const NullMap::value_type* null_map = nullptr); |
| |
| // prepare_unpack_dictionaries -> prepare_remove_nullable -> prepare_impl |
| |
| WrapperType prepare_unpack_dictionaries(FunctionContext* context, const DataTypePtr& from_type, |
| const DataTypePtr& to_type); |
| |
| WrapperType prepare_remove_nullable(FunctionContext* context, const DataTypePtr& from_type, |
| const DataTypePtr& to_type); |
| |
| WrapperType prepare_impl(FunctionContext* context, const DataTypePtr& from_type, |
| const DataTypePtr& to_type); |
| |
| ElementWrappers get_element_wrappers(FunctionContext* context, const DataTypes& from_element_types, |
| const DataTypes& to_element_types); |
| |
| WrapperType create_identity_wrapper(const DataTypePtr&); |
| |
| } // namespace CastWrapper |
| |
| enum class CastModeType { StrictMode, NonStrictMode }; |
| |
| inline std::string cast_mode_type_to_string(CastModeType cast_mode) { |
| switch (cast_mode) { |
| case CastModeType::StrictMode: |
| return "StrictMode"; |
| case CastModeType::NonStrictMode: |
| return "NonStrictMode"; |
| default: |
| return "Unknown"; |
| } |
| } |
| inline std::string cast_mode_type_to_string(CastModeType cast_mode, const DataTypePtr& from_type, |
| const DataTypePtr& to_type) { |
| return fmt::format("{}: from {} cast to {}", cast_mode_type_to_string(cast_mode), |
| from_type->get_name(), to_type->get_name()); |
| } |
| |
| class CastToBase { |
| public: |
| virtual ~CastToBase() = default; |
| virtual Status execute_impl(FunctionContext* context, Block& block, |
| const ColumnNumbers& arguments, uint32_t result, |
| size_t input_rows_count, |
| const NullMap::value_type* null_map = nullptr) const = 0; |
| }; |
| |
| template <CastModeType CastMode, typename FromDataType, typename ToDataType> |
| class CastToImpl : public CastToBase { |
| public: |
| Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
| uint32_t result, size_t input_rows_count, |
| const NullMap::value_type* null_map = nullptr) const override { |
| return Status::RuntimeError( |
| "not support {} ", |
| cast_mode_type_to_string(CastMode, block.get_by_position(arguments[0]).type, |
| block.get_by_position(result).type)); |
| } |
| }; |
| |
| #ifdef BE_TEST |
| inline CastWrapper::WrapperType get_cast_wrapper(FunctionContext* context, |
| const DataTypePtr& from_type, |
| const DataTypePtr& to_type) { |
| return CastWrapper::prepare_unpack_dictionaries(context, from_type, to_type); |
| } |
| #endif |
| } // namespace doris |