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
15namespace DB
16{
17namespace
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
29NamesAndTypesList 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
57void 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