mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +00:00
Merge pull request #21859 from kitaisreal/ddl-dictionary-current-database-name
DDL dictionary use current database name
This commit is contained in:
commit
f340e71913
@ -80,12 +80,29 @@ public:
|
||||
std::shared_ptr<const IDictionaryBase> getDictionary(const String & dictionary_name)
|
||||
{
|
||||
String resolved_name = DatabaseCatalog::instance().resolveDictionaryName(dictionary_name);
|
||||
|
||||
bool can_load_dictionary = external_loader.hasDictionary(resolved_name);
|
||||
|
||||
if (!can_load_dictionary)
|
||||
{
|
||||
/// If dictionary not found. And database was not implicitly specified
|
||||
/// we can qualify dictionary name with current database name.
|
||||
/// It will help if dictionary is created with DDL and is in current database.
|
||||
if (dictionary_name.find('.') == std::string::npos)
|
||||
{
|
||||
String dictionary_name_with_database = context.getCurrentDatabase() + '.' + dictionary_name;
|
||||
resolved_name = DatabaseCatalog::instance().resolveDictionaryName(dictionary_name_with_database);
|
||||
}
|
||||
}
|
||||
|
||||
auto dict = external_loader.getDictionary(resolved_name);
|
||||
|
||||
if (!access_checked)
|
||||
{
|
||||
context.checkAccess(AccessType::dictGet, dict->getDatabaseOrNoDatabaseTag(), dict->getDictionaryID().getTableName());
|
||||
access_checked = true;
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
@ -118,14 +135,29 @@ public:
|
||||
DictionaryStructure getDictionaryStructure(const String & dictionary_name) const
|
||||
{
|
||||
String resolved_name = DatabaseCatalog::instance().resolveDictionaryName(dictionary_name);
|
||||
|
||||
auto load_result = external_loader.getLoadResult(resolved_name);
|
||||
if (!load_result.config)
|
||||
{
|
||||
/// If dictionary not found. And database was not implicitly specified
|
||||
/// we can qualify dictionary name with current database name.
|
||||
/// It will help if dictionary is created with DDL and is in current database.
|
||||
if (dictionary_name.find('.') == std::string::npos)
|
||||
{
|
||||
String dictionary_name_with_database = context.getCurrentDatabase() + '.' + dictionary_name;
|
||||
resolved_name = DatabaseCatalog::instance().resolveDictionaryName(dictionary_name_with_database);
|
||||
load_result = external_loader.getLoadResult(resolved_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!load_result.config)
|
||||
throw Exception("Dictionary " + backQuote(dictionary_name) + " not found", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
return ExternalDictionariesLoader::getDictionaryStructure(*load_result.config);
|
||||
}
|
||||
|
||||
private:
|
||||
const Context & context;
|
||||
private:
|
||||
const ExternalDictionariesLoader & external_loader;
|
||||
/// Access cannot be not granted, since in this case checkAccess() will throw and access_checked will not be updated.
|
||||
std::atomic<bool> access_checked = false;
|
||||
@ -296,10 +328,12 @@ public:
|
||||
|
||||
DataTypes types;
|
||||
|
||||
auto dictionary_structure = helper.getDictionaryStructure(dictionary_name);
|
||||
|
||||
for (auto & attribute_name : attribute_names)
|
||||
{
|
||||
/// We're extracting the return type from the dictionary's config, without loading the dictionary.
|
||||
auto attribute = helper.getDictionaryStructure(dictionary_name).getAttribute(attribute_name);
|
||||
auto attribute = dictionary_structure.getAttribute(attribute_name);
|
||||
types.emplace_back(attribute.type);
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ public:
|
||||
using DictPtr = std::shared_ptr<const IDictionaryBase>;
|
||||
|
||||
/// Dictionaries will be loaded immediately and then will be updated in separate thread, each 'reload_period' seconds.
|
||||
ExternalDictionariesLoader(Context & context_);
|
||||
explicit ExternalDictionariesLoader(Context & context_);
|
||||
|
||||
DictPtr getDictionary(const std::string & name) const
|
||||
{
|
||||
@ -28,6 +28,11 @@ public:
|
||||
return std::static_pointer_cast<const IDictionaryBase>(tryLoad(name));
|
||||
}
|
||||
|
||||
bool hasDictionary(const std::string & name) const
|
||||
{
|
||||
return has(name);
|
||||
}
|
||||
|
||||
static DictionaryStructure getDictionaryStructure(const Poco::Util::AbstractConfiguration & config, const std::string & key_in_config = "dictionary");
|
||||
static DictionaryStructure getDictionaryStructure(const ObjectConfig & config);
|
||||
|
||||
|
@ -625,6 +625,12 @@ public:
|
||||
return collectLoadResults<ReturnType>(filter);
|
||||
}
|
||||
|
||||
bool has(const String & name) const
|
||||
{
|
||||
std::lock_guard lock{mutex};
|
||||
return infos.contains(name);
|
||||
}
|
||||
|
||||
/// Starts reloading all the object which update time is earlier than now.
|
||||
/// The function doesn't touch the objects which were never tried to load.
|
||||
void reloadOutdated()
|
||||
@ -1391,6 +1397,11 @@ ReturnType ExternalLoader::reloadAllTriedToLoad() const
|
||||
return loadOrReload<ReturnType>([&names](const String & name) { return names.count(name); });
|
||||
}
|
||||
|
||||
bool ExternalLoader::has(const String & name) const
|
||||
{
|
||||
return loading_dispatcher->has(name);
|
||||
}
|
||||
|
||||
Strings ExternalLoader::getAllTriedToLoadNames() const
|
||||
{
|
||||
return loading_dispatcher->getAllTriedToLoadNames();
|
||||
|
@ -196,6 +196,9 @@ public:
|
||||
template <typename ReturnType = Loadables, typename = std::enable_if_t<is_vector_load_result_type<ReturnType>, void>>
|
||||
ReturnType reloadAllTriedToLoad() const;
|
||||
|
||||
/// Check if object with name exists in configuration
|
||||
bool has(const String & name) const;
|
||||
|
||||
/// Reloads all config repositories.
|
||||
void reloadConfig() const;
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
dictGet
|
||||
0
|
||||
1
|
||||
0
|
||||
dictHas
|
||||
1
|
||||
1
|
||||
0
|
@ -0,0 +1,29 @@
|
||||
DROP TABLE IF EXISTS ddl_dictonary_test_source;
|
||||
CREATE TABLE ddl_dictonary_test_source
|
||||
(
|
||||
id UInt64,
|
||||
value UInt64
|
||||
)
|
||||
ENGINE = TinyLog;
|
||||
|
||||
INSERT INTO ddl_dictonary_test_source VALUES (0, 0);
|
||||
INSERT INTO ddl_dictonary_test_source VALUES (1, 1);
|
||||
|
||||
DROP DICTIONARY IF EXISTS ddl_dictionary_test;
|
||||
CREATE DICTIONARY ddl_dictionary_test
|
||||
(
|
||||
id UInt64,
|
||||
value UInt64 DEFAULT 0
|
||||
)
|
||||
PRIMARY KEY id
|
||||
SOURCE(CLICKHOUSE(HOST 'localhost' PORT tcpPort() USER 'default' TABLE 'ddl_dictonary_test_source'))
|
||||
LAYOUT(DIRECT());
|
||||
|
||||
SELECT 'dictGet';
|
||||
SELECT dictGet('ddl_dictionary_test', 'value', number) FROM system.numbers LIMIT 3;
|
||||
|
||||
SELECT 'dictHas';
|
||||
SELECT dictHas('ddl_dictionary_test', number) FROM system.numbers LIMIT 3;
|
||||
|
||||
DROP TABLE ddl_dictonary_test_source;
|
||||
DROP DICTIONARY ddl_dictionary_test;
|
Loading…
Reference in New Issue
Block a user