Skip to content

Instantly share code, notes, and snippets.

@ucasfl
Last active November 1, 2020 03:17
Show Gist options
  • Save ucasfl/85ef9e87f844c8e50714db851c4fe005 to your computer and use it in GitHub Desktop.
Save ucasfl/85ef9e87f844c8e50714db851c4fe005 to your computer and use it in GitHub Desktop.
#include <Parsers/ASTExpressionList.h>
#include <Parsers/ASTSelectWithUnionQuery.h>
#include <Parsers/ExpressionListParsers.h>
#include <Parsers/ParserSelectWithUnionQuery.h>
#include <Parsers/ParserUnionQueryElement.h>
#include <Common/typeid_cast.h>
namespace DB
{
static void getSelectsFromUnionListNode(ASTPtr & ast_select, ASTs & selects)
{
if (auto * inner_union = ast_select->as<ASTSelectWithUnionQuery>())
{
for (auto & node : inner_union->flatten_nodes_list->children)
{
selects.push_back(std::move(node));
}
return;
}
selects.push_back(std::move(ast_select));
}
bool ParserSelectWithUnionQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
ASTPtr list_node;
ParserUnionList parser(
std::make_unique<ParserUnionQueryElement>(),
std::make_unique<ParserKeyword>("UNION"),
std::make_unique<ParserKeyword>("ALL"),
std::make_unique<ParserKeyword>("DISTINCT"));
if (!parser.parse(pos, list_node, expected))
return false;
auto select_with_union_query = std::make_shared<ASTSelectWithUnionQuery>();
node = select_with_union_query;
select_with_union_query->list_of_selects = std::make_shared<ASTExpressionList>();
select_with_union_query->children.push_back(select_with_union_query->list_of_selects);
select_with_union_query->list_of_selects->children.insert(
select_with_union_query->list_of_selects->children.begin(), list_node->children.begin(), list_node->children.end());
select_with_union_query->union_modes = parser.getUnionModes();
/// NOTE: We cann't simply flatten inner union query now, since we may have different union mode in query,
/// so flatten may change it's semantics. For example:
/// flatten `SELECT 1 UNION (SELECT 1 UNION ALL SELETC 1)` -> `SELECT 1 UNION SELECT 1 UNION ALL SELECT 1`
/// We can use a non-flatten AST to help build QueryPlan in InterpreterSelectWithUnionQuery
select_with_union_query->flatten_nodes_list = std::make_shared<ASTExpressionList>();
for (auto & child : list_node->children)
{
getSelectsFromUnionListNode(child, select_with_union_query->flatten_nodes_list->children);
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment