From 4be393fba53da27ca59c48a6e534f8e125a4803e Mon Sep 17 00:00:00 2001 From: Maksim Kita Date: Fri, 21 Jan 2022 15:14:31 +0000 Subject: [PATCH] Support cast from Map to Array of Tuple --- src/Functions/FunctionsConversion.h | 27 ++++++++++++++++--- .../02179_map_cast_to_array.reference | 8 ++++++ .../0_stateless/02179_map_cast_to_array.sql | 26 ++++++++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 tests/queries/0_stateless/02179_map_cast_to_array.reference create mode 100644 tests/queries/0_stateless/02179_map_cast_to_array.sql diff --git a/src/Functions/FunctionsConversion.h b/src/Functions/FunctionsConversion.h index f8d3a7a4e02..f2accb9bb22 100644 --- a/src/Functions/FunctionsConversion.h +++ b/src/Functions/FunctionsConversion.h @@ -2805,10 +2805,18 @@ private: } const auto * from_type = checkAndGetDataType(from_type_untyped.get()); + + if (!from_type) + { + /// Convert from Map + const auto * from_type_map = checkAndGetDataType(from_type_untyped.get()); + from_type = checkAndGetDataType(from_type_map->getNestedType().get()); + } + if (!from_type) { throw Exception(ErrorCodes::TYPE_MISMATCH, - "CAST AS Array can only be performed between same-dimensional Array or String types"); + "CAST AS Array can only be performed between same-dimensional Array, Map or String types"); } DataTypePtr from_nested_type = from_type->getNestedType(); @@ -2828,9 +2836,16 @@ private: return [nested_function, from_nested_type, to_nested_type]( ColumnsWithTypeAndName & arguments, const DataTypePtr &, const ColumnNullable * nullable_source, size_t /*input_rows_count*/) -> ColumnPtr { - const auto & array_arg = arguments.front(); + const auto & argument_column = arguments.front(); - if (const ColumnArray * col_array = checkAndGetColumn(array_arg.column.get())) + const ColumnArray * col_array = nullptr; + + if (const ColumnMap * col_map = checkAndGetColumn(argument_column.column.get())) + col_array = &col_map->getNestedColumn(); + else + col_array = checkAndGetColumn(argument_column.column.get()); + + if (col_array) { /// create columns for converting nested column containing original and result columns ColumnsWithTypeAndName nested_columns{{ col_array->getDataPtr(), from_nested_type, "" }}; @@ -2842,7 +2857,11 @@ private: return ColumnArray::create(result_column, col_array->getOffsetsPtr()); } else - throw Exception{"Illegal column " + array_arg.column->getName() + " for function CAST AS Array", ErrorCodes::LOGICAL_ERROR}; + { + throw Exception(ErrorCodes::LOGICAL_ERROR, + "Illegal column {} for function CAST AS Array", + argument_column.column->getName()); + } }; } diff --git a/tests/queries/0_stateless/02179_map_cast_to_array.reference b/tests/queries/0_stateless/02179_map_cast_to_array.reference new file mode 100644 index 00000000000..c1870e78bb7 --- /dev/null +++ b/tests/queries/0_stateless/02179_map_cast_to_array.reference @@ -0,0 +1,8 @@ +{1:'Test'} [(1,'Test')] [(1,'Test')] +{1:'1234'} [(1,1234)] [(1,1234)] +{1:[1,2,3]} [(1,['1','2','3'])] [(1,['1','2','3'])] +{1:['1','2','3']} [(1,[1,2,3])] [(1,[1,2,3])] +{1:{1:'1234'}} [(1,{1:'1234'})] [(1,{1:'1234'})] +{1:{1:'1234'}} [(1,{1:1234})] [(1,{1:1234})] +{1:{1:'1234'}} [(1,[(1,'1234')])] [(1,[(1,'1234')])] +{1:{1:'1234'}} [(1,[(1,1234)])] [(1,[(1,1234)])] diff --git a/tests/queries/0_stateless/02179_map_cast_to_array.sql b/tests/queries/0_stateless/02179_map_cast_to_array.sql new file mode 100644 index 00000000000..b1320d7a43c --- /dev/null +++ b/tests/queries/0_stateless/02179_map_cast_to_array.sql @@ -0,0 +1,26 @@ +WITH map(1, 'Test') AS value, 'Array(Tuple(UInt64, String))' AS type +SELECT value, cast(value, type), cast(materialize(value), type); + +WITH map(1, 'Test') AS value, 'Array(Tuple(UInt64, UInt64))' AS type +SELECT value, cast(value, type), cast(materialize(value), type); --{serverError 6} + +WITH map(1, '1234') AS value, 'Array(Tuple(UInt64, UInt64))' AS type +SELECT value, cast(value, type), cast(materialize(value), type); + +WITH map(1, [1, 2, 3]) AS value, 'Array(Tuple(UInt64, Array(String)))' AS type +SELECT value, cast(value, type), cast(materialize(value), type); + +WITH map(1, ['1', '2', '3']) AS value, 'Array(Tuple(UInt64, Array(UInt64)))' AS type +SELECT value, cast(value, type), cast(materialize(value), type); + +WITH map(1, map(1, '1234')) AS value, 'Array(Tuple(UInt64, Map(UInt64, String)))' AS type +SELECT value, cast(value, type), cast(materialize(value), type); + +WITH map(1, map(1, '1234')) AS value, 'Array(Tuple(UInt64, Map(UInt64, UInt64)))' AS type +SELECT value, cast(value, type), cast(materialize(value), type); + +WITH map(1, map(1, '1234')) AS value, 'Array(Tuple(UInt64, Array(Tuple(UInt64, String))))' AS type +SELECT value, cast(value, type), cast(materialize(value), type); + +WITH map(1, map(1, '1234')) as value, 'Array(Tuple(UInt64, Array(Tuple(UInt64, UInt64))))' AS type +SELECT value, cast(value, type), cast(materialize(value), type);