2019-12-18 03:56:03 +00:00
|
|
|
#include <Interpreters/ExtractExpressionInfoVisitor.h>
|
|
|
|
#include <Functions/FunctionFactory.h>
|
|
|
|
#include <AggregateFunctions/AggregateFunctionFactory.h>
|
|
|
|
#include <Interpreters/IdentifierSemantic.h>
|
2020-01-06 10:33:08 +00:00
|
|
|
#include <Parsers/ASTSubquery.h>
|
2019-12-18 03:56:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
void ExpressionInfoMatcher::visit(const ASTPtr & ast, Data & data)
|
|
|
|
{
|
|
|
|
if (const auto * function = ast->as<ASTFunction>())
|
|
|
|
visit(*function, ast, data);
|
|
|
|
else if (const auto * identifier = ast->as<ASTIdentifier>())
|
|
|
|
visit(*identifier, ast, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExpressionInfoMatcher::visit(const ASTFunction & ast_function, const ASTPtr &, Data & data)
|
|
|
|
{
|
|
|
|
if (ast_function.name == "arrayJoin")
|
2020-12-16 21:44:05 +00:00
|
|
|
{
|
2019-12-18 03:56:03 +00:00
|
|
|
data.is_array_join = true;
|
2020-12-16 21:44:05 +00:00
|
|
|
}
|
2020-12-18 17:13:28 +00:00
|
|
|
// "is_aggregate_function" doesn't mean much by itself. Apparently here it is
|
|
|
|
// used to move filters from HAVING to WHERE, and probably for this purpose
|
|
|
|
// an aggregate function calculated as a window function is not relevant.
|
2020-12-16 21:44:05 +00:00
|
|
|
else if (!ast_function.is_window_function
|
|
|
|
&& AggregateFunctionFactory::instance().isAggregateFunctionName(
|
|
|
|
ast_function.name))
|
|
|
|
{
|
2019-12-18 03:56:03 +00:00
|
|
|
data.is_aggregate_function = true;
|
2020-12-16 21:44:05 +00:00
|
|
|
}
|
2019-12-18 03:56:03 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
const auto & function = FunctionFactory::instance().tryGet(ast_function.name, data.context);
|
|
|
|
|
|
|
|
/// Skip lambda, tuple and other special functions
|
2020-11-22 14:17:09 +00:00
|
|
|
if (function)
|
|
|
|
{
|
|
|
|
if (function->isStateful())
|
|
|
|
data.is_stateful_function = true;
|
|
|
|
|
|
|
|
if (!function->isDeterministicInScopeOfQuery())
|
|
|
|
data.is_deterministic_function = false;
|
|
|
|
}
|
2019-12-18 03:56:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExpressionInfoMatcher::visit(const ASTIdentifier & identifier, const ASTPtr &, Data & data)
|
|
|
|
{
|
|
|
|
if (!identifier.compound())
|
|
|
|
{
|
|
|
|
for (size_t index = 0; index < data.tables.size(); ++index)
|
|
|
|
{
|
2020-06-05 21:17:00 +00:00
|
|
|
const auto & table = data.tables[index];
|
2019-12-18 03:56:03 +00:00
|
|
|
|
|
|
|
// TODO: make sure no collision ever happens
|
2020-10-24 18:46:10 +00:00
|
|
|
if (table.hasColumn(identifier.name()))
|
2019-12-18 03:56:03 +00:00
|
|
|
{
|
|
|
|
data.unique_reference_tables_pos.emplace(index);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-08 11:07:05 +00:00
|
|
|
if (auto best_table_pos = IdentifierSemantic::chooseTable(identifier, data.tables))
|
|
|
|
data.unique_reference_tables_pos.emplace(*best_table_pos);
|
2019-12-18 03:56:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-06 10:33:08 +00:00
|
|
|
bool ExpressionInfoMatcher::needChildVisit(const ASTPtr & node, const ASTPtr &)
|
|
|
|
{
|
|
|
|
return !node->as<ASTSubquery>();
|
|
|
|
}
|
|
|
|
|
2020-01-04 04:31:45 +00:00
|
|
|
bool hasStatefulFunction(const ASTPtr & node, const Context & context)
|
|
|
|
{
|
|
|
|
for (const auto & select_expression : node->children)
|
|
|
|
{
|
|
|
|
ExpressionInfoVisitor::Data expression_info{.context = context, .tables = {}};
|
|
|
|
ExpressionInfoVisitor(expression_info).visit(select_expression);
|
|
|
|
|
|
|
|
if (expression_info.is_stateful_function)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-12-18 03:56:03 +00:00
|
|
|
}
|
|
|
|
|