Merge pull request #70651 from ClickHouse/backport/24.8/70631

Backport #70631 to 24.8: Fix creation of stateful window functions on misaligned memory
This commit is contained in:
Raúl Marín 2024-10-15 18:29:05 +08:00 committed by GitHub
commit 185337a8e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 38 additions and 30 deletions

View File

@ -78,11 +78,6 @@ struct WindowFunction : public IAggregateFunctionHelper<WindowFunction>, public
} }
String getName() const override { return name; } String getName() const override { return name; }
void create(AggregateDataPtr __restrict) const override { }
void destroy(AggregateDataPtr __restrict) const noexcept override { }
bool hasTrivialDestructor() const override { return true; }
size_t sizeOfData() const override { return 0; }
size_t alignOfData() const override { return 1; }
void add(AggregateDataPtr __restrict, const IColumn **, size_t, Arena *) const override { fail(); } void add(AggregateDataPtr __restrict, const IColumn **, size_t, Arena *) const override { fail(); }
void merge(AggregateDataPtr __restrict, ConstAggregateDataPtr, Arena *) const override { fail(); } void merge(AggregateDataPtr __restrict, ConstAggregateDataPtr, Arena *) const override { fail(); }
void serialize(ConstAggregateDataPtr __restrict, WriteBuffer &, std::optional<size_t>) const override { fail(); } void serialize(ConstAggregateDataPtr __restrict, WriteBuffer &, std::optional<size_t>) const override { fail(); }
@ -90,6 +85,22 @@ struct WindowFunction : public IAggregateFunctionHelper<WindowFunction>, public
void insertResultInto(AggregateDataPtr __restrict, IColumn &, Arena *) const override { fail(); } void insertResultInto(AggregateDataPtr __restrict, IColumn &, Arena *) const override { fail(); }
}; };
struct StatelessWindowFunction : public WindowFunction
{
StatelessWindowFunction(
const std::string & name_, const DataTypes & argument_types_, const Array & parameters_, const DataTypePtr & result_type_)
: WindowFunction(name_, argument_types_, parameters_, result_type_)
{
}
size_t sizeOfData() const override { return 0; }
size_t alignOfData() const override { return 1; }
void create(AggregateDataPtr __restrict) const override { }
void destroy(AggregateDataPtr __restrict) const noexcept override { }
bool hasTrivialDestructor() const override { return true; }
};
template <typename State> template <typename State>
struct StatefulWindowFunction : public WindowFunction struct StatefulWindowFunction : public WindowFunction
{ {
@ -100,7 +111,7 @@ struct StatefulWindowFunction : public WindowFunction
} }
size_t sizeOfData() const override { return sizeof(State); } size_t sizeOfData() const override { return sizeof(State); }
size_t alignOfData() const override { return 1; } size_t alignOfData() const override { return alignof(State); }
void create(AggregateDataPtr __restrict place) const override { new (place) State(); } void create(AggregateDataPtr __restrict place) const override { new (place) State(); }

View File

