2019-09-26 11:19:10 +00:00
|
|
|
#include <Interpreters/ExternalDictionariesLoader.h>
|
2021-03-19 12:47:27 +00:00
|
|
|
#include <Interpreters/DatabaseCatalog.h>
|
|
|
|
#include <Interpreters/Context.h>
|
2019-09-26 11:19:10 +00:00
|
|
|
#include <Dictionaries/DictionaryFactory.h>
|
2020-04-12 20:50:32 +00:00
|
|
|
#include <Dictionaries/DictionaryStructure.h>
|
2021-03-19 12:47:27 +00:00
|
|
|
#include <Databases/IDatabase.h>
|
|
|
|
#include <Storages/IStorage.h>
|
2020-04-16 12:31:57 +00:00
|
|
|
|
|
|
|
#if !defined(ARCADIA_BUILD)
|
|
|
|
# include "config_core.h"
|
|
|
|
#endif
|
2019-09-26 11:19:10 +00:00
|
|
|
|
2019-10-08 17:27:00 +00:00
|
|
|
#if USE_MYSQL
|
|
|
|
# include <mysqlxx/PoolFactory.h>
|
|
|
|
#endif
|
|
|
|
|
2019-09-26 11:19:10 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2021-03-19 12:47:27 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int BAD_ARGUMENTS;
|
|
|
|
}
|
|
|
|
|
2019-09-26 11:19:10 +00:00
|
|
|
/// Must not acquire Context lock in constructor to avoid possibility of deadlocks.
|
2021-06-01 12:20:52 +00:00
|
|
|
ExternalDictionariesLoader::ExternalDictionariesLoader(ContextPtr global_context_)
|
2020-05-30 21:57:37 +00:00
|
|
|
: ExternalLoader("external dictionary", &Poco::Logger::get("ExternalDictionariesLoader"))
|
2021-06-01 12:20:52 +00:00
|
|
|
, WithContext(global_context_)
|
2019-09-26 11:19:10 +00:00
|
|
|
{
|
2020-07-15 19:25:31 +00:00
|
|
|
setConfigSettings({"dictionary", "name", "database", "uuid"});
|
2019-09-26 11:19:10 +00:00
|
|
|
enableAsyncLoading(true);
|
|
|
|
enablePeriodicUpdates(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExternalLoader::LoadablePtr ExternalDictionariesLoader::create(
|
2019-12-11 11:09:21 +00:00
|
|
|
const std::string & name, const Poco::Util::AbstractConfiguration & config,
|
|
|
|
const std::string & key_in_config, const std::string & repository_name) const
|
2019-09-26 11:19:10 +00:00
|
|
|
{
|
2020-01-11 09:50:41 +00:00
|
|
|
/// For dictionaries from databases (created with DDL queries) we have to perform
|
2019-12-10 17:27:29 +00:00
|
|
|
/// additional checks, so we identify them here.
|
2021-05-24 21:27:24 +00:00
|
|
|
bool created_from_ddl = !repository_name.empty();
|
|
|
|
return DictionaryFactory::instance().create(name, config, key_in_config, getContext(), created_from_ddl);
|
2019-09-26 11:19:10 +00:00
|
|
|
}
|
2020-02-27 09:34:06 +00:00
|
|
|
|
2021-06-01 12:20:52 +00:00
|
|
|
ExternalDictionariesLoader::DictPtr ExternalDictionariesLoader::getDictionary(const std::string & dictionary_name, ContextPtr local_context) const
|
2021-03-19 12:47:27 +00:00
|
|
|
{
|
2021-04-10 23:33:54 +00:00
|
|
|
std::string resolved_dictionary_name = resolveDictionaryName(dictionary_name, local_context->getCurrentDatabase());
|
2021-08-12 15:16:55 +00:00
|
|
|
|
|
|
|
if (local_context->hasQueryContext() && local_context->getSettingsRef().log_queries)
|
|
|
|
local_context->addQueryFactoriesInfo(Context::QueryLogFactories::Dictionary, resolved_dictionary_name);
|
|
|
|
|
2021-03-24 16:31:00 +00:00
|
|
|
return std::static_pointer_cast<const IDictionary>(load(resolved_dictionary_name));
|
2021-03-19 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
2021-06-01 12:20:52 +00:00
|
|
|
ExternalDictionariesLoader::DictPtr ExternalDictionariesLoader::tryGetDictionary(const std::string & dictionary_name, ContextPtr local_context) const
|
2021-03-19 12:47:27 +00:00
|
|
|
{
|
2021-04-10 23:33:54 +00:00
|
|
|
std::string resolved_dictionary_name = resolveDictionaryName(dictionary_name, local_context->getCurrentDatabase());
|
2021-08-12 15:16:55 +00:00
|
|
|
|
|
|
|
if (local_context->hasQueryContext() && local_context->getSettingsRef().log_queries)
|
|
|
|
local_context->addQueryFactoriesInfo(Context::QueryLogFactories::Dictionary, resolved_dictionary_name);
|
|
|
|
|
2021-03-24 16:31:00 +00:00
|
|
|
return std::static_pointer_cast<const IDictionary>(tryLoad(resolved_dictionary_name));
|
2021-03-19 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-01 12:20:52 +00:00
|
|
|
void ExternalDictionariesLoader::reloadDictionary(const std::string & dictionary_name, ContextPtr local_context) const
|
2021-03-19 12:47:27 +00:00
|
|
|
{
|
2021-04-10 23:33:54 +00:00
|
|
|
std::string resolved_dictionary_name = resolveDictionaryName(dictionary_name, local_context->getCurrentDatabase());
|
2021-03-19 12:47:27 +00:00
|
|
|
loadOrReload(resolved_dictionary_name);
|
|
|
|
}
|
|
|
|
|
2021-06-01 12:20:52 +00:00
|
|
|
DictionaryStructure ExternalDictionariesLoader::getDictionaryStructure(const std::string & dictionary_name, ContextPtr query_context) const
|
2021-03-19 12:47:27 +00:00
|
|
|
{
|
2021-04-10 23:33:54 +00:00
|
|
|
std::string resolved_name = resolveDictionaryName(dictionary_name, query_context->getCurrentDatabase());
|
2021-03-19 12:47:27 +00:00
|
|
|
|
|
|
|
auto load_result = getLoadResult(resolved_name);
|
2021-06-05 20:37:24 +00:00
|
|
|
|
|
|
|
if (load_result.object)
|
|
|
|
{
|
|
|
|
const auto dictionary = std::static_pointer_cast<const IDictionary>(load_result.object);
|
|
|
|
return dictionary->getStructure();
|
|
|
|
}
|
|
|
|
|
2021-03-19 12:47:27 +00:00
|
|
|
if (!load_result.config)
|
2021-06-05 20:37:24 +00:00
|
|
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Dictionary {} config not found", backQuote(dictionary_name));
|
2021-03-19 12:47:27 +00:00
|
|
|
|
|
|
|
return ExternalDictionariesLoader::getDictionaryStructure(*load_result.config);
|
|
|
|
}
|
|
|
|
|
2021-03-20 15:02:09 +00:00
|
|
|
std::string ExternalDictionariesLoader::resolveDictionaryName(const std::string & dictionary_name, const std::string & current_database_name) const
|
2021-03-19 12:47:27 +00:00
|
|
|
{
|
2021-09-13 19:11:16 +00:00
|
|
|
if (has(dictionary_name))
|
2021-07-20 08:35:10 +00:00
|
|
|
return dictionary_name;
|
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
std::string resolved_name = resolveDictionaryNameFromDatabaseCatalog(dictionary_name, current_database_name);
|
2021-03-19 12:47:27 +00:00
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
if (has(resolved_name))
|
|
|
|
return resolved_name;
|
2021-03-19 12:47:27 +00:00
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Dictionary ({}) not found", backQuote(dictionary_name));
|
2021-03-19 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
std::string ExternalDictionariesLoader::resolveDictionaryNameFromDatabaseCatalog(const std::string & name, const std::string & current_database_name) const
|
2021-03-19 12:47:27 +00:00
|
|
|
{
|
|
|
|
/// If it's dictionary from Atomic database, then we need to convert qualified name to UUID.
|
|
|
|
/// Try to split name and get id from associated StorageDictionary.
|
|
|
|
/// If something went wrong, return name as is.
|
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
auto qualified_name = QualifiedTableName::tryParseFromString(name);
|
|
|
|
if (!qualified_name)
|
2021-03-19 12:47:27 +00:00
|
|
|
return name;
|
|
|
|
|
2021-09-13 19:11:16 +00:00
|
|
|
if (qualified_name->database.empty())
|
|
|
|
{
|
|
|
|
/// Ether database name is not specified and we should use current one
|
|
|
|
/// or it's an XML dictionary.
|
|
|
|
bool is_xml_dictionary = has(name);
|
|
|
|
if (is_xml_dictionary)
|
|
|
|
return name;
|
|
|
|
else
|
|
|
|
qualified_name->database = current_database_name;
|
|
|
|
}
|
2021-03-19 12:47:27 +00:00
|
|
|
|
2021-05-28 16:44:59 +00:00
|
|
|
auto [db, table] = DatabaseCatalog::instance().tryGetDatabaseAndTable(
|
2021-09-13 19:11:16 +00:00
|
|
|
{qualified_name->database, qualified_name->table},
|
2021-05-28 16:44:59 +00:00
|
|
|
const_pointer_cast<Context>(getContext()));
|
|
|
|
|
2021-03-19 12:47:27 +00:00
|
|
|
if (!db)
|
|
|
|
return name;
|
|
|
|
assert(table);
|
|
|
|
|
|
|
|
if (db->getUUID() == UUIDHelpers::Nil)
|
|
|
|
return name;
|
|
|
|
if (table->getName() != "Dictionary")
|
|
|
|
return name;
|
|
|
|
|
|
|
|
return toString(table->getStorageID().uuid);
|
|
|
|
}
|
2020-04-12 20:50:32 +00:00
|
|
|
|
|
|
|
DictionaryStructure
|
|
|
|
ExternalDictionariesLoader::getDictionaryStructure(const Poco::Util::AbstractConfiguration & config, const std::string & key_in_config)
|
|
|
|
{
|
2021-06-05 20:37:24 +00:00
|
|
|
return DictionaryStructure(config, key_in_config);
|
2020-04-12 20:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DictionaryStructure ExternalDictionariesLoader::getDictionaryStructure(const ObjectConfig & config)
|
|
|
|
{
|
|
|
|
return getDictionaryStructure(*config.config, config.key_in_config);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-27 09:34:06 +00:00
|
|
|
void ExternalDictionariesLoader::resetAll()
|
|
|
|
{
|
2020-04-16 12:31:57 +00:00
|
|
|
#if USE_MYSQL
|
|
|
|
mysqlxx::PoolFactory::instance().reset();
|
|
|
|
#endif
|
2020-02-27 09:34:06 +00:00
|
|
|
}
|
|
|
|
|
2019-09-26 11:19:10 +00:00
|
|
|
}
|