Handle overflow in quantileTDigest

This commit is contained in:
vdimir 2021-09-16 16:02:31 +03:00 committed by vdimir
parent 2c0b59576e
commit 58a756da9e
No known key found for this signature in database
GPG Key ID: 9B404D301C0CC7EB
4 changed files with 22 additions and 7 deletions

View File

@ -1,8 +1,10 @@
#pragma once
#include <cmath>
#include <Common/Exception.h>
#include <Common/RadixSort.h>
#include <Common/PODArray.h>
#include <Core/AccurateComparison.h>
#include <IO/WriteBuffer.h>
#include <IO/ReadBuffer.h>
#include <IO/VarInt.h>
@ -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<ResultType>(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<ResultType>(prev_mean);
else if (x >= right)
return c.mean;
return checkOverflow<ResultType>(c.mean);
else
return interpolate(x, left, prev_mean, right, c.mean);
return checkOverflow<ResultType>(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<ResultType>(centroids.back().mean);
}
/** Get multiple quantiles (`size` parts).
@ -438,6 +441,16 @@ public:
{
getManyImpl(levels, indices, size, result);
}
private:
template <typename ResultType>
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);
}
};
}

View File

@ -1 +0,0 @@
SELECT cityHash64(toString(quantileDeterministicState(number, sipHash64(number)))) FROM numbers(8193);

View File

@ -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 }