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