| 1 | #include <DataTypes/DataTypeArray.h> |
| 2 | #include <DataTypes/DataTypeDateTime.h> |
| 3 | #include <DataTypes/DataTypesNumber.h> |
| 4 | #include <DataTypes/DataTypeString.h> |
| 5 | #include <DataTypes/DataTypeEnum.h> |
| 6 | #include <Dictionaries/IDictionary.h> |
| 7 | #include <Dictionaries/IDictionarySource.h> |
| 8 | #include <Dictionaries/DictionaryStructure.h> |
| 9 | #include <Interpreters/Context.h> |
| 10 | #include <Interpreters/ExternalDictionariesLoader.h> |
| 11 | #include <Storages/System/StorageSystemDictionaries.h> |
| 12 | #include <Storages/VirtualColumnUtils.h> |
| 13 | #include <Columns/ColumnString.h> |
| 14 | #include <Core/Names.h> |
| 15 | |
| 16 | #include <ext/map.h> |
| 17 | #include <mutex> |
| 18 | |
| 19 | namespace DB |
| 20 | { |
| 21 | |
| 22 | NamesAndTypesList StorageSystemDictionaries::getNamesAndTypes() |
| 23 | { |
| 24 | return { |
| 25 | {"database" , std::make_shared<DataTypeString>()}, |
| 26 | {"name" , std::make_shared<DataTypeString>()}, |
| 27 | {"status" , std::make_shared<DataTypeEnum8>(ExternalLoader::getStatusEnumAllPossibleValues())}, |
| 28 | {"origin" , std::make_shared<DataTypeString>()}, |
| 29 | {"type" , std::make_shared<DataTypeString>()}, |
| 30 | {"key" , std::make_shared<DataTypeString>()}, |
| 31 | {"attribute.names" , std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())}, |
| 32 | {"attribute.types" , std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())}, |
| 33 | {"bytes_allocated" , std::make_shared<DataTypeUInt64>()}, |
| 34 | {"query_count" , std::make_shared<DataTypeUInt64>()}, |
| 35 | {"hit_rate" , std::make_shared<DataTypeFloat64>()}, |
| 36 | {"element_count" , std::make_shared<DataTypeUInt64>()}, |
| 37 | {"load_factor" , std::make_shared<DataTypeFloat64>()}, |
| 38 | {"source" , std::make_shared<DataTypeString>()}, |
| 39 | {"lifetime_min" , std::make_shared<DataTypeUInt64>()}, |
| 40 | {"lifetime_max" , std::make_shared<DataTypeUInt64>()}, |
| 41 | {"loading_start_time" , std::make_shared<DataTypeDateTime>()}, |
| 42 | {"loading_duration" , std::make_shared<DataTypeFloat32>()}, |
| 43 | //{ "creation_time", std::make_shared<DataTypeDateTime>() }, |
| 44 | {"last_exception" , std::make_shared<DataTypeString>()} |
| 45 | }; |
| 46 | } |
| 47 | |
| 48 | void StorageSystemDictionaries::fillData(MutableColumns & res_columns, const Context & context, const SelectQueryInfo & /*query_info*/) const |
| 49 | { |
| 50 | const auto & external_dictionaries = context.getExternalDictionariesLoader(); |
| 51 | for (const auto & load_result : external_dictionaries.getCurrentLoadResults()) |
| 52 | { |
| 53 | const auto dict_ptr = std::dynamic_pointer_cast<const IDictionaryBase>(load_result.object); |
| 54 | |
| 55 | String database, short_name; |
| 56 | if (dict_ptr) |
| 57 | { |
| 58 | database = dict_ptr->getDatabase(); |
| 59 | short_name = dict_ptr->getName(); |
| 60 | } |
| 61 | else |
| 62 | { |
| 63 | short_name = load_result.name; |
| 64 | if (!load_result.repository_name.empty() && startsWith(short_name, load_result.repository_name + "." )) |
| 65 | { |
| 66 | database = load_result.repository_name; |
| 67 | short_name = short_name.substr(database.length() + 1); |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | size_t i = 0; |
| 72 | res_columns[i++]->insert(database); |
| 73 | res_columns[i++]->insert(short_name); |
| 74 | res_columns[i++]->insert(static_cast<Int8>(load_result.status)); |
| 75 | res_columns[i++]->insert(load_result.origin); |
| 76 | |
| 77 | std::exception_ptr last_exception = load_result.exception; |
| 78 | |
| 79 | if (dict_ptr) |
| 80 | { |
| 81 | res_columns[i++]->insert(dict_ptr->getTypeName()); |
| 82 | |
| 83 | const auto & dict_struct = dict_ptr->getStructure(); |
| 84 | res_columns[i++]->insert(dict_struct.getKeyDescription()); |
| 85 | res_columns[i++]->insert(ext::map<Array>(dict_struct.attributes, [] (auto & attr) { return attr.name; })); |
| 86 | res_columns[i++]->insert(ext::map<Array>(dict_struct.attributes, [] (auto & attr) { return attr.type->getName(); })); |
| 87 | res_columns[i++]->insert(dict_ptr->getBytesAllocated()); |
| 88 | res_columns[i++]->insert(dict_ptr->getQueryCount()); |
| 89 | res_columns[i++]->insert(dict_ptr->getHitRate()); |
| 90 | res_columns[i++]->insert(dict_ptr->getElementCount()); |
| 91 | res_columns[i++]->insert(dict_ptr->getLoadFactor()); |
| 92 | res_columns[i++]->insert(dict_ptr->getSource()->toString()); |
| 93 | |
| 94 | const auto & lifetime = dict_ptr->getLifetime(); |
| 95 | res_columns[i++]->insert(lifetime.min_sec); |
| 96 | res_columns[i++]->insert(lifetime.max_sec); |
| 97 | if (!last_exception) |
| 98 | last_exception = dict_ptr->getLastException(); |
| 99 | } |
| 100 | else |
| 101 | { |
| 102 | for (size_t j = 0; j != 12; ++j) // Number of empty fields if dict_ptr is null |
| 103 | res_columns[i++]->insertDefault(); |
| 104 | } |
| 105 | |
| 106 | res_columns[i++]->insert(static_cast<UInt64>(std::chrono::system_clock::to_time_t(load_result.loading_start_time))); |
| 107 | res_columns[i++]->insert(std::chrono::duration_cast<std::chrono::duration<float>>(load_result.loading_duration).count()); |
| 108 | |
| 109 | if (last_exception) |
| 110 | res_columns[i++]->insert(getExceptionMessage(last_exception, false)); |
| 111 | else |
| 112 | res_columns[i++]->insertDefault(); |
| 113 | |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | } |
| 118 | |
| 119 | |