libpqxx 7.8.1
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-2023, 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#if !defined(PQXX_HEADER_PRE)
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
16#endif
17
18#include <array>
19
20#include "pqxx/internal/concat.hxx"
21#include "pqxx/internal/statement_parameters.hxx"
22#include "pqxx/types.hxx"
23
24
27{
29
46template<typename IT>
47[[deprecated("Use the params class instead.")]] constexpr inline auto
48make_dynamic_params(IT begin, IT end)
49{
50 return pqxx::internal::dynamic_params(begin, end);
51}
52
53
55
71template<typename C>
72[[deprecated("Use the params class instead.")]] constexpr inline auto
73make_dynamic_params(C const &container)
74{
75 using IT = typename C::const_iterator;
76#include "pqxx/internal/ignore-deprecated-pre.hxx"
77 return pqxx::internal::dynamic_params<IT>{container};
78#include "pqxx/internal/ignore-deprecated-post.hxx"
79}
80
81
83
100template<typename C, typename ACCESSOR>
101[[deprecated("Use the params class instead.")]] constexpr inline auto
102make_dynamic_params(C &container, ACCESSOR accessor)
103{
104 using IT = decltype(std::begin(container));
105#include "pqxx/internal/ignore-deprecated-pre.hxx"
106 return pqxx::internal::dynamic_params<IT, ACCESSOR>{container, accessor};
107#include "pqxx/internal/ignore-deprecated-post.hxx"
108}
109} // namespace pqxx::prepare
110
111
112namespace pqxx
113{
115
125template<typename COUNTER = unsigned int> class placeholders
126{
127public:
129 static inline constexpr unsigned int max_params{
130 (std::numeric_limits<COUNTER>::max)()};
131
133 {
134 static constexpr auto initial{"$1\0"sv};
135 initial.copy(std::data(m_buf), std::size(initial));
136 }
137
139
142 constexpr zview view() const &noexcept
143 {
144 return zview{std::data(m_buf), m_len};
145 }
146
148
153 std::string get() const { return std::string(std::data(m_buf), m_len); }
154
156 void next() &
157 {
158 if (m_current >= max_params)
159 throw range_error{pqxx::internal::concat(
160 "Too many parameters in one statement: limit is ", max_params, ".")};
161 ++m_current;
162 if (m_current % 10 == 0)
163 {
164 // Carry the 1. Don't get too clever for this relatively rare
165 // case, just rewrite the entire number. Leave the $ in place
166 // though.
167 char *const data{std::data(m_buf)};
168 char *const end{string_traits<COUNTER>::into_buf(
169 data + 1, data + std::size(m_buf), m_current)};
170 // (Subtract because we don't include the trailing zero.)
171 m_len = check_cast<COUNTER>(end - data, "placeholders counter") - 1;
172 }
173 else
174 {
175 PQXX_LIKELY
176 // Shortcut for the common case: just increment that last digit.
177 ++m_buf[m_len - 1];
178 }
179 }
180
182 COUNTER count() const noexcept { return m_current; }
183
184private:
186 COUNTER m_current = 1;
187
189 COUNTER m_len = 2;
190
192
199 std::array<char, std::numeric_limits<COUNTER>::digits10 + 3> m_buf;
200};
201
202
204
219class PQXX_LIBEXPORT params
220{
221public:
222 params() = default;
223
225 template<typename... Args> constexpr params(Args &&...args)
226 {
227 reserve(sizeof...(args));
228 append_pack(std::forward<Args>(args)...);
229 }
230
232
238 void reserve(std::size_t n) &;
239
240 // C++20: constexpr.
242 [[nodiscard]] auto size() const noexcept { return m_params.size(); }
243
244 // C++20: Use the vector's ssize() directly and go noexcept+constexpr.
246
251 [[nodiscard]] auto ssize() const { return pqxx::internal::ssize(m_params); }
252
254 void append() &;
255
257
260 void append(zview) &;
261
263
266 void append(std::string const &) &;
267
269 void append(std::string &&) &;
270
272
275 void append(std::basic_string_view<std::byte>) &;
276
278
282 void append(std::basic_string<std::byte> const &) &;
283
284#if defined(PQXX_HAVE_CONCEPTS)
286
289 template<binary DATA> void append(DATA const &data) &
290 {
291 append(
292 std::basic_string_view<std::byte>{std::data(data), std::size(data)});
293 }
294#endif // PQXX_HAVE_CONCEPTS
295
297 void append(std::basic_string<std::byte> &&) &;
298
300
303 void append(binarystring const &value) &;
304
306 template<typename IT, typename ACCESSOR>
307 void append(pqxx::internal::dynamic_params<IT, ACCESSOR> const &value) &
308 {
309 for (auto &param : value) append(value.access(param));
310 }
311
312 void append(params const &value) &;
313
314 void append(params &&value) &;
315
318 template<typename TYPE> void append(TYPE const &value) &
319 {
320 // TODO: Pool storage for multiple string conversions in one buffer?
321 if constexpr (nullness<strip_t<TYPE>>::always_null)
322 {
323 ignore_unused(value);
324 m_params.emplace_back();
325 }
326 else if (is_null(value))
327 {
328 m_params.emplace_back();
329 }
330 else
331 {
332 m_params.emplace_back(entry{to_string(value)});
333 }
334 }
335
337 template<PQXX_RANGE_ARG RANGE> void append_multi(RANGE const &range) &
338 {
339#if defined(PQXX_HAVE_CONCEPTS)
340 if constexpr (std::ranges::sized_range<RANGE>)
341 reserve(std::size(*this) + std::size(range));
342#endif
343 for (auto &value : range) append(value);
344 }
345
347
356 pqxx::internal::c_params make_c_params() const;
357
358private:
360 template<typename Arg, typename... More>
361 void append_pack(Arg &&arg, More &&...args)
362 {
363 this->append(std::forward<Arg>(arg));
364 // Recurse for remaining args.
365 append_pack(std::forward<More>(args)...);
366 }
367
369 constexpr void append_pack() noexcept {}
370
371 // The way we store a parameter depends on whether it's binary or text
372 // (most types are text), and whether we're responsible for storing the
373 // contents.
374 using entry = std::variant<
375 std::nullptr_t, zview, std::string, std::basic_string_view<std::byte>,
376 std::basic_string<std::byte>>;
377 std::vector<entry> m_params;
378
379 static constexpr std::string_view s_overflow{
380 "Statement parameter length overflow."sv};
381};
382} // namespace pqxx
383#endif
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
constexpr void ignore_unused(T &&...) noexcept
Suppress compiler warning about an unused item.
Definition util.hxx:142
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
auto ssize(T const &c)
Transitional: std::ssize(), or custom implementation if not available.
Definition util.hxx:453
Definition params.hxx:27
constexpr auto make_dynamic_params(IT begin, IT end)
Pass a number of statement parameters only known at runtime.
Definition params.hxx:48
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
Generate parameter placeholders for use in an SQL statement.
Definition params.hxx:126
static constexpr unsigned int max_params
Maximum number of parameters we support.
Definition params.hxx:129
COUNTER count() const noexcept
Return the current placeholder number. The initial placeholder is 1.
Definition params.hxx:182
std::string get() const
Read the current placeholder text, as a std::string.
Definition params.hxx:153
placeholders()
Definition params.hxx:132
constexpr zview view() const &noexcept
Read an ephemeral version of the current placeholder text.
Definition params.hxx:142
void next() &
Move on to the next parameter.
Definition params.hxx:156
Build a parameter list for a parameterised or prepared statement.
Definition params.hxx:220
auto size() const noexcept
Get the number of parameters currently in this params.
Definition params.hxx:242
void append_multi(RANGE const &range) &
Append all elements of range as parameters.
Definition params.hxx:337
void append(TYPE const &value) &
Definition params.hxx:318
params()=default
auto ssize() const
Get the number of parameters (signed).
Definition params.hxx:251
void append(pqxx::internal::dynamic_params< IT, ACCESSOR > const &value) &
Append all parameters from value.
Definition params.hxx:307
constexpr params(Args &&...args)
Pre-populate a params with args. Feel free to add more later.
Definition params.hxx:225
A C++ equivalent to PostgreSQL's range types.
Definition range.hxx:234
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
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