diff --git a/dbms/include/DB/Storages/MergeTree/MergeTreeBlockInputStream.h b/dbms/include/DB/Storages/MergeTree/MergeTreeBlockInputStream.h index ff8e7254cfe..a214ab2ba8e 100644 --- a/dbms/include/DB/Storages/MergeTree/MergeTreeBlockInputStream.h +++ b/dbms/include/DB/Storages/MergeTree/MergeTreeBlockInputStream.h @@ -99,6 +99,47 @@ protected: /// Будем вызывать progressImpl самостоятельно. void progress(size_t rows, size_t bytes) {} + void injectRequiredColumns(NamesAndTypesList & columns) const { + std::set required_columns; + auto modified = false; + + for (auto it = std::begin(columns); it != std::end(columns);) + { + required_columns.emplace(*it); + + if (!owned_data_part->hasColumnFiles(it->name)) + { + const auto default_it = storage.column_defaults.find(it->name); + if (default_it != std::end(storage.column_defaults)) + { + IdentifierNameSet identifiers; + default_it->second.expression->collectIdentifierNames(identifiers); + + for (const auto & identifier : identifiers) + { + if (storage.hasColumn(identifier)) + { + NameAndTypePair column{identifier, storage.getDataTypeByName(identifier)}; + if (required_columns.count(column) == 0) + { + it = columns.emplace(++it, std::move(column)); + modified = true; + } + } + } + + if (modified) + continue; + } + } + + ++it; + } + + if (modified) + columns = NamesAndTypesList{std::begin(required_columns), std::end(required_columns)}; + } + Block readImpl() { Block res; @@ -108,6 +149,8 @@ protected: if (!reader) { + injectRequiredColumns(columns); + injectRequiredColumns(pre_columns); /// @todo resolve missing columns UncompressedCache * uncompressed_cache = use_uncompressed_cache ? storage.context.getUncompressedCache() : NULL; reader.reset(new MergeTreeReader(path, owned_data_part->name, columns, uncompressed_cache, storage, all_mark_ranges));