2021-08-26 13:19:52 +00:00
|
|
|
#include <Databases/DDLDependencyVisitor.h>
|
|
|
|
#include <Parsers/ASTFunction.h>
|
|
|
|
#include <Parsers/ASTCreateQuery.h>
|
|
|
|
#include <Parsers/ASTLiteral.h>
|
|
|
|
#include <Parsers/ASTIdentifier.h>
|
2021-09-02 13:34:46 +00:00
|
|
|
#include <Dictionaries/getDictionaryConfigurationFromAST.h>
|
2021-09-02 13:48:41 +00:00
|
|
|
#include <Poco/String.h>
|
2021-08-26 13:19:52 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
void DDLDependencyVisitor::visit(const ASTPtr & ast, Data & data)
|
|
|
|
{
|
2021-09-13 19:11:16 +00:00
|
|
|
/// Looking for functions in column default expressions and dictionary source definition
|
2021-08-26 13:19:52 +00:00
|
|
|
if (const auto * function = ast->as<ASTFunction>())
|
|
|
|
visit(*function, data);
|
2021-09-02 13:34:46 +00:00
|
|
|
else if (const auto * dict_source = ast->as<ASTFunctionWithKeyValueArguments>())
|
|
|
|
visit(*dict_source, data);
|
2021-08-26 13:19:52 +00:00
|
|
|
}
|
|
|
|
|
2021-09-24 10:22:22 +00:00
|
|
|
bool DDLDependencyVisitor::needChildVisit(const ASTPtr & node, const ASTPtr & child)
|
2021-08-26 13:19:52 +00:00
|
|
|
{
|
2021-09-24 10:22:22 +00:00
|
|
|
if (node->as<ASTStorage>())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (auto * create = node->as<ASTCreateQuery>())
|
|
|
|
{
|
|
|
|
if (child.get() == create->select)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2021-08-26 13:19:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DDLDependencyVisitor::visit(const ASTFunction & function, Data & data)
|
|
|
|
{
|
|
|
|
if (function.name == "joinGet" ||
|
|
|
|
function.name == "dictHas" ||
|
|
|
|
function.name == "dictIsIn" ||
|
|
|
|
function.name.starts_with("dictGet"))
|
|
|
|
{
|
|
|
|
extractTableNameFromArgument(function, data, 0);
|
|
|
|
}
|
2021-09-02 13:48:41 +00:00
|
|
|
else if (Poco::toLower(function.name) == "in")
|
|
|
|
{
|
|
|
|
extractTableNameFromArgument(function, data, 1);
|
|
|
|
}
|
|
|
|
|
2021-08-26 13:19:52 +00:00
|
|
|
}
|
|
|
|
|
2021-09-02 13:34:46 +00:00
|
|
|
void DDLDependencyVisitor::visit(const ASTFunctionWithKeyValueArguments & dict_source, Data & data)
|
|
|
|
{
|
|
|
|
if (dict_source.name != "clickhouse")
|
|
|
|
return;
|
|
|
|
if (!dict_source.elements)
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto config = getDictionaryConfigurationFromAST(data.create_query->as<ASTCreateQuery &>(), data.global_context);
|
2021-09-13 19:11:16 +00:00
|
|
|
auto info = getInfoIfClickHouseDictionarySource(config, data.global_context);
|
|
|
|
|
|
|
|
if (!info || !info->is_local)
|
2021-09-02 13:34:46 +00:00
|
|
|
return;
|
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
if (info->table_name.database.empty())
|
|
|
|
info->table_name.database = data.default_database;
|
|
|
|
data.dependencies.emplace(std::move(info->table_name));
|
2021-09-02 13:34:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-08-26 13:19:52 +00:00
|
|
|
void DDLDependencyVisitor::extractTableNameFromArgument(const ASTFunction & function, Data & data, size_t arg_idx)
|
|
|
|
{
|
|
|
|
/// Just ignore incorrect arguments, proper exception will be thrown later
|
|
|
|
if (!function.arguments || function.arguments->children.size() <= arg_idx)
|
|
|
|
return;
|
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
QualifiedTableName qualified_name;
|
2021-08-26 13:19:52 +00:00
|
|
|
|
|
|
|
const auto * arg = function.arguments->as<ASTExpressionList>()->children[arg_idx].get();
|
|
|
|
if (const auto * literal = arg->as<ASTLiteral>())
|
|
|
|
{
|
|
|
|
if (literal->value.getType() != Field::Types::String)
|
|
|
|
return;
|
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
auto maybe_qualified_name = QualifiedTableName::tryParseFromString(literal->value.get<String>());
|
|
|
|
/// Just return if name if invalid
|
|
|
|
if (!maybe_qualified_name)
|
2021-08-26 13:19:52 +00:00
|
|
|
return;
|
2021-09-13 19:11:16 +00:00
|
|
|
|
|
|
|
qualified_name = std::move(*maybe_qualified_name);
|
2021-08-26 13:19:52 +00:00
|
|
|
}
|
|
|
|
else if (const auto * identifier = arg->as<ASTIdentifier>())
|
|
|
|
{
|
|
|
|
auto table_identifier = identifier->createTable();
|
2021-09-13 19:11:16 +00:00
|
|
|
/// Just return if table identified is invalid
|
2021-08-26 13:19:52 +00:00
|
|
|
if (!table_identifier)
|
|
|
|
return;
|
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
qualified_name.database = table_identifier->getDatabaseName();
|
|
|
|
qualified_name.table = table_identifier->shortName();
|
2021-08-26 13:19:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
if (qualified_name.database.empty())
|
|
|
|
qualified_name.database = data.default_database;
|
|
|
|
data.dependencies.emplace(std::move(qualified_name));
|
2021-08-26 13:19:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|