diff --git a/src/Interpreters/InterpreterInsertQuery.cpp b/src/Interpreters/InterpreterInsertQuery.cpp index aa8bcd74ea6..5ffd667bf40 100644 --- a/src/Interpreters/InterpreterInsertQuery.cpp +++ b/src/Interpreters/InterpreterInsertQuery.cpp @@ -140,34 +140,39 @@ Block InterpreterInsertQuery::getSampleBlock( /** A query that just reads all data without any complex computations or filetering. * If we just pipe the result to INSERT, we don't have to use too many threads for read. */ -static bool isTrivialSelect(const ASTSelectQuery & select_query) +static bool isTrivialSelect(const ASTPtr & select) { - const auto & tables = select_query.tables(); + if (auto select_query = select->as()) + { + const auto & tables = select_query->tables(); - if (!tables) - return false; + if (!tables) + return false; - const auto & tables_in_select_query = tables->as(); + const auto & tables_in_select_query = tables->as(); - if (tables_in_select_query.children.size() != 1) - return false; + if (tables_in_select_query.children.size() != 1) + return false; - const auto & child = tables_in_select_query.children.front(); - const auto & table_element = child->as(); - const auto & table_expr = table_element.table_expression->as(); + const auto & child = tables_in_select_query.children.front(); + const auto & table_element = child->as(); + const auto & table_expr = table_element.table_expression->as(); - if (table_expr.subquery) - return false; + if (table_expr.subquery) + return false; - /// Note: how to write it in more generic way? - return (!select_query.distinct - && !select_query.limit_with_ties - && !select_query.prewhere() - && !select_query.where() - && !select_query.groupBy() - && !select_query.having() - && !select_query.orderBy() - && !select_query.limitBy()); + /// Note: how to write it in more generic way? + return (!select_query->distinct + && !select_query->limit_with_ties + && !select_query->prewhere() + && !select_query->where() + && !select_query->groupBy() + && !select_query->having() + && !select_query->orderBy() + && !select_query->limitBy()); + } + /// This query is ASTSelectWithUnionQuery subquery + return false; }; @@ -196,23 +201,25 @@ BlockIO InterpreterInsertQuery::execute() auto new_query = std::dynamic_pointer_cast(query.clone()); if (select.list_of_selects->children.size() == 1) { - auto & select_query = select.list_of_selects->children.at(0)->as(); - JoinedTables joined_tables(Context(context), select_query); - - if (joined_tables.tablesCount() == 1) + if (auto select_query = select.list_of_selects->children.at(0)->as()) { - storage_src = std::dynamic_pointer_cast(joined_tables.getLeftTableStorage()); - if (storage_src) + JoinedTables joined_tables(Context(context), *select_query); + + if (joined_tables.tablesCount() == 1) { - const auto select_with_union_query = std::make_shared(); - select_with_union_query->list_of_selects = std::make_shared(); + storage_src = std::dynamic_pointer_cast(joined_tables.getLeftTableStorage()); + if (storage_src) + { + const auto select_with_union_query = std::make_shared(); + select_with_union_query->list_of_selects = std::make_shared(); - auto new_select_query = std::dynamic_pointer_cast(select_query.clone()); - select_with_union_query->list_of_selects->children.push_back(new_select_query); + auto new_select_query = std::dynamic_pointer_cast(select_query->clone()); + select_with_union_query->list_of_selects->children.push_back(new_select_query); - new_select_query->replaceDatabaseAndTable(storage_src->getRemoteDatabaseName(), storage_src->getRemoteTableName()); + new_select_query->replaceDatabaseAndTable(storage_src->getRemoteDatabaseName(), storage_src->getRemoteTableName()); - new_query->select = select_with_union_query; + new_query->select = select_with_union_query; + } } } } @@ -277,10 +284,8 @@ BlockIO InterpreterInsertQuery::execute() { const auto & selects = query.select->as().list_of_selects->children; - is_trivial_insert_select = std::all_of(selects.begin(), selects.end(), [](const ASTPtr & select) - { - return isTrivialSelect(select->as()); - }); + is_trivial_insert_select + = std::all_of(selects.begin(), selects.end(), [](const ASTPtr & select) { return isTrivialSelect(select); }); } if (is_trivial_insert_select) diff --git a/src/Parsers/ASTSelectWithUnionQuery.cpp b/src/Parsers/ASTSelectWithUnionQuery.cpp index 57a3c00543c..29aa1b81acf 100644 --- a/src/Parsers/ASTSelectWithUnionQuery.cpp +++ b/src/Parsers/ASTSelectWithUnionQuery.cpp @@ -48,7 +48,8 @@ void ASTSelectWithUnionQuery::formatQueryImpl(const FormatSettings & settings, F } else { - settings.ostr << settings.nl_or_ws; + if (it != list_of_selects->children.begin()) + settings.ostr << settings.nl_or_ws; (*it)->formatImpl(settings, state, frame); } } diff --git a/src/Storages/SelectQueryDescription.cpp b/src/Storages/SelectQueryDescription.cpp index 0935a5be5ca..db886793f7c 100644 --- a/src/Storages/SelectQueryDescription.cpp +++ b/src/Storages/SelectQueryDescription.cpp @@ -98,20 +98,35 @@ void checkAllowedQueries(const ASTSelectQuery & query) } +/// check if only one single select query in SelectWithUnionQuery +static bool isSingleSelect(const ASTPtr & select, ASTPtr & res) +{ + auto new_select = select->as(); + if (new_select.list_of_selects->children.size() != 1) + return false; + auto & new_inner_query = new_select.list_of_selects->children.at(0); + if (auto _ = new_inner_query->as()) + { + res = new_inner_query; + return true; + } + else + return isSingleSelect(new_inner_query, res); +} + SelectQueryDescription SelectQueryDescription::getSelectQueryFromASTForMatView(const ASTPtr & select, const Context & context) { - auto & new_select = select->as(); + ASTPtr new_inner_query; - if (new_select.list_of_selects->children.size() != 1) + if (!isSingleSelect(select, new_inner_query)) throw Exception("UNION is not supported for MATERIALIZED VIEW", ErrorCodes::QUERY_IS_NOT_SUPPORTED_IN_MATERIALIZED_VIEW); - auto & new_inner_query = new_select.list_of_selects->children.at(0); auto & select_query = new_inner_query->as(); checkAllowedQueries(select_query); SelectQueryDescription result; result.select_table_id = extractDependentTableFromSelectQuery(select_query, context); - result.select_query = new_select.clone(); + result.select_query = select->as().clone(); result.inner_query = new_inner_query->clone(); return result;