| 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 |  | 
|---|