diff --git a/docker/test/fuzzer/run-fuzzer.sh b/docker/test/fuzzer/run-fuzzer.sh index dc1b35b3a21..63471c288dd 100755 --- a/docker/test/fuzzer/run-fuzzer.sh +++ b/docker/test/fuzzer/run-fuzzer.sh @@ -343,7 +343,7 @@ quit # which is confusing. task_exit_code=$fuzzer_exit_code echo "failure" > status.txt - echo "Achtung!" > description.txt + echo "Let op!" > description.txt echo "Fuzzer went wrong with error code: ($fuzzer_exit_code). Its process died somehow when the server stayed alive. The server log probably won't tell you much so try to find information in other files." >>description.txt { rg -ao "Found error:.*" fuzzer.log || rg -ao "Exception:.*" fuzzer.log; } | tail -1 >>description.txt fi diff --git a/src/Core/Field.h b/src/Core/Field.h index 414874310a6..43f175cb476 100644 --- a/src/Core/Field.h +++ b/src/Core/Field.h @@ -497,7 +497,7 @@ public: switch (which) { - case Types::Null: return false; + case Types::Null: return get() < rhs.get(); case Types::Bool: [[fallthrough]]; case Types::UInt64: return get() < rhs.get(); case Types::UInt128: return get() < rhs.get(); @@ -541,7 +541,7 @@ public: switch (which) { - case Types::Null: return true; + case Types::Null: return get() <= rhs.get(); case Types::Bool: [[fallthrough]]; case Types::UInt64: return get() <= rhs.get(); case Types::UInt128: return get() <= rhs.get(); @@ -590,7 +590,7 @@ public: switch (which) { - case Types::Null: return true; + case Types::Null: return get() == rhs.get(); case Types::Bool: [[fallthrough]]; case Types::UInt64: return get() == rhs.get(); case Types::Int64: return get() == rhs.get(); diff --git a/src/Core/Types.h b/src/Core/Types.h index 74e18e9494d..2a930d09873 100644 --- a/src/Core/Types.h +++ b/src/Core/Types.h @@ -23,9 +23,9 @@ struct Null { enum class Value { - Null, - PositiveInfinity, - NegativeInfinity, + NegativeInfinity = -1, + Null = 0, + PositiveInfinity = 1, }; Value value{Value::Null}; @@ -34,15 +34,12 @@ struct Null bool isPositiveInfinity() const { return value == Value::PositiveInfinity; } bool isNegativeInfinity() const { return value == Value::NegativeInfinity; } - bool operator==(const Null & other) const + auto operator<=>(const Null & other) const { - return value == other.value; + return static_cast(value) <=> static_cast(other.value); } - bool operator!=(const Null & other) const - { - return !(*this == other); - } + bool operator==(const Null &) const = default; }; using UInt128 = ::UInt128; diff --git a/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp b/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp index 93b9ad60e3c..ef679b61a79 100644 --- a/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp +++ b/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp @@ -1130,6 +1130,7 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPKRange( bool part_offset_condition_exact_range = !part_offset_condition || part_offset_condition->alwaysUnknownOrTrue() || part_offset_condition->matchesExactContinuousRange(); const String & part_name = part->isProjectionPart() ? fmt::format("{}.{}", part->name, part->getParentPart()->name) : part->name; + if (!key_condition_exact_range || !part_offset_condition_exact_range) { // Do exclusion search, where we drop ranges that do not match @@ -1144,10 +1145,10 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPKRange( part->index_granularity_info.index_granularity_bytes); /** There will always be disjoint suspicious segments on the stack, the leftmost one at the top (back). - * At each step, take the left segment and check if it fits. - * If fits, split it into smaller ones and put them on the stack. If not, discard it. - * If the segment is already of one mark length, add it to response and discard it. - */ + * At each step, take the left segment and check if it fits. + * If fits, split it into smaller ones and put them on the stack. If not, discard it. + * If the segment is already of one mark length, add it to response and discard it. + */ std::vector ranges_stack = { {0, marks_count} }; size_t steps = 0; @@ -1157,7 +1158,7 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPKRange( MarkRange range = ranges_stack.back(); ranges_stack.pop_back(); - steps++; + ++steps; if (!may_be_true_in_range(range)) continue; diff --git a/tests/queries/0_stateless/03008_index_small.reference b/tests/queries/0_stateless/03008_index_small.reference new file mode 100644 index 00000000000..a5c8806279f --- /dev/null +++ b/tests/queries/0_stateless/03008_index_small.reference @@ -0,0 +1,2 @@ +3 +3 diff --git a/tests/queries/0_stateless/03008_index_small.sql b/tests/queries/0_stateless/03008_index_small.sql new file mode 100644 index 00000000000..4eb2db3abc3 --- /dev/null +++ b/tests/queries/0_stateless/03008_index_small.sql @@ -0,0 +1,19 @@ +DROP TABLE IF EXISTS test; + +CREATE TABLE test (a UInt8, b UInt8) ENGINE = MergeTree ORDER BY (a, b) +SETTINGS index_granularity = 1, primary_key_ratio_of_unique_prefix_values_to_skip_suffix_columns = 0.01; + +SET optimize_move_to_prewhere = 0; + +INSERT INTO test +SELECT number DIV 2, number +FROM numbers(3); + +SELECT count() FROM test WHERE b >= 0; + +DETACH TABLE test; +ATTACH TABLE test; + +SELECT count() FROM test WHERE b >= 0; + +-- DROP TABLE test;