libpqxx 7.8.1
field.hxx
1/* Definitions for the pqxx::field class.
2 *
3 * pqxx::field refers to a field in a query result.
4 *
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.
6 *
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
8 *
9 * See COPYING for copyright license. If you did not receive a file called
10 * COPYING with this source code, please notify the distributor of this
11 * mistake, or contact the author.
12 */
13#ifndef PQXX_H_FIELD
14#define PQXX_H_FIELD
15
16#if !defined(PQXX_HEADER_PRE)
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
18#endif
19
20#include <optional>
21
22#include "pqxx/array.hxx"
23#include "pqxx/composite.hxx"
24#include "pqxx/result.hxx"
25#include "pqxx/strconv.hxx"
26#include "pqxx/types.hxx"
27
28namespace pqxx
29{
31
34class PQXX_LIBEXPORT field
35{
36public:
38
40
44 [[deprecated(
45 "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept;
46
48 [[deprecated(
49 "Do not construct fields yourself. Get them from the "
50 "row.")]] field() noexcept = default;
51
57
73 [[nodiscard]] PQXX_PURE bool operator==(field const &) const noexcept;
74
76
78 [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept
79 {
80 return not operator==(rhs);
81 }
83
89 [[nodiscard]] PQXX_PURE char const *name() const &;
90
92 [[nodiscard]] oid PQXX_PURE type() const;
93
95 [[nodiscard]] PQXX_PURE oid table() const;
96
98 PQXX_PURE constexpr row_size_type num() const noexcept { return col(); }
99
101 [[nodiscard]] PQXX_PURE row_size_type table_column() const;
103
109
113 [[nodiscard]] PQXX_PURE std::string_view view() const &
114 {
115 return std::string_view(c_str(), size());
116 }
117
119
128 [[nodiscard]] PQXX_PURE char const *c_str() const &;
129
131 [[nodiscard]] PQXX_PURE bool is_null() const noexcept;
132
134 [[nodiscard]] PQXX_PURE size_type size() const noexcept;
135
137
140 template<typename T>
141 auto to(T &obj) const -> typename std::enable_if_t<
142 (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
143 bool>
144 {
145 if (is_null())
146 {
147 return false;
148 }
149 else
150 {
151 auto const bytes{c_str()};
152 from_string(bytes, obj);
153 return true;
154 }
155 }
156
158
163 template<typename... T> bool composite_to(T &...fields) const
164 {
165 if (is_null())
166 {
167 return false;
168 }
169 else
170 {
171 parse_composite(m_home.m_encoding, view(), fields...);
172 return true;
173 }
174 }
175
177 template<typename T> bool operator>>(T &obj) const { return to(obj); }
178
180
190 template<typename T>
191 auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<
192 (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
193 bool>
194 {
195 bool const null{is_null()};
196 if (null)
197 obj = default_value;
198 else
199 obj = from_string<T>(this->view());
200 return not null;
201 }
202
204
207 template<typename T> T as(T const &default_value) const
208 {
209 if (is_null())
210 return default_value;
211 else
212 return from_string<T>(this->view());
213 }
214
216
221 template<typename T> T as() const
222 {
223 if (is_null())
224 {
225 if constexpr (not nullness<T>::has_null)
227 else
228 return nullness<T>::null();
229 }
230 else
231 {
232 return from_string<T>(this->view());
233 }
234 }
235
237
240 template<typename T, template<typename> class O = std::optional>
241 constexpr O<T> get() const
242 {
243 return as<O<T>>();
244 }
245
247
253 array_parser as_array() const &noexcept
254 {
255 return array_parser{c_str(), m_home.m_encoding};
256 }
258
259
260protected:
261 constexpr result const &home() const noexcept { return m_home; }
262 constexpr result::size_type idx() const noexcept { return m_row; }
263 constexpr row_size_type col() const noexcept { return m_col; }
264
265 // TODO: Create gates.
266 friend class pqxx::result;
267 friend class pqxx::row;
269 result const &r, result_size_type row_num, row_size_type col_num) noexcept
270 :
271 m_col{col_num}, m_home{r}, m_row{row_num}
272 {}
273
279
280private:
281 result m_home;
282 result::size_type m_row;
283};
284
285
286template<> inline bool field::to<std::string>(std::string &obj) const
287{
288 bool const null{is_null()};
289 if (not null)
290 obj = std::string{view()};
291 return not null;
292}
293
294
295template<>
296inline bool field::to<std::string>(
297 std::string &obj, std::string const &default_value) const
298{
299 bool const null{is_null()};
300 if (null)
301 obj = default_value;
302 else
303 obj = std::string{view()};
304 return not null;
305}
306
307
309
314template<> inline bool field::to<char const *>(char const *&obj) const
315{
316 bool const null{is_null()};
317 if (not null)
318 obj = c_str();
319 return not null;
320}
321
322
323template<> inline bool field::to<std::string_view>(std::string_view &obj) const
324{
325 bool const null{is_null()};
326 if (not null)
327 obj = view();
328 return not null;
329}
330
331
332template<>
333inline bool field::to<std::string_view>(
334 std::string_view &obj, std::string_view const &default_value) const
335{
336 bool const null{is_null()};
337 if (null)
338 obj = default_value;
339 else
340 obj = view();
341 return not null;
342}
343
344
345template<> inline std::string_view field::as<std::string_view>() const
346{
347 if (is_null())
348 PQXX_UNLIKELY
349 internal::throw_null_conversion(type_name<std::string_view>);
350 return view();
351}
352
353
354template<>
355inline std::string_view
356field::as<std::string_view>(std::string_view const &default_value) const
357{
358 return is_null() ? default_value : view();
359}
360
361
362template<> inline bool field::to<zview>(zview &obj) const
363{
364 bool const null{is_null()};
365 if (not null)
366 obj = zview{c_str(), size()};
367 return not null;
368}
369
370
371template<>
372inline bool field::to<zview>(zview &obj, zview const &default_value) const
373{
374 bool const null{is_null()};
375 if (null)
376 obj = default_value;
377 else
378 obj = zview{c_str(), size()};
379 return not null;
380}
381
382
383template<> inline zview field::as<zview>() const
384{
385 if (is_null())
386 PQXX_UNLIKELY
387 internal::throw_null_conversion(type_name<zview>);
388 return zview{c_str(), size()};
389}
390
391
392template<> inline zview field::as<zview>(zview const &default_value) const
393{
394 return is_null() ? default_value : zview{c_str(), size()};
395}
396
397
398template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
399class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
400{
401public:
402 using char_type = CHAR;
403 using traits_type = TRAITS;
404 using int_type = typename traits_type::int_type;
405 using pos_type = typename traits_type::pos_type;
406 using off_type = typename traits_type::off_type;
407 using openmode = std::ios::openmode;
408 using seekdir = std::ios::seekdir;
409
410 explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
411
412protected:
413 virtual int sync() override { return traits_type::eof(); }
414
416 {
417 return traits_type::eof();
418 }
420 {
421 return traits_type::eof();
422 }
423 virtual int_type overflow(int_type) override { return traits_type::eof(); }
424 virtual int_type underflow() override { return traits_type::eof(); }
425
426private:
427 field const &m_field;
428
429 int_type initialize()
430 {
431 auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
432 this->setg(g, g, g + std::size(m_field));
433 return int_type(std::size(m_field));
434 }
435};
436
437
439
452template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
453class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
454{
455 using super = std::basic_istream<CHAR, TRAITS>;
456
457public:
458 using char_type = CHAR;
459 using traits_type = TRAITS;
460 using int_type = typename traits_type::int_type;
461 using pos_type = typename traits_type::pos_type;
462 using off_type = typename traits_type::off_type;
463
464 [[deprecated("Use field::as<...>() or field::c_str().")]] basic_fieldstream(
465 field const &f) :
466 super{nullptr}, m_buf{f}
467 {
468 super::init(&m_buf);
469 }
470
471private:
473};
474
475
478
479
481
505template<typename CHAR>
506[[deprecated(
507 "Do this by hand, probably with better error checking.")]] inline std::
508 basic_ostream<CHAR> &
509 operator<<(std::basic_ostream<CHAR> &s, field const &value)
510{
511 s.write(value.c_str(), std::streamsize(std::size(value)));
512 return s;
513}
514
515
517
520template<typename T> inline T from_string(field const &value)
521{
522 if (value.is_null())
523 {
524 if constexpr (nullness<T>::has_null)
525 return nullness<T>::null();
526 else
528 }
529 else
530 {
531 return from_string<T>(value.view());
532 }
533}
534
535
537
543template<>
544inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
545{
546 if (not value.is_null())
547 throw conversion_error{
548 "Extracting non-null field into nullptr_t variable."};
549 return nullptr;
550}
551
552
554template<> PQXX_LIBEXPORT std::string to_string(field const &value);
555} // namespace pqxx
556#endif
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field const &value)
Write a result field to any type of stream.
Definition field.hxx:509
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
std::size_t field_size_type
Number of bytes in a field of database data.
Definition types.hxx:40
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
void parse_composite(pqxx::internal::encoding_group enc, std::string_view text, T &...fields)
Parse a string representation of a value of a composite type.
Definition composite.hxx:35
std::nullptr_t from_string< std::nullptr_t >(field const &value)
Convert a field's value to nullptr_t.
Definition field.hxx:544
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:520
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition strconv.cxx:253
Low-level array parser.
Definition array.hxx:527
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
Reference to a field in a result set.
Definition field.hxx:35
constexpr result const & home() const noexcept
Definition field.hxx:261
PQXX_PURE size_type size() const noexcept
Return number of bytes taken up by the field's value.
Definition field.cxx:77
T as(T const &default_value) const
Return value as object of given type, or default value if null.
Definition field.hxx:207
row_size_type m_col
Definition field.hxx:278
array_parser as_array() const &noexcept
Parse the field as an SQL array.
Definition field.hxx:253
auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<(not std::is_pointer< T >::value or std::is_same< T, char const * >::value), bool >
Read value into obj; or if null, use default value and return false.
Definition field.hxx:191
field_size_type size_type
Definition field.hxx:37
bool operator>>(T &obj) const
Read value into obj; or leave obj untouched and return false if null.
Definition field.hxx:177
PQXX_PURE char const * c_str() const &
Read as plain C string.
Definition field.cxx:65
T as() const
Return value as object of given type, or throw exception if null.
Definition field.hxx:221
field(result const &r, result_size_type row_num, row_size_type col_num) noexcept
Definition field.hxx:268
constexpr row_size_type col() const noexcept
Definition field.hxx:263
PQXX_PURE std::string_view view() const &
Read as string_view, or an empty one if null.
Definition field.hxx:113
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition field.hxx:163
field() noexcept=default
Constructor. Do not call this yourself; libpqxx will do it for you.
PQXX_PURE bool is_null() const noexcept
Is this field's value null?
Definition field.cxx:71
constexpr O< T > get() const
Return value wrapped in some optional type (empty for nulls).
Definition field.hxx:241
constexpr result::size_type idx() const noexcept
Definition field.hxx:262
Definition field.hxx:400
TRAITS traits_type
Definition field.hxx:403
typename traits_type::off_type off_type
Definition field.hxx:406
field_streambuf(field const &f)
Definition field.hxx:410
virtual pos_type seekoff(off_type, seekdir, openmode) override
Definition field.hxx:415
virtual pos_type seekpos(pos_type, openmode) override
Definition field.hxx:419
std::ios::openmode openmode
Definition field.hxx:407
virtual int_type overflow(int_type) override
Definition field.hxx:423
typename traits_type::pos_type pos_type
Definition field.hxx:405
virtual int sync() override
Definition field.hxx:413
typename traits_type::int_type int_type
Definition field.hxx:404
virtual int_type underflow() override
Definition field.hxx:424
CHAR char_type
Definition field.hxx:402
std::ios::seekdir seekdir
Definition field.hxx:408
Input stream that gets its data from a result field.
Definition field.hxx:454
TRAITS traits_type
Definition field.hxx:459
basic_fieldstream(field const &f)
Definition field.hxx:464
typename traits_type::pos_type pos_type
Definition field.hxx:461
typename traits_type::off_type off_type
Definition field.hxx:462
typename traits_type::int_type int_type
Definition field.hxx:460
CHAR char_type
Definition field.hxx:458
Result set containing data returned by a query or command.
Definition result.hxx:73
result_size_type size_type
Definition result.hxx:75
Reference to one row in a result.
Definition row.hxx:47
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
static TYPE null()
Return a null value.
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38