diff --git a/dbms/include/DB/Storages/StorageMerge.h b/dbms/include/DB/Storages/StorageMerge.h index e02e349bf79..214b1d4dc34 100644 --- a/dbms/include/DB/Storages/StorageMerge.h +++ b/dbms/include/DB/Storages/StorageMerge.h @@ -45,8 +45,8 @@ public: bool supportsIndexForIn() const override { return true; } const NamesAndTypesList & getColumnsListImpl() const override { return *columns; } - NameAndTypePair getColumn(const String &column_name) const override; - bool hasColumn(const String &column_name) const override; + NameAndTypePair getColumn(const String & column_name) const override; + bool hasColumn(const String & column_name) const override; BlockInputStreams read( const Names & column_names, diff --git a/dbms/src/Interpreters/ExpressionAnalyzer.cpp b/dbms/src/Interpreters/ExpressionAnalyzer.cpp index aa502cc5a33..5e8045822fc 100644 --- a/dbms/src/Interpreters/ExpressionAnalyzer.cpp +++ b/dbms/src/Interpreters/ExpressionAnalyzer.cpp @@ -1265,7 +1265,7 @@ void ExpressionAnalyzer::makeExplicitSet(ASTFunction * node, const Block & sampl } else { - /// Отличм случай (x, y) in ((1, 2), (3, 4)) от случая (x, y) in (1, 2). + /// Отличим случай (x, y) in ((1, 2), (3, 4)) от случая (x, y) in (1, 2). ASTFunction * any_element = typeid_cast(set_func->arguments->children.at(0).get()); if (set_element_types.size() >= 2 && (!any_element || any_element->name != "tuple")) single_value = true; diff --git a/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp b/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp index 4126d4efff8..d68b8db6a65 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp @@ -37,7 +37,7 @@ MergeTreeDataSelectExecutor::MergeTreeDataSelectExecutor(MergeTreeData & data_) /// Построить блок состоящий только из возможных значений виртуальных столбцов -static Block getBlockWithVirtualColumns(const MergeTreeData::DataPartsVector & parts) +static Block getBlockWithPartColumn(const MergeTreeData::DataPartsVector & parts) { Block res; ColumnWithTypeAndName _part(new ColumnString, new DataTypeString, "_part"); @@ -120,13 +120,19 @@ BlockInputStreams MergeTreeDataSelectExecutor::read( Names virt_column_names; Names real_column_names; + bool part_column_queried = false; + bool sample_factor_column_queried = false; Float64 used_sample_factor = 1; for (const String & name : column_names_to_return) { - if (name == "_part" - || name == "_part_index") + if (name == "_part") + { + part_column_queried = true; + virt_column_names.push_back(name); + } + else if (name == "_part_index") { virt_column_names.push_back(name); } @@ -141,23 +147,28 @@ BlockInputStreams MergeTreeDataSelectExecutor::read( } } + NamesAndTypesList available_real_columns = data.getColumnsList(); + + NamesAndTypesList available_real_and_virtual_columns = available_real_columns; + for (const auto & name : virt_column_names) + available_real_and_virtual_columns.emplace_back(data.getColumn(name)); + /// Если в запросе только виртуальные столбцы, надо запросить хотя бы один любой другой. if (real_column_names.empty()) - real_column_names.push_back(ExpressionActions::getSmallestColumn(data.getColumnsList())); + real_column_names.push_back(ExpressionActions::getSmallestColumn(available_real_columns)); - Block virtual_columns_block = getBlockWithVirtualColumns(parts); - - /// Если запрошен хотя бы один виртуальный столбец, пробуем индексировать - if (!virt_column_names.empty()) + /// Если запрошен виртуальный столбец _part, пробуем использовать его в качестве индекса. + Block virtual_columns_block = getBlockWithPartColumn(parts); + if (part_column_queried) VirtualColumnUtils::filterBlockWithQuery(query, virtual_columns_block, context); - std::multiset values = VirtualColumnUtils::extractSingleValueFromBlock(virtual_columns_block, "_part"); + std::multiset part_values = VirtualColumnUtils::extractSingleValueFromBlock(virtual_columns_block, "_part"); data.check(real_column_names); processed_stage = QueryProcessingStage::FetchColumns; - PKCondition key_condition(query, context, data.getColumnsList(), data.getSortDescription()); - PKCondition date_condition(query, context, data.getColumnsList(), SortDescription(1, SortColumnDescription(data.date_column_name, 1))); + PKCondition key_condition(query, context, available_real_and_virtual_columns, data.getSortDescription()); + PKCondition date_condition(query, context, available_real_and_virtual_columns, SortDescription(1, SortColumnDescription(data.date_column_name, 1))); if (settings.force_primary_key && key_condition.alwaysUnknownOrTrue()) throw Exception("Primary key is not used and setting 'force_primary_key' is set.", ErrorCodes::INDEX_NOT_USED); @@ -175,7 +186,7 @@ BlockInputStreams MergeTreeDataSelectExecutor::read( for (const auto & part : prev_parts) { - if (values.find(part->name) == values.end()) + if (part_values.find(part->name) == part_values.end()) continue; Field left = static_cast(part->left_date); @@ -401,7 +412,7 @@ BlockInputStreams MergeTreeDataSelectExecutor::read( filter_function->children.push_back(filter_function->arguments); } - filter_expression = ExpressionAnalyzer(filter_function, context, nullptr, data.getColumnsList()).getActions(false); + filter_expression = ExpressionAnalyzer(filter_function, context, nullptr, available_real_columns).getActions(false); /// Добавим столбцы, нужные для sampling_expression. std::vector add_columns = filter_expression->getRequiredColumns(); @@ -425,7 +436,7 @@ BlockInputStreams MergeTreeDataSelectExecutor::read( String prewhere_column; if (select.prewhere_expression) { - ExpressionAnalyzer analyzer(select.prewhere_expression, context, nullptr, data.getColumnsList()); + ExpressionAnalyzer analyzer(select.prewhere_expression, context, nullptr, available_real_columns); prewhere_actions = analyzer.getActions(false); prewhere_column = select.prewhere_expression->getColumnName(); SubqueriesForSets prewhere_subqueries = analyzer.getSubqueriesForSets(); @@ -801,7 +812,8 @@ BlockInputStreams MergeTreeDataSelectExecutor::spreadMarkRangesAmongThreadsFinal return res; } -void MergeTreeDataSelectExecutor::createPositiveSignCondition(ExpressionActionsPtr & out_expression, String & out_column, const Context & context) const +void MergeTreeDataSelectExecutor::createPositiveSignCondition( + ExpressionActionsPtr & out_expression, String & out_column, const Context & context) const { ASTFunction * function = new ASTFunction; ASTPtr function_ptr = function; diff --git a/dbms/src/Storages/MergeTree/PKCondition.cpp b/dbms/src/Storages/MergeTree/PKCondition.cpp index ddbdb6ee631..188fdc5ceec 100644 --- a/dbms/src/Storages/MergeTree/PKCondition.cpp +++ b/dbms/src/Storages/MergeTree/PKCondition.cpp @@ -112,8 +112,8 @@ PKCondition::PKCondition(ASTPtr & query, const Context & context, const NamesAnd } /** Вычисление выражений, зависящих только от констант. - * Чтобы индекс мог использоваться, если написано, например WHERE Date = toDate(now()). - */ + * Чтобы индекс мог использоваться, если написано, например WHERE Date = toDate(now()). + */ Block block_with_constants = getBlockWithConstants(query, context, all_columns); /// Преобразуем секцию WHERE в обратную польскую строку. diff --git a/dbms/tests/queries/0_stateless/00314_sample_factor_virtual_column.reference b/dbms/tests/queries/0_stateless/00314_sample_factor_virtual_column.reference index d00491fd7e5..6ed281c757a 100644 --- a/dbms/tests/queries/0_stateless/00314_sample_factor_virtual_column.reference +++ b/dbms/tests/queries/0_stateless/00314_sample_factor_virtual_column.reference @@ -1 +1,2 @@ 1 +1 diff --git a/dbms/tests/queries/0_stateless/00314_sample_factor_virtual_column.sql b/dbms/tests/queries/0_stateless/00314_sample_factor_virtual_column.sql index 6b404718e08..1d222db4e60 100644 --- a/dbms/tests/queries/0_stateless/00314_sample_factor_virtual_column.sql +++ b/dbms/tests/queries/0_stateless/00314_sample_factor_virtual_column.sql @@ -11,6 +11,7 @@ INSERT INTO test.sample2 (x) SELECT number AS x FROM system.numbers LIMIT 200000 CREATE TABLE test.sample_merge AS test.sample1 ENGINE = Merge(test, '^sample\\d$'); SELECT abs(sum(_sample_factor) - 3000000) / 3000000 < 0.001 FROM test.sample_merge SAMPLE 100000; +SELECT abs(sum(_sample_factor) - 3000000) / 3000000 < 0.001 FROM merge(test, '^sample\\d$') SAMPLE 100000; DROP TABLE test.sample1; DROP TABLE test.sample2;