#include #include #include #include #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int LOGICAL_ERROR; } std::shared_ptr interpretSubquery( const ASTPtr & table_expression, const Context & context, size_t subquery_depth, const Names & required_source_columns) { auto subquery_options = SelectQueryOptions(QueryProcessingStage::Complete, subquery_depth); return interpretSubquery(table_expression, context, required_source_columns, subquery_options); } std::shared_ptr interpretSubquery( const ASTPtr & table_expression, const Context & context, const Names & required_source_columns, const SelectQueryOptions & options) { if (auto * expr = table_expression->as()) { ASTPtr table; if (expr->subquery) table = expr->subquery; else if (expr->table_function) table = expr->table_function; else if (expr->database_and_table_name) table = expr->database_and_table_name; return interpretSubquery(table, context, required_source_columns, options); } /// Subquery or table name. The name of the table is similar to the subquery `SELECT * FROM t`. const auto * subquery = table_expression->as(); const auto * function = table_expression->as(); const auto * table = table_expression->as(); if (!subquery && !table && !function) throw Exception("Table expression is undefined, Method: ExpressionAnalyzer::interpretSubquery." , ErrorCodes::LOGICAL_ERROR); /** The subquery in the IN / JOIN section does not have any restrictions on the maximum size of the result. * Because the result of this query is not the result of the entire query. * Constraints work instead * max_rows_in_set, max_bytes_in_set, set_overflow_mode, * max_rows_in_join, max_bytes_in_join, join_overflow_mode, * which are checked separately (in the Set, Join objects). */ Context subquery_context = context; Settings subquery_settings = context.getSettings(); subquery_settings.max_result_rows = 0; subquery_settings.max_result_bytes = 0; /// 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). subquery_settings.extremes = false; subquery_context.setSettings(subquery_settings); auto subquery_options = options.subquery(); ASTPtr query; if (table || function) { /// create ASTSelectQuery for "SELECT * FROM table" as if written by hand const auto select_with_union_query = std::make_shared(); query = select_with_union_query; select_with_union_query->list_of_selects = std::make_shared(); const auto select_query = std::make_shared(); select_with_union_query->list_of_selects->children.push_back(select_query); select_query->setExpression(ASTSelectQuery::Expression::SELECT, std::make_shared()); const auto select_expression_list = select_query->select(); NamesAndTypesList columns; /// get columns list for target table if (function) { auto query_context = const_cast(&context.getQueryContext()); const auto & storage = query_context->executeTableFunction(table_expression); columns = storage->getColumns().getOrdinary(); select_query->addTableFunction(*const_cast(&table_expression)); // XXX: const_cast should be avoided! } else { auto table_id = context.resolveStorageID(table_expression); const auto & storage = DatabaseCatalog::instance().getTable(table_id); columns = storage->getColumns().getOrdinary(); select_query->replaceDatabaseAndTable(table_id); } select_expression_list->children.reserve(columns.size()); /// manually substitute column names in place of asterisk for (const auto & column : columns) select_expression_list->children.emplace_back(std::make_shared(column.name)); } else { query = subquery->children.at(0); subquery_options.removeDuplicates(); } return std::make_shared(query, subquery_context, subquery_options, required_source_columns); } }