From 7b4bffe0884508f8a9ffccc7b8be1540bcda1f90 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Wed, 29 Nov 2017 02:31:21 +0300 Subject: [PATCH] Unification of serde of data types: development [#CLICKHOUSE-2838]. --- dbms/src/DataTypes/DataTypeArray.cpp | 4 +- .../Storages/MergeTree/MergeTreeReader.cpp | 47 +++++++++++++++---- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/dbms/src/DataTypes/DataTypeArray.cpp b/dbms/src/DataTypes/DataTypeArray.cpp index 1b30122270e..c9ba02d1e44 100644 --- a/dbms/src/DataTypes/DataTypeArray.cpp +++ b/dbms/src/DataTypes/DataTypeArray.cpp @@ -243,9 +243,7 @@ void DataTypeArray::deserializeBinaryBulkWithMultipleStreams( /// Check consistency between offsets and elements subcolumns. /// But if elements column is empty - it's ok for columns of Nested types that was added by ALTER. - if (nested_column.empty()) - column_array.getOffsetsColumn() = column_array.getOffsetsColumn()->cloneEmpty(); - else if (nested_column.size() != last_offset) + if (!nested_column.empty() && nested_column.size() != last_offset) throw Exception("Cannot read all array values", ErrorCodes::CANNOT_READ_ALL_DATA); } diff --git a/dbms/src/Storages/MergeTree/MergeTreeReader.cpp b/dbms/src/Storages/MergeTree/MergeTreeReader.cpp index efd083e7c96..daa9e8c59f1 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeReader.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeReader.cpp @@ -431,17 +431,35 @@ void MergeTreeReader::readData( } +static bool arrayHasNoElementsRead(const IColumn & column) +{ + const ColumnArray * column_array = typeid_cast(&column); + + if (!column_array) + return false; + + size_t size = column_array->size(); + if (!size) + return false; + + size_t data_size = column_array->getData().size(); + if (data_size) + return false; + + size_t last_offset = column_array->getOffsets()[size - 1]; + return last_offset != 0; +} + + void MergeTreeReader::fillMissingColumns(Block & res, const Names & ordered_names, bool always_reorder) { if (!res) - throw Exception("Empty block passed to fillMissingColumnsImpl", ErrorCodes::LOGICAL_ERROR); + throw Exception("Empty block passed to fillMissingColumns", ErrorCodes::LOGICAL_ERROR); try { /// For a missing column of a nested data structure we must create not a column of empty /// arrays, but a column of arrays of correct length. - /// TODO: If for some nested data structure only missing columns were selected, the arrays in these columns will be empty, - /// even if the offsets for this nested structure are present in the current part. This can be fixed. /// NOTE: Similar, but slightly different code is present in Block::addDefaults. /// First, collect offset columns for all arrays in the block. @@ -462,13 +480,26 @@ void MergeTreeReader::fillMissingColumns(Block & res, const Names & ordered_name } } - auto should_evaluate_defaults = false; - auto should_sort = always_reorder; + bool should_evaluate_defaults = false; + bool should_sort = always_reorder; + size_t rows = res.rows(); + + /// insert default values only for columns without default expressions for (const auto & requested_column : columns) { - /// insert default values only for columns without default expressions - if (!res.has(requested_column.name)) + bool has_column = res.has(requested_column.name); + if (has_column) + { + const auto & col = *res.getByName(requested_column.name).column; + if (arrayHasNoElementsRead(col)) + { + res.erase(requested_column.name); + has_column = false; + } + } + + if (!has_column) { should_sort = true; if (storage.column_defaults.count(requested_column.name) != 0) @@ -499,7 +530,7 @@ void MergeTreeReader::fillMissingColumns(Block & res, const Names & ordered_name /// We must turn a constant column into a full column because the interpreter could infer that it is constant everywhere /// but in some blocks (from other parts) it can be a full column. column_to_add.column = column_to_add.type->createConstColumn( - res.rows(), column_to_add.type->getDefault())->convertToFullColumnIfConst(); + rows, column_to_add.type->getDefault())->convertToFullColumnIfConst(); } res.insert(std::move(column_to_add));