userver: uPg: Mapping a C++ enum to PostgreSQL enum type.
Loading...
Searching...
No Matches
uPg: Mapping a C++ enum to PostgreSQL enum type.

A C++ enumeration can be mapped to a PostgreSQL enum type by providing a list of PostgreSQL literals mapped to the enumeration values.

For example, if we have a C++ enumeration declared as follows:

enum class Rainbow { kRed, kOrange, kYellow, kGreen, kCyan };
enum class AnotherRainbow { kRed, kOrange, kYellow, kGreen, kCyan };

and a PostgreSQL enum type:

create type __pgtest.rainbow as enum (
'red', 'orange', 'yellow', 'green', 'cyan'
)

all we need to do to declare the mapping between the C++ type and PosgtreSQL enumeration is provide a specialization of CppToUserPg template. The difference from mapping a C++ type to other user PosgreSQL types, for an enumeration we need to provide a list of enumerators with corresponding literals.

Warning
The type mapping specialization must be accessible at the points where parsing/formatting of the C++ type is instantiated. The header where the C++ type is declared is an appropriate place to do it.
// This specialization MUST go to the header together with the mapped type
template <>
struct CppToUserPg<Rainbow> : EnumMappingBase<Rainbow> {
static constexpr DBTypeName postgres_name = "__pgtest.rainbow";
static constexpr Enumerator enumerators[] {
{EnumType::kRed, "red"},
{EnumType::kOrange, "orange"},
{EnumType::kYellow, "yellow"},
{EnumType::kGreen, "green"},
{EnumType::kCyan, "cyan"}};
};
} // namespace storages::postgres::io

The specialization of CppToUserPg derives from EnumMappingBase for it to provide type aliases for EnumeratorList and EnumType. EnumType is an alias to the enumeration type for convenience of declaring pairs, as the enumeration can have a long qualified name.

There is an alternative way to specialize the CppToUserPg template using TrivialBiMap. This way is much more efficient, so it is preferable to use it. It also becomes possible to reuse an existing TrivialBiMap.

// This specialization MUST go to the header together with the mapped type
template <>
struct CppToUserPg<AnotherRainbow> : EnumMappingBase<AnotherRainbow> {
static constexpr DBTypeName postgres_name = "__pgtest.rainbow";
static constexpr USERVER_NAMESPACE::utils::TrivialBiMap enumerators =
[](auto selector) {
return selector()
.Case("red", AnotherRainbow::kRed)
.Case("orange", AnotherRainbow::kOrange)
.Case("yellow", AnotherRainbow::kYellow)
.Case("green", AnotherRainbow::kGreen)
.Case("cyan", AnotherRainbow::kCyan);
};
};
} // namespace storages::postgres::io