This commit is contained in:
feng lv 2020-11-02 05:28:37 +00:00
parent f04d74172f
commit 3dce3c6a21
3 changed files with 63 additions and 42 deletions

View File

@ -140,34 +140,39 @@ Block InterpreterInsertQuery::getSampleBlock(
/** A query that just reads all data without any complex computations or filetering. /** 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. * 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<ASTSelectQuery>())
{
const auto & tables = select_query->tables();
if (!tables) if (!tables)
return false; return false;
const auto & tables_in_select_query = tables->as<ASTTablesInSelectQuery &>(); const auto & tables_in_select_query = tables->as<ASTTablesInSelectQuery &>();
if (tables_in_select_query.children.size() != 1) if (tables_in_select_query.children.size() != 1)
return false; return false;
const auto & child = tables_in_select_query.children.front(); const auto & child = tables_in_select_query.children.front();
const auto & table_element = child->as<ASTTablesInSelectQueryElement &>(); const auto & table_element = child->as<ASTTablesInSelectQueryElement &>();
const auto & table_expr = table_element.table_expression->as<ASTTableExpression &>(); const auto & table_expr = table_element.table_expression->as<ASTTableExpression &>();
if (table_expr.subquery) if (table_expr.subquery)
return false; return false;
/// Note: how to write it in more generic way? /// Note: how to write it in more generic way?
return (!select_query.distinct return (!select_query->distinct
&& !select_query.limit_with_ties && !select_query->limit_with_ties
&& !select_query.prewhere() && !select_query->prewhere()
&& !select_query.where() && !select_query->where()
&& !select_query.groupBy() && !select_query->groupBy()
&& !select_query.having() && !select_query->having()
&& !select_query.orderBy() && !select_query->orderBy()
&& !select_query.limitBy()); && !select_query->limitBy());
}
/// This query is ASTSelectWithUnionQuery subquery
return false;
}; };
@ -196,23 +201,25 @@ BlockIO InterpreterInsertQuery::execute()
auto new_query = std::dynamic_pointer_cast<ASTInsertQuery>(query.clone()); auto new_query = std::dynamic_pointer_cast<ASTInsertQuery>(query.clone());
if (select.list_of_selects->children.size() == 1) if (select.list_of_selects->children.size() == 1)
{ {
auto & select_query = select.list_of_selects->children.at(0)->as<ASTSelectQuery &>(); if (auto select_query = select.list_of_selects->children.at(0)->as<ASTSelectQuery>())
JoinedTables joined_tables(Context(context), select_query);
if (joined_tables.tablesCount() == 1)
{ {
storage_src = std::dynamic_pointer_cast<StorageDistributed>(joined_tables.getLeftTableStorage()); JoinedTables joined_tables(Context(context), *select_query);
if (storage_src)
if (joined_tables.tablesCount() == 1)
{ {
const auto select_with_union_query = std::make_shared<ASTSelectWithUnionQuery>(); storage_src = std::dynamic_pointer_cast<StorageDistributed>(joined_tables.getLeftTableStorage());
select_with_union_query->list_of_selects = std::make_shared<ASTExpressionList>(); if (storage_src)
{
const auto select_with_union_query = std::make_shared<ASTSelectWithUnionQuery>();
select_with_union_query->list_of_selects = std::make_shared<ASTExpressionList>();
auto new_select_query = std::dynamic_pointer_cast<ASTSelectQuery>(select_query.clone()); auto new_select_query = std::dynamic_pointer_cast<ASTSelectQuery>(select_query->clone());
select_with_union_query->list_of_selects->children.push_back(new_select_query); 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<ASTSelectWithUnionQuery &>().list_of_selects->children; const auto & selects = query.select->as<ASTSelectWithUnionQuery &>().list_of_selects->children;
is_trivial_insert_select = std::all_of(selects.begin(), selects.end(), [](const ASTPtr & select) is_trivial_insert_select
{ = std::all_of(selects.begin(), selects.end(), [](const ASTPtr & select) { return isTrivialSelect(select); });
return isTrivialSelect(select->as<ASTSelectQuery &>());
});
} }
if (is_trivial_insert_select) if (is_trivial_insert_select)

View File

@ -48,7 +48,8 @@ void ASTSelectWithUnionQuery::formatQueryImpl(const FormatSettings & settings, F
} }
else 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); (*it)->formatImpl(settings, state, frame);
} }
} }

View File

@ -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<ASTSelectWithUnionQuery &>();
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<ASTSelectQuery>())
{
res = new_inner_query;
return true;
}
else
return isSingleSelect(new_inner_query, res);
}
SelectQueryDescription SelectQueryDescription::getSelectQueryFromASTForMatView(const ASTPtr & select, const Context & context) SelectQueryDescription SelectQueryDescription::getSelectQueryFromASTForMatView(const ASTPtr & select, const Context & context)
{ {
auto & new_select = select->as<ASTSelectWithUnionQuery &>(); 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); 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<ASTSelectQuery &>(); auto & select_query = new_inner_query->as<ASTSelectQuery &>();
checkAllowedQueries(select_query); checkAllowedQueries(select_query);
SelectQueryDescription result; SelectQueryDescription result;
result.select_table_id = extractDependentTableFromSelectQuery(select_query, context); result.select_table_id = extractDependentTableFromSelectQuery(select_query, context);
result.select_query = new_select.clone(); result.select_query = select->as<ASTSelectWithUnionQuery &>().clone();
result.inner_query = new_inner_query->clone(); result.inner_query = new_inner_query->clone();
return result; return result;