mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 08:32:02 +00:00
ISSUES-2906 support join for table function
This commit is contained in:
parent
5637b30556
commit
83ceeca199
@ -623,14 +623,15 @@ void ExpressionAnalyzer::findExternalTables(ASTPtr & ast)
|
||||
}
|
||||
|
||||
static std::shared_ptr<InterpreterSelectWithUnionQuery> 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<const ASTSubquery *>(subquery_or_table_name.get());
|
||||
const ASTIdentifier * table = typeid_cast<const ASTIdentifier *>(subquery_or_table_name.get());
|
||||
const ASTSubquery * subquery = typeid_cast<const ASTSubquery *>(table_expression.get());
|
||||
const ASTFunction * function = typeid_cast<const ASTFunction *>(table_expression.get());
|
||||
const ASTIdentifier * table = typeid_cast<const ASTIdentifier *>(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<InterpreterSelectWithUnionQuery> 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<ASTSelectWithUnionQuery>();
|
||||
@ -663,17 +664,27 @@ static std::shared_ptr<InterpreterSelectWithUnionQuery> interpretSubquery(
|
||||
select_query->select_expression_list = select_expression_list;
|
||||
select_query->children.emplace_back(select_query->select_expression_list);
|
||||
|
||||
/// 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());
|
||||
NamesAndTypesList columns;
|
||||
|
||||
/// get columns list for target table
|
||||
if (function)
|
||||
{
|
||||
const auto & storage = const_cast<Context *>(&context)->executeTableFunction(table_expression);
|
||||
columns = storage->getColumns().ordinary;
|
||||
select_query->addTableFunction(*const_cast<ASTPtr *>(&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<ASTIdentifier>(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 *>(&context.getQueryContext())->executeTableFunction(table_function);
|
||||
nested_result_sample = join_storage->getSampleBlockNonMaterialized();
|
||||
}
|
||||
else if (table_expression.database_and_table_name)
|
||||
{
|
||||
const auto & identifier = static_cast<const ASTIdentifier &>(*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<LazyBlockInputStream>(
|
||||
|
@ -0,0 +1,3 @@
|
||||
0 0
|
||||
1 1
|
||||
2 2
|
@ -0,0 +1 @@
|
||||
SELECT * FROM numbers(3) AS a ANY LEFT JOIN numbers(3) AS b ON a.number = b.number
|
Loading…
Reference in New Issue
Block a user