#include #include #include #include namespace DB { template struct GreatestBaseImpl { using ResultType = NumberTraits::ResultOfGreatest; static const constexpr bool allow_fixed_string = false; template static inline Result apply(A a, B b) { return bigint_cast(a) > bigint_cast(b) ? bigint_cast(a) : bigint_cast(b); } #if USE_EMBEDDED_COMPILER static constexpr bool compilable = true; static inline llvm::Value * compile(llvm::IRBuilder<> & b, llvm::Value * left, llvm::Value * right, bool is_signed) { if (!left->getType()->isIntegerTy()) /// XXX maxnum is basically fmax(), it may or may not match whatever apply() does /// XXX CreateMaxNum is broken on LLVM 5.0 and 6.0 (generates minnum instead; fixed in 7) return b.CreateBinaryIntrinsic(llvm::Intrinsic::maxnum, left, right); return b.CreateSelect(is_signed ? b.CreateICmpSGT(left, right) : b.CreateICmpUGT(left, right), left, right); } #endif }; template struct GreatestSpecialImpl { using ResultType = make_unsigned_t; static const constexpr bool allow_fixed_string = false; template static inline Result apply(A a, B b) { static_assert(std::is_same_v, "ResultType != Result"); return accurate::greaterOp(a, b) ? static_cast(a) : static_cast(b); } #if USE_EMBEDDED_COMPILER static constexpr bool compilable = false; /// ??? #endif }; template using GreatestImpl = std::conditional_t, GreatestBaseImpl, GreatestSpecialImpl>; struct NameGreatest { static constexpr auto name = "greatest"; }; using FunctionGreatest = FunctionBinaryArithmetic; void registerFunctionGreatest(FunctionFactory & factory) { factory.registerFunction>(FunctionFactory::CaseInsensitive); } }