aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Storages/System/StorageSystemPrivileges.cpp
blob: ee412d0e6481823b287f102b08e5a30eec9d5c37 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <Storages/System/StorageSystemPrivileges.h>
#include <Access/AccessControl.h>
#include <Access/Common/AccessFlags.h>
#include <Access/SettingsProfile.h>
#include <Columns/ColumnArray.h>
#include <Columns/ColumnString.h>
#include <Columns/ColumnsNumber.h>
#include <Columns/ColumnNullable.h>
#include <DataTypes/DataTypeString.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeEnum.h>
#include <DataTypes/DataTypeArray.h>
#include <DataTypes/DataTypeNullable.h>
#include <Interpreters/Context.h>
#include <Parsers/Access/ASTRolesOrUsersSet.h>


namespace DB
{
namespace
{
    enum Level
    {
        GROUP = -1,
        GLOBAL,
        DATABASE,
        TABLE,
        DICTIONARY,
        VIEW,
        COLUMN,
        NAMED_COLLECTION,
    };

    DataTypeEnum8::Values getLevelEnumValues()
    {
        DataTypeEnum8::Values enum_values;
        enum_values.emplace_back("GLOBAL", static_cast<Int8>(GLOBAL));
        enum_values.emplace_back("DATABASE", static_cast<Int8>(DATABASE));
        enum_values.emplace_back("TABLE", static_cast<Int8>(TABLE));
        enum_values.emplace_back("DICTIONARY", static_cast<Int8>(DICTIONARY));
        enum_values.emplace_back("VIEW", static_cast<Int8>(VIEW));
        enum_values.emplace_back("COLUMN", static_cast<Int8>(COLUMN));
        enum_values.emplace_back("NAMED_COLLECTION", static_cast<Int8>(NAMED_COLLECTION));
        return enum_values;
    }
}


const std::vector<std::pair<String, Int16>> & StorageSystemPrivileges::getAccessTypeEnumValues()
{
    static const std::vector<std::pair<String, Int16>> values = []
    {
        std::vector<std::pair<String, Int16>> res;

#define ADD_ACCESS_TYPE_ENUM_VALUE(name, aliases, node_type, parent_group_name) \
        res.emplace_back(toString(AccessType::name), static_cast<size_t>(AccessType::name));

        APPLY_FOR_ACCESS_TYPES(ADD_ACCESS_TYPE_ENUM_VALUE)
#undef ADD_ACCESS_TYPE_ENUM_VALUE

        return res;
    }();
    return values;
}


NamesAndTypesList StorageSystemPrivileges::getNamesAndTypes()
{
    NamesAndTypesList names_and_types{
        {"privilege", std::make_shared<DataTypeEnum16>(getAccessTypeEnumValues())},
        {"aliases", std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>())},
        {"level", std::make_shared<DataTypeNullable>(std::make_shared<DataTypeEnum8>(getLevelEnumValues()))},
        {"parent_group", std::make_shared<DataTypeNullable>(std::make_shared<DataTypeEnum16>(getAccessTypeEnumValues()))},
    };
    return names_and_types;
}


void StorageSystemPrivileges::fillData(MutableColumns & res_columns, ContextPtr, const SelectQueryInfo &) const
{
    size_t column_index = 0;
    auto & column_access_type = assert_cast<ColumnInt16 &>(*res_columns[column_index++]).getData();
    auto & column_aliases = assert_cast<ColumnString &>(assert_cast<ColumnArray &>(*res_columns[column_index]).getData());
    auto & column_aliases_offsets = assert_cast<ColumnArray &>(*res_columns[column_index++]).getOffsets();
    auto & column_level = assert_cast<ColumnInt8 &>(assert_cast<ColumnNullable &>(*res_columns[column_index]).getNestedColumn()).getData();
    auto & column_level_null_map = assert_cast<ColumnNullable &>(*res_columns[column_index++]).getNullMapData();
    auto & column_parent_group = assert_cast<ColumnInt16 &>(assert_cast<ColumnNullable &>(*res_columns[column_index]).getNestedColumn()).getData();
    auto & column_parent_group_null_map = assert_cast<ColumnNullable &>(*res_columns[column_index++]).getNullMapData();

    auto add_row = [&](AccessType access_type, std::string_view aliases, Level max_level, AccessType parent_group)
    {
        column_access_type.push_back(static_cast<Int16>(access_type));

        for (size_t pos = 0; pos < aliases.length();)
        {
            size_t next_pos = aliases.find_first_of(',', pos);
            std::string_view alias = aliases.substr(pos, next_pos - pos);
            pos = ((next_pos == std::string_view::npos) ? next_pos : next_pos + 1);

            while (alias.starts_with(' '))
                alias.remove_prefix(1);
            while (alias.ends_with(' '))
                alias.remove_suffix(1);
            column_aliases.insertData(alias.data(), alias.length());
        }
        column_aliases_offsets.push_back(column_aliases.size());

        if (max_level == GROUP)
        {
            column_level.push_back(0);
            column_level_null_map.push_back(true);
        }
        else
        {
            column_level.push_back(static_cast<Int8>(max_level));
            column_level_null_map.push_back(false);
        }

        if (parent_group == AccessType::NONE)
        {
            column_parent_group.push_back(0);
            column_parent_group_null_map.push_back(true);
        }
        else
        {
            column_parent_group.push_back(static_cast<Int16>(parent_group));
            column_parent_group_null_map.push_back(false);
        }
    };

#define STORAGE_SYSTEM_PRIVILEGES_ADD_ROW(name, aliases, node_type, parent_group_name) \
    add_row(AccessType::name, aliases, node_type, AccessType::parent_group_name);

    APPLY_FOR_ACCESS_TYPES(STORAGE_SYSTEM_PRIVILEGES_ADD_ROW)

#undef STORAGE_SYSTEM_PRIVILEGES_ADD_ROW
}

}