Analyzer: Do not execute table functions multiple times

This commit is contained in:
Dmitry Novik 2023-05-22 16:36:34 +00:00
parent 7bed59e1d2
commit fc10ba871f
3 changed files with 29 additions and 1 deletions

View File

@ -6355,7 +6355,7 @@ void QueryAnalyzer::resolveTableFunction(QueryTreeNodePtr & table_function_node,
auto table_function_ast = table_function_node_typed.toAST();
table_function_ptr->parseArguments(table_function_ast, scope_context);
auto table_function_storage = table_function_ptr->execute(table_function_ast, scope_context, table_function_ptr->getName());
auto table_function_storage = scope_context->getQueryContext()->executeTableFunction(table_function_ast, table_function_ptr);
table_function_node_typed.resolve(std::move(table_function_ptr), std::move(table_function_storage), scope_context);
}

View File

@ -1623,6 +1623,31 @@ StoragePtr Context::executeTableFunction(const ASTPtr & table_expression, const
return res;
}
StoragePtr Context::executeTableFunction(const ASTPtr & table_expression, const TableFunctionPtr & table_function_ptr)
{
auto hash = table_expression->getTreeHash();
String key = toString(hash.first) + '_' + toString(hash.second);
StoragePtr & res = table_function_results[key];
if (!res)
{
res = table_function_ptr->execute(table_expression, shared_from_this(), table_function_ptr->getName());
/// Since ITableFunction::parseArguments() may change table_expression, i.e.:
///
/// remote('127.1', system.one) -> remote('127.1', 'system.one'),
///
auto new_hash = table_expression->getTreeHash();
if (hash != new_hash)
{
key = toString(new_hash.first) + '_' + toString(new_hash.second);
table_function_results[key] = res;
}
}
return res;
}
void Context::addViewSource(const StoragePtr & storage)
{

View File

@ -108,6 +108,7 @@ class StorageS3Settings;
class IDatabase;
class DDLWorker;
class ITableFunction;
using TableFunctionPtr = std::shared_ptr<ITableFunction>;
class Block;
class ActionLocksManager;
using ActionLocksManagerPtr = std::shared_ptr<ActionLocksManager>;
@ -650,6 +651,8 @@ public:
/// For table functions s3/file/url/hdfs/input we can use structure from
/// insertion table depending on select expression.
StoragePtr executeTableFunction(const ASTPtr & table_expression, const ASTSelectQuery * select_query_hint = nullptr);
/// Overload for the new analyzer. Structure inference is performed in QueryAnalysisPass.
StoragePtr executeTableFunction(const ASTPtr & table_expression, const TableFunctionPtr & table_function_ptr);
void addViewSource(const StoragePtr & storage);
StoragePtr getViewSource() const;