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.
* 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)
return false;
if (!tables)
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)
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<ASTTablesInSelectQueryElement &>();
const auto & table_expr = table_element.table_expression->as<ASTTableExpression &>();
const auto & child = tables_in_select_query.children.front();
const auto & table_element = child->as<ASTTablesInSelectQueryElement &>();
const auto & table_expr = table_element.table_expression->as<ASTTableExpression &>();
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<ASTInsertQuery>(query.clone());
if (select.list_of_selects->children.size() == 1)
{
auto & select_query = select.list_of_selects->children.at(0)->as<ASTSelectQuery &>();
JoinedTables joined_tables(Context(context), select_query);
if (joined_tables.tablesCount() == 1)
if (auto select_query = select.list_of_selects->children.at(0)->as<ASTSelectQuery>())
{
storage_src = std::dynamic_pointer_cast<StorageDistributed>(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<ASTSelectWithUnionQuery>();
select_with_union_query->list_of_selects = std::make_shared<ASTExpressionList>();
storage_src = std::dynamic_pointer_cast<StorageDistributed>(joined_tables.getLeftTableStorage());
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());
select_with_union_query->list_of_selects->children.push_back(new_select_query);
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);
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;
is_trivial_insert_select = std::all_of(selects.begin(), selects.end(), [](const ASTPtr & select)
{
return isTrivialSelect(select->as<ASTSelectQuery &>());
});
is_trivial_insert_select
= std::all_of(selects.begin(), selects.end(), [](const ASTPtr & select) { return isTrivialSelect(select); });
}
if (is_trivial_insert_select)

View File

@ -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);
}
}

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)
{
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);
auto & new_inner_query = new_select.list_of_selects->children.at(0);
auto & select_query = new_inner_query->as<ASTSelectQuery &>();
checkAllowedQueries(select_query);
SelectQueryDescription result;
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();
return result;