5#include <userver/storages/postgres/io/nullable_traits.hpp>
6#include <userver/storages/postgres/io/traits.hpp>
7#include <userver/storages/postgres/io/type_mapping.hpp>
9#include <userver/storages/postgres/io/supported_types.hpp>
11#include <userver/storages/postgres/null.hpp>
13USERVER_NAMESPACE_BEGIN
18class QueryParameters {
20 QueryParameters() =
default;
22 template <
class ParamsHolder>
23 explicit QueryParameters(ParamsHolder& ph)
25 types_(ph.ParamTypesBuffer()),
26 values_(ph.ParamBuffers()),
27 lengths_(ph.ParamLengthsBuffer()),
28 formats_(ph.ParamFormatsBuffer()) {}
30 bool Empty()
const {
return size_ == 0; }
31 std::size_t Size()
const {
return size_; }
32 const char*
const* ParamBuffers()
const {
return values_; }
33 const Oid* ParamTypesBuffer()
const {
return types_; }
34 const int* ParamLengthsBuffer()
const {
return lengths_; }
35 const int* ParamFormatsBuffer()
const {
return formats_; }
37 std::size_t TypeHash()
const;
40 std::size_t size_ = 0;
41 const Oid* types_ =
nullptr;
42 const char*
const* values_ =
nullptr;
43 const int* lengths_ =
nullptr;
44 const int* formats_ =
nullptr;
47template <std::size_t ParamsCount>
48class StaticQueryParameters {
50 StaticQueryParameters() =
default;
51 StaticQueryParameters(
const StaticQueryParameters&) =
delete;
52 StaticQueryParameters(StaticQueryParameters&&) =
delete;
53 StaticQueryParameters& operator=(
const StaticQueryParameters&) =
delete;
54 StaticQueryParameters& operator=(StaticQueryParameters&&) =
delete;
56 std::size_t Size()
const {
return ParamsCount; }
57 const char*
const* ParamBuffers()
const {
return param_buffers; }
58 const Oid* ParamTypesBuffer()
const {
return param_types; }
59 const int* ParamLengthsBuffer()
const {
return param_lengths; }
60 const int* ParamFormatsBuffer()
const {
return param_formats; }
63 void Write(std::size_t index,
const UserTypes& types,
const T& arg) {
64 static_assert(
io::
traits::kIsMappedToPg<T> || std::is_enum_v<T>,
65 "Type doesn't have mapping to Postgres type.");
67 io::
traits::kIsMappedToPg<T> || !std::is_enum_v<T>,
68 "Type doesn't have mapping to Postgres type. "
69 "Enums should be either streamed as their underlying value via the "
70 "`template<> struct CanUseEnumAsStrongTypedef<T>: std::true_type {};` "
71 "specialization or as a PostgreSQL datatype via the "
72 "`template<> struct CppToUserPg<T> : EnumMappingBase<R> { ... };` "
74 "See page `uPg: Supported data types` for more information.");
75 WriteParamType(index, types, arg);
79 template <
typename... T>
80 void Write(
const UserTypes& types,
const T&... args) {
81 std::size_t index = 0;
82 (Write(index++, types, args), ...);
87 void WriteParamType(std::size_t index,
const UserTypes& types,
const T&) {
89 param_types[index] = io::CppToPg<T>::GetOid(types);
93 void WriteNullable(std::size_t index,
const UserTypes& types,
const T& arg,
96 if (NullDetector::IsNull(arg)) {
97 param_formats[index] =
io::kPgBinaryDataFormat;
99 param_buffers[index] =
nullptr;
101 WriteNullable(index, types, arg, std::false_type{});
105 template <
typename T>
106 void WriteNullable(std::size_t index,
const UserTypes& types,
const T& arg,
108 param_formats[index] =
io::kPgBinaryDataFormat;
109 auto& buffer = parameters[index];
110 io::WriteBuffer(types, buffer, arg);
111 auto size = buffer.size();
112 param_lengths[index] = size;
114 param_buffers[index] = empty_buffer;
116 param_buffers[index] = buffer.data();
120 using OidList = Oid[ParamsCount];
121 using BufferType = std::string;
122 using ParameterList = BufferType[ParamsCount];
123 using IntList =
int[ParamsCount];
125 static constexpr const char* empty_buffer =
"";
127 ParameterList parameters{};
128 OidList param_types{};
129 const char* param_buffers[ParamsCount]{};
130 IntList param_lengths{};
131 IntList param_formats{};
135class StaticQueryParameters<0> {
137 static std::size_t Size() {
return 0; }
138 static const char*
const* ParamBuffers() {
return nullptr; }
139 static const Oid* ParamTypesBuffer() {
return nullptr; }
140 static const int* ParamLengthsBuffer() {
return nullptr; }
141 static const int* ParamFormatsBuffer() {
return nullptr; }
146class DynamicQueryParameters {
148 DynamicQueryParameters() =
default;
149 DynamicQueryParameters(
const DynamicQueryParameters&) =
delete;
150 DynamicQueryParameters(DynamicQueryParameters&&) =
default;
151 DynamicQueryParameters& operator=(
const DynamicQueryParameters&) =
delete;
152 DynamicQueryParameters& operator=(DynamicQueryParameters&&) =
default;
154 std::size_t Size()
const {
return param_types.size(); }
155 const char*
const* ParamBuffers()
const {
return param_buffers.data(); }
156 const Oid* ParamTypesBuffer()
const {
return param_types.data(); }
157 const int* ParamLengthsBuffer()
const {
return param_lengths.data(); }
158 const int* ParamFormatsBuffer()
const {
return param_formats.data(); }
160 template <
typename T>
161 void Write(
const UserTypes& types,
const T& arg) {
162 static_assert(
io::
traits::kIsMappedToPg<T>,
163 "Type doesn't have mapping to Postgres type");
164 WriteParamType(types, arg);
168 template <
typename... T>
169 void Write(
const UserTypes& types,
const T&... args) {
170 (Write(types, args), ...);
174 template <
typename T>
175 void WriteParamType(
const UserTypes& types,
const T&) {
177 param_types.push_back(io::CppToPg<T>::GetOid(types));
180 template <
typename T>
181 void WriteNullable(
const UserTypes& types,
const T& arg, std::true_type) {
183 if (NullDetector::IsNull(arg)) {
184 param_formats.push_back(io::kPgBinaryDataFormat);
185 param_lengths.push_back(io::kPgNullBufferSize);
186 param_buffers.push_back(
nullptr);
188 WriteNullable(types, arg, std::false_type{});
192 template <
typename T>
193 void WriteNullable(
const UserTypes& types,
const T& arg, std::false_type) {
194 param_formats.push_back(io::kPgBinaryDataFormat);
195 auto& buffer = parameters.emplace_back();
196 io::WriteBuffer(types, buffer, arg);
197 auto size = buffer.size();
198 param_lengths.push_back(size);
200 param_buffers.push_back(empty_buffer);
202 param_buffers.push_back(buffer.data());
206 using OidList = std::vector<Oid>;
207 using BufferType = std::vector<
char>;
208 using ParameterList = std::vector<BufferType>;
209 using IntList = std::vector<
int>;
211 static constexpr const char* empty_buffer =
"";
213 ParameterList parameters;
215 std::vector<
const char*> param_buffers;
216 IntList param_lengths;
217 IntList param_formats;