mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +00:00
refactor code2
This commit is contained in:
parent
4a1535cc37
commit
2cf83d2cee
@ -27,8 +27,11 @@ inline void throwIfDivisionLeadsToFPE(A a, B b)
|
||||
throw Exception(ErrorCodes::ILLEGAL_DIVISION, "Division by zero");
|
||||
|
||||
/// http://avva.livejournal.com/2548306.html
|
||||
if (unlikely(is_signed_v<A> && is_signed_v<B> && a == std::numeric_limits<A>::min() && b == -1))
|
||||
throw Exception(ErrorCodes::ILLEGAL_DIVISION, "Division of minimal signed number by minus one");
|
||||
if constexpr (is_signed_v<A> && is_signed_v<B>)
|
||||
{
|
||||
if (unlikely(a == std::numeric_limits<A>::min() && b == -1))
|
||||
throw Exception(ErrorCodes::ILLEGAL_DIVISION, "Division of minimal signed number by minus one");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
@ -37,8 +40,11 @@ inline bool divisionLeadsToFPE(A a, B b)
|
||||
if (unlikely(b == 0))
|
||||
return true;
|
||||
|
||||
if (unlikely(is_signed_v<A> && is_signed_v<B> && a == std::numeric_limits<A>::min() && b == -1))
|
||||
return true;
|
||||
if constexpr (is_signed_v<A> && is_signed_v<B>)
|
||||
{
|
||||
if (unlikely(a == std::numeric_limits<A>::min() && b == -1))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -284,7 +284,7 @@ struct BinaryOperation
|
||||
|
||||
static ResultType process(A a, B b) { return Op::template apply<ResultType>(a, b); }
|
||||
|
||||
static ResultType process(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr) { return Op::template apply<ResultType>(a, b, m); }
|
||||
static ResultType process(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr) { return Op::template apply<ResultType>(a, b); }
|
||||
|
||||
private:
|
||||
template <OpCase op_case>
|
||||
@ -553,7 +553,7 @@ private:
|
||||
public:
|
||||
template <OpCase op_case, bool is_decimal_a, bool is_decimal_b>
|
||||
static void NO_INLINE process(const auto & a, const auto & b, ResultContainerType & c,
|
||||
NativeResultType scale_a, NativeResultType scale_b, const NullMap * right_nullmap = nullptr)
|
||||
NativeResultType scale_a, NativeResultType scale_b, const NullMap * right_nullmap = nullptr, NullMap * res_nullmap = nullptr)
|
||||
{
|
||||
if constexpr (op_case == OpCase::LeftConstant) static_assert(!is_decimal<decltype(a)>);
|
||||
if constexpr (op_case == OpCase::RightConstant) static_assert(!is_decimal<decltype(b)>);
|
||||
@ -609,7 +609,7 @@ public:
|
||||
}
|
||||
else if constexpr (is_division && is_decimal_b)
|
||||
{
|
||||
processWithRightNullmapImpl<op_case>(a, b, c, size, right_nullmap, [&scale_a](const auto & left, const auto & right)
|
||||
processWithRightNullmapImpl<op_case>(a, b, c, size, right_nullmap, res_nullmap, [&scale_a](const auto & left, const auto & right)
|
||||
{
|
||||
return applyScaledDiv<is_decimal_a>(
|
||||
static_cast<NativeResultType>(left), right, scale_a);
|
||||
@ -618,7 +618,7 @@ public:
|
||||
}
|
||||
|
||||
processWithRightNullmapImpl<op_case>(
|
||||
a, b, c, size, right_nullmap,
|
||||
a, b, c, size, right_nullmap, res_nullmap,
|
||||
[](const auto & left, const auto & right)
|
||||
{
|
||||
return apply(
|
||||
@ -628,25 +628,42 @@ public:
|
||||
}
|
||||
|
||||
template <bool is_decimal_a, bool is_decimal_b, class A, class B>
|
||||
static ResultType process(A a, B b, NativeResultType scale_a, NativeResultType scale_b)
|
||||
static ResultType process(A a, B b, NativeResultType scale_a, NativeResultType scale_b, NullMap * res_nullmap)
|
||||
requires(!is_decimal<A> && !is_decimal<B>)
|
||||
{
|
||||
if constexpr (is_division && is_decimal_b)
|
||||
return applyScaledDiv<is_decimal_a>(a, b, scale_a);
|
||||
else if constexpr (is_plus_minus_compare)
|
||||
try
|
||||
{
|
||||
if (scale_a != 1)
|
||||
return applyScaled<true>(a, b, scale_a);
|
||||
if (scale_b != 1)
|
||||
return applyScaled<false>(a, b, scale_b);
|
||||
}
|
||||
if constexpr (is_division && is_decimal_b)
|
||||
return applyScaledDiv<is_decimal_a>(a, b, scale_a);
|
||||
else if constexpr (is_plus_minus_compare)
|
||||
{
|
||||
if (scale_a != 1)
|
||||
return applyScaled<true>(a, b, scale_a);
|
||||
if (scale_b != 1)
|
||||
return applyScaled<false>(a, b, scale_b);
|
||||
}
|
||||
|
||||
return apply(a, b);
|
||||
ResultType res = apply(a, b);
|
||||
if constexpr (std::is_floating_point_v<ResultType>)
|
||||
{
|
||||
if (!std::isfinite(res) && res_nullmap)
|
||||
(*res_nullmap)[0] = 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
if (res_nullmap)
|
||||
(*res_nullmap)[0] = 1;
|
||||
else
|
||||
throw;
|
||||
return ResultType();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <OpCase op_case, typename ApplyFunc>
|
||||
static void processWithRightNullmapImpl(const auto & a, const auto & b, ResultContainerType & c, size_t size, const NullMap * right_nullmap, ApplyFunc apply_func)
|
||||
static void processWithRightNullmapImpl(const auto & a, const auto & b, ResultContainerType & c, size_t size, const NullMap * right_nullmap, NullMap * res_nullmap, ApplyFunc apply_func)
|
||||
{
|
||||
if (right_nullmap)
|
||||
{
|
||||
@ -660,7 +677,24 @@ private:
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
c[i] = apply_func(undec(a[i]), undec(b));
|
||||
{
|
||||
try
|
||||
{
|
||||
c[i] = apply_func(undec(a[i]), undec(b));
|
||||
if constexpr (std::is_floating_point_v<ResultContainerType>)
|
||||
{
|
||||
if (!std::isfinite(c[i]) && res_nullmap)
|
||||
(*res_nullmap)[i] = 1;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
if (res_nullmap)
|
||||
(*res_nullmap)[i] = 1;
|
||||
else
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -669,19 +703,55 @@ private:
|
||||
if ((*right_nullmap)[i])
|
||||
c[i] = ResultType();
|
||||
else
|
||||
c[i] = apply_func(unwrap<op_case, OpCase::LeftConstant>(a, i), undec(b[i]));
|
||||
{
|
||||
try
|
||||
{
|
||||
c[i] = apply_func(unwrap<op_case, OpCase::LeftConstant>(a, i), undec(b[i]));
|
||||
if constexpr (std::is_floating_point_v<ResultContainerType>)
|
||||
{
|
||||
if (!std::isfinite(c[i]) && res_nullmap)
|
||||
(*res_nullmap)[i] = 1;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
if (res_nullmap)
|
||||
(*res_nullmap)[i] = 1;
|
||||
else
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
c[i] = apply_func(unwrap<op_case, OpCase::LeftConstant>(a, i), unwrap<op_case, OpCase::RightConstant>(b, i));
|
||||
{
|
||||
try
|
||||
{
|
||||
c[i] = apply_func(unwrap<op_case, OpCase::LeftConstant>(a, i), unwrap<op_case, OpCase::RightConstant>(b, i));
|
||||
if constexpr (std::is_floating_point_v<ResultContainerType>)
|
||||
{
|
||||
if (!std::isfinite(c[i]) && res_nullmap)
|
||||
(*res_nullmap)[i] = 1;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
if (res_nullmap)
|
||||
(*res_nullmap)[i] = 1;
|
||||
else
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr bool is_plus_minus = IsOperation<Operation>::plus ||
|
||||
IsOperation<Operation>::minus;
|
||||
static constexpr bool is_multiply = IsOperation<Operation>::multiply;
|
||||
static constexpr bool is_float_division = IsOperation<Operation>::div_floating;
|
||||
static constexpr bool is_float_division = IsOperation<Operation>::div_floating || IsOperation<Operation>::divide_or_null;
|
||||
static constexpr bool is_int_division = IsOperation<Operation>::int_div ||
|
||||
IsOperation<Operation>::int_div_or_zero;
|
||||
static constexpr bool is_division = is_float_division || is_int_division;
|
||||
@ -1346,12 +1416,12 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
}
|
||||
|
||||
template <OpCase op_case, bool left_decimal, bool right_decimal, typename OpImpl, typename OpImplCheck>
|
||||
void helperInvokeEither(const auto& left, const auto& right, auto& vec_res, auto scale_a, auto scale_b, const NullMap * right_nullmap) const
|
||||
void helperInvokeEither(const auto& left, const auto& right, auto& vec_res, auto scale_a, auto scale_b, const NullMap * right_nullmap, NullMap * res_nullmap) const
|
||||
{
|
||||
if (check_decimal_overflow)
|
||||
OpImplCheck::template process<op_case, left_decimal, right_decimal>(left, right, vec_res, scale_a, scale_b, right_nullmap);
|
||||
OpImplCheck::template process<op_case, left_decimal, right_decimal>(left, right, vec_res, scale_a, scale_b, right_nullmap, res_nullmap);
|
||||
else
|
||||
OpImpl::template process<op_case, left_decimal, right_decimal>(left, right, vec_res, scale_a, scale_b, right_nullmap);
|
||||
OpImpl::template process<op_case, left_decimal, right_decimal>(left, right, vec_res, scale_a, scale_b, right_nullmap, res_nullmap);
|
||||
}
|
||||
|
||||
template <class LeftDataType, class RightDataType, class ResultDataType>
|
||||
@ -1359,7 +1429,7 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
const auto & left, const auto & right,
|
||||
const ColumnConst * const col_left_const, const ColumnConst * const col_right_const,
|
||||
const auto * const col_left, const auto * const col_right,
|
||||
size_t col_left_size, const NullMap * right_nullmap) const
|
||||
size_t col_left_size, const NullMap * right_nullmap, NullMap * res_nullmap) const
|
||||
{
|
||||
using T0 = typename LeftDataType::FieldType;
|
||||
using T1 = typename RightDataType::FieldType;
|
||||
@ -1414,8 +1484,8 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
ResultType res = {};
|
||||
if (!right_nullmap || !(*right_nullmap)[0])
|
||||
res = check_decimal_overflow
|
||||
? OpImplCheck::template process<left_is_decimal, right_is_decimal>(const_a, const_b, scale_a, scale_b)
|
||||
: OpImpl::template process<left_is_decimal, right_is_decimal>(const_a, const_b, scale_a, scale_b);
|
||||
? OpImplCheck::template process<left_is_decimal, right_is_decimal>(const_a, const_b, scale_a, scale_b, res_nullmap)
|
||||
: OpImpl::template process<left_is_decimal, right_is_decimal>(const_a, const_b, scale_a, scale_b, res_nullmap);
|
||||
|
||||
return ResultDataType(type.getPrecision(), type.getScale())
|
||||
.createColumnConst(col_left_const->size(), toField(res, type.getScale()));
|
||||
@ -1429,7 +1499,7 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
if (col_left && col_right)
|
||||
{
|
||||
helperInvokeEither<OpCase::Vector, left_is_decimal, right_is_decimal, OpImpl, OpImplCheck>(
|
||||
col_left->getData(), col_right->getData(), vec_res, scale_a, scale_b, right_nullmap);
|
||||
col_left->getData(), col_right->getData(), vec_res, scale_a, scale_b, right_nullmap, res_nullmap);
|
||||
}
|
||||
else if (col_left_const && col_right)
|
||||
{
|
||||
@ -1437,7 +1507,7 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
helperGetOrConvert<T0, ResultDataType>(col_left_const, left));
|
||||
|
||||
helperInvokeEither<OpCase::LeftConstant, left_is_decimal, right_is_decimal, OpImpl, OpImplCheck>(
|
||||
const_a, col_right->getData(), vec_res, scale_a, scale_b, right_nullmap);
|
||||
const_a, col_right->getData(), vec_res, scale_a, scale_b, right_nullmap, res_nullmap);
|
||||
}
|
||||
else if (col_left && col_right_const)
|
||||
{
|
||||
@ -1445,7 +1515,7 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
helperGetOrConvert<T1, ResultDataType>(col_right_const, right));
|
||||
|
||||
helperInvokeEither<OpCase::RightConstant, left_is_decimal, right_is_decimal, OpImpl, OpImplCheck>(
|
||||
col_left->getData(), const_b, vec_res, scale_a, scale_b, right_nullmap);
|
||||
col_left->getData(), const_b, vec_res, scale_a, scale_b, right_nullmap, res_nullmap);
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
@ -2098,7 +2168,8 @@ ColumnPtr executeStringInteger(const ColumnsWithTypeAndName & arguments, const A
|
||||
col_left_const, col_right_const,
|
||||
col_left, col_right,
|
||||
col_left_size,
|
||||
right_nullmap);
|
||||
right_nullmap,
|
||||
res_nullmap);
|
||||
}
|
||||
/// Here we check if we have `intDiv` or `intDivOrZero` and at least one of the arguments is decimal, because in this case originally we had result as decimal, so we need to convert result into integer after calculations
|
||||
else if constexpr (!decimal_with_float && (is_int_div || is_int_div_or_zero) && (IsDataTypeDecimal<LeftDataType> || IsDataTypeDecimal<RightDataType>))
|
||||
@ -2122,7 +2193,8 @@ ColumnPtr executeStringInteger(const ColumnsWithTypeAndName & arguments, const A
|
||||
col_left_const, col_right_const,
|
||||
col_left, col_right,
|
||||
col_left_size,
|
||||
right_nullmap);
|
||||
right_nullmap,
|
||||
res_nullmap);
|
||||
|
||||
auto col = ColumnWithTypeAndName(res, type_res, name);
|
||||
return castColumn(col, std::make_shared<ResultDataType>());
|
||||
@ -2253,10 +2325,9 @@ ColumnPtr executeStringInteger(const ColumnsWithTypeAndName & arguments, const A
|
||||
auto res = executeImpl2(createBlockWithNestedColumns(arguments), removeNullable(result_type), input_rows_count, &right_null_map, &res_null_map);
|
||||
return wrapInNullable(res, arguments, result_type, input_rows_count, &res_null_map);
|
||||
}
|
||||
/// Process special case when operation is divideOrNull and moduloOrNull
|
||||
/// Process special case when operation is divideOrNull and moduloOrNull which will return NULL divided zero.
|
||||
else if ((is_divide_or_null || is_modulo_or_null) && !res_nullmap)
|
||||
{
|
||||
std::cerr << "gethere divornull or modornull and resnull map is null" << std::endl;
|
||||
NullMap res_null_map(input_rows_count, 0);
|
||||
auto res = executeImpl2(arguments, result_type, input_rows_count, nullptr, &res_null_map);
|
||||
return wrapInNullable(res, arguments, result_type, input_rows_count, &res_null_map);
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <base/extended_types.h>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <Columns/ColumnNullable.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@ -50,20 +49,6 @@ struct GCDLCMImpl
|
||||
return Impl::applyImpl(a, b);
|
||||
}
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a, B b, NullMap::value_type *m)
|
||||
{
|
||||
try
|
||||
{
|
||||
return apply(a, b);
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
*m = 1;
|
||||
return Result();
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
static constexpr bool compilable = false; /// exceptions (and a non-trivial algorithm)
|
||||
#endif
|
||||
|
@ -64,7 +64,7 @@ struct IsOperation
|
||||
|
||||
static constexpr bool bit_hamming_distance = IsSameOperation<Op, BitHammingDistanceImpl>::value;
|
||||
|
||||
static constexpr bool division = div_floating || int_div || int_div_or_zero || modulo || modulo_or_null;
|
||||
static constexpr bool division = div_floating || int_div || int_div_or_zero || modulo || modulo_or_null || divide_or_null;
|
||||
// NOTE: allow_decimal should not fully contain `division` because of divInt
|
||||
static constexpr bool allow_decimal = plus || minus || multiply || division || least || greatest;
|
||||
};
|
||||
|
@ -20,7 +20,7 @@ struct BitAndImpl
|
||||
static constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply(A a, B b)
|
||||
{
|
||||
return static_cast<Result>(a) & static_cast<Result>(b);
|
||||
}
|
||||
|
@ -25,20 +25,12 @@ struct BitBoolMaskAndImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply([[maybe_unused]] A left, [[maybe_unused]] B right, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply([[maybe_unused]] A left, [[maybe_unused]] B right)
|
||||
{
|
||||
// Should be a logical error, but this function is callable from SQL.
|
||||
// Need to investigate this.
|
||||
if constexpr (!std::is_same_v<A, ResultType> || !std::is_same_v<B, ResultType>)
|
||||
{
|
||||
if (!m)
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS, "It's a bug! Only UInt8 type is supported by __bitBoolMaskAnd.");
|
||||
else
|
||||
{
|
||||
*m = 1;
|
||||
return Result();
|
||||
}
|
||||
}
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS, "It's a bug! Only UInt8 type is supported by __bitBoolMaskAnd.");
|
||||
|
||||
auto left_bits = littleBits<A>(left);
|
||||
auto right_bits = littleBits<B>(right);
|
||||
|
@ -25,20 +25,12 @@ struct BitBoolMaskOrImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply([[maybe_unused]] A left, [[maybe_unused]] B right, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply([[maybe_unused]] A left, [[maybe_unused]] B right)
|
||||
{
|
||||
if constexpr (!std::is_same_v<A, ResultType> || !std::is_same_v<B, ResultType>)
|
||||
{
|
||||
if (!m)
|
||||
// Should be a logical error, but this function is callable from SQL.
|
||||
// Need to investigate this.
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS, "It's a bug! Only UInt8 type is supported by __bitBoolMaskOr.");
|
||||
else
|
||||
{
|
||||
*m = 1;
|
||||
return Result();
|
||||
}
|
||||
}
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS, "It's a bug! Only UInt8 type is supported by __bitBoolMaskOr.");
|
||||
|
||||
auto left_bits = littleBits<A>(left);
|
||||
auto right_bits = littleBits<B>(right);
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
#include <bit>
|
||||
|
||||
|
||||
@ -20,7 +19,7 @@ struct BitHammingDistanceImpl
|
||||
static constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a, B b)
|
||||
{
|
||||
/// Note: it's unspecified if signed integers should be promoted with sign-extension or with zero-fill.
|
||||
/// This behavior can change in the future.
|
||||
@ -40,15 +39,7 @@ struct BitHammingDistanceImpl
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m)
|
||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Unsupported data type combination in function 'bitHammingDistance'");
|
||||
else
|
||||
{
|
||||
*m = 1;
|
||||
return Result();
|
||||
}
|
||||
}
|
||||
throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Unsupported data type combination in function 'bitHammingDistance'");
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
|
@ -19,7 +19,7 @@ struct BitOrImpl
|
||||
static constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply(A a, B b)
|
||||
{
|
||||
return static_cast<Result>(a) | static_cast<Result>(b);
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
#include "Core/Types.h"
|
||||
|
||||
namespace DB
|
||||
@ -22,7 +21,7 @@ struct BitRotateLeftImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]], NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]])
|
||||
{
|
||||
if constexpr (is_big_int_v<A> || is_big_int_v<B>)
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Bit rotate is not implemented for big integers");
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -21,7 +20,7 @@ struct BitRotateRightImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]], NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]])
|
||||
{
|
||||
if constexpr (is_big_int_v<A> || is_big_int_v<B>)
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Bit rotate is not implemented for big integers");
|
||||
|
@ -21,20 +21,12 @@ struct BitShiftLeftImpl
|
||||
static const constexpr bool allow_string_integer = true;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]], NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]])
|
||||
{
|
||||
if constexpr (is_big_int_v<B>)
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "BitShiftLeft is not implemented for big integers as second argument");
|
||||
else if (b < 0 || static_cast<UInt256>(b) > 8 * sizeof(A))
|
||||
{
|
||||
if (!m)
|
||||
throw Exception(ErrorCodes::ARGUMENT_OUT_OF_BOUND, "The number of shift positions needs to be a non-negative value and less or equal to the bit width of the value to shift");
|
||||
else
|
||||
{
|
||||
*m = 1;
|
||||
return Result();
|
||||
}
|
||||
}
|
||||
throw Exception(ErrorCodes::ARGUMENT_OUT_OF_BOUND, "The number of shift positions needs to be a non-negative value and less or equal to the bit width of the value to shift");
|
||||
else if constexpr (is_big_int_v<A>)
|
||||
return static_cast<Result>(a) << static_cast<UInt32>(b);
|
||||
else
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include <base/hex.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -23,20 +22,12 @@ struct BitShiftRightImpl
|
||||
static const constexpr bool allow_string_integer = true;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]], NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]])
|
||||
{
|
||||
if constexpr (is_big_int_v<B>)
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "BitShiftRight is not implemented for big integers as second argument");
|
||||
else if (b < 0 || static_cast<UInt256>(b) > 8 * sizeof(A))
|
||||
{
|
||||
if (!m)
|
||||
throw Exception(ErrorCodes::ARGUMENT_OUT_OF_BOUND, "The number of shift positions needs to be a non-negative value and less or equal to the bit width of the value to shift");
|
||||
else
|
||||
{
|
||||
*m = 1;
|
||||
return Result();
|
||||
}
|
||||
}
|
||||
else if constexpr (is_big_int_v<A>)
|
||||
return static_cast<Result>(a) >> static_cast<UInt32>(b);
|
||||
else
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include <Core/Defines.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -23,7 +22,7 @@ struct BitTestImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a [[maybe_unused]], B b [[maybe_unused]], NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply(A a [[maybe_unused]], B b [[maybe_unused]])
|
||||
{
|
||||
if constexpr (is_big_int_v<A> || is_big_int_v<B>)
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "bitTest is not implemented for big integers as second argument");
|
||||
@ -33,17 +32,9 @@ struct BitTestImpl
|
||||
typename NumberTraits::ToInteger<B>::Type b_int = b;
|
||||
const auto max_position = static_cast<decltype(b)>((8 * sizeof(a)) - 1);
|
||||
if (b_int > max_position || b_int < 0)
|
||||
{
|
||||
if (!m)
|
||||
throw Exception(ErrorCodes::PARAMETER_OUT_OF_BOUND,
|
||||
throw Exception(ErrorCodes::PARAMETER_OUT_OF_BOUND,
|
||||
"The bit position argument needs to a positive value and less or equal to {} for integer {}",
|
||||
std::to_string(max_position), std::to_string(a_int));
|
||||
else
|
||||
{
|
||||
*m = 1;
|
||||
return Result();
|
||||
}
|
||||
}
|
||||
return (a_int >> b_int) & 1;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -20,7 +19,7 @@ struct BitXorImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply(A a, B b)
|
||||
{
|
||||
return static_cast<Result>(a) ^ static_cast<Result>(b);
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include <Functions/GCDLCMImpl.h>
|
||||
|
||||
#include <boost/integer/common_factor.hpp>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -19,7 +18,7 @@ struct GCDImpl : public GCDLCMImpl<A, B, GCDImpl<A, B>, NameGCD>
|
||||
{
|
||||
using ResultType = typename GCDLCMImpl<A, B, GCDImpl, NameGCD>::ResultType;
|
||||
|
||||
static ResultType applyImpl(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static ResultType applyImpl(A a, B b)
|
||||
{
|
||||
using Int = typename NumberTraits::ToInteger<ResultType>::Type;
|
||||
return boost::integer::gcd(Int(a), Int(b)); // NOLINT(clang-analyzer-core.UndefinedBinaryOperatorResult)
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include <Core/AccurateComparison.h>
|
||||
#include <Functions/LeastGreatestGeneric.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -16,7 +15,7 @@ struct GreatestBaseImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply(A a, B b)
|
||||
{
|
||||
return static_cast<Result>(a) > static_cast<Result>(b) ?
|
||||
static_cast<Result>(a) : static_cast<Result>(b);
|
||||
@ -47,7 +46,7 @@ struct GreatestSpecialImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply(A a, B b)
|
||||
{
|
||||
static_assert(std::is_same_v<Result, ResultType>, "ResultType != Result");
|
||||
return accurate::greaterOp(a, b) ? static_cast<Result>(a) : static_cast<Result>(b);
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
|
||||
#include "Columns/ColumnNullable.h"
|
||||
#include "divide/divide.h"
|
||||
|
||||
|
||||
@ -27,7 +26,7 @@ struct DivideIntegralByConstantImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <OpCase op_case>
|
||||
static void NO_INLINE process(const A * __restrict a, const B * __restrict b, ResultType * __restrict c, size_t size, const NullMap * right_nullmap, NullMap * res_nullmap)
|
||||
static void NO_INLINE process(const A * __restrict a, const B * __restrict b, ResultType * __restrict c, size_t size, const NullMap * right_nullmap, NullMap * res_nullmap[[maybe_unused]])
|
||||
{
|
||||
if constexpr (op_case == OpCase::RightConstant)
|
||||
{
|
||||
@ -40,20 +39,19 @@ struct DivideIntegralByConstantImpl
|
||||
{
|
||||
if (right_nullmap)
|
||||
{
|
||||
assert(res_nullmap);
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
if ((*right_nullmap)[i])
|
||||
c[i] = ResultType();
|
||||
else
|
||||
apply<op_case, true>(a, b, c, i, &((*res_nullmap)[i]));
|
||||
apply<op_case>(a, b, c, i);
|
||||
}
|
||||
else
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
apply<op_case, false>(a, b, c, i);
|
||||
apply<op_case>(a, b, c, i);
|
||||
}
|
||||
}
|
||||
|
||||
static ResultType process(A a, B b, NullMap::value_type * m = nullptr) { return Op::template apply<ResultType>(a, b, m); }
|
||||
static ResultType process(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr) { return Op::template apply<ResultType>(a, b); }
|
||||
|
||||
static void NO_INLINE NO_SANITIZE_UNDEFINED vectorConstant(const A * __restrict a_pos, B b, ResultType * __restrict c_pos, size_t size)
|
||||
{
|
||||
@ -81,23 +79,13 @@ struct DivideIntegralByConstantImpl
|
||||
}
|
||||
|
||||
private:
|
||||
template <OpCase op_case, bool nullable>
|
||||
static void apply(const A * __restrict a, const B * __restrict b, ResultType * __restrict c, size_t i, NullMap::value_type * m = nullptr)
|
||||
template <OpCase op_case>
|
||||
static void apply(const A * __restrict a, const B * __restrict b, ResultType * __restrict c, size_t i)
|
||||
{
|
||||
if constexpr (nullable)
|
||||
{
|
||||
if constexpr (op_case == OpCase::Vector)
|
||||
c[i] = Op::template apply<ResultType>(a[i], b[i], m);
|
||||
else
|
||||
c[i] = Op::template apply<ResultType>(*a, b[i], m);
|
||||
}
|
||||
if constexpr (op_case == OpCase::Vector)
|
||||
c[i] = Op::template apply<ResultType>(a[i], b[i]);
|
||||
else
|
||||
{
|
||||
if constexpr (op_case == OpCase::Vector)
|
||||
c[i] = Op::template apply<ResultType>(a[i], b[i]);
|
||||
else
|
||||
c[i] = Op::template apply<ResultType>(*a, b[i]);
|
||||
}
|
||||
c[i] = Op::template apply<ResultType>(*a, b[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,7 @@ struct DivideIntegralOrZeroImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply(A a, B b)
|
||||
{
|
||||
if (unlikely(divisionLeadsToFPE(a, b)))
|
||||
return 0;
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include <Functions/GCDLCMImpl.h>
|
||||
|
||||
#include <boost/integer/common_factor.hpp>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
|
||||
namespace
|
||||
@ -38,7 +37,7 @@ struct LCMImpl : public GCDLCMImpl<A, B, LCMImpl<A, B>, NameLCM>
|
||||
{
|
||||
using ResultType = typename GCDLCMImpl<A, B, LCMImpl<A, B>, NameLCM>::ResultType;
|
||||
|
||||
static ResultType applyImpl(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static ResultType applyImpl(A a, B b)
|
||||
{
|
||||
using Int = typename NumberTraits::ToInteger<ResultType>::Type;
|
||||
using Unsigned = make_unsigned_t<Int>;
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include <Core/AccurateComparison.h>
|
||||
#include <Functions/LeastGreatestGeneric.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -22,13 +21,6 @@ struct LeastBaseImpl
|
||||
return static_cast<Result>(a) < static_cast<Result>(b) ? static_cast<Result>(a) : static_cast<Result>(b);
|
||||
}
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a, B b, NullMap::value_type *)
|
||||
{
|
||||
/** gcc 4.9.2 successfully vectorizes a loop from this function. */
|
||||
return static_cast<Result>(a) < static_cast<Result>(b) ? static_cast<Result>(a) : static_cast<Result>(b);
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
static constexpr bool compilable = true;
|
||||
|
||||
@ -54,7 +46,7 @@ struct LeastSpecialImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply(A a, B b)
|
||||
{
|
||||
static_assert(std::is_same_v<Result, ResultType>, "ResultType != Result");
|
||||
return accurate::lessOp(a, b) ? static_cast<Result>(a) : static_cast<Result>(b);
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include <base/arithmeticOverflow.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -14,7 +13,7 @@ struct MinusImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a, B b)
|
||||
{
|
||||
if constexpr (is_big_int_v<A> || is_big_int_v<B>)
|
||||
{
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
|
||||
#include <libdivide-config.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
#include <libdivide.h>
|
||||
|
||||
|
||||
@ -28,7 +27,7 @@ struct ModuloByConstantImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <OpCase op_case>
|
||||
static void NO_INLINE process(const A * __restrict a, const B * __restrict b, ResultType * __restrict c, size_t size, const NullMap * right_nullmap, NullMap * res_nullmap)
|
||||
static void NO_INLINE process(const A * __restrict a, const B * __restrict b, ResultType * __restrict c, size_t size, const NullMap * right_nullmap, NullMap * res_nullmap [[maybe_unused]] = nullptr)
|
||||
{
|
||||
if constexpr (op_case == OpCase::RightConstant)
|
||||
{
|
||||
@ -44,20 +43,29 @@ struct ModuloByConstantImpl
|
||||
if ((*right_nullmap)[i])
|
||||
c[i] = ResultType();
|
||||
else
|
||||
apply<op_case, true>(a, b, c, i, &((*res_nullmap)[i]));
|
||||
apply<op_case>(a, b, c, i);
|
||||
}
|
||||
else
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
apply<op_case, false>(a, b, c, i);
|
||||
apply<op_case>(a, b, c, i);
|
||||
}
|
||||
}
|
||||
|
||||
static ResultType process(A a, B b, NullMap::value_type * m = nullptr) { return Op::template apply<ResultType>(a, b, m); }
|
||||
static ResultType process(A a, B b, NullMap::value_type * res_nullmap [[maybe_unused]] = nullptr) { return Op::template apply<ResultType>(a, b); }
|
||||
|
||||
static void NO_INLINE NO_SANITIZE_UNDEFINED vectorConstant(const A * __restrict src, B b, ResultType * __restrict dst, size_t size)
|
||||
{
|
||||
/// Modulo with too small divisor.
|
||||
if (unlikely((std::is_signed_v<B> && b == -1) || b == 1))
|
||||
if constexpr (std::is_signed_v<B>)
|
||||
{
|
||||
if (unlikely((b == -1)))
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
dst[i] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (b == 1)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
dst[i] = 0;
|
||||
@ -105,24 +113,13 @@ struct ModuloByConstantImpl
|
||||
}
|
||||
|
||||
private:
|
||||
template <OpCase op_case, bool nullable>
|
||||
static void apply(const A * __restrict a, const B * __restrict b, ResultType * __restrict c, size_t i, NullMap::value_type * m = nullptr)
|
||||
template <OpCase op_case>
|
||||
static void apply(const A * __restrict a, const B * __restrict b, ResultType * __restrict c, size_t i)
|
||||
{
|
||||
if constexpr (nullable)
|
||||
{
|
||||
if constexpr (op_case == OpCase::Vector)
|
||||
c[i] = Op::template apply<ResultType>(a[i], b[i], m);
|
||||
else
|
||||
c[i] = Op::template apply<ResultType>(*a, b[i], m);
|
||||
}
|
||||
if constexpr (op_case == OpCase::Vector)
|
||||
c[i] = Op::template apply<ResultType>(a[i], b[i]);
|
||||
else
|
||||
{
|
||||
if constexpr (op_case == OpCase::Vector)
|
||||
c[i] = Op::template apply<ResultType>(a[i], b[i]);
|
||||
else
|
||||
c[i] = Op::template apply<ResultType>(*a, b[i]);
|
||||
|
||||
}
|
||||
c[i] = Op::template apply<ResultType>(*a, b[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include "Common/StackTrace.h"
|
||||
#include <Common/Exception.h>
|
||||
#include "Functions/StringHelpers.h"
|
||||
#include "base/extended_types.h"
|
||||
#include <libdivide.h>
|
||||
|
||||
@ -46,11 +47,21 @@ struct ModuloOrNullImpl
|
||||
try
|
||||
{
|
||||
res = Op::template apply<ResultType>(a, b);
|
||||
if constexpr (std::is_floating_point_v<ResultType>)
|
||||
{
|
||||
if (!std::isfinite(res) && m)
|
||||
*m = 1;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
if (m)
|
||||
*m = 1;
|
||||
else
|
||||
{
|
||||
std::cerr << "gethere 1" << std::endl;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -58,7 +69,16 @@ struct ModuloOrNullImpl
|
||||
static void NO_INLINE NO_SANITIZE_UNDEFINED vectorConstant(const A * __restrict src, B b, ResultType * __restrict dst, size_t size, NullMap * res_nullmap)
|
||||
{
|
||||
/// Modulo with too small divisor.
|
||||
if (unlikely((std::is_signed_v<B> && b == -1) || b == 1))
|
||||
if constexpr (std::is_signed_v<B>)
|
||||
{
|
||||
if (unlikely((b == -1)))
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
dst[i] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (b == 1)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
dst[i] = 0;
|
||||
@ -120,7 +140,7 @@ struct ModuloOrNullImpl
|
||||
if constexpr (std::is_floating_point_v<Result>)
|
||||
{
|
||||
if (!std::isfinite(res) && m)
|
||||
* m = 1;
|
||||
*m = 1;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&)
|
||||
@ -128,6 +148,11 @@ struct ModuloOrNullImpl
|
||||
std::cerr <<"gethere 6 exception, m vallue:" << !!m << std::endl;
|
||||
std::cerr << StackTrace().toString() << std::endl;
|
||||
if (m) *m = 1;
|
||||
else
|
||||
{
|
||||
std::cerr << "gethere 7" << std::endl;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -15,7 +14,7 @@ struct ModuloOrZeroImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static Result apply(A a, B b)
|
||||
{
|
||||
if constexpr (std::is_floating_point_v<ResultType>)
|
||||
{
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include <base/arithmeticOverflow.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -15,7 +14,7 @@ struct MultiplyImpl
|
||||
static const constexpr bool allow_string_integer = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a, B b)
|
||||
{
|
||||
if constexpr (is_big_int_v<A> || is_big_int_v<B>)
|
||||
{
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include <base/arithmeticOverflow.h>
|
||||
#include "Columns/ColumnNullable.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -15,7 +14,7 @@ struct PlusImpl
|
||||
static const constexpr bool is_commutative = true;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a, B b, NullMap::value_type * m [[maybe_unused]] = nullptr)
|
||||
static NO_SANITIZE_UNDEFINED Result apply(A a, B b)
|
||||
{
|
||||
/// Next everywhere, static_cast - so that there is no wrong result in expressions of the form Int64 c = UInt32(a) * Int32(-1).
|
||||
if constexpr (is_big_int_v<A> || is_big_int_v<B>)
|
||||
|
@ -54,7 +54,9 @@ struct PlusName { static constexpr auto name = "plus"; };
|
||||
struct MinusName { static constexpr auto name = "minus"; };
|
||||
struct MultiplyName { static constexpr auto name = "multiply"; };
|
||||
struct DivideName { static constexpr auto name = "divide"; };
|
||||
struct DivideOrNullName { static constexpr auto name = "divideOrNull"; };
|
||||
struct ModuloName { static constexpr auto name = "modulo"; };
|
||||
struct ModuloOrNullName { static constexpr auto name = "moduloOrNull"; };
|
||||
struct IntDivName { static constexpr auto name = "intDiv"; };
|
||||
struct IntDivOrZeroName { static constexpr auto name = "intDivOrZero"; };
|
||||
|
||||
@ -152,8 +154,12 @@ using FunctionTupleMultiply = FunctionTupleOperator<MultiplyName>;
|
||||
|
||||
using FunctionTupleDivide = FunctionTupleOperator<DivideName>;
|
||||
|
||||
using FunctionTupleDivideOrNull = FunctionTupleOperator<DivideOrNullName>;
|
||||
|
||||
using FunctionTupleModulo = FunctionTupleOperator<ModuloName>;
|
||||
|
||||
using FunctionTupleModuloOrNull = FunctionTupleOperator<ModuloOrNullName>;
|
||||
|
||||
using FunctionTupleIntDiv = FunctionTupleOperator<IntDivName>;
|
||||
|
||||
using FunctionTupleIntDivOrZero = FunctionTupleOperator<IntDivOrZeroName>;
|
||||
@ -307,12 +313,16 @@ using FunctionTupleMultiplyByNumber = FunctionTupleOperatorByNumber<MultiplyName
|
||||
|
||||
using FunctionTupleDivideByNumber = FunctionTupleOperatorByNumber<DivideName>;
|
||||
|
||||
using FunctionTupleDivideOrNullByNumber = FunctionTupleOperatorByNumber<DivideOrNullName>;
|
||||
|
||||
using FunctionTupleModuloByNumber = FunctionTupleOperatorByNumber<ModuloName>;
|
||||
|
||||
using FunctionTupleIntDivByNumber = FunctionTupleOperatorByNumber<IntDivName>;
|
||||
|
||||
using FunctionTupleIntDivOrZeroByNumber = FunctionTupleOperatorByNumber<IntDivOrZeroName>;
|
||||
|
||||
using FunctionTupleModuloOrNullByNumber = FunctionTupleOperatorByNumber<ModuloOrNullName>;
|
||||
|
||||
class FunctionDotProduct : public ITupleFunction
|
||||
{
|
||||
public:
|
||||
@ -1581,7 +1591,9 @@ REGISTER_FUNCTION(VectorFunctions)
|
||||
factory.registerAlias("vectorDifference", FunctionTupleMinus::name, FunctionFactory::Case::Insensitive);
|
||||
factory.registerFunction<FunctionTupleMultiply>();
|
||||
factory.registerFunction<FunctionTupleDivide>();
|
||||
factory.registerFunction<FunctionTupleDivideOrNull>();
|
||||
factory.registerFunction<FunctionTupleModulo>();
|
||||
factory.registerFunction<FunctionTupleModuloOrNull>();
|
||||
factory.registerFunction<FunctionTupleIntDiv>();
|
||||
factory.registerFunction<FunctionTupleIntDivOrZero>();
|
||||
factory.registerFunction<FunctionTupleNegate>();
|
||||
@ -1647,7 +1659,9 @@ If the types of the first interval (or the interval in the tuple) and the second
|
||||
|
||||
factory.registerFunction<FunctionTupleMultiplyByNumber>();
|
||||
factory.registerFunction<FunctionTupleDivideByNumber>();
|
||||
factory.registerFunction<FunctionTupleDivideOrNullByNumber>();
|
||||
factory.registerFunction<FunctionTupleModuloByNumber>();
|
||||
factory.registerFunction<FunctionTupleModuloOrNullByNumber>();
|
||||
factory.registerFunction<FunctionTupleIntDivByNumber>();
|
||||
factory.registerFunction<FunctionTupleIntDivOrZeroByNumber>();
|
||||
|
||||
|
@ -20,3 +20,13 @@ Nullable(UInt8)
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
(NULL,1,1)
|
||||
(0,1,1)
|
||||
(NULL,NULL,NULL)
|
||||
(1,0,1)
|
||||
|
@ -9,14 +9,14 @@ select moduloOrNull(1, materialize(0));
|
||||
select moduloOrNull(materialize(1), 0);
|
||||
select moduloOrNull(materialize(1), materialize(0));
|
||||
|
||||
select moduloOrNull(1, toNullable(materialize(toUInt64(0))));
|
||||
select moduloOrNull(1.1, toNullable(materialize(toUInt64(0))));
|
||||
select moduloOrNull(materialize(1), toNullable(materialize(toUInt64(0))));
|
||||
select moduloOrNull(toNullable(materialize(1)), toNullable(materialize(toUInt64(0))));
|
||||
select moduloOrNull(toNullable(materialize(toFloat32(1))), toNullable(materialize(toInt64(0))));
|
||||
select moduloOrNull(1, toNullable(materialize(toInt128(0))));
|
||||
select moduloOrNull(1.1, toNullable(materialize(toInt128(0))));
|
||||
select moduloOrNull(toNullable(materialize(toFloat64(1))), toNullable(materialize(toInt128(0))));
|
||||
select moduloOrNull(toNullable(materialize(toFloat64(1))), toNullable(materialize(toInt256(0))));
|
||||
select moduloOrNull(1, toNullable(materialize(toInt256(0))));
|
||||
select moduloOrNull(1.0, toNullable(materialize(toInt256(0))));
|
||||
|
||||
SELECT moduloOrNull(toNullable(materialize(1)), toNullable(materialize(0)));
|
||||
SELECT moduloOrNull(toNullable(materialize(toFloat32(1))), toNullable(materialize(0)));
|
||||
@ -24,3 +24,16 @@ SELECT moduloOrNull(toNullable(materialize(toFloat32(1))), materialize(0));
|
||||
SELECT moduloOrNull(toNullable(materialize(toFloat32(1))), toNullable(0));
|
||||
|
||||
SELECT moduloOrNull(materialize(1), CAST(materialize(NULL), 'Nullable(Float32)'));
|
||||
|
||||
SELECT moduloOrNull(toDecimal32(16.2, 2), 0.0);
|
||||
SELECT moduloOrNull(toDecimal32(16.2, 2), toDecimal32(0.0, 2));
|
||||
|
||||
SELECT moduloOrNull((16.2), 0.0);
|
||||
SELECT moduloOrNull(materialize(16.2), 0.0);
|
||||
SELECT moduloOrNull(16.2, materialize(0.0));
|
||||
SELECT moduloOrNull(materialize(16.2), materialize(0.0));
|
||||
|
||||
SELECT tupleModuloOrNull((15, 10, 5), (0, 3, 2));
|
||||
SELECT tupleModuloOrNull((15, 10, 5), (5, 3, 2));
|
||||
SELECT tupleModuloOrNullByNumber((15, 10, 5), 0);
|
||||
SELECT tupleModuloOrNullByNumber((15, 10, 5), 2);
|
@ -17,3 +17,14 @@
|
||||
1.7777777777777777
|
||||
1.7777777777777777
|
||||
1.7777777777777777
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
\N
|
||||
(NULL,NULL,NULL)
|
||||
(3,NULL,NULL)
|
||||
(3,2,1)
|
||||
(NULL,NULL,NULL)
|
||||
|
@ -22,3 +22,17 @@ SELECT divideOrNull(CAST(16, 'Int8'), CAST(materialize(9), 'Nullable(Int128)'));
|
||||
SELECT divideOrNull(CAST(16, 'Int128'), CAST(materialize(9), 'Nullable(Int128)'));
|
||||
SELECT divideOrNull(CAST(16, 'UInt256'), CAST(materialize(9), 'Nullable(UInt128)'));
|
||||
SELECT divideOrNull(CAST(16, 'UInt256'), CAST(materialize(9), 'Nullable(UInt128)'));
|
||||
|
||||
SELECT divideOrNull(toDecimal32(16.2, 2), toDecimal32(0.0, 1));
|
||||
SELECT divideOrNull(toDecimal32(16.2, 2), materialize(toDecimal32(0.0, 1)));
|
||||
SELECT divideOrNull(materialize(toDecimal32(16.2, 2)), toDecimal32(0.0, 1));
|
||||
SELECT divideOrNull(materialize(toDecimal32(16.2, 2)), materialize(toDecimal32(0.0, 1)));
|
||||
|
||||
SELECT divideOrNull(toDecimal32(16.2, 2), 0.0);
|
||||
SELECT divideOrNull(toDecimal32(16.2, 2), materialize(0.0));
|
||||
SELECT divideOrNull(materialize(toDecimal32(16.2, 2)), materialize(0.0));
|
||||
|
||||
SELECT tupleDivideOrNull((15, 10, 5), (0, 0, 0));
|
||||
SELECT tupleDivideOrNull((15, 10, 5), (5, 0, 0));
|
||||
SELECT tupleDivideOrNullByNumber((15, 10, 5), 5);
|
||||
SELECT tupleDivideOrNullByNumber((15, 10, 5), 0);
|
||||
|
Loading…
Reference in New Issue
Block a user