fix another issue with dependencies

This commit is contained in:
Alexander Tokmakov 2023-05-05 16:27:12 +02:00
parent 6cf3e5b77a
commit dd1bbf7c78
6 changed files with 44 additions and 8 deletions

View File

@ -12,6 +12,8 @@
#include <Parsers/ASTLiteral.h>
#include <Parsers/ASTSelectWithUnionQuery.h>
#include <Parsers/ASTTablesInSelectQuery.h>
#include <Parsers/ParserSelectWithUnionQuery.h>
#include <Parsers/parseQuery.h>
#include <Common/KnownObjectNames.h>
#include <Poco/String.h>
@ -25,6 +27,7 @@ namespace
/// Used to visits ASTCreateQuery and extracts the names of all tables explicitly referenced in the create query.
class DDLDependencyVisitorData
{
friend void tryVisitNestedSelect(const String & query, DDLDependencyVisitorData & data);
public:
DDLDependencyVisitorData(const ContextPtr & context_, const QualifiedTableName & table_name_, const ASTPtr & ast_)
: create_query(ast_), table_name(table_name_), current_database(context_->getCurrentDatabase()), context(context_)
@ -106,9 +109,17 @@ namespace
if (!info || !info->is_local)
return;
if (info->table_name.database.empty())
info->table_name.database = current_database;
dependencies.emplace(std::move(info->table_name));
if (!info->table_name.table.empty())
{
if (info->table_name.database.empty())
info->table_name.database = current_database;
dependencies.emplace(std::move(info->table_name));
}
else
{
/// We don't have a table name, we have a select query instead
tryVisitNestedSelect(info->query, *this);
}
}
/// ASTTableExpression represents a reference to a table in SELECT query.
@ -424,6 +435,24 @@ namespace
static bool needChildVisit(const ASTPtr &, const ASTPtr & child, const Data & data) { return data.needChildVisit(child); }
static void visit(const ASTPtr & ast, Data & data) { data.visit(ast); }
};
void tryVisitNestedSelect(const String & query, DDLDependencyVisitorData & data)
{
try
{
ParserSelectWithUnionQuery parser;
String description = fmt::format("Query for ClickHouse dictionary {}", data.table_name);
ASTPtr select = parseQuery(parser, query, description,
data.context->getSettingsRef().max_query_size, data.context->getSettingsRef().max_parser_depth);
DDLDependencyVisitor::Visitor visitor{data};
visitor.visit(select);
}
catch (...)
{
tryLogCurrentException("DDLDependencyVisitor");
}
}
}

View File

@ -103,7 +103,7 @@ void DDLLoadingDependencyVisitor::visit(const ASTFunctionWithKeyValueArguments &
auto config = getDictionaryConfigurationFromAST(data.create_query->as<ASTCreateQuery &>(), data.global_context);
auto info = getInfoIfClickHouseDictionarySource(config, data.global_context);
if (!info || !info->is_local)
if (!info || !info->is_local || info->table_name.table.empty())
return;
if (info->table_name.database.empty())

View File

@ -137,7 +137,7 @@ namespace
auto config = getDictionaryConfigurationFromAST(data.create_query->as<ASTCreateQuery &>(), data.global_context);
auto info = getInfoIfClickHouseDictionarySource(config, data.global_context);
if (!info || !info->is_local)
if (!info || !info->is_local || info->table_name.table.empty())
return;
auto * source_list = dictionary.source->elements->as<ASTExpressionList>();

View File

@ -649,10 +649,12 @@ getInfoIfClickHouseDictionarySource(DictionaryConfigurationPtr & config, Context
String database = config->getString("dictionary.source.clickhouse.db", "");
String table = config->getString("dictionary.source.clickhouse.table", "");
if (table.empty())
return {};
info.query = config->getString("dictionary.source.clickhouse.query", "");
info.table_name = {database, table};
if (!table.empty())
info.table_name = {database, table};
else if (info.query.empty())
return {};
try
{

View File

@ -18,6 +18,7 @@ getDictionaryConfigurationFromAST(const ASTCreateQuery & query, ContextPtr conte
struct ClickHouseDictionarySourceInfo
{
QualifiedTableName table_name;
String query;
bool is_local = false;
};

View File

@ -210,4 +210,8 @@ def test_no_lazy_load():
assert "42\n" == node2.query("select dictGet('no_lazy.dict', 'mm', 42)")
assert "some tables depend on it" in node2.query_and_get_error(
"drop table no_lazy.src", settings={"check_referential_table_dependencies": 1}
)
node2.query("drop database no_lazy")