ClickHouse
106 строк · 3.4 Кб
1#include <Functions/IFunction.h>
2#include <Functions/FunctionFactory.h>
3#include <Interpreters/Context.h>
4#include <Access/AccessControl.h>
5#include <Access/User.h>
6#include <Columns/ColumnArray.h>
7#include <Columns/ColumnConst.h>
8#include <Columns/ColumnString.h>
9#include <DataTypes/DataTypeString.h>
10#include <DataTypes/DataTypeArray.h>
11
12
13namespace DB
14{
15
16namespace
17{
18enum class Kind
19{
20currentProfiles,
21enabledProfiles,
22defaultProfiles,
23};
24
25String toString(Kind kind)
26{
27switch (kind)
28{
29case Kind::currentProfiles: return "currentProfiles";
30case Kind::enabledProfiles: return "enabledProfiles";
31case Kind::defaultProfiles: return "defaultProfiles";
32}
33}
34
35class FunctionProfiles : public IFunction
36{
37public:
38bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override
39{
40return false;
41}
42
43String getName() const override
44{
45return toString(kind);
46}
47
48explicit FunctionProfiles(const ContextPtr & context_, Kind kind_)
49: kind(kind_)
50, context(context_)
51{}
52
53size_t getNumberOfArguments() const override { return 0; }
54bool isDeterministic() const override { return false; }
55
56DataTypePtr getReturnTypeImpl(const DataTypes & /*arguments*/) const override
57{
58return std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>());
59}
60
61ColumnPtr executeImpl(const ColumnsWithTypeAndName &, const DataTypePtr &, size_t input_rows_count) const override
62{
63std::call_once(initialized_flag, [&]{ initialize(); });
64
65auto col_res = ColumnArray::create(ColumnString::create());
66ColumnString & res_strings = typeid_cast<ColumnString &>(col_res->getData());
67ColumnArray::Offsets & res_offsets = col_res->getOffsets();
68for (const String & profile_name : profile_names)
69res_strings.insertData(profile_name.data(), profile_name.length());
70res_offsets.push_back(res_strings.size());
71return ColumnConst::create(std::move(col_res), input_rows_count);
72}
73
74private:
75void initialize() const
76{
77const auto & manager = context->getAccessControl();
78
79std::vector<UUID> profile_ids;
80
81switch (kind)
82{
83case Kind::currentProfiles: profile_ids = context->getCurrentProfiles(); break;
84case Kind::enabledProfiles: profile_ids = context->getEnabledProfiles(); break;
85case Kind::defaultProfiles: profile_ids = context->getUser()->settings.toProfileIDs(); break;
86}
87
88profile_names = manager.tryReadNames(profile_ids);
89}
90
91mutable std::once_flag initialized_flag;
92
93Kind kind;
94ContextPtr context;
95mutable Strings profile_names;
96};
97}
98
99REGISTER_FUNCTION(Profiles)
100{
101factory.registerFunction("currentProfiles", [](ContextPtr context){ return std::make_shared<FunctionProfiles>(context, Kind::currentProfiles); });
102factory.registerFunction("enabledProfiles", [](ContextPtr context){ return std::make_shared<FunctionProfiles>(context, Kind::enabledProfiles); });
103factory.registerFunction("defaultProfiles", [](ContextPtr context){ return std::make_shared<FunctionProfiles>(context, Kind::defaultProfiles); });
104}
105
106}
107