From cfc4c987c5e1b4290ceb15247846ca39225496eb Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Fri, 12 May 2017 23:57:24 +0300 Subject: [PATCH] Added optional length parameter to aggregate function groupArrayInsertAt [#CLICKHOUSE-3003]. --- .../AggregateFunctionGroupArrayInsertAt.h | 31 ++++++++++++++++--- .../00459_group_array_insert_at.reference | 11 +++++++ .../00459_group_array_insert_at.sql | 1 + 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/dbms/src/AggregateFunctions/AggregateFunctionGroupArrayInsertAt.h b/dbms/src/AggregateFunctions/AggregateFunctionGroupArrayInsertAt.h index e6881a9354..6a48e62144 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionGroupArrayInsertAt.h +++ b/dbms/src/AggregateFunctions/AggregateFunctionGroupArrayInsertAt.h @@ -34,7 +34,11 @@ namespace ErrorCodes * If more than one value was inserted to single position, the any value (first in case of single thread) is stored. * If no values was inserted to some position, then default value will be substituted. * - * Default value is optional parameter for aggregate function. + * Aggregate function also accept optional parameters: + * - default value to substitute; + * - length to resize result arrays (if you want to have results of same length for all aggregation keys); + * + * If you want to pass length, default value should be also given. */ @@ -51,6 +55,7 @@ class AggregateFunctionGroupArrayInsertAtGeneric final private: DataTypePtr type; Field default_value; + size_t length_to_resize = 0; /// zero means - do not do resizing. public: String getName() const override { return "groupArrayInsertAt"; } @@ -85,16 +90,26 @@ public: if (params.empty()) return; - if (params.size() != 1) - throw Exception("Aggregate function " + getName() + " requires at most one parameter.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); + if (params.size() > 2) + throw Exception("Aggregate function " + getName() + " requires at most two parameters.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); + + default_value = params[0]; - default_value = params.front(); + if (params.size() == 2) + { + length_to_resize = applyVisitor(FieldVisitorConvertToNumber(), params[1]); + } } void addImpl(AggregateDataPtr place, const IColumn & column_value, const IColumn & column_position, size_t row_num, Arena *) const { /// TODO Do positions need to be 1-based for this function? size_t position = column_position.get64(row_num); + + /// If position is larger than size to which array will be cutted - simply ignore value. + if (length_to_resize && position >= length_to_resize) + return; + if (position >= AGGREGATE_FUNCTION_GROUP_ARRAY_INSERT_AT_MAX_SIZE) throw Exception("Too large array size: position argument (" + toString(position) + ")" " is greater or equals to limit (" + toString(AGGREGATE_FUNCTION_GROUP_ARRAY_INSERT_AT_MAX_SIZE) + ")", @@ -179,7 +194,13 @@ public: to_data.insert(default_value); } - to_offsets.push_back((to_offsets.empty() ? 0 : to_offsets.back()) + arr.size()); + size_t result_array_size = length_to_resize ? length_to_resize : arr.size(); + + /// Pad array if need. + for (size_t i = arr.size(); i < result_array_size; ++i) + to_data.insert(default_value); + + to_offsets.push_back((to_offsets.empty() ? 0 : to_offsets.back()) + result_array_size); } }; diff --git a/dbms/tests/queries/0_stateless/00459_group_array_insert_at.reference b/dbms/tests/queries/0_stateless/00459_group_array_insert_at.reference index ebd7abe32e..f55b099b52 100644 --- a/dbms/tests/queries/0_stateless/00459_group_array_insert_at.reference +++ b/dbms/tests/queries/0_stateless/00459_group_array_insert_at.reference @@ -12,3 +12,14 @@ 8 [0,0,0,0,0,0,0,0,8] 9 [0,0,0,0,0,0,0,0,0,9] 0 0 +0 ['0','-','-','-','-','-','-','-','-','-'] +1 ['-','1','-','-','-','-','-','-','-','-'] +2 ['-','-','2','-','-','-','-','-','-','-'] +3 ['-','-','-','3','-','-','-','-','-','-'] +4 ['-','-','-','-','4','-','-','-','-','-'] +5 ['-','-','-','-','-','5','-','-','-','-'] +6 ['-','-','-','-','-','-','6','-','-','-'] +7 ['-','-','-','-','-','-','-','7','-','-'] +8 ['-','-','-','-','-','-','-','-','8','-'] +9 ['-','-','-','-','-','-','-','-','-','9'] +10 ['-','-','-','-','-','-','-','-','-','-'] diff --git a/dbms/tests/queries/0_stateless/00459_group_array_insert_at.sql b/dbms/tests/queries/0_stateless/00459_group_array_insert_at.sql index 0dff44d633..b692038e9c 100644 --- a/dbms/tests/queries/0_stateless/00459_group_array_insert_at.sql +++ b/dbms/tests/queries/0_stateless/00459_group_array_insert_at.sql @@ -3,3 +3,4 @@ SELECT groupArrayInsertAt('-')(toString(number), number * 2) FROM (SELECT * FROM SELECT groupArrayInsertAt([123])(range(number), number * 2) FROM (SELECT * FROM system.numbers LIMIT 10); SELECT number, groupArrayInsertAt(number, number) FROM (SELECT * FROM system.numbers LIMIT 10) GROUP BY number ORDER BY number; SELECT k, ignore(groupArrayInsertAt(x, x)) FROM (SELECT dummy AS k, randConstant() % 10 AS x FROM remote('127.0.0.{1,1}', system.one)) GROUP BY k ORDER BY k; +SELECT k, groupArrayInsertAt('-', 10)(toString(x), x) FROM (SELECT number AS k, number AS x FROM system.numbers LIMIT 11) GROUP BY k ORDER BY k; \ No newline at end of file -- GitLab