diff --git a/src/AggregateFunctions/QuantileTDigest.h b/src/AggregateFunctions/QuantileTDigest.h index b12673bc507..14b34e9e968 100644 --- a/src/AggregateFunctions/QuantileTDigest.h +++ b/src/AggregateFunctions/QuantileTDigest.h @@ -1,8 +1,10 @@ #pragma once #include +#include #include #include +#include #include #include #include @@ -14,8 +16,9 @@ struct Settings; namespace ErrorCodes { - extern const int TOO_LARGE_ARRAY_SIZE; extern const int CANNOT_PARSE_INPUT_ASSERTION_FAILED; + extern const int DECIMAL_OVERFLOW; + extern const int TOO_LARGE_ARRAY_SIZE; } @@ -314,7 +317,7 @@ public: compress(); if (centroids.size() == 1) - return centroids.front().mean; + return checkOverflow(centroids.front().mean); Float64 x = level * count; Float64 prev_x = 0; @@ -333,11 +336,11 @@ public: Float64 right = current_x - 0.5 * (c.count == 1); if (x <= left) - return prev_mean; + return checkOverflow(prev_mean); else if (x >= right) - return c.mean; + return checkOverflow(c.mean); else - return interpolate(x, left, prev_mean, right, c.mean); + return checkOverflow(interpolate(x, left, prev_mean, right, c.mean)); } sum += c.count; @@ -346,7 +349,7 @@ public: prev_x = current_x; } - return centroids.back().mean; + return checkOverflow(centroids.back().mean); } /** Get multiple quantiles (`size` parts). @@ -438,6 +441,16 @@ public: { getManyImpl(levels, indices, size, result); } + +private: + template + static ResultType checkOverflow(Value val) + { + ResultType result; + if (bool ok = accurate::convertNumeric(val, result); ok) + return result; + throw DB::Exception("Numeric overflow", ErrorCodes::DECIMAL_OVERFLOW); + } }; } diff --git a/tests/queries/0_stateless/01779_quantile_deterministic_msan.sql b/tests/queries/0_stateless/01779_quantile_deterministic_msan.sql deleted file mode 100644 index ef4234da306..00000000000 --- a/tests/queries/0_stateless/01779_quantile_deterministic_msan.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT cityHash64(toString(quantileDeterministicState(number, sipHash64(number)))) FROM numbers(8193); diff --git a/tests/queries/0_stateless/01779_quantile_deterministic_msan.reference b/tests/queries/0_stateless/01779_quantile_sanitizer.reference similarity index 100% rename from tests/queries/0_stateless/01779_quantile_deterministic_msan.reference rename to tests/queries/0_stateless/01779_quantile_sanitizer.reference diff --git a/tests/queries/0_stateless/01779_quantile_sanitizer.sql b/tests/queries/0_stateless/01779_quantile_sanitizer.sql new file mode 100644 index 00000000000..d9761c65969 --- /dev/null +++ b/tests/queries/0_stateless/01779_quantile_sanitizer.sql @@ -0,0 +1,3 @@ +SELECT cityHash64(toString(quantileDeterministicState(number, sipHash64(number)))) FROM numbers(8193); +SELECT quantileTDigest(0.8)(toDateTime('2106-02-07 09:28:15')); -- { serverError DECIMAL_OVERFLOW } +SELECT quantileTDigestWeighted(-0.)(toDateTime(10000000000.), 1); -- { serverError DECIMAL_OVERFLOW }