diff --git a/src/Columns/ColumnArray.cpp b/src/Columns/ColumnArray.cpp index 7e4e6233f73..58543d6a4dd 100644 --- a/src/Columns/ColumnArray.cpp +++ b/src/Columns/ColumnArray.cpp @@ -31,8 +31,17 @@ namespace ErrorCodes extern const int PARAMETER_OUT_OF_BOUND; extern const int SIZES_OF_COLUMNS_DOESNT_MATCH; extern const int LOGICAL_ERROR; + extern const int TOO_LARGE_ARRAY_SIZE; } +/** Obtaining array as Field can be slow for large arrays and consume vast amount of memory. + * Just don't allow to do it. + * You can increase the limit if the following query: + * SELECT range(10000000) + * will take less than 500ms on your machine. + */ +static constexpr size_t max_array_size_as_field = 1000000; + ColumnArray::ColumnArray(MutableColumnPtr && nested_column, MutableColumnPtr && offsets_column) : data(std::move(nested_column)), offsets(std::move(offsets_column)) @@ -117,6 +126,11 @@ Field ColumnArray::operator[](size_t n) const { size_t offset = offsetAt(n); size_t size = sizeAt(n); + + if (size > max_array_size_as_field) + throw Exception(ErrorCodes::TOO_LARGE_ARRAY_SIZE, "Array of size {} is too large to be manipulated as single field, maximum size {}", + size, max_array_size_as_field); + Array res(size); for (size_t i = 0; i < size; ++i) @@ -130,6 +144,11 @@ void ColumnArray::get(size_t n, Field & res) const { size_t offset = offsetAt(n); size_t size = sizeAt(n); + + if (size > max_array_size_as_field) + throw Exception(ErrorCodes::TOO_LARGE_ARRAY_SIZE, "Array of size {} is too large to be manipulated as single field, maximum size {}", + size, max_array_size_as_field); + res = Array(size); Array & res_arr = DB::get(res); diff --git a/src/Functions/array/range.cpp b/src/Functions/array/range.cpp index 16f95ac2682..9468b4df75d 100644 --- a/src/Functions/array/range.cpp +++ b/src/Functions/array/range.cpp @@ -102,7 +102,8 @@ private: } template - bool executeConstStartStep(Block & block, const IColumn * end_arg, const T start, const T step, const size_t input_rows_count, const size_t result) const + bool executeConstStartStep( + Block & block, const IColumn * end_arg, const T start, const T step, const size_t input_rows_count, const size_t result) const { auto end_column = checkAndGetColumn>(end_arg); if (!end_column) @@ -155,7 +156,8 @@ private: } template - bool executeConstStep(Block & block, const IColumn * start_arg, const IColumn * end_arg, const T step, const size_t input_rows_count, const size_t result) const + bool executeConstStep( + Block & block, const IColumn * start_arg, const IColumn * end_arg, const T step, const size_t input_rows_count, const size_t result) const { auto start_column = checkAndGetColumn>(start_arg); auto end_column = checkAndGetColumn>(end_arg); @@ -210,7 +212,8 @@ private: } template - bool executeConstStart(Block & block, const IColumn * end_arg, const IColumn * step_arg, const T start, const size_t input_rows_count, const size_t result) const + bool executeConstStart( + Block & block, const IColumn * end_arg, const IColumn * step_arg, const T start, const size_t input_rows_count, const size_t result) const { auto end_column = checkAndGetColumn>(end_arg); auto step_column = checkAndGetColumn>(step_arg); @@ -265,7 +268,9 @@ private: } template - bool executeGeneric(Block & block, const IColumn * start_col, const IColumn * end_col, const IColumn * step_col, const size_t input_rows_count, const size_t result) const + bool executeGeneric( + Block & block, const IColumn * start_col, const IColumn * end_col, const IColumn * step_col, + const size_t input_rows_count, const size_t result) const { auto start_column = checkAndGetColumn>(start_col); auto end_column = checkAndGetColumn>(end_col);