diff --git a/dbms/src/Interpreters/ExpressionAnalyzer.cpp b/dbms/src/Interpreters/ExpressionAnalyzer.cpp index aeb44ee4afb93e927044af222cf3f37bbea295d7..144e6123fe367f3fa4613ed4f9bf058d05da197e 100644 --- a/dbms/src/Interpreters/ExpressionAnalyzer.cpp +++ b/dbms/src/Interpreters/ExpressionAnalyzer.cpp @@ -623,14 +623,15 @@ void ExpressionAnalyzer::findExternalTables(ASTPtr & ast) } static std::shared_ptr interpretSubquery( - const ASTPtr & subquery_or_table_name, const Context & context, size_t subquery_depth, const Names & required_source_columns) + const ASTPtr & table_expression, const Context & context, size_t subquery_depth, const Names & required_source_columns) { /// Subquery or table name. The name of the table is similar to the subquery `SELECT * FROM t`. - const ASTSubquery * subquery = typeid_cast(subquery_or_table_name.get()); - const ASTIdentifier * table = typeid_cast(subquery_or_table_name.get()); + const ASTSubquery * subquery = typeid_cast(table_expression.get()); + const ASTFunction * function = typeid_cast(table_expression.get()); + const ASTIdentifier * table = typeid_cast(table_expression.get()); - if (!subquery && !table) - throw Exception("IN/JOIN supports only SELECT subqueries.", ErrorCodes::BAD_ARGUMENTS); + 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. @@ -648,7 +649,7 @@ static std::shared_ptr interpretSubquery( subquery_context.setSettings(subquery_settings); ASTPtr query; - if (table) + if (table || function) { /// create ASTSelectQuery for "SELECT * FROM table" as if written by hand const auto select_with_union_query = std::make_shared(); @@ -663,17 +664,27 @@ static std::shared_ptr interpretSubquery( select_query->select_expression_list = select_expression_list; select_query->children.emplace_back(select_query->select_expression_list); + NamesAndTypesList columns; + /// get columns list for target table - auto database_table = getDatabaseAndTableNameFromIdentifier(*table); - const auto & storage = context.getTable(database_table.first, database_table.second); - const auto & columns = storage->getColumns().ordinary; - select_expression_list->children.reserve(columns.size()); + if (function) + { + const auto & storage = const_cast(&context)->executeTableFunction(table_expression); + columns = storage->getColumns().ordinary; + select_query->addTableFunction(*const_cast(&table_expression)); + } + else + { + auto database_table = getDatabaseAndTableNameFromIdentifier(*table); + const auto & storage = context.getTable(database_table.first, database_table.second); + columns = storage->getColumns().ordinary; + select_query->replaceDatabaseAndTable(database_table.first, database_table.second); + } + 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)); - - select_query->replaceDatabaseAndTable(database_table.first, database_table.second); } else { @@ -2453,6 +2464,12 @@ NamesAndTypesList ExpressionAnalyzer::AnalyzedJoin::getColumnsFromJoinedTable(co const auto & subquery = table_expression.subquery->children.at(0); nested_result_sample = InterpreterSelectWithUnionQuery::getSampleBlock(subquery, context); } + else if (table_expression.table_function) + { + const auto table_function = table_expression.table_function; + const auto join_storage = const_cast(&context.getQueryContext())->executeTableFunction(table_function); + nested_result_sample = join_storage->getSampleBlockNonMaterialized(); + } else if (table_expression.database_and_table_name) { const auto & identifier = static_cast(*table_expression.database_and_table_name); @@ -2529,10 +2546,12 @@ bool ExpressionAnalyzer::appendJoin(ExpressionActionsChain & chain, bool only_ty { ASTPtr table; - if (table_to_join.database_and_table_name) - table = table_to_join.database_and_table_name; - else + if (table_to_join.subquery) table = table_to_join.subquery; + else if (table_to_join.table_function) + table = table_to_join.table_function; + else if (table_to_join.database_and_table_name) + table = table_to_join.database_and_table_name; auto interpreter = interpretSubquery(table, context, subquery_depth, analyzed_join.required_columns_from_joined_table); subquery_for_set.source = std::make_shared( diff --git a/dbms/tests/queries/0_stateless/00689_join_table_function.reference b/dbms/tests/queries/0_stateless/00689_join_table_function.reference new file mode 100644 index 0000000000000000000000000000000000000000..014b6737cc712db103198372f7dbed3209ccccd2 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00689_join_table_function.reference @@ -0,0 +1,3 @@ +0 0 +1 1 +2 2 diff --git a/dbms/tests/queries/0_stateless/00689_join_table_function.sql b/dbms/tests/queries/0_stateless/00689_join_table_function.sql new file mode 100644 index 0000000000000000000000000000000000000000..d44d1009ce8fc2d073cd2b230bece8bb1d5f9fd9 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00689_join_table_function.sql @@ -0,0 +1 @@ +SELECT * FROM numbers(3) AS a ANY LEFT JOIN numbers(3) AS b ON a.number = b.number