|
23 | 23 | #include <cstddef> |
24 | 24 | #include <cstdint> |
25 | 25 | #include <memory> |
| 26 | +#include <string> |
26 | 27 | #include <string_view> |
27 | 28 | #include <type_traits> |
28 | 29 | #include <utility> |
@@ -1819,118 +1820,71 @@ class PeriodDiffImpl { |
1819 | 1820 | } |
1820 | 1821 | }; |
1821 | 1822 |
|
1822 | | -struct AddTimeImpl { |
1823 | | - static constexpr auto name = "add_time"; |
1824 | | - static bool is_negative() { return false; } |
1825 | | -}; |
1826 | | - |
1827 | | -struct SubTimeImpl { |
1828 | | - static constexpr auto name = "sub_time"; |
1829 | | - static bool is_negative() { return true; } |
1830 | | -}; |
1831 | | - |
1832 | | -template <PrimitiveType PType, typename Impl> |
1833 | | -class FunctionAddTime : public IFunction { |
| 1823 | +template <PrimitiveType PType, bool IsNegative> |
| 1824 | +class AddTimeImplBase { |
1834 | 1825 | public: |
1835 | | - static constexpr auto name = Impl::name; |
1836 | | - static constexpr PrimitiveType ReturnType = PType; |
1837 | | - static constexpr PrimitiveType ArgType1 = PType; |
1838 | | - static constexpr PrimitiveType ArgType2 = TYPE_TIMEV2; |
1839 | | - using ColumnType1 = typename PrimitiveTypeTraits<PType>::ColumnType; |
1840 | | - using ColumnType2 = typename PrimitiveTypeTraits<TYPE_TIMEV2>::ColumnType; |
| 1826 | + static constexpr auto name = IsNegative ? "sub_time" : "add_time"; |
1841 | 1827 | using InputType1 = typename PrimitiveTypeTraits<PType>::DataType::FieldType; |
1842 | 1828 | using InputType2 = typename PrimitiveTypeTraits<TYPE_TIMEV2>::DataType::FieldType; |
1843 | | - using ReturnNativeType = InputType1; |
1844 | | - using ReturnDataType = typename PrimitiveTypeTraits<PType>::DataType; |
| 1829 | + using ResultColumnType = typename PrimitiveTypeTraits<PType>::ColumnType; |
1845 | 1830 |
|
1846 | | - String get_name() const override { return name; } |
1847 | | - size_t get_number_of_arguments() const override { return 2; } |
1848 | | - DataTypes get_variadic_argument_types_impl() const override { |
| 1831 | + static size_t get_number_of_arguments() { return 2; } |
| 1832 | + static bool is_variadic() { return true; } |
| 1833 | + static DataTypes get_variadic_argument_types_impl() { |
1849 | 1834 | return {std::make_shared<typename PrimitiveTypeTraits<PType>::DataType>(), |
1850 | 1835 | std::make_shared<typename PrimitiveTypeTraits<TYPE_TIMEV2>::DataType>()}; |
1851 | 1836 | } |
1852 | | - DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments) const override { |
1853 | | - return std::make_shared<ReturnDataType>(); |
1854 | | - } |
1855 | | - |
1856 | | - ReturnNativeType compute(const InputType1& arg1, const InputType2& arg2) const { |
1857 | | - if constexpr (PType == TYPE_DATETIMEV2) { |
1858 | | - DateV2Value<DateTimeV2ValueType> dtv1 = |
1859 | | - binary_cast<InputType1, DateV2Value<DateTimeV2ValueType>>(arg1); |
1860 | | - auto tv2 = static_cast<TimeValue::TimeType>(arg2); |
1861 | | - TimeInterval interval(TimeUnit::MICROSECOND, tv2, Impl::is_negative()); |
1862 | | - bool out_range = dtv1.template date_add_interval<TimeUnit::MICROSECOND>(interval); |
1863 | | - if (UNLIKELY(!out_range)) { |
1864 | | - throw Exception(ErrorCode::INVALID_ARGUMENT, |
1865 | | - "datetime value is out of range in function {}", name); |
1866 | | - } |
1867 | | - return binary_cast<DateV2Value<DateTimeV2ValueType>, ReturnNativeType>(dtv1); |
1868 | | - } else if constexpr (PType == TYPE_TIMEV2) { |
1869 | | - auto tv1 = static_cast<TimeValue::TimeType>(arg1); |
1870 | | - auto tv2 = static_cast<TimeValue::TimeType>(arg2); |
1871 | | - double res = TimeValue::limit_with_bound(Impl::is_negative() ? tv1 - tv2 : tv1 + tv2); |
1872 | | - return res; |
1873 | | - } else { |
1874 | | - throw Exception(ErrorCode::FATAL_ERROR, "not support type for function {}", name); |
| 1837 | + static DataTypePtr get_return_type_impl(const DataTypes& arguments) { |
| 1838 | + if (arguments[0]->is_nullable() || arguments[1]->is_nullable()) { |
| 1839 | + return make_nullable(std::make_shared<typename PrimitiveTypeTraits<PType>::DataType>()); |
1875 | 1840 | } |
| 1841 | + return std::make_shared<typename PrimitiveTypeTraits<PType>::DataType>(); |
1876 | 1842 | } |
1877 | 1843 |
|
1878 | | - static FunctionPtr create() { return std::make_shared<FunctionAddTime>(); } |
1879 | | - |
1880 | | - Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
1881 | | - uint32_t result, size_t input_rows_count) const override { |
1882 | | - DCHECK_EQ(arguments.size(), 2); |
1883 | | - const auto& [left_col, left_const] = |
1884 | | - unpack_if_const(block.get_by_position(arguments[0]).column); |
1885 | | - const auto& [right_col, right_const] = |
1886 | | - unpack_if_const(block.get_by_position(arguments[1]).column); |
1887 | | - ColumnPtr nest_col1 = remove_nullable(left_col); |
1888 | | - ColumnPtr nest_col2 = remove_nullable(right_col); |
1889 | | - auto res = ColumnVector<ReturnType>::create(input_rows_count, 0); |
1890 | | - |
1891 | | - if (left_const) { |
1892 | | - execute_constant_vector(assert_cast<const ColumnType1&>(*nest_col1).get_element(0), |
1893 | | - assert_cast<const ColumnType2&>(*nest_col2).get_data(), |
1894 | | - res->get_data(), input_rows_count); |
1895 | | - } else if (right_const) { |
1896 | | - execute_vector_constant(assert_cast<const ColumnType1&>(*nest_col1).get_data(), |
1897 | | - assert_cast<const ColumnType2&>(*nest_col2).get_element(0), |
1898 | | - res->get_data(), input_rows_count); |
1899 | | - } else { |
1900 | | - execute_vector_vector(assert_cast<const ColumnType1&>(*nest_col1).get_data(), |
1901 | | - assert_cast<const ColumnType2&>(*nest_col2).get_data(), |
1902 | | - res->get_data(), input_rows_count); |
1903 | | - } |
1904 | | - |
1905 | | - block.replace_by_position(result, std::move(res)); |
1906 | | - return Status::OK(); |
1907 | | - } |
1908 | | - void execute_vector_vector(const PaddedPODArray<InputType1>& left_col, |
1909 | | - const PaddedPODArray<InputType2>& right_col, |
1910 | | - PaddedPODArray<ReturnNativeType>& res_data, |
1911 | | - size_t input_rows_count) const { |
1912 | | - for (size_t i = 0; i < input_rows_count; ++i) { |
1913 | | - res_data[i] = compute(left_col[i], right_col[i]); |
1914 | | - } |
1915 | | - } |
| 1844 | + static void execute(const std::vector<ColumnWithConstAndNullMap>& cols_info, |
| 1845 | + typename ResultColumnType::MutablePtr& res_col, |
| 1846 | + PaddedPODArray<UInt8>& res_null_map_data, size_t input_rows_count) { |
| 1847 | + const auto& left_data = |
| 1848 | + assert_cast<const ResultColumnType*>(cols_info[0].nested_col)->get_data(); |
| 1849 | + const auto& right_data = |
| 1850 | + assert_cast<const ColumnVector<TYPE_TIMEV2>*>(cols_info[1].nested_col)->get_data(); |
1916 | 1851 |
|
1917 | | - void execute_vector_constant(const PaddedPODArray<InputType1>& left_col, |
1918 | | - const InputType2 right_value, |
1919 | | - PaddedPODArray<ReturnNativeType>& res_data, |
1920 | | - size_t input_rows_count) const { |
1921 | 1852 | for (size_t i = 0; i < input_rows_count; ++i) { |
1922 | | - res_data[i] = compute(left_col[i], right_value); |
1923 | | - } |
1924 | | - } |
| 1853 | + if (cols_info[0].is_null_at(i) || cols_info[1].is_null_at(i)) { |
| 1854 | + res_col->insert_default(); |
| 1855 | + res_null_map_data[i] = 1; |
| 1856 | + continue; |
| 1857 | + } |
1925 | 1858 |
|
1926 | | - void execute_constant_vector(const InputType1 left_value, |
1927 | | - const PaddedPODArray<InputType2>& right_col, |
1928 | | - PaddedPODArray<ReturnNativeType>& res_data, |
1929 | | - size_t input_rows_count) const { |
1930 | | - for (size_t i = 0; i < input_rows_count; ++i) { |
1931 | | - res_data[i] = compute(left_value, right_col[i]); |
| 1859 | + const auto& arg1 = left_data[index_check_const(i, cols_info[0].is_const)]; |
| 1860 | + const auto& arg2 = right_data[index_check_const(i, cols_info[1].is_const)]; |
| 1861 | + |
| 1862 | + if constexpr (PType == TYPE_DATETIMEV2) { |
| 1863 | + DateV2Value<DateTimeV2ValueType> dtv1 = |
| 1864 | + binary_cast<InputType1, DateV2Value<DateTimeV2ValueType>>(arg1); |
| 1865 | + auto tv2 = static_cast<TimeValue::TimeType>(arg2); |
| 1866 | + TimeInterval interval(TimeUnit::MICROSECOND, tv2, IsNegative); |
| 1867 | + bool out_range = dtv1.template date_add_interval<TimeUnit::MICROSECOND>(interval); |
| 1868 | + if (!out_range) [[unlikely]] { |
| 1869 | + throw_invalid_strings(name, dtv1.to_string(), std::to_string(arg2)); |
| 1870 | + } |
| 1871 | + res_col->insert_value( |
| 1872 | + binary_cast<DateV2Value<DateTimeV2ValueType>, InputType1>(dtv1)); |
| 1873 | + } else if constexpr (PType == TYPE_TIMEV2) { |
| 1874 | + auto tv1 = static_cast<TimeValue::TimeType>(arg1); |
| 1875 | + auto tv2 = static_cast<TimeValue::TimeType>(arg2); |
| 1876 | + double res = TimeValue::limit_with_bound(IsNegative ? tv1 - tv2 : tv1 + tv2); |
| 1877 | + res_col->insert_value(res); |
| 1878 | + } else { |
| 1879 | + throw Exception(ErrorCode::FATAL_ERROR, "not support type for function {}", name); |
| 1880 | + } |
1932 | 1881 | } |
1933 | 1882 | } |
1934 | 1883 | }; |
| 1884 | + |
| 1885 | +using AddTimeDatetimeImpl = AddTimeImplBase<TYPE_DATETIMEV2, false>; |
| 1886 | +using AddTimeTimeImpl = AddTimeImplBase<TYPE_TIMEV2, false>; |
| 1887 | +using SubTimeDatetimeImpl = AddTimeImplBase<TYPE_DATETIMEV2, true>; |
| 1888 | +using SubTimeTimeImpl = AddTimeImplBase<TYPE_TIMEV2, true>; |
1935 | 1889 | #include "common/compile_check_avoid_end.h" |
1936 | 1890 | } // namespace doris::vectorized |
0 commit comments