@ -1500,11 +1500,10 @@ void WindowTransform::work()
} }
} }
struct WindowFunctionRank final : public WindowFunction struct WindowFunctionRank final : public StatelessWindowFunction
{ {
WindowFunctionRank(const std::string & name_, WindowFunctionRank(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_)
const DataTypes & argument_types_, const Array & parameters_) : StatelessWindowFunction(name_, argument_types_, parameters_, std::make_shared<DataTypeUInt64>())
: WindowFunction(name_, argument_types_, parameters_, std::make_shared<DataTypeUInt64>())
{} {}
bool allocatesMemoryInArena() const override { return false; } bool allocatesMemoryInArena() const override { return false; }
@ -1519,11 +1518,10 @@ struct WindowFunctionRank final : public WindowFunction
} }
}; };
struct WindowFunctionDenseRank final : public WindowFunction struct WindowFunctionDenseRank final : public StatelessWindowFunction
{ {
WindowFunctionDenseRank(const std::string & name_, WindowFunctionDenseRank(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_)
const DataTypes & argument_types_, const Array & parameters_) : StatelessWindowFunction(name_, argument_types_, parameters_, std::make_shared<DataTypeUInt64>())
: WindowFunction(name_, argument_types_, parameters_, std::make_shared<DataTypeUInt64>())
{} {}
bool allocatesMemoryInArena() const override { return false; } bool allocatesMemoryInArena() const override { return false; }
@ -1721,7 +1719,7 @@ struct WindowFunctionExponentialTimeDecayedSum final : public StatefulWindowFunc
const Float64 decay_length; const Float64 decay_length;
}; };
struct WindowFunctionExponentialTimeDecayedMax final : public WindowFunction struct WindowFunctionExponentialTimeDecayedMax final : public StatelessWindowFunction
{ {
static constexpr size_t ARGUMENT_VALUE = 0; static constexpr size_t ARGUMENT_VALUE = 0;
static constexpr size_t ARGUMENT_TIME = 1; static constexpr size_t ARGUMENT_TIME = 1;
@ -1736,9 +1734,8 @@ struct WindowFunctionExponentialTimeDecayedMax final : public WindowFunction
return applyVisitor(FieldVisitorConvertToNumber<Float64>(), parameters_[0]); return applyVisitor(FieldVisitorConvertToNumber<Float64>(), parameters_[0]);
} }
WindowFunctionExponentialTimeDecayedMax(const std::string & name_, WindowFunctionExponentialTimeDecayedMax(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_)
const DataTypes & argument_types_, const Array & parameters_) : StatelessWindowFunction(name_, argument_types_, parameters_, std::make_shared<DataTypeFloat64>())
: WindowFunction(name_, argument_types_, parameters_, std::make_shared<DataTypeFloat64>())
, decay_length(getDecayLength(parameters_, name_)) , decay_length(getDecayLength(parameters_, name_))
{ {
if (argument_types.size() != 2) if (argument_types.size() != 2)
@ -1996,11 +1993,10 @@ struct WindowFunctionExponentialTimeDecayedAvg final : public StatefulWindowFunc
const Float64 decay_length; const Float64 decay_length;
}; };
struct WindowFunctionRowNumber final : public WindowFunction struct WindowFunctionRowNumber final : public StatelessWindowFunction
{ {
WindowFunctionRowNumber(const std::string & name_, WindowFunctionRowNumber(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_)
const DataTypes & argument_types_, const Array & parameters_) : StatelessWindowFunction(name_, argument_types_, parameters_, std::make_shared<DataTypeUInt64>())
: WindowFunction(name_, argument_types_, parameters_, std::make_shared<DataTypeUInt64>())
{} {}
bool allocatesMemoryInArena() const override { return false; } bool allocatesMemoryInArena() const override { return false; }
@ -2278,13 +2274,12 @@ public:
// ClickHouse-specific variant of lag/lead that respects the window frame. // ClickHouse-specific variant of lag/lead that respects the window frame.
template <bool is_lead> template <bool is_lead>
struct WindowFunctionLagLeadInFrame final : public WindowFunction struct WindowFunctionLagLeadInFrame final : public StatelessWindowFunction
{ {
FunctionBasePtr func_cast = nullptr; FunctionBasePtr func_cast = nullptr;
WindowFunctionLagLeadInFrame(const std::string & name_, WindowFunctionLagLeadInFrame(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_)
const DataTypes & argument_types_, const Array & parameters_) : StatelessWindowFunction(name_, argument_types_, parameters_, createResultType(argument_types_, name_))
: WindowFunction(name_, argument_types_, parameters_, createResultType(argument_types_, name_))
{ {
if (!parameters.empty()) if (!parameters.empty())
{ {
@ -2432,11 +2427,10 @@ struct WindowFunctionLagLeadInFrame final : public WindowFunction
} }
}; };
struct WindowFunctionNthValue final : public WindowFunction struct WindowFunctionNthValue final : public StatelessWindowFunction
{ {
WindowFunctionNthValue(const std::string & name_, WindowFunctionNthValue(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_)
const DataTypes & argument_types_, const Array & parameters_) : StatelessWindowFunction(name_, argument_types_, parameters_, createResultType(name_, argument_types_))
: WindowFunction(name_, argument_types_, parameters_, createResultType(name_, argument_types_))
{ {
if (!parameters.empty()) if (!parameters.empty())
{ {

View File

@ -0,0 +1,3 @@
-- https://github.com/ClickHouse/ClickHouse/issues/70569
-- Reproduces UBSAN alert about misaligned address
SELECT anyLast(id), anyLast(time), exponentialTimeDecayedAvg(10)(id, time) FROM values('id Int8, time DateTime', (1,1),(1,2),(2,3),(3,3),(3,5)); -- { serverError BAD_ARGUMENTS }