libpqxx 7.7.0
params.hxx
1/* Helpers for prepared statements and parameterised statements.
2 *
3 * See the connection class for more about such statements.
4 *
5 * Copyright (c) 2000-2022, Jeroen T. Vermeulen.
6 *
7 * See COPYING for copyright license. If you did not receive a file called
8 * COPYING with this source code, please notify the distributor of this
9 * mistake, or contact the author.
10 */
11#ifndef PQXX_H_PARAMS
12#define PQXX_H_PARAMS
13
14#include <array>
15
16#include "pqxx/internal/concat.hxx"
17#include "pqxx/internal/statement_parameters.hxx"
18#include "pqxx/types.hxx"
19
20
23{
25
42template<typename IT>
43[[deprecated("Use the params class instead.")]] constexpr inline auto
44make_dynamic_params(IT begin, IT end)
45{
46 return pqxx::internal::dynamic_params(begin, end);
47}
48
49
51
67template<typename C>
68[[deprecated("Use the params class instead.")]] constexpr inline auto
69make_dynamic_params(C const &container)
70{
71 using IT = typename C::const_iterator;
72#include "pqxx/internal/ignore-deprecated-pre.hxx"
73 return pqxx::internal::dynamic_params<IT>{container};
74#include "pqxx/internal/ignore-deprecated-post.hxx"
75}
76
77
79
96template<typename C, typename ACCESSOR>
97[[deprecated("Use the params class instead.")]] constexpr inline auto
98make_dynamic_params(C &container, ACCESSOR accessor)
99{
100 using IT = decltype(std::begin(container));
101#include "pqxx/internal/ignore-deprecated-pre.hxx"
102 return pqxx::internal::dynamic_params<IT, ACCESSOR>{container, accessor};
103#include "pqxx/internal/ignore-deprecated-post.hxx"
104}
105} // namespace pqxx::prepare
106
107
108namespace pqxx
109{
111
121template<typename COUNTER = unsigned int> class placeholders
122{
123public:
125 static inline constexpr unsigned int max_params{
126 (std::numeric_limits<COUNTER>::max)()};
127
129 {
130 // C++20: constinit.
131 static constexpr auto initial{"$1\0"sv};
132 initial.copy(std::data(m_buf), std::size(initial));
133 }
134
136
139 zview view() const &noexcept { return zview{std::data(m_buf), m_len}; }
140
142
147 std::string get() const { return std::string(std::data(m_buf), m_len); }
148
150 void next() &
151 {
152 if (m_current >= max_params)
153 throw range_error{pqxx::internal::concat(
154 "Too many parameters in one statement: limit is ", max_params, ".")};
155 ++m_current;
156 if (m_current % 10 == 0)
157 {
158 // Carry the 1. Don't get too clever for this relatively rare
159 // case, just rewrite the entire number. Leave the $ in place
160 // though.
161 char *const data{std::data(m_buf)};
162 char *const end{string_traits<COUNTER>::into_buf(
163 data + 1, data + std::size(m_buf), m_current)};
164 // (Subtract because we don't include the trailing zero.)
165 m_len = check_cast<COUNTER>(end - data, "placeholders counter") - 1;
166 }
167 else
168 {
169 PQXX_LIKELY
170 // Shortcut for the common case: just increment that last digit.
171 ++m_buf[m_len - 1];
172 }
173 }
174
176 COUNTER count() const noexcept { return m_current; }
177
178private:
180 COUNTER m_current = 1;
181
183 COUNTER m_len = 2;
184
186
193 std::array<char, std::numeric_limits<COUNTER>::digits10 + 3> m_buf;
194};
195
196
198
213class PQXX_LIBEXPORT params
214{
215public:
216 params() = default;
217
219 template<typename... Args> constexpr params(Args &&...args)
220 {
221 reserve(sizeof...(args));
222 append_pack(std::forward<Args>(args)...);
223 }
224
226
232 void reserve(std::size_t n) &;
233
235 [[nodiscard]] auto size() const noexcept { return m_params.size(); }
236
237 // C++20: Use the vector's ssize() directly and go noexcept.
239
244 [[nodiscard]] auto ssize() const { return pqxx::internal::ssize(m_params); }
245
247 void append() &;
248
250
253 void append(zview) &;
254
256
259 void append(std::string const &) &;
260
262 void append(std::string &&) &;
263
265
268 void append(std::basic_string_view<std::byte>) &;
269
271
275 void append(std::basic_string<std::byte> const &) &;
276
277#if defined(PQXX_HAVE_CONCEPTS)
279
282 template<binary DATA> void append(DATA const &data) &
283 {
284 append(
285 std::basic_string_view<std::byte>{std::data(data), std::size(data)});
286 }
287#endif // PQXX_HAVE_CONCEPTS
288
290 void append(std::basic_string<std::byte> &&) &;
291
293
296 void append(binarystring const &value) &;
297
299 template<typename IT, typename ACCESSOR>
300 void append(pqxx::internal::dynamic_params<IT, ACCESSOR> const &value) &
301 {
302 for (auto &param : value) append(value.access(param));
303 }
304
305 void append(params const &value) &;
306
307 void append(params &&value) &;
308
311 template<typename TYPE> void append(TYPE const &value) &
312 {
313 // TODO: Pool storage for multiple string conversions in one buffer?
314 if constexpr (nullness<strip_t<TYPE>>::always_null)
315 {
316 ignore_unused(value);
317 m_params.emplace_back();
318 }
319 else if (is_null(value))
320 {
321 m_params.emplace_back();
322 }
323 else
324 {
325 m_params.emplace_back(entry{to_string(value)});
326 }
327 }
328
330 template<PQXX_RANGE_ARG RANGE> void append_multi(RANGE const &range) &
331 {
332#if defined(PQXX_HAVE_CONCEPTS)
333 if constexpr (std::ranges::sized_range<RANGE>)
334 reserve(std::size(*this) + std::size(range));
335#endif
336 for (auto &value : range) append(value);
337 }
338
340
349 pqxx::internal::c_params make_c_params() const;
350
351private:
353 template<typename Arg, typename... More>
354 void append_pack(Arg &&arg, More &&...args)
355 {
356 this->append(std::forward<Arg>(arg));
357 // Recurse for remaining args.
358 append_pack(std::forward<More>(args)...);
359 }
360
362 void append_pack() {}
363
364 // The way we store a parameter depends on whether it's binary or text
365 // (most types are text), and whether we're responsible for storing the
366 // contents.
367 using entry = std::variant<
368 std::nullptr_t, zview, std::string, std::basic_string_view<std::byte>,
369 std::basic_string<std::byte>>;
370 std::vector<entry> m_params;
371
372 // C++20: constinit.
373 static constexpr std::string_view s_overflow{
374 "Statement parameter length overflow."sv};
375};
376} // namespace pqxx
377#endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:23
void ignore_unused(T &&...)
Suppress compiler warning about an unused item.
Definition: util.hxx:128
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:528
bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:364
auto ssize(T const &c)
Transitional: std::ssize(), or custom implementation if not available.
Definition: util.hxx:439
Definition: params.hxx:23
constexpr auto make_dynamic_params(IT begin, IT end)
Pass a number of statement parameters only known at runtime.
Definition: params.hxx:44
Something is out of range, similar to std::out_of_range.
Definition: except.hxx:190
Generate parameter placeholders for use in an SQL statement.
Definition: params.hxx:122
static constexpr unsigned int max_params
Maximum number of parameters we support.
Definition: params.hxx:125
COUNTER count() const noexcept
Return the current placeholder number. The initial placeholder is 1.
Definition: params.hxx:176
std::string get() const
Read the current placeholder text, as a std::string.
Definition: params.hxx:147
placeholders()
Definition: params.hxx:128
zview view() const &noexcept
Read an ephemeral version of the current placeholder text.
Definition: params.hxx:139
void next() &
Move on to the next parameter.
Definition: params.hxx:150
Build a parameter list for a parameterised or prepared statement.
Definition: params.hxx:214
auto size() const noexcept
Get the number of parameters currently in this params.
Definition: params.hxx:235
void append_multi(RANGE const &range) &
Append all elements of range as parameters.
Definition: params.hxx:330
void append(TYPE const &value) &
Definition: params.hxx:311
params()=default
auto ssize() const
Get the number of parameters (signed).
Definition: params.hxx:244
void append(pqxx::internal::dynamic_params< IT, ACCESSOR > const &value) &
Append all parameters from value.
Definition: params.hxx:300
constexpr params(Args &&...args)
Pre-populate a params with args. Feel free to add more later.
Definition: params.hxx:219
A C++ equivalent to PostgreSQL's range types.
Definition: range.hxx:199
Traits describing a type's "null value," if any.
Definition: strconv.hxx:89
static char * into_buf(char *begin, char *end, TYPE const &value)
Write value's string representation into buffer at begin.
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:38