1 | #include <Storages/System/StorageSystemQuotas.h> |
2 | #include <DataTypes/DataTypeString.h> |
3 | #include <DataTypes/DataTypeEnum.h> |
4 | #include <DataTypes/DataTypesNumber.h> |
5 | #include <DataTypes/DataTypeUUID.h> |
6 | #include <DataTypes/DataTypeDateTime.h> |
7 | #include <DataTypes/DataTypeArray.h> |
8 | #include <Columns/ColumnArray.h> |
9 | #include <Interpreters/Context.h> |
10 | #include <Access/AccessControlManager.h> |
11 | #include <Access/Quota.h> |
12 | #include <ext/range.h> |
13 | |
14 | |
15 | namespace DB |
16 | { |
17 | namespace |
18 | { |
19 | DataTypeEnum8::Values getKeyTypeEnumValues() |
20 | { |
21 | DataTypeEnum8::Values enum_values; |
22 | for (auto key_type : ext::range_with_static_cast<Quota::KeyType>(Quota::MAX_KEY_TYPE)) |
23 | enum_values.push_back({Quota::getNameOfKeyType(key_type), static_cast<UInt8>(key_type)}); |
24 | return enum_values; |
25 | } |
26 | } |
27 | |
28 | |
29 | NamesAndTypesList StorageSystemQuotas::getNamesAndTypes() |
30 | { |
31 | NamesAndTypesList names_and_types{ |
32 | {"name" , std::make_shared<DataTypeString>()}, |
33 | {"id" , std::make_shared<DataTypeUUID>()}, |
34 | {"source" , std::make_shared<DataTypeString>()}, |
35 | {"key_type" , std::make_shared<DataTypeEnum8>(getKeyTypeEnumValues())}, |
36 | {"roles" , std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())}, |
37 | {"all_roles" , std::make_shared<DataTypeUInt8>()}, |
38 | {"except_roles" , std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())}, |
39 | {"intervals.duration" , std::make_shared<DataTypeArray>(std::make_shared<DataTypeUInt64>())}, |
40 | {"intervals.randomize_interval" , std::make_shared<DataTypeArray>(std::make_shared<DataTypeUInt8>())}}; |
41 | |
42 | for (auto resource_type : ext::range_with_static_cast<Quota::ResourceType>(Quota::MAX_RESOURCE_TYPE)) |
43 | { |
44 | DataTypePtr data_type; |
45 | if (resource_type == Quota::EXECUTION_TIME) |
46 | data_type = std::make_shared<DataTypeFloat64>(); |
47 | else |
48 | data_type = std::make_shared<DataTypeUInt64>(); |
49 | |
50 | String column_name = String("intervals.max_" ) + Quota::resourceTypeToColumnName(resource_type); |
51 | names_and_types.push_back({column_name, std::make_shared<DataTypeArray>(data_type)}); |
52 | } |
53 | return names_and_types; |
54 | } |
55 | |
56 | |
57 | void StorageSystemQuotas::fillData(MutableColumns & res_columns, const Context & context, const SelectQueryInfo &) const |
58 | { |
59 | size_t i = 0; |
60 | auto & name_column = *res_columns[i++]; |
61 | auto & id_column = *res_columns[i++]; |
62 | auto & storage_name_column = *res_columns[i++]; |
63 | auto & key_type_column = *res_columns[i++]; |
64 | auto & roles_data = assert_cast<ColumnArray &>(*res_columns[i]).getData(); |
65 | auto & roles_offsets = assert_cast<ColumnArray &>(*res_columns[i++]).getOffsets(); |
66 | auto & all_roles_column = *res_columns[i++]; |
67 | auto & except_roles_data = assert_cast<ColumnArray &>(*res_columns[i]).getData(); |
68 | auto & except_roles_offsets = assert_cast<ColumnArray &>(*res_columns[i++]).getOffsets(); |
69 | auto & durations_data = assert_cast<ColumnArray &>(*res_columns[i]).getData(); |
70 | auto & durations_offsets = assert_cast<ColumnArray &>(*res_columns[i++]).getOffsets(); |
71 | auto & randomize_intervals_data = assert_cast<ColumnArray &>(*res_columns[i]).getData(); |
72 | auto & randomize_intervals_offsets = assert_cast<ColumnArray &>(*res_columns[i++]).getOffsets(); |
73 | IColumn * limits_data[Quota::MAX_RESOURCE_TYPE]; |
74 | ColumnArray::Offsets * limits_offsets[Quota::MAX_RESOURCE_TYPE]; |
75 | for (auto resource_type : ext::range(Quota::MAX_RESOURCE_TYPE)) |
76 | { |
77 | limits_data[resource_type] = &assert_cast<ColumnArray &>(*res_columns[i]).getData(); |
78 | limits_offsets[resource_type] = &assert_cast<ColumnArray &>(*res_columns[i++]).getOffsets(); |
79 | } |
80 | |
81 | const auto & access_control = context.getAccessControlManager(); |
82 | for (const auto & id : access_control.findAll<Quota>()) |
83 | { |
84 | auto quota = access_control.tryRead<Quota>(id); |
85 | if (!quota) |
86 | continue; |
87 | const auto * storage = access_control.findStorage(id); |
88 | String storage_name = storage ? storage->getStorageName() : "" ; |
89 | |
90 | name_column.insert(quota->getName()); |
91 | id_column.insert(id); |
92 | storage_name_column.insert(storage_name); |
93 | key_type_column.insert(static_cast<UInt8>(quota->key_type)); |
94 | |
95 | for (const auto & role : quota->roles) |
96 | roles_data.insert(role); |
97 | roles_offsets.push_back(roles_data.size()); |
98 | |
99 | all_roles_column.insert(static_cast<UInt8>(quota->all_roles)); |
100 | |
101 | for (const auto & except_role : quota->except_roles) |
102 | except_roles_data.insert(except_role); |
103 | except_roles_offsets.push_back(except_roles_data.size()); |
104 | |
105 | for (const auto & limits : quota->all_limits) |
106 | { |
107 | durations_data.insert(std::chrono::seconds{limits.duration}.count()); |
108 | randomize_intervals_data.insert(static_cast<UInt8>(limits.randomize_interval)); |
109 | for (auto resource_type : ext::range(Quota::MAX_RESOURCE_TYPE)) |
110 | { |
111 | if (resource_type == Quota::EXECUTION_TIME) |
112 | limits_data[resource_type]->insert(Quota::executionTimeToSeconds(limits.max[resource_type])); |
113 | else |
114 | limits_data[resource_type]->insert(limits.max[resource_type]); |
115 | } |
116 | } |
117 | |
118 | durations_offsets.push_back(durations_data.size()); |
119 | randomize_intervals_offsets.push_back(randomize_intervals_data.size()); |
120 | for (auto resource_type : ext::range(Quota::MAX_RESOURCE_TYPE)) |
121 | limits_offsets[resource_type]->push_back(limits_data[resource_type]->size()); |
122 | } |
123 | } |
124 | } |
125 | |