mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 16:50:48 +00:00
Fix error with ownership of aggregate function states with nested states
This commit is contained in:
parent
12e00411b4
commit
c610a4b0a8
@ -247,6 +247,11 @@ public:
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isState() const override
|
||||||
|
{
|
||||||
|
return nested_func->isState();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,8 +122,9 @@ public:
|
|||||||
throw Exception("Method predictValues is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
throw Exception("Method predictValues is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true for aggregate functions of type -State.
|
/** Returns true for aggregate functions of type -State
|
||||||
* They are executed as other aggregate functions, but not finalized (return an aggregation state that can be combined with another).
|
* They are executed as other aggregate functions, but not finalized (return an aggregation state that can be combined with another).
|
||||||
|
* Also returns true when the final value of this aggregate function contains State of other aggregate function inside.
|
||||||
*/
|
*/
|
||||||
virtual bool isState() const { return false; }
|
virtual bool isState() const { return false; }
|
||||||
|
|
||||||
|
@ -85,6 +85,20 @@ void ColumnAggregateFunction::addArena(ConstArenaPtr arena_)
|
|||||||
foreign_arenas.push_back(arena_);
|
foreign_arenas.push_back(arena_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
ConstArenas concatArenas(const ConstArenas & array, ConstArenaPtr arena)
|
||||||
|
{
|
||||||
|
ConstArenas result = array;
|
||||||
|
if (arena)
|
||||||
|
result.push_back(std::move(arena));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
MutableColumnPtr ColumnAggregateFunction::convertToValues(MutableColumnPtr column)
|
MutableColumnPtr ColumnAggregateFunction::convertToValues(MutableColumnPtr column)
|
||||||
{
|
{
|
||||||
/** If the aggregate function returns an unfinalized/unfinished state,
|
/** If the aggregate function returns an unfinalized/unfinished state,
|
||||||
@ -121,19 +135,26 @@ MutableColumnPtr ColumnAggregateFunction::convertToValues(MutableColumnPtr colum
|
|||||||
auto & func = column_aggregate_func.func;
|
auto & func = column_aggregate_func.func;
|
||||||
auto & data = column_aggregate_func.data;
|
auto & data = column_aggregate_func.data;
|
||||||
|
|
||||||
if (const AggregateFunctionState *function_state = typeid_cast<const AggregateFunctionState *>(func.get()))
|
|
||||||
{
|
|
||||||
auto res = column_aggregate_func.createView();
|
|
||||||
res->set(function_state->getNestedFunction());
|
|
||||||
res->data.assign(data.begin(), data.end());
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
column_aggregate_func.ensureOwnership();
|
column_aggregate_func.ensureOwnership();
|
||||||
|
|
||||||
MutableColumnPtr res = func->getReturnType()->createColumn();
|
MutableColumnPtr res = func->getReturnType()->createColumn();
|
||||||
res->reserve(data.size());
|
res->reserve(data.size());
|
||||||
|
|
||||||
|
/// If there are references to states in final column, we must hold their ownership
|
||||||
|
/// by holding arenas and source.
|
||||||
|
|
||||||
|
auto callback = [&](auto & subcolumn)
|
||||||
|
{
|
||||||
|
if (auto * aggregate_subcolumn = typeid_cast<ColumnAggregateFunction *>(subcolumn.get()))
|
||||||
|
{
|
||||||
|
aggregate_subcolumn->foreign_arenas = concatArenas(column_aggregate_func.foreign_arenas, column_aggregate_func.my_arena);
|
||||||
|
aggregate_subcolumn->src = column_aggregate_func.getPtr();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
callback(res);
|
||||||
|
res->forEachSubcolumn(callback);
|
||||||
|
|
||||||
for (auto * val : data)
|
for (auto * val : data)
|
||||||
func->insertResultInto(val, *res, &column_aggregate_func.createOrGetArena());
|
func->insertResultInto(val, *res, &column_aggregate_func.createOrGetArena());
|
||||||
|
|
||||||
@ -629,20 +650,6 @@ void ColumnAggregateFunction::getExtremes(Field & min, Field & max) const
|
|||||||
max = serialized;
|
max = serialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
ConstArenas concatArenas(const ConstArenas & array, ConstArenaPtr arena)
|
|
||||||
{
|
|
||||||
ConstArenas result = array;
|
|
||||||
if (arena)
|
|
||||||
result.push_back(std::move(arena));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnAggregateFunction::MutablePtr ColumnAggregateFunction::createView() const
|
ColumnAggregateFunction::MutablePtr ColumnAggregateFunction::createView() const
|
||||||
{
|
{
|
||||||
auto res = create(func, concatArenas(foreign_arenas, my_arena));
|
auto res = create(func, concatArenas(foreign_arenas, my_arena));
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
5B27015C30012CCBC234272C27015C305C30275D
|
||||||
|
02000000000000000100012CCBC234010000
|
||||||
|
['0100012CCBC234','010000']
|
||||||
|
[1,0]
|
||||||
|
5B27015C30012CCBC234272C27015C305C30275D
|
||||||
|
|
||||||
|
5B27015C30012CCBC234272C27015C305C30275D
|
||||||
|
02000000000000000100012CCBC234010000
|
||||||
|
|
||||||
|
02000000000000000100012CCBC234010000
|
||||||
|
['0100012CCBC234','010000']
|
||||||
|
|
||||||
|
['0100012CCBC234','010000']
|
||||||
|
[1,0]
|
||||||
|
|
||||||
|
[1,0]
|
9
tests/queries/0_stateless/01381_for_each_with_states.sql
Normal file
9
tests/queries/0_stateless/01381_for_each_with_states.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
SELECT hex(toString(uniqStateForEach([1, NULL])));
|
||||||
|
SELECT hex(toString(uniqStateForEachState([1, NULL])));
|
||||||
|
SELECT arrayMap(x -> hex(toString(x)), finalizeAggregation(uniqStateForEachState([1, NULL])));
|
||||||
|
SELECT arrayMap(x -> finalizeAggregation(x), finalizeAggregation(uniqStateForEachState([1, NULL])));
|
||||||
|
|
||||||
|
SELECT hex(toString(uniqStateForEach([1, NULL]))) WITH TOTALS;
|
||||||
|
SELECT hex(toString(uniqStateForEachState([1, NULL]))) WITH TOTALS;
|
||||||
|
SELECT arrayMap(x -> hex(toString(x)), finalizeAggregation(uniqStateForEachState([1, NULL]))) WITH TOTALS;
|
||||||
|
SELECT arrayMap(x -> finalizeAggregation(x), finalizeAggregation(uniqStateForEachState([1, NULL]))) WITH TOTALS;
|
Loading…
Reference in New Issue
Block a user