diff --git a/dbms/src/Functions/bitBoolMaskAnd.cpp b/dbms/src/Functions/bitBoolMaskAnd.cpp new file mode 100644 index 00000000000..f1ecea1bbcb --- /dev/null +++ b/dbms/src/Functions/bitBoolMaskAnd.cpp @@ -0,0 +1,40 @@ +#include +#include +#include + +namespace DB +{ + + template + struct BitBoolMaskAndImpl + { + using ResultType = UInt8; + + template + static inline Result apply(A left, B right) + { + return static_cast( + ((static_cast(left) & static_cast(right)) & 1) + | ((((static_cast(left) >> 1) | (static_cast(right) >> 1)) & 1) << 1)); + } + +#if USE_EMBEDDED_COMPILER + static constexpr bool compilable = false; + + static inline llvm::Value * compile(llvm::IRBuilder<> & b, llvm::Value * left, llvm::Value * right, bool) + { + if (!left->getType()->isIntegerTy() && !right->getType()->isIntegerTy()) + throw Exception("__bitBoolMaskAnd expected an integral type", ErrorCodes::LOGICAL_ERROR); + } +#endif + }; + + struct NameBitBoolMaskAnd { static constexpr auto name = "__bitBoolMaskAnd"; }; + using FunctionBitBoolMaskAnd = FunctionBinaryArithmetic; + + void registerFunctionBitBoolMaskAnd(FunctionFactory & factory) + { + factory.registerFunction(); + } + +} diff --git a/dbms/src/Functions/bitBoolMaskOr.cpp b/dbms/src/Functions/bitBoolMaskOr.cpp new file mode 100644 index 00000000000..e79e04c7eaa --- /dev/null +++ b/dbms/src/Functions/bitBoolMaskOr.cpp @@ -0,0 +1,40 @@ +#include +#include +#include + +namespace DB +{ + + template + struct BitBoolMaskOrImpl + { + using ResultType = UInt8; + + template + static inline Result apply(A left, B right) + { + return static_cast( + ((static_cast(left) & 1) | (static_cast(right) & 1)) + | ((((static_cast(left) >> 1) & (static_cast(right) >> 1)) & 1) << 1)); + } + +#if USE_EMBEDDED_COMPILER + static constexpr bool compilable = false; + + static inline llvm::Value * compile(llvm::IRBuilder<> & b, llvm::Value * left, llvm::Value * right, bool) + { + if (!left->getType()->isIntegerTy() && !right->getType()->isIntegerTy()) + throw Exception("__bitBoolMaskOr expected an integral type", ErrorCodes::LOGICAL_ERROR); + } +#endif + }; + + struct NameBitBoolMaskOr { static constexpr auto name = "__bitBoolMaskOr"; }; + using FunctionBitBoolMaskOr = FunctionBinaryArithmetic; + + void registerFunctionBitBoolMaskOr(FunctionFactory & factory) + { + factory.registerFunction(); + } + +} diff --git a/dbms/src/Functions/bitNotFunc.cpp b/dbms/src/Functions/bitWrapperFunc.cpp similarity index 57% rename from dbms/src/Functions/bitNotFunc.cpp rename to dbms/src/Functions/bitWrapperFunc.cpp index b5057e72801..362740d3ac3 100644 --- a/dbms/src/Functions/bitNotFunc.cpp +++ b/dbms/src/Functions/bitWrapperFunc.cpp @@ -6,13 +6,13 @@ namespace DB { template - struct BitNotFuncImpl + struct BitWrapperFuncImpl { using ResultType = UInt8; static inline ResultType NO_SANITIZE_UNDEFINED apply(A a) { - return a == 0 ? static_cast(0b10) : static_cast(0b1); + return a == static_cast(0) ? static_cast(0b10) : static_cast(0b1); } #if USE_EMBEDDED_COMPILER @@ -21,10 +21,10 @@ namespace DB #endif }; - struct NameBitNotFunc { static constexpr auto name = "__bitNotFunc"; }; - using FunctionBitNotFunc = FunctionUnaryArithmetic; + struct NameBitWrapperFunc { static constexpr auto name = "__bitWrapperFunc"; }; + using FunctionBitWrapperFunc = FunctionUnaryArithmetic; - template <> struct FunctionUnaryArithmeticMonotonicity + template <> struct FunctionUnaryArithmeticMonotonicity { static bool has() { return false; } static IFunction::Monotonicity get(const Field &, const Field &) @@ -33,9 +33,9 @@ namespace DB } }; - void registerFunctionBitNotFunc(FunctionFactory & factory) + void registerFunctionBitWrapperFunc(FunctionFactory & factory) { - factory.registerFunction(); + factory.registerFunction(); } } diff --git a/dbms/src/Functions/registerFunctionsArithmetic.cpp b/dbms/src/Functions/registerFunctionsArithmetic.cpp index 0ac0223a822..1faa28e395e 100644 --- a/dbms/src/Functions/registerFunctionsArithmetic.cpp +++ b/dbms/src/Functions/registerFunctionsArithmetic.cpp @@ -33,7 +33,9 @@ void registerFunctionRoundToExp2(FunctionFactory & factory); void registerFunctionRoundDuration(FunctionFactory & factory); void registerFunctionRoundAge(FunctionFactory & factory); -void registerFunctionBitNotFunc(FunctionFactory & factory); +void registerFunctionBitBoolMaskOr(FunctionFactory & factory); +void registerFunctionBitBoolMaskAnd(FunctionFactory & factory); +void registerFunctionBitWrapperFunc(FunctionFactory & factory); void registerFunctionBitSwapLastTwo(FunctionFactory & factory); void registerFunctionsArithmetic(FunctionFactory & factory) @@ -69,7 +71,9 @@ void registerFunctionsArithmetic(FunctionFactory & factory) registerFunctionRoundAge(factory); /// Not for external use. - registerFunctionBitNotFunc(factory); + registerFunctionBitBoolMaskOr(factory); + registerFunctionBitBoolMaskAnd(factory); + registerFunctionBitWrapperFunc(factory); registerFunctionBitSwapLastTwo(factory); } diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexSet.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndexSet.cpp index 0371bd9e1a7..06c873ea7c9 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeIndexSet.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexSet.cpp @@ -306,7 +306,10 @@ void MergeTreeIndexConditionSet::traverseAST(ASTPtr & node) const } if (atomFromAST(node)) - node = makeASTFunction("__bitNotFunc", node); + { + if (node->as() || node->as()) + node = makeASTFunction("__bitWrapperFunc", node); + } else node = std::make_shared(UNKNOWN_FIELD); } @@ -366,12 +369,12 @@ bool MergeTreeIndexConditionSet::operatorFromAST(ASTPtr & node) const ASTPtr new_func; if (args.size() > 1) new_func = makeASTFunction( - "bitAnd", + "__bitBoolMaskAnd", node, last_arg); else new_func = makeASTFunction( - "bitAnd", + "__bitBoolMaskAnd", args.back(), last_arg); @@ -385,12 +388,12 @@ bool MergeTreeIndexConditionSet::operatorFromAST(ASTPtr & node) const ASTPtr new_func; if (args.size() > 1) new_func = makeASTFunction( - "bitOr", + "__bitBoolMaskOr", node, last_arg); else new_func = makeASTFunction( - "bitOr", + "__bitBoolMaskOr", args.back(), last_arg); diff --git a/dbms/tests/queries/0_stateless/00838_unique_index.reference b/dbms/tests/queries/0_stateless/00838_unique_index.reference index 9ba14877884..1686ed17bb2 100644 --- a/dbms/tests/queries/0_stateless/00838_unique_index.reference +++ b/dbms/tests/queries/0_stateless/00838_unique_index.reference @@ -3,4 +3,22 @@ 12 5 4.7 6.50 cba b 2014-06-11 13 5 4.7 6.50 cba b 2015-01-01 "rows_read": 4, +2 2 4.5 2.50 abc a 2014-01-01 +6 2 4.5 2.50 abc a 2014-02-11 +7 5 6.9 1.57 bac c 2014-04-11 +8 2 4.5 2.50 abc a 2014-05-11 +9 5 6.9 1.57 bac c 2014-07-11 +5 5 6.9 1.57 bac c 2014-11-11 +4 2 4.5 2.50 abc a 2016-01-01 +3 5 6.9 1.57 bac c 2017-01-01 + "rows_read": 8, "rows_read": 2, +2 2 4.5 2.50 abc a 2014-01-01 +6 2 4.5 2.50 abc a 2014-02-11 +7 5 6.9 1.57 bac c 2014-04-11 +8 2 4.5 2.50 abc a 2014-05-11 +9 5 6.9 1.57 bac c 2014-07-11 +5 5 6.9 1.57 bac c 2014-11-11 +4 2 4.5 2.50 abc a 2016-01-01 +3 5 6.9 1.57 bac c 2017-01-01 + "rows_read": 8, \ No newline at end of file diff --git a/dbms/tests/queries/0_stateless/00838_unique_index.sh b/dbms/tests/queries/0_stateless/00838_unique_index.sh index 9445d6af98a..ede8326c49a 100755 --- a/dbms/tests/queries/0_stateless/00838_unique_index.sh +++ b/dbms/tests/queries/0_stateless/00838_unique_index.sh @@ -43,8 +43,15 @@ $CLICKHOUSE_CLIENT --query="INSERT INTO set_idx VALUES $CLICKHOUSE_CLIENT --query="SELECT * FROM set_idx WHERE i32 = 5 AND i32 + f64 < 12 AND 3 < d AND d < 7 AND (s = 'bac' OR s = 'cba') ORDER BY dt" $CLICKHOUSE_CLIENT --query="SELECT * FROM set_idx WHERE i32 = 5 AND i32 + f64 < 12 AND 3 < d AND d < 7 AND (s = 'bac' OR s = 'cba') ORDER BY dt FORMAT JSON" | grep "rows_read" +$CLICKHOUSE_CLIENT --query="SELECT * FROM set_idx WHERE NOT (i32 = 5 AND i32 + f64 < 12 AND 3 < d AND d < 7 AND (s = 'bac' OR s = 'cba')) ORDER BY dt" +$CLICKHOUSE_CLIENT --query="SELECT * FROM set_idx WHERE NOT (i32 = 5 AND i32 + f64 < 12 AND 3 < d AND d < 7 AND (s = 'bac' OR s = 'cba')) ORDER BY dt FORMAT JSON" | grep "rows_read" + # select with hole made by primary key $CLICKHOUSE_CLIENT --query="SELECT * FROM set_idx WHERE (u64 < 2 OR u64 > 10) AND s != 'cba' ORDER BY dt" $CLICKHOUSE_CLIENT --query="SELECT * FROM set_idx WHERE (u64 < 2 OR u64 > 10) AND s != 'cba' ORDER BY dt FORMAT JSON" | grep "rows_read" +$CLICKHOUSE_CLIENT --query="SELECT * FROM set_idx WHERE (u64 < 2 OR NOT u64 > 10) AND NOT (s = 'cba') ORDER BY dt" +$CLICKHOUSE_CLIENT --query="SELECT * FROM set_idx WHERE (u64 < 2 OR NOT u64 > 10) AND NOT (s = 'cba') ORDER BY dt FORMAT JSON" | grep "rows_read" + + $CLICKHOUSE_CLIENT --query="DROP TABLE set_idx;" \ No newline at end of file