diff --git a/src/AggregateFunctions/WindowFunction.h b/src/AggregateFunctions/WindowFunction.h index f7fbd7389ea..be214f4c824 100644 --- a/src/AggregateFunctions/WindowFunction.h +++ b/src/AggregateFunctions/WindowFunction.h @@ -78,11 +78,6 @@ struct WindowFunction : public IAggregateFunctionHelper, public } 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 merge(AggregateDataPtr __restrict, ConstAggregateDataPtr, Arena *) const override { fail(); } void serialize(ConstAggregateDataPtr __restrict, WriteBuffer &, std::optional) const override { fail(); } @@ -90,6 +85,22 @@ struct WindowFunction : public IAggregateFunctionHelper, public 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 struct StatefulWindowFunction : public WindowFunction { @@ -100,7 +111,7 @@ struct StatefulWindowFunction : public WindowFunction } 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(); } diff --git a/src/Processors/Transforms/WindowTransform.cpp b/src/Processors/Transforms/WindowTransform.cpp index bd11aa4cd28..6ebe013f485 100644 --- a/src/Processors/Transforms/WindowTransform.cpp +++ b/src/Processors/Transforms/WindowTransform.cpp @@ -1500,11 +1500,10 @@ void WindowTransform::work() } } -struct WindowFunctionRank final : public WindowFunction +struct WindowFunctionRank final : public StatelessWindowFunction { - WindowFunctionRank(const std::string & name_, - const DataTypes & argument_types_, const Array & parameters_) - : WindowFunction(name_, argument_types_, parameters_, std::make_shared()) + WindowFunctionRank(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_) + : StatelessWindowFunction(name_, argument_types_, parameters_, std::make_shared()) {} 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_, - const DataTypes & argument_types_, const Array & parameters_) - : WindowFunction(name_, argument_types_, parameters_, std::make_shared()) + WindowFunctionDenseRank(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_) + : StatelessWindowFunction(name_, argument_types_, parameters_, std::make_shared()) {} bool allocatesMemoryInArena() const override { return false; } @@ -1721,7 +1719,7 @@ struct WindowFunctionExponentialTimeDecayedSum final : public StatefulWindowFunc 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_TIME = 1; @@ -1736,9 +1734,8 @@ struct WindowFunctionExponentialTimeDecayedMax final : public WindowFunction return applyVisitor(FieldVisitorConvertToNumber(), parameters_[0]); } - WindowFunctionExponentialTimeDecayedMax(const std::string & name_, - const DataTypes & argument_types_, const Array & parameters_) - : WindowFunction(name_, argument_types_, parameters_, std::make_shared()) + WindowFunctionExponentialTimeDecayedMax(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_) + : StatelessWindowFunction(name_, argument_types_, parameters_, std::make_shared()) , decay_length(getDecayLength(parameters_, name_)) { if (argument_types.size() != 2) @@ -1996,11 +1993,10 @@ struct WindowFunctionExponentialTimeDecayedAvg final : public StatefulWindowFunc const Float64 decay_length; }; -struct WindowFunctionRowNumber final : public WindowFunction +struct WindowFunctionRowNumber final : public StatelessWindowFunction { - WindowFunctionRowNumber(const std::string & name_, - const DataTypes & argument_types_, const Array & parameters_) - : WindowFunction(name_, argument_types_, parameters_, std::make_shared()) + WindowFunctionRowNumber(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_) + : StatelessWindowFunction(name_, argument_types_, parameters_, std::make_shared()) {} bool allocatesMemoryInArena() const override { return false; } @@ -2278,13 +2274,12 @@ public: // ClickHouse-specific variant of lag/lead that respects the window frame. template -struct WindowFunctionLagLeadInFrame final : public WindowFunction +struct WindowFunctionLagLeadInFrame final : public StatelessWindowFunction { FunctionBasePtr func_cast = nullptr; - WindowFunctionLagLeadInFrame(const std::string & name_, - const DataTypes & argument_types_, const Array & parameters_) - : WindowFunction(name_, argument_types_, parameters_, createResultType(argument_types_, name_)) + WindowFunctionLagLeadInFrame(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_) + : StatelessWindowFunction(name_, argument_types_, parameters_, createResultType(argument_types_, name_)) { 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_, - const DataTypes & argument_types_, const Array & parameters_) - : WindowFunction(name_, argument_types_, parameters_, createResultType(name_, argument_types_)) + WindowFunctionNthValue(const std::string & name_, const DataTypes & argument_types_, const Array & parameters_) + : StatelessWindowFunction(name_, argument_types_, parameters_, createResultType(name_, argument_types_)) { if (!parameters.empty()) { diff --git a/tests/queries/0_stateless/03251_unaligned_window_function_state.reference b/tests/queries/0_stateless/03251_unaligned_window_function_state.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/03251_unaligned_window_function_state.sql b/tests/queries/0_stateless/03251_unaligned_window_function_state.sql new file mode 100644 index 00000000000..2ff75f61f76 --- /dev/null +++ b/tests/queries/0_stateless/03251_unaligned_window_function_state.sql @@ -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 }