13#include <userver/storages/postgres/exceptions.hpp>
14#include <userver/storages/postgres/io/buffer_io.hpp>
15#include <userver/storages/postgres/io/buffer_io_base.hpp>
16#include <userver/storages/postgres/io/type_mapping.hpp>
18USERVER_NAMESPACE_BEGIN
31template <
typename... VectorArgs>
33template <
typename... VectorArgs>
43template <
typename ByteContainerRef>
44struct ByteaRefWrapper {
45 static_assert(std::is_reference<ByteContainerRef>::value,
"The container must be passed by reference");
47 using BytesType = std::decay_t<ByteContainerRef>;
49 io::
traits::kIsByteaCompatible<BytesType>,
50 "This C++ type cannot be used with PostgreSQL `bytea` data type"
53 ByteContainerRef bytes;
64template <
typename ByteContainer>
65detail::ByteaRefWrapper<
const ByteContainer&>
Bytea(
const ByteContainer& bytes) {
75template <
typename ByteContainer>
76detail::ByteaRefWrapper<ByteContainer&>
Bytea(ByteContainer& bytes) {
81template <
typename ByteContainer>
83 using BytesType = std::decay_t<ByteContainer>;
85 constexpr static bool kIsPostgresBuildInTypeWrapper =
true;
88 io::
traits::kIsByteaCompatible<BytesType>,
89 "This C++ type cannot be used with PostgreSQL `bytea` data type"
97template <
typename ByteContainer>
98requires traits::kIsByteaCompatible<std::decay_t<ByteContainer>>
99struct BufferParser<
postgres::detail::ByteaRefWrapper<ByteContainer>>
100 : detail::BufferParserBase<
postgres::detail::ByteaRefWrapper<ByteContainer>&&> {
101 using BaseType = detail::BufferParserBase<
postgres::detail::ByteaRefWrapper<ByteContainer>&&>;
102 using BaseType::BaseType;
103 using ByteaType =
postgres::detail::ByteaRefWrapper<ByteContainer>;
106 if constexpr (std::is_same<
typename ByteaType::BytesType, std::string_view>{}) {
107 this->value.bytes = std::string_view{
reinterpret_cast<
const char*>(buffer.buffer), buffer.length};
109 this->value.bytes.resize(buffer.length);
110 std::copy(buffer.buffer, buffer.buffer + buffer.length,
this->value.bytes.begin());
115template <
typename ByteContainer>
116requires traits::kIsByteaCompatible<std::decay_t<ByteContainer>>
120 using BaseType::BaseType;
122 void operator()(
const FieldBuffer& buffer) { ReadBuffer(buffer, Bytea(
this->value.bytes)); }
125template <
typename ByteContainer>
126requires traits::kIsByteaCompatible<std::decay_t<ByteContainer>>
127struct BufferFormatter<
postgres::detail::ByteaRefWrapper<ByteContainer>>
128 : detail::BufferFormatterBase<
postgres::detail::ByteaRefWrapper<ByteContainer>> {
129 using BaseType = detail::BufferFormatterBase<
postgres::detail::ByteaRefWrapper<ByteContainer>>;
130 using BaseType::BaseType;
132 template <
typename Buffer>
133 void operator()(
const UserTypes&, Buffer& buf)
const {
134 buf.reserve(buf.size() +
this->value.bytes.size());
135 buf.insert(buf.end(),
this->value.bytes.begin(),
this->value.bytes.end());
139template <
typename ByteContainer>
140requires traits::kIsByteaCompatible<std::decay_t<ByteContainer>>
144 using BaseType::BaseType;
146 template <
typename Buffer>
147 void operator()(
const UserTypes& types, Buffer& buffer)
const {
148 WriteBuffer(types, buffer, Bytea(
this->value.bytes));
152template <
typename ByteContainer>
153struct CppToSystemPg<
postgres::detail::ByteaRefWrapper<ByteContainer>> : PredefinedOid<
PredefinedOids::kBytea> {};
154template <
typename ByteContainer>