From 3dec67ca6d850f907821b1953b6f8bb85886e806 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Fri, 17 Jan 2020 22:16:02 +0300 Subject: [PATCH] Fixed the case of mixed-constness of arguments of function arrayZip --- dbms/src/Functions/array/arrayZip.cpp | 41 ++++++++++++------- .../01065_array_zip_mixed_const.reference | 24 +++++++++++ .../01065_array_zip_mixed_const.sql | 7 ++++ 3 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 dbms/tests/queries/0_stateless/01065_array_zip_mixed_const.reference create mode 100644 dbms/tests/queries/0_stateless/01065_array_zip_mixed_const.sql diff --git a/dbms/src/Functions/array/arrayZip.cpp b/dbms/src/Functions/array/arrayZip.cpp index 20fca29bae8..b191a055468 100644 --- a/dbms/src/Functions/array/arrayZip.cpp +++ b/dbms/src/Functions/array/arrayZip.cpp @@ -14,6 +14,7 @@ namespace ErrorCodes { extern const int SIZES_OF_ARRAYS_DOESNT_MATCH; extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; + extern const int ILLEGAL_COLUMN; } /// arrayZip(['a', 'b', 'c'], ['d', 'e', 'f']) = [('a', 'd'), ('b', 'e'), ('c', 'f')] @@ -44,9 +45,8 @@ public: const DataTypeArray * array_type = checkAndGetDataType(arguments[index].type.get()); if (!array_type) - throw Exception( - "Argument " + toString(index + 1) + " of function must be array. Found " + arguments[0].type->getName() + " instead.", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception("Argument " + toString(index + 1) + " of function " + getName() + + " must be array. Found " + arguments[0].type->getName() + " instead.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); arguments_types.emplace_back(array_type->getNestedType()); } @@ -56,26 +56,37 @@ public: void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override { - auto first_argument = block.getByPosition(arguments[0]); - const auto & first_array_column = checkAndGetColumn(first_argument.column.get()); + size_t num_arguments = arguments.size(); - Columns res_tuple_columns(arguments.size()); - res_tuple_columns[0] = first_array_column->getDataPtr(); + ColumnPtr first_array_column; + Columns tuple_columns(num_arguments); - for (size_t index = 1; index < arguments.size(); ++index) + for (size_t i = 0; i < num_arguments; ++i) { - const auto & argument_type_and_column = block.getByPosition(arguments[index]); - const auto & argument_array_column = checkAndGetColumn(argument_type_and_column.column.get()); + /// Constant columns cannot be inside tuple. It's only possible to have constant tuple as a whole. + ColumnPtr holder = block.getByPosition(arguments[i]).column->convertToFullColumnIfConst(); - if (!first_array_column->hasEqualOffsets(*argument_array_column)) - throw Exception("The argument 1 and argument " + toString(index + 1) + " of function have different array sizes", - ErrorCodes::SIZES_OF_ARRAYS_DOESNT_MATCH); + const ColumnArray * column_array = checkAndGetColumn(holder.get()); - res_tuple_columns[index] = argument_array_column->getDataPtr(); + if (!column_array) + throw Exception("Argument " + toString(i + 1) + " of function " + getName() + " must be array." + " Found column " + holder->getName() + " instead.", ErrorCodes::ILLEGAL_COLUMN); + + if (i == 0) + { + first_array_column = holder; + } + else if (!column_array->hasEqualOffsets(static_cast(*first_array_column))) + { + throw Exception("The argument 1 and argument " + toString(i + 1) + " of function " + getName() + " have different array sizes", + ErrorCodes::SIZES_OF_ARRAYS_DOESNT_MATCH); + } + + tuple_columns[i] = column_array->getDataPtr(); } block.getByPosition(result).column = ColumnArray::create( - ColumnTuple::create(res_tuple_columns), first_array_column->getOffsetsPtr()); + ColumnTuple::create(tuple_columns), static_cast(*first_array_column).getOffsetsPtr()); } }; diff --git a/dbms/tests/queries/0_stateless/01065_array_zip_mixed_const.reference b/dbms/tests/queries/0_stateless/01065_array_zip_mixed_const.reference new file mode 100644 index 00000000000..dc683e2bf4d --- /dev/null +++ b/dbms/tests/queries/0_stateless/01065_array_zip_mixed_const.reference @@ -0,0 +1,24 @@ +[(0,'hello'),(1,'world')] +[(0,'hello'),(1,'world')] +[(0,'hello'),(1,'world')] +[(0,'hello'),(1,'world')] +[(0,'0'),(0,'world')] +[(0,'1'),(1,'world')] +[(0,'2'),(2,'world')] +[(0,'3'),(3,'world')] +[(0,'4'),(4,'world')] +[(0,'5'),(5,'world')] +[(0,'6'),(6,'world')] +[(0,'7'),(7,'world')] +[(0,'8'),(8,'world')] +[(0,'9'),(9,'world')] +[(1,[]),(0,[]),(0,[])] +[(1,[]),(1,[]),(1,[])] +[(1,[]),(2,[]),(4,[])] +[(1,[]),(3,[]),(9,[])] +[(1,[]),(4,[]),(16,[])] +[(1,[]),(5,[]),(25,[])] +[(1,[]),(6,[]),(36,[])] +[(1,[]),(7,[]),(49,[])] +[(1,[]),(8,[]),(64,[])] +[(1,[]),(9,[]),(81,[])] diff --git a/dbms/tests/queries/0_stateless/01065_array_zip_mixed_const.sql b/dbms/tests/queries/0_stateless/01065_array_zip_mixed_const.sql new file mode 100644 index 00000000000..0cd369739f4 --- /dev/null +++ b/dbms/tests/queries/0_stateless/01065_array_zip_mixed_const.sql @@ -0,0 +1,7 @@ +SELECT arrayZip([0, 1], ['hello', 'world']); +SELECT arrayZip(materialize([0, 1]), ['hello', 'world']); +SELECT arrayZip([0, 1], materialize(['hello', 'world'])); +SELECT arrayZip(materialize([0, 1]), materialize(['hello', 'world'])); + +SELECT arrayZip([0, number], [toString(number), 'world']) FROM numbers(10); +SELECT arrayZip([1, number, number * number], [[], [], []]) FROM numbers(10);