#include #include #include namespace DB { namespace ErrorCodes { extern const int BAD_ARGUMENTS; } namespace { /// Working with UInt8: last bit = can be true, previous = can be false (Like src/Storages/MergeTree/BoolMask.h). /// This function provides "AND" operation for BoolMasks. /// Returns: "can be true" = A."can be true" AND B."can be true" /// "can be false" = A."can be false" OR B."can be false" template struct BitBoolMaskAndImpl { using ResultType = UInt8; static const constexpr bool allow_fixed_string = false; static const constexpr bool allow_string_integer = false; template static inline 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 || !std::is_same_v) throw DB::Exception(ErrorCodes::BAD_ARGUMENTS, "It's a bug! Only UInt8 type is supported by __bitBoolMaskAnd."); auto left_bits = littleBits(left); auto right_bits = littleBits(right); return static_cast((left_bits & right_bits & 1) | ((((left_bits >> 1) | (right_bits >> 1)) & 1) << 1)); } #if USE_EMBEDDED_COMPILER static constexpr bool compilable = false; #endif }; struct NameBitBoolMaskAnd { static constexpr auto name = "__bitBoolMaskAnd"; }; using FunctionBitBoolMaskAnd = BinaryArithmeticOverloadResolver; } REGISTER_FUNCTION(BitBoolMaskAnd) { factory.registerFunction(); } }