1 | #include <Common/typeid_cast.h> |
2 | #include <IO/WriteHelpers.h> |
3 | |
4 | #include <Storages/IStorage.h> |
5 | |
6 | #include <Parsers/ASTFunction.h> |
7 | #include <Parsers/ASTIdentifier.h> |
8 | #include <Parsers/ASTSelectQuery.h> |
9 | #include <Parsers/ASTSelectWithUnionQuery.h> |
10 | #include <Parsers/ASTSubquery.h> |
11 | |
12 | #include <Interpreters/interpretSubquery.h> |
13 | #include <Interpreters/DatabaseAndTableWithAlias.h> |
14 | |
15 | namespace DB |
16 | { |
17 | |
18 | std::shared_ptr<InterpreterSelectWithUnionQuery> interpretSubquery( |
19 | const ASTPtr & table_expression, const Context & context, size_t subquery_depth, const Names & required_source_columns) |
20 | { |
21 | if (auto * expr = table_expression->as<ASTTableExpression>()) |
22 | { |
23 | ASTPtr table; |
24 | if (expr->subquery) |
25 | table = expr->subquery; |
26 | else if (expr->table_function) |
27 | table = expr->table_function; |
28 | else if (expr->database_and_table_name) |
29 | table = expr->database_and_table_name; |
30 | |
31 | return interpretSubquery(table, context, subquery_depth, required_source_columns); |
32 | } |
33 | |
34 | /// Subquery or table name. The name of the table is similar to the subquery `SELECT * FROM t`. |
35 | const auto * subquery = table_expression->as<ASTSubquery>(); |
36 | const auto * function = table_expression->as<ASTFunction>(); |
37 | const auto * table = table_expression->as<ASTIdentifier>(); |
38 | |
39 | if (!subquery && !table && !function) |
40 | throw Exception("Table expression is undefined, Method: ExpressionAnalyzer::interpretSubquery." , ErrorCodes::LOGICAL_ERROR); |
41 | |
42 | /** The subquery in the IN / JOIN section does not have any restrictions on the maximum size of the result. |
43 | * Because the result of this query is not the result of the entire query. |
44 | * Constraints work instead |
45 | * max_rows_in_set, max_bytes_in_set, set_overflow_mode, |
46 | * max_rows_in_join, max_bytes_in_join, join_overflow_mode, |
47 | * which are checked separately (in the Set, Join objects). |
48 | */ |
49 | Context subquery_context = context; |
50 | Settings subquery_settings = context.getSettings(); |
51 | subquery_settings.max_result_rows = 0; |
52 | subquery_settings.max_result_bytes = 0; |
53 | /// The calculation of `extremes` does not make sense and is not necessary (if you do it, then the `extremes` of the subquery can be taken instead of the whole query). |
54 | subquery_settings.extremes = 0; |
55 | subquery_context.setSettings(subquery_settings); |
56 | |
57 | auto subquery_options = SelectQueryOptions(QueryProcessingStage::Complete, subquery_depth).subquery(); |
58 | |
59 | ASTPtr query; |
60 | if (table || function) |
61 | { |
62 | /// create ASTSelectQuery for "SELECT * FROM table" as if written by hand |
63 | const auto select_with_union_query = std::make_shared<ASTSelectWithUnionQuery>(); |
64 | query = select_with_union_query; |
65 | |
66 | select_with_union_query->list_of_selects = std::make_shared<ASTExpressionList>(); |
67 | |
68 | const auto select_query = std::make_shared<ASTSelectQuery>(); |
69 | select_with_union_query->list_of_selects->children.push_back(select_query); |
70 | |
71 | select_query->setExpression(ASTSelectQuery::Expression::SELECT, std::make_shared<ASTExpressionList>()); |
72 | const auto select_expression_list = select_query->select(); |
73 | |
74 | NamesAndTypesList columns; |
75 | |
76 | /// get columns list for target table |
77 | if (function) |
78 | { |
79 | auto query_context = const_cast<Context *>(&context.getQueryContext()); |
80 | const auto & storage = query_context->executeTableFunction(table_expression); |
81 | columns = storage->getColumns().getOrdinary(); |
82 | select_query->addTableFunction(*const_cast<ASTPtr *>(&table_expression)); // XXX: const_cast should be avoided! |
83 | } |
84 | else |
85 | { |
86 | DatabaseAndTableWithAlias database_table(*table); |
87 | const auto & storage = context.getTable(database_table.database, database_table.table); |
88 | columns = storage->getColumns().getOrdinary(); |
89 | select_query->replaceDatabaseAndTable(database_table.database, database_table.table); |
90 | } |
91 | |
92 | select_expression_list->children.reserve(columns.size()); |
93 | /// manually substitute column names in place of asterisk |
94 | for (const auto & column : columns) |
95 | select_expression_list->children.emplace_back(std::make_shared<ASTIdentifier>(column.name)); |
96 | } |
97 | else |
98 | { |
99 | query = subquery->children.at(0); |
100 | subquery_options.removeDuplicates(); |
101 | } |
102 | |
103 | return std::make_shared<InterpreterSelectWithUnionQuery>(query, subquery_context, subquery_options, required_source_columns); |
104 | } |
105 | |
106 | } |
107 | |