7#include <userver/storages/postgres/exceptions.hpp>
8#include <userver/storages/postgres/io/buffer_io.hpp>
9#include <userver/storages/postgres/io/buffer_io_base.hpp>
10#include <userver/storages/postgres/io/nullable_traits.hpp>
12#include <userver/utils/strong_typedef.hpp>
13#include <userver/utils/void_t.hpp>
15USERVER_NAMESPACE_BEGIN
44template <
typename Tag,
typename T, USERVER_NAMESPACE::utils::StrongTypedefOps Ops,
typename Enable>
45inline constexpr bool kIsStrongTypedefDirectlyMapped =
47 kIsMappedToUserType<USERVER_NAMESPACE::utils::StrongTypedef<Tag, T, Ops, Enable>> ||
49 kIsMappedToSystemType<USERVER_NAMESPACE::utils::StrongTypedef<Tag, T, Ops, Enable>> ||
51 kIsMappedToArray<USERVER_NAMESPACE::utils::StrongTypedef<Tag, T, Ops, Enable>>;
68 using ValueType = USERVER_NAMESPACE::
utils::StrongTypedef<Tag, T, Ops, Enable>;
70 inline static bool IsNull(
const ValueType& v) {
return UnderlyingGetSet::IsNull(v.GetUnderlying()); }
71 inline static void SetNull(ValueType& v) { UnderlyingGetSet::SetNull(v.GetUnderlying()); }
72 inline static void SetDefault(ValueType& v) { UnderlyingGetSet::SetDefault(v.GetUnderlying()); }
77template <
typename T,
typename = USERVER_NAMESPACE::
utils::
void_t<>>
83constexpr bool CheckCanUseEnumAsStrongTypedef() {
84 if constexpr (CanUseEnumAsStrongTypedef<T>{}) {
87 "storages::postgres::io::traits::CanUseEnumAsStrongTypedef "
88 "should be specialized only for enums"
91 std::is_signed_v<std::underlying_type_t<T>>,
92 "storages::postgres::io::traits::CanUseEnumAsStrongTypedef should be "
93 "specialized only for enums with signed underlying type"
109template <
typename Tag,
typename T, USERVER_NAMESPACE::utils::StrongTypedefOps Ops,
typename Enable>
110struct BufferFormatter<USERVER_NAMESPACE::utils::StrongTypedef<Tag, T, Ops, Enable>>
111 : detail::BufferFormatterBase<USERVER_NAMESPACE::utils::StrongTypedef<Tag, T, Ops, Enable>> {
112 using BaseType = detail::BufferFormatterBase<USERVER_NAMESPACE::utils::StrongTypedef<Tag, T, Ops, Enable>>;
113 using BaseType::BaseType;
115 template <
typename Buffer>
116 void operator()(
const UserTypes& types, Buffer& buf)
const {
117 io::WriteBuffer(types, buf,
this->value.GetUnderlying());
122template <
typename StrongTypedef,
bool Categories =
false>
123struct StrongTypedefParser : BufferParserBase<StrongTypedef> {
124 using BaseType = BufferParserBase<StrongTypedef>;
125 using UnderlyingType =
typename StrongTypedef::UnderlyingType;
127 using BaseType::BaseType;
130 UnderlyingType& v =
this->value.GetUnderlying();
131 io::ReadBuffer(buffer, v);
135template <
typename StrongTypedef>
136struct StrongTypedefParser<StrongTypedef,
true> : BufferParserBase<StrongTypedef> {
137 using BaseType = BufferParserBase<StrongTypedef>;
138 using UnderlyingType =
typename StrongTypedef::UnderlyingType;
140 using BaseType::BaseType;
142 void operator()(
const FieldBuffer& buffer,
const TypeBufferCategory& categories) {
143 UnderlyingType& v =
this->value.GetUnderlying();
144 io::ReadBuffer(buffer, v, categories);
150template <
typename Tag,
typename T, USERVER_NAMESPACE::utils::StrongTypedefOps Ops,
typename Enable>
151struct BufferParser<USERVER_NAMESPACE::utils::StrongTypedef<Tag, T, Ops, Enable>>
152 : detail::StrongTypedefParser<
153 USERVER_NAMESPACE::utils::StrongTypedef<Tag, T, Ops, Enable>,
154 detail::kParserRequiresTypeCategories<T>> {
155 using BaseType = detail::StrongTypedefParser<
156 USERVER_NAMESPACE::utils::StrongTypedef<Tag, T, Ops, Enable>,
157 detail::kParserRequiresTypeCategories<T>>;
158 using BaseType::BaseType;
162template <
typename Tag,
typename T, USERVER_NAMESPACE::utils::StrongTypedefOps Ops,
typename Enable>
164 USERVER_NAMESPACE::utils::StrongTypedef<Tag, T, Ops, Enable>,
165 std::enable_if_t<!traits::kIsStrongTypedefDirectlyMapped<Tag, T, Ops, Enable> && traits::kIsMappedToPg<T>>>
179struct EnumStrongTypedefFormatter : BufferFormatterBase<T> {
180 using BaseType = BufferFormatterBase<T>;
181 using BaseType::BaseType;
183 template <
typename Buffer>
184 void operator()(
const UserTypes& types, Buffer& buf)
const {
185 io::WriteBuffer(types, buf, USERVER_NAMESPACE::
utils::UnderlyingValue(
this->value));
190struct EnumStrongTypedefParser : BufferParserBase<T> {
191 using BaseType = BufferParserBase<T>;
192 using ValueType =
typename BaseType::ValueType;
193 using UnderlyingType = std::underlying_type_t<ValueType>;
195 using BaseType::BaseType;
199 io::ReadBuffer(buffer, v);
200 this->value =
static_cast<ValueType>(v);
228struct CppToPg<T, traits::EnableIfCanUseEnumAsStrongTypedef<T>> : CppToPg<std::underlying_type_t<T>> {};