aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Access/resolveSetting.h
blob: bed7608b11859f9c16585270de563101402485b3 (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
#pragma once

#include <Core/Settings.h>
#include <Storages/MergeTree/MergeTreeSettings.h>

//
// Settings from different classes (Settings, MergeTreeSettings) can coexist in the same "namespace".
// This is, for example, required to define settings constraints inside user profiles.
// `resolveSetting(full_name)` is used to resolve setting name and choose which class is to be used.
// Templated lambda syntax should be used:
//
// return resolveSetting(name, [] <typename T> (std::string_view name, SettingsType<T>)
// {
//     return T::castValueUtil(name, value); // T will be deduced into `Settings`, `MergeTreeSettings`, ...
// });
//

namespace DB
{

constexpr std::string_view MERGE_TREE_SETTINGS_PREFIX = "merge_tree_";

template <typename T> struct SettingsType {};

// Resolve setting name and call function `f` back with short name and class
template <typename F>
auto resolveSetting(std::string_view full_name, F && f)
{
    if (full_name.starts_with(MERGE_TREE_SETTINGS_PREFIX))
    {
        std::string_view short_name = static_cast<std::string_view>(full_name).substr(MERGE_TREE_SETTINGS_PREFIX.size());
        if (MergeTreeSettings::hasBuiltin(short_name)) // Check is required because `Settings` also contain names starting with 'merge_tree_' prefix
            return f(short_name, SettingsType<MergeTreeSettings>());
    }
    // NOTE: other setting name resolution rules are to be added here

    // If no rule works - use global namespace
    return f(full_name, SettingsType<Settings>());
}

inline Field settingCastValueUtil(std::string_view full_name, const Field & value)
{
    return resolveSetting(full_name, [&] <typename T> (std::string_view short_name, SettingsType<T>)
    {
        return T::castValueUtil(short_name, value);
    });
}

inline String settingValueToStringUtil(std::string_view full_name, const Field & value)
{
    return resolveSetting(full_name, [&] <typename T> (std::string_view short_name, SettingsType<T>)
    {
        return T::valueToStringUtil(short_name, value);
    });
}

inline Field settingStringToValueUtil(std::string_view full_name, const String & str)
{
    return resolveSetting(full_name, [&] <typename T> (std::string_view short_name, SettingsType<T>)
    {
        return T::stringToValueUtil(short_name, str);
    });
}

inline bool settingIsBuiltin(std::string_view full_name)
{
    return resolveSetting(full_name, [&] <typename T> (std::string_view short_name, SettingsType<T>)
    {
        return T::hasBuiltin(short_name);
    });
}

template <typename T>
inline String settingFullName(std::string_view short_name);

template <>
inline String settingFullName<Settings>(std::string_view short_name)
{
    return String(short_name);
}

template <>
inline String settingFullName<MergeTreeSettings>(std::string_view short_name)
{
    String full_name(MERGE_TREE_SETTINGS_PREFIX);
    full_name += short_name; // Just because you cannot concatenate `std::string_view` and `std::string` using operator+ in C++20 yet
    return full_name;
}

inline std::string resolveSettingName(std::string_view full_name)
{
    return resolveSetting(full_name, [&] <typename T> (std::string_view short_name, SettingsType<T>)
    {
        return settingFullName<T>(T::Traits::resolveName(short_name));
    });
}

}