libpqxx  7.9.0
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-2024, 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 
28 namespace pqxx
29 {
31 
34 class PQXX_LIBEXPORT field
35 {
36 public:
38 
44 
60  [[nodiscard]] PQXX_PURE bool operator==(field const &) const noexcept;
61 
63 
65  [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept
66  {
67  return not operator==(rhs);
68  }
70 
76  [[nodiscard]] PQXX_PURE char const *name() const &;
77 
79  [[nodiscard]] oid PQXX_PURE type() const;
80 
82  [[nodiscard]] PQXX_PURE oid table() const;
83 
85  PQXX_PURE constexpr row_size_type num() const noexcept { return col(); }
86 
88  [[nodiscard]] PQXX_PURE row_size_type table_column() const;
90 
107 
111  [[nodiscard]] PQXX_PURE std::string_view view() const &
112  {
113  return std::string_view(c_str(), size());
114  }
115 
117 
126  [[nodiscard]] PQXX_PURE char const *c_str() const &;
127 
129  [[nodiscard]] PQXX_PURE bool is_null() const noexcept;
130 
132  [[nodiscard]] PQXX_PURE size_type size() const noexcept;
133 
135 
138  template<typename T>
139  auto to(T &obj) const -> typename std::enable_if_t<
140  (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
141  bool>
142  {
143  if (is_null())
144  {
145  return false;
146  }
147  else
148  {
149  auto const data{c_str()};
150  from_string(data, obj);
151  return true;
152  }
153  }
154 
156 
161  template<typename... T> bool composite_to(T &...fields) const
162  {
163  if (is_null())
164  {
165  return false;
166  }
167  else
168  {
169  parse_composite(m_home.m_encoding, view(), fields...);
170  return true;
171  }
172  }
173 
175  template<typename T> bool operator>>(T &obj) const { return to(obj); }
176 
178 
188  template<typename T>
189  auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<
190  (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
191  bool>
192  {
193  bool const null{is_null()};
194  if (null)
195  obj = default_value;
196  else
197  obj = from_string<T>(this->view());
198  return not null;
199  }
200 
202 
205  template<typename T> T as(T const &default_value) const
206  {
207  if (is_null())
208  return default_value;
209  else
210  return from_string<T>(this->view());
211  }
212 
214 
219  template<typename T> T as() const
220  {
221  if (is_null())
222  {
223  if constexpr (not nullness<T>::has_null)
224  internal::throw_null_conversion(type_name<T>);
225  else
226  return nullness<T>::null();
227  }
228  else
229  {
230  return from_string<T>(this->view());
231  }
232  }
233 
235 
238  template<typename T, template<typename> class O = std::optional>
239  constexpr O<T> get() const
240  {
241  return as<O<T>>();
242  }
243 
245 
251  array_parser as_array() const & noexcept
252  {
253  return array_parser{c_str(), m_home.m_encoding};
254  }
256 
258 
262  [[deprecated(
263  "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept;
264 
266  [[deprecated(
267  "Do not construct fields yourself. Get them from the "
268  "row.")]] field() noexcept = default;
269 
270 
271 protected:
272  constexpr result const &home() const noexcept { return m_home; }
273  constexpr result::size_type idx() const noexcept { return m_row; }
274  constexpr row_size_type col() const noexcept { return m_col; }
275 
276  // TODO: Create gates.
277  friend class pqxx::result;
278  friend class pqxx::row;
280  result const &r, result_size_type row_num, row_size_type col_num) noexcept
281  :
282  m_col{col_num}, m_home{r}, m_row{row_num}
283  {}
284 
290 
291 private:
292  result m_home;
293  result::size_type m_row;
294 };
295 
296 
297 template<> inline bool field::to<std::string>(std::string &obj) const
298 {
299  bool const null{is_null()};
300  if (not null)
301  obj = std::string{view()};
302  return not null;
303 }
304 
305 
306 template<>
307 inline bool field::to<std::string>(
308  std::string &obj, std::string const &default_value) const
309 {
310  bool const null{is_null()};
311  if (null)
312  obj = default_value;
313  else
314  obj = std::string{view()};
315  return not null;
316 }
317 
318 
320 
325 template<> inline bool field::to<char const *>(char const *&obj) const
326 {
327  bool const null{is_null()};
328  if (not null)
329  obj = c_str();
330  return not null;
331 }
332 
333 
334 template<> inline bool field::to<std::string_view>(std::string_view &obj) const
335 {
336  bool const null{is_null()};
337  if (not null)
338  obj = view();
339  return not null;
340 }
341 
342 
343 template<>
344 inline bool field::to<std::string_view>(
345  std::string_view &obj, std::string_view const &default_value) const
346 {
347  bool const null{is_null()};
348  if (null)
349  obj = default_value;
350  else
351  obj = view();
352  return not null;
353 }
354 
355 
356 template<> inline std::string_view field::as<std::string_view>() const
357 {
358  if (is_null())
359  PQXX_UNLIKELY
360  internal::throw_null_conversion(type_name<std::string_view>);
361  return view();
362 }
363 
364 
365 template<>
366 inline std::string_view
367 field::as<std::string_view>(std::string_view const &default_value) const
368 {
369  return is_null() ? default_value : view();
370 }
371 
372 
373 template<> inline bool field::to<zview>(zview &obj) const
374 {
375  bool const null{is_null()};
376  if (not null)
377  obj = zview{c_str(), size()};
378  return not null;
379 }
380 
381 
382 template<>
383 inline bool field::to<zview>(zview &obj, zview const &default_value) const
384 {
385  bool const null{is_null()};
386  if (null)
387  obj = default_value;
388  else
389  obj = zview{c_str(), size()};
390  return not null;
391 }
392 
393 
394 template<> inline zview field::as<zview>() const
395 {
396  if (is_null())
397  PQXX_UNLIKELY
398  internal::throw_null_conversion(type_name<zview>);
399  return zview{c_str(), size()};
400 }
401 
402 
403 template<> inline zview field::as<zview>(zview const &default_value) const
404 {
405  return is_null() ? default_value : zview{c_str(), size()};
406 }
407 
408 
409 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
410 class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
411 {
412 public:
413  using char_type = CHAR;
414  using traits_type = TRAITS;
415  using int_type = typename traits_type::int_type;
416  using pos_type = typename traits_type::pos_type;
417  using off_type = typename traits_type::off_type;
418  using openmode = std::ios::openmode;
419  using seekdir = std::ios::seekdir;
420 
421  explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
422 
423 protected:
424  virtual int sync() override { return traits_type::eof(); }
425 
427  {
428  return traits_type::eof();
429  }
430  virtual pos_type seekpos(pos_type, openmode) override
431  {
432  return traits_type::eof();
433  }
434  virtual int_type overflow(int_type) override { return traits_type::eof(); }
435  virtual int_type underflow() override { return traits_type::eof(); }
436 
437 private:
438  field const &m_field;
439 
440  int_type initialize()
441  {
442  auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
443  this->setg(g, g, g + std::size(m_field));
444  return int_type(std::size(m_field));
445  }
446 };
447 
448 
450 
463 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
464 class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
465 {
466  using super = std::basic_istream<CHAR, TRAITS>;
467 
468 public:
469  using char_type = CHAR;
470  using traits_type = TRAITS;
471  using int_type = typename traits_type::int_type;
472  using pos_type = typename traits_type::pos_type;
473  using off_type = typename traits_type::off_type;
474 
475  [[deprecated("Use field::as<...>() or field::c_str().")]] basic_fieldstream(
476  field const &f) :
477  super{nullptr}, m_buf{f}
478  {
479  super::init(&m_buf);
480  }
481 
482 private:
484 };
485 
486 
489 
490 
492 
516 template<typename CHAR>
517 [[deprecated(
518  "Do this by hand, probably with better error checking.")]] inline std::
519  basic_ostream<CHAR> &
520  operator<<(std::basic_ostream<CHAR> &s, field const &value)
521 {
522  s.write(value.c_str(), std::streamsize(std::size(value)));
523  return s;
524 }
525 
526 
528 
531 template<typename T> inline T from_string(field const &value)
532 {
533  if (value.is_null())
534  {
535  if constexpr (nullness<T>::has_null)
536  return nullness<T>::null();
537  else
538  internal::throw_null_conversion(type_name<T>);
539  }
540  else
541  {
542  return from_string<T>(value.view());
543  }
544 }
545 
546 
548 
554 template<>
555 inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
556 {
557  if (not value.is_null())
558  throw conversion_error{
559  "Extracting non-null field into nullptr_t variable."};
560  return nullptr;
561 }
562 
563 
565 template<> PQXX_LIBEXPORT std::string to_string(field const &value);
566 } // namespace pqxx
567 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:33
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
constexpr bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:513
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:520
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::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:566
T from_string(field const &value)
Convert a field's value to type T.
Definition: field.hxx:531
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
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:205
row_size_type m_col
Definition: field.hxx:289
array_parser as_array() const &noexcept
Parse the field as an SQL array.
Definition: field.hxx:251
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:189
constexpr O< T > get() const
Return value wrapped in some optional type (empty for nulls).
Definition: field.hxx:239
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:175
PQXX_PURE bool operator!=(field const &rhs) const noexcept
Byte-by-byte comparison (all nulls are considered equal)
Definition: field.hxx:65
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:219
field(result const &r, result_size_type row_num, row_size_type col_num) noexcept
Definition: field.hxx:279
constexpr row_size_type col() const noexcept
Definition: field.hxx:274
PQXX_PURE std::string_view view() const &
Read as string_view, or an empty one if null.
Definition: field.hxx:111
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition: field.hxx:161
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 result::size_type idx() const noexcept
Definition: field.hxx:273
Definition: field.hxx:411
TRAITS traits_type
Definition: field.hxx:414
typename traits_type::off_type off_type
Definition: field.hxx:417
field_streambuf(field const &f)
Definition: field.hxx:421
virtual pos_type seekoff(off_type, seekdir, openmode) override
Definition: field.hxx:426
virtual pos_type seekpos(pos_type, openmode) override
Definition: field.hxx:430
std::ios::openmode openmode
Definition: field.hxx:418
virtual int_type overflow(int_type) override
Definition: field.hxx:434
typename traits_type::pos_type pos_type
Definition: field.hxx:416
virtual int sync() override
Definition: field.hxx:424
typename traits_type::int_type int_type
Definition: field.hxx:415
virtual int_type underflow() override
Definition: field.hxx:435
CHAR char_type
Definition: field.hxx:413
std::ios::seekdir seekdir
Definition: field.hxx:419
Input stream that gets its data from a result field.
Definition: field.hxx:465
TRAITS traits_type
Definition: field.hxx:470
basic_fieldstream(field const &f)
Definition: field.hxx:475
typename traits_type::pos_type pos_type
Definition: field.hxx:472
typename traits_type::off_type off_type
Definition: field.hxx:473
typename traits_type::int_type int_type
Definition: field.hxx:471
CHAR char_type
Definition: field.hxx:469
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:91
static TYPE null()
Return a null value.
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:38