11#include <userver/storages/postgres/exceptions.hpp>
12#include <userver/storages/postgres/io/buffer_io.hpp>
13#include <userver/storages/postgres/io/buffer_io_base.hpp>
14#include <userver/storages/postgres/io/type_mapping.hpp>
16USERVER_NAMESPACE_BEGIN
29template <
typename... VectorArgs>
31template <
typename... VectorArgs>
35inline constexpr bool kIsByteaCompatible = IsByteaCompatible<T>::value;
44template <
typename ByteContainerRef>
45struct ByteaRefWrapper {
46 static_assert(std::is_reference<ByteContainerRef>::value,
"The container must be passed by reference");
48 using BytesType = std::decay_t<ByteContainerRef>;
50 io::traits::kIsByteaCompatible<BytesType>,
51 "This C++ type cannot be used with PostgreSQL `bytea` data type"
54 ByteContainerRef bytes;
68template <
typename ByteContainer>
69detail::ByteaRefWrapper<
const ByteContainer&>
Bytea(
const ByteContainer& bytes) {
82template <
typename ByteContainer>
83detail::ByteaRefWrapper<ByteContainer&>
Bytea(ByteContainer& bytes) {
88template <
typename ByteContainer>
92 constexpr static bool kIsPostgresBuildInTypeWrapper =
true;
96 "This C++ type cannot be used with PostgreSQL `bytea` data type"
104template <
typename ByteContainer>
106 postgres::detail::ByteaRefWrapper<ByteContainer>,
107 traits::EnableIfByteaCompatible<std::decay_t<ByteContainer>>>
108 : detail::BufferParserBase<postgres::detail::ByteaRefWrapper<ByteContainer>&&> {
109 using BaseType = detail::BufferParserBase<postgres::detail::ByteaRefWrapper<ByteContainer>&&>;
110 using BaseType::BaseType;
111 using ByteaType = postgres::detail::ByteaRefWrapper<ByteContainer>;
113 void operator()(
const FieldBuffer& buffer) {
114 if constexpr (std::is_same<
typename ByteaType::BytesType, std::string_view>{}) {
115 this->value.bytes = std::string_view{
reinterpret_cast<
const char*>(buffer.buffer), buffer.length};
117 this->value.bytes.resize(buffer.length);
118 std::copy(buffer.buffer, buffer.buffer + buffer.length,
this->value.bytes.begin());
123template <
typename ByteContainer>
124struct BufferParser<postgres::ByteaWrapper<ByteContainer>, traits::EnableIfByteaCompatible<std::decay_t<ByteContainer>>>
125 : detail::BufferParserBase<postgres::ByteaWrapper<ByteContainer>> {
126 using BaseType = detail::BufferParserBase<postgres::ByteaWrapper<ByteContainer>>;
127 using BaseType::BaseType;
129 void operator()(
const FieldBuffer& buffer) { ReadBuffer(buffer, Bytea(
this->value.bytes)); }
132template <
typename ByteContainer>
133struct BufferFormatter<
134 postgres::detail::ByteaRefWrapper<ByteContainer>,
135 traits::EnableIfByteaCompatible<std::decay_t<ByteContainer>>>
136 : detail::BufferFormatterBase<postgres::detail::ByteaRefWrapper<ByteContainer>> {
137 using BaseType = detail::BufferFormatterBase<postgres::detail::ByteaRefWrapper<ByteContainer>>;
138 using BaseType::BaseType;
140 template <
typename Buffer>
141 void operator()(
const UserTypes&, Buffer& buf)
const {
142 buf.reserve(buf.size() +
this->value.bytes.size());
143 buf.insert(buf.end(),
this->value.bytes.begin(),
this->value.bytes.end());
147template <
typename ByteContainer>
148struct BufferFormatter<
149 postgres::ByteaWrapper<ByteContainer>,
150 traits::EnableIfByteaCompatible<std::decay_t<ByteContainer>>>
151 : detail::BufferFormatterBase<postgres::ByteaWrapper<ByteContainer>> {
152 using BaseType = detail::BufferFormatterBase<postgres::ByteaWrapper<ByteContainer>>;
153 using BaseType::BaseType;
155 template <
typename Buffer>
156 void operator()(
const UserTypes& types, Buffer& buffer)
const {
157 WriteBuffer(types, buffer, Bytea(
this->value.bytes));
161template <
typename ByteContainer>
162struct CppToSystemPg<
postgres::detail::ByteaRefWrapper<ByteContainer>> : PredefinedOid<PredefinedOids::kBytea> {};
163template <
typename ByteContainer>