2021-03-09 14:10:28 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <unordered_map>
|
2021-05-06 13:07:36 +00:00
|
|
|
#include <Common/HashTable/HashMap.h>
|
|
|
|
#include <Common/NamePrompter.h>
|
2021-03-09 14:10:28 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2023-12-19 16:43:30 +00:00
|
|
|
namespace ErrorCodesEnumValues
|
2021-03-09 14:10:28 +00:00
|
|
|
{
|
|
|
|
extern const int BAD_ARGUMENTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2023-09-10 03:48:12 +00:00
|
|
|
class EnumValues : public IHints<>
|
2021-03-09 14:10:28 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
using Value = std::pair<std::string, T>;
|
|
|
|
using Values = std::vector<Value>;
|
|
|
|
using NameToValueMap = HashMap<StringRef, T, StringRefHash>;
|
|
|
|
using ValueToNameMap = std::unordered_map<T, StringRef>;
|
|
|
|
|
|
|
|
private:
|
|
|
|
Values values;
|
|
|
|
NameToValueMap name_to_value_map;
|
|
|
|
ValueToNameMap value_to_name_map;
|
|
|
|
|
|
|
|
void fillMaps();
|
|
|
|
|
|
|
|
public:
|
2022-02-20 11:45:13 +00:00
|
|
|
explicit EnumValues(const Values & values_);
|
2021-03-09 14:10:28 +00:00
|
|
|
|
|
|
|
const Values & getValues() const { return values; }
|
|
|
|
|
|
|
|
auto findByValue(const T & value) const
|
|
|
|
{
|
|
|
|
const auto it = value_to_name_map.find(value);
|
|
|
|
if (it == std::end(value_to_name_map))
|
2023-01-23 21:13:58 +00:00
|
|
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unexpected value {} in enum", toString(value));
|
2021-03-09 14:10:28 +00:00
|
|
|
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
|
2023-12-19 16:43:30 +00:00
|
|
|
bool hasValue(const T & value) const
|
|
|
|
{
|
|
|
|
return value_to_name_map.contains(value);
|
|
|
|
}
|
|
|
|
|
2021-07-12 09:55:34 +00:00
|
|
|
/// throws exception if value is not valid
|
2021-03-09 14:10:28 +00:00
|
|
|
const StringRef & getNameForValue(const T & value) const
|
|
|
|
{
|
|
|
|
return findByValue(value)->second;
|
|
|
|
}
|
|
|
|
|
2021-07-12 09:55:34 +00:00
|
|
|
/// returns false if value is not valid
|
|
|
|
bool getNameForValue(const T & value, StringRef & result) const
|
2021-07-09 12:17:11 +00:00
|
|
|
{
|
|
|
|
const auto it = value_to_name_map.find(value);
|
|
|
|
if (it == std::end(value_to_name_map))
|
2021-07-12 09:55:34 +00:00
|
|
|
return false;
|
2021-07-09 12:17:11 +00:00
|
|
|
|
2021-07-12 09:55:34 +00:00
|
|
|
result = it->second;
|
|
|
|
return true;
|
2021-07-09 12:17:11 +00:00
|
|
|
}
|
|
|
|
|
2021-03-09 14:10:28 +00:00
|
|
|
T getValue(StringRef field_name, bool try_treat_as_id = false) const;
|
2023-12-19 16:43:30 +00:00
|
|
|
bool tryGetValue(T & x, StringRef field_name, bool try_treat_as_id = false) const;
|
2021-03-09 14:10:28 +00:00
|
|
|
|
|
|
|
template <typename TValues>
|
|
|
|
bool containsAll(const TValues & rhs_values) const
|
|
|
|
{
|
|
|
|
auto check = [&](const auto & value)
|
|
|
|
{
|
|
|
|
auto it = name_to_value_map.find(value.first);
|
|
|
|
/// If we don't have this name, than we have to be sure,
|
|
|
|
/// that this value exists in enum
|
|
|
|
if (it == name_to_value_map.end())
|
|
|
|
return value_to_name_map.count(value.second) > 0;
|
|
|
|
|
|
|
|
/// If we have this name, than it should have the same value
|
|
|
|
return it->value.second == value.second;
|
|
|
|
};
|
|
|
|
|
|
|
|
return std::all_of(rhs_values.begin(), rhs_values.end(), check);
|
|
|
|
}
|
2021-05-06 13:07:36 +00:00
|
|
|
|
|
|
|
Names getAllRegisteredNames() const override;
|
2021-09-28 12:59:22 +00:00
|
|
|
|
|
|
|
std::unordered_set<String> getSetOfAllNames(bool to_lower) const;
|
|
|
|
|
|
|
|
std::unordered_set<T> getSetOfAllValues() const;
|
2021-03-09 14:10:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|