Fix review notes

This commit is contained in:
Aleksei Filatov 2023-01-19 17:02:57 +03:00
parent 5e9340f682
commit afada0ecb3
4 changed files with 133 additions and 152 deletions

View File

@ -22,69 +22,34 @@ namespace DB
{
namespace
{
/// Used for column indexes! Don't change the numbers!
enum SystemDictionariesColumn
{
Database = 0,
Name,
Uuid,
Status,
Origin,
Type,
KeyNames,
KeyTypes,
AttributeNames,
AttributeTypes,
BytesAllocated,
HierarchicalIndexBytesAllocated,
QueryCount,
HitRate,
FoundRate,
ElementCount,
LoadFactor,
Source,
LifetimeMin,
LifetimeMax,
LoadingStartTime,
LastSuccessfulUpdateTime,
LoadingDuration,
LastException,
Comment,
/// Virtual columns
Key
};
std::shared_ptr<const IDictionary> getDictionaryPtr(const ExternalLoader::LoadResult & load_result)
{
return std::dynamic_pointer_cast<const IDictionary>(load_result.object);
}
StorageID getDictionaryID(const ExternalLoader::LoadResult & load_result, const std::shared_ptr<const IDictionary> & dict_ptr)
{
StorageID dict_id = StorageID::createEmpty();
StorageID getDictionaryID(const ExternalLoader::LoadResult & load_result, const std::shared_ptr<const IDictionary> & dict_ptr)
{
StorageID dict_id = StorageID::createEmpty();
if (dict_ptr)
dict_id = dict_ptr->getDictionaryID();
else if (load_result.config)
dict_id = StorageID::fromDictionaryConfig(*load_result.config->config, load_result.config->key_in_config);
else
dict_id.table_name = load_result.name;
if (dict_ptr)
dict_id = dict_ptr->getDictionaryID();
else if (load_result.config)
dict_id = StorageID::fromDictionaryConfig(*load_result.config->config, load_result.config->key_in_config);
else
dict_id.table_name = load_result.name;
return dict_id;
}
return dict_id;
}
std::optional<DictionaryStructure>
getDictionaryStructure(const ExternalLoader::LoadResult & load_result, std::exception_ptr & last_exception)
try
{
return ExternalDictionariesLoader::getDictionaryStructure(*load_result.config);
}
catch (const DB::Exception &)
{
if (!last_exception)
last_exception = std::current_exception();
return {};
}
std::optional<DictionaryStructure>
getDictionaryStructure(const ExternalLoader::LoadResult & load_result, std::exception_ptr & last_exception)
try
{
return ExternalDictionariesLoader::getDictionaryStructure(*load_result.config);
}
catch (const DB::Exception &)
{
if (!last_exception)
last_exception = std::current_exception();
return {};
}
}
NamesAndTypesList StorageSystemDictionaries::getNamesAndTypes()
@ -135,83 +100,99 @@ void StorageSystemDictionaries::fillData(MutableColumns & res_columns, ContextPt
if (!check_access_for_dictionaries)
return;
for (size_t index = 0; const auto & load_result : external_dictionaries.getLoadResults())
for (const auto & load_result : external_dictionaries.getLoadResults())
{
const auto dict_ptr = getDictionaryPtr(load_result);
StorageID dict_id = getDictionaryID(load_result, dict_ptr);
const auto dict_ptr = std::dynamic_pointer_cast<const IDictionary>(load_result.object);
auto last_exception = load_result.exception;
std::exception_ptr last_exception = load_result.exception;
auto dict_structure = getDictionaryStructure(load_result, last_exception);
StorageID dict_id = getDictionaryID(load_result, dict_ptr);
String db_or_tag = dict_id.database_name.empty() ? IDictionary::NO_DATABASE_TAG : dict_id.database_name;
if (!access->isGranted(AccessType::SHOW_DICTIONARIES, db_or_tag, dict_id.table_name))
continue;
res_columns[SystemDictionariesColumn::Database]->insert(dict_id.database_name);
res_columns[SystemDictionariesColumn::Name]->insert(dict_id.table_name);
res_columns[SystemDictionariesColumn::Uuid]->insert(dict_id.uuid);
res_columns[SystemDictionariesColumn::Status]->insert(static_cast<Int8>(load_result.status));
res_columns[SystemDictionariesColumn::Origin]->insert(load_result.config ? load_result.config->path : "");
size_t i = 0;
res_columns[i++]->insert(dict_id.database_name);
res_columns[i++]->insert(dict_id.table_name);
res_columns[i++]->insert(dict_id.uuid);
res_columns[i++]->insert(static_cast<Int8>(load_result.status));
res_columns[i++]->insert(load_result.config ? load_result.config->path : "");
if (dict_ptr)
{
res_columns[SystemDictionariesColumn::Type]->insert(dict_ptr->getTypeName());
res_columns[SystemDictionariesColumn::BytesAllocated]->insert(dict_ptr->getBytesAllocated());
res_columns[SystemDictionariesColumn::HierarchicalIndexBytesAllocated]->insert(dict_ptr->getHierarchicalIndexBytesAllocated());
res_columns[SystemDictionariesColumn::QueryCount]->insert(dict_ptr->getQueryCount());
res_columns[SystemDictionariesColumn::HitRate]->insert(dict_ptr->getHitRate());
res_columns[SystemDictionariesColumn::FoundRate]->insert(dict_ptr->getFoundRate());
res_columns[SystemDictionariesColumn::ElementCount]->insert(dict_ptr->getElementCount());
res_columns[SystemDictionariesColumn::LoadFactor]->insert(dict_ptr->getLoadFactor());
res_columns[SystemDictionariesColumn::Source]->insert(dict_ptr->getSource()->toString());
const auto & lifetime = dict_ptr->getLifetime();
res_columns[SystemDictionariesColumn::LifetimeMin]->insert(lifetime.min_sec);
res_columns[SystemDictionariesColumn::LifetimeMax]->insert(lifetime.max_sec);
res_columns[SystemDictionariesColumn::Comment]->insert(dict_ptr->getDictionaryComment());
if (!last_exception)
last_exception = dict_ptr->getLastException();
}
else if (load_result.config && load_result.config->config->has("dictionary.comment"))
{
res_columns[SystemDictionariesColumn::Comment]->insert(load_result.config->config->getString("dictionary.comment"));
}
res_columns[i++]->insert(dict_ptr->getTypeName());
else
res_columns[i++]->insertDefault();
if (dict_structure)
{
res_columns[SystemDictionariesColumn::KeyNames]->insert(
collections::map<Array>(dict_structure->getKeysNames(), [](auto & name) { return name; }));
res_columns[i++]->insert(collections::map<Array>(dict_structure->getKeysNames(), [](auto & name) { return name; }));
if (dict_structure->id)
res_columns[SystemDictionariesColumn::KeyTypes]->insert(Array({"UInt64"}));
res_columns[i++]->insert(Array({"UInt64"}));
else
res_columns[SystemDictionariesColumn::KeyTypes]->insert(
collections::map<Array>(*dict_structure->key, [](auto & attr) { return attr.type->getName(); }));
res_columns[i++]->insert(collections::map<Array>(*dict_structure->key, [](auto & attr) { return attr.type->getName(); }));
res_columns[SystemDictionariesColumn::AttributeNames]->insert(
collections::map<Array>(dict_structure->attributes, [](auto & attr) { return attr.name; }));
res_columns[SystemDictionariesColumn::AttributeTypes]->insert(
collections::map<Array>(dict_structure->attributes, [](auto & attr) { return attr.type->getName(); }));
res_columns[SystemDictionariesColumn::Key]->insert(dict_structure->getKeyDescription());
res_columns[i++]->insert(collections::map<Array>(dict_structure->attributes, [](auto & attr) { return attr.name; }));
res_columns[i++]->insert(collections::map<Array>(dict_structure->attributes, [](auto & attr) { return attr.type->getName(); }));
}
else
{
for (size_t j = 0; j != 4; ++j) // Number of empty fields if dict_structure is null
res_columns[i++]->insertDefault();
}
res_columns[SystemDictionariesColumn::LoadingStartTime]->insert(
static_cast<UInt64>(std::chrono::system_clock::to_time_t(load_result.loading_start_time)));
res_columns[SystemDictionariesColumn::LastSuccessfulUpdateTime]->insert(
static_cast<UInt64>(std::chrono::system_clock::to_time_t(load_result.last_successful_update_time)));
res_columns[SystemDictionariesColumn::LoadingDuration]->insert(
std::chrono::duration_cast<std::chrono::duration<float>>(load_result.loading_duration).count());
if (dict_ptr)
{
res_columns[i++]->insert(dict_ptr->getBytesAllocated());
res_columns[i++]->insert(dict_ptr->getHierarchicalIndexBytesAllocated());
res_columns[i++]->insert(dict_ptr->getQueryCount());
res_columns[i++]->insert(dict_ptr->getHitRate());
res_columns[i++]->insert(dict_ptr->getFoundRate());
res_columns[i++]->insert(dict_ptr->getElementCount());
res_columns[i++]->insert(dict_ptr->getLoadFactor());
res_columns[i++]->insert(dict_ptr->getSource()->toString());
const auto & lifetime = dict_ptr->getLifetime();
res_columns[i++]->insert(lifetime.min_sec);
res_columns[i++]->insert(lifetime.max_sec);
if (!last_exception)
last_exception = dict_ptr->getLastException();
}
else
{
for (size_t j = 0; j != 10; ++j) // Number of empty fields if dict_ptr is null
res_columns[i++]->insertDefault();
}
res_columns[i++]->insert(static_cast<UInt64>(std::chrono::system_clock::to_time_t(load_result.loading_start_time)));
res_columns[i++]->insert(static_cast<UInt64>(std::chrono::system_clock::to_time_t(load_result.last_successful_update_time)));
res_columns[i++]->insert(std::chrono::duration_cast<std::chrono::duration<float>>(load_result.loading_duration).count());
if (last_exception)
res_columns[SystemDictionariesColumn::LastException]->insert(getExceptionMessage(last_exception, false));
res_columns[i++]->insert(getExceptionMessage(last_exception, false));
else
res_columns[i++]->insertDefault();
index++;
/// Set to default unfilled columns
for (auto & column : res_columns)
if (column->size() < index)
column->insertDefault();
if (dict_ptr)
{
res_columns[i++]->insert(dict_ptr->getDictionaryComment());
}
else
{
if (load_result.config && load_result.config->config->has("dictionary.comment"))
res_columns[i++]->insert(load_result.config->config->getString("dictionary.comment"));
else
res_columns[i++]->insertDefault();
}
/// Start fill virtual columns
if (dict_structure)
res_columns[i++]->insert(dict_structure->getKeyDescription());
else
res_columns[i++]->insertDefault();
}
}

View File

@ -1,37 +0,0 @@
<clickhouse>
<dictionary>
<name>bad_dict</name>
<source>
<clickhouse>
<host>localhost</host>
<port>9000</port>
<user>default</user>
<password></password>
<db>test</db>
<table>source</table>
</clickhouse>
</source>
<lifetime>0</lifetime>
<layout>
<cache><size_in_cells>128</size_in_cells></cache>
</layout>
<structure>
<id>
<name>id</name>
</id>
<attribute>
<name>bad_attr</name>
<type>bad_type</type>
<null_value></null_value>
<hierarchical>false</hierarchical>
<injective>false</injective>
</attribute>
</structure>
</dictionary>
</clickhouse>

View File

@ -0,0 +1,37 @@
<clickhouse>
<dictionary>
<name>invalid_dict</name>
<source>
<clickhouse>
<host>localhost</host>
<port>9000</port>
<user>default</user>
<password></password>
<db>test</db>
<table>source</table>
</clickhouse>
</source>
<lifetime>0</lifetime>
<layout>
<cache><size_in_cells>128</size_in_cells></cache>
</layout>
<structure>
<id>
<name>id</name>
</id>
<attribute>
<name>bad_attr</name>
<type>bad_type</type>
<null_value></null_value>
<hierarchical>false</hierarchical>
<injective>false</injective>
</attribute>
</structure>
</dictionary>
</clickhouse>

View File

@ -4,7 +4,7 @@ from helpers.client import QueryRuntimeException
from helpers.cluster import ClickHouseCluster
DICTIONARY_FILES = [
"configs/dictionaries/bad_dict.xml",
"configs/dictionaries/invalid_dict.xml",
"configs/dictionaries/valid_dict.xml",
]
@ -12,7 +12,7 @@ cluster = ClickHouseCluster(__file__)
instance = cluster.add_instance("instance", dictionaries=DICTIONARY_FILES)
VALID_DICT_NAME = "valid_dict"
BAD_DICT_NAME = "bad_dict"
BAD_DICT_NAME = "invalid_dict"
UNKNOWN_DATA_TYPE_EXCEPTION_STR = "DB::Exception: Unknown data type"