libpqxx  7.7.4
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-2022, 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 
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 
56  // TODO: noexcept. Breaks ABI.
58 
74  [[nodiscard]] PQXX_PURE bool operator==(field const &) const;
75 
77 
79  [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept
80  {
81  return not operator==(rhs);
82  }
84 
89  [[nodiscard]] PQXX_PURE char const *name() const &;
91 
93  [[nodiscard]] oid PQXX_PURE type() const;
94 
96  [[nodiscard]] PQXX_PURE oid table() const;
97 
99  PQXX_PURE constexpr row_size_type num() const noexcept { return col(); }
100 
102  [[nodiscard]] PQXX_PURE row_size_type table_column() const;
104 
109 
114  [[nodiscard]] PQXX_PURE std::string_view view() const &
115  {
116  return std::string_view(c_str(), size());
117  }
118 
120 
129  [[nodiscard]] PQXX_PURE char const *c_str() const &;
130 
132  [[nodiscard]] PQXX_PURE bool is_null() const noexcept;
133 
135  [[nodiscard]] PQXX_PURE size_type size() const noexcept;
136 
138 
141  template<typename T>
142  auto to(T &obj) const -> typename std::enable_if_t<
143  (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
144  bool>
145  {
146  if (is_null())
147  {
148  return false;
149  }
150  else
151  {
152  auto const bytes{c_str()};
153  from_string(bytes, obj);
154  return true;
155  }
156  }
157 
159 
164  template<typename... T> bool composite_to(T &...fields) const
165  {
166  if (is_null())
167  {
168  return false;
169  }
170  else
171  {
172  parse_composite(m_home.m_encoding, view(), fields...);
173  return true;
174  }
175  }
176 
178  template<typename T> bool operator>>(T &obj) const { return to(obj); }
179 
181 
191  template<typename T>
192  auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<
193  (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
194  bool>
195  {
196  bool const null{is_null()};
197  if (null)
198  obj = default_value;
199  else
200  obj = from_string<T>(this->view());
201  return not null;
202  }
203 
205 
208  template<typename T> T as(T const &default_value) const
209  {
210  if (is_null())
211  return default_value;
212  else
213  return from_string<T>(this->view());
214  }
215 
217 
222  template<typename T> T as() const
223  {
224  if (is_null())
225  {
226  if constexpr (not nullness<T>::has_null)
227  internal::throw_null_conversion(type_name<T>);
228  else
229  return nullness<T>::null();
230  }
231  else
232  {
233  return from_string<T>(this->view());
234  }
235  }
236 
238 
241  template<typename T, template<typename> class O = std::optional>
242  constexpr O<T> get() const
243  {
244  return as<O<T>>();
245  }
246 
247  // TODO: constexpr noexcept, once array_parser constructor gets those.
249 
256  {
257  return array_parser{c_str(), m_home.m_encoding};
258  }
260 
261 
262 protected:
263  constexpr result const &home() const noexcept { return m_home; }
264  constexpr result::size_type idx() const noexcept { return m_row; }
265  constexpr row_size_type col() const noexcept { return m_col; }
266 
267  // TODO: Create gates.
268  friend class pqxx::result;
269  friend class pqxx::row;
271  result const &r, result_size_type row_num, row_size_type col_num) noexcept
272  :
273  m_col{col_num}, m_home{r}, m_row{row_num}
274  {}
275 
281 
282 private:
283  result m_home;
284  result::size_type m_row;
285 };
286 
287 
288 template<> inline bool field::to<std::string>(std::string &obj) const
289 {
290  bool const null{is_null()};
291  if (not null)
292  obj = std::string{view()};
293  return not null;
294 }
295 
296 
297 template<>
298 inline bool field::to<std::string>(
299  std::string &obj, std::string const &default_value) const
300 {
301  bool const null{is_null()};
302  if (null)
303  obj = default_value;
304  else
305  obj = std::string{view()};
306  return not null;
307 }
308 
309 
311 
316 template<> inline bool field::to<char const *>(char const *&obj) const
317 {
318  bool const null{is_null()};
319  if (not null)
320  obj = c_str();
321  return not null;
322 }
323 
324 
325 template<> inline bool field::to<std::string_view>(std::string_view &obj) const
326 {
327  bool const null{is_null()};
328  if (not null)
329  obj = view();
330  return not null;
331 }
332 
333 
334 template<>
335 inline bool field::to<std::string_view>(
336  std::string_view &obj, std::string_view const &default_value) const
337 {
338  bool const null{is_null()};
339  if (null)
340  obj = default_value;
341  else
342  obj = view();
343  return not null;
344 }
345 
346 
347 template<> inline std::string_view field::as<std::string_view>() const
348 {
349  if (is_null())
350  PQXX_UNLIKELY
351  internal::throw_null_conversion(type_name<std::string_view>);
352  return view();
353 }
354 
355 
356 template<>
357 inline std::string_view
358 field::as<std::string_view>(std::string_view const &default_value) const
359 {
360  return is_null() ? default_value : view();
361 }
362 
363 
364 template<> inline bool field::to<zview>(zview &obj) const
365 {
366  bool const null{is_null()};
367  if (not null)
368  obj = zview{c_str(), size()};
369  return not null;
370 }
371 
372 
373 template<>
374 inline bool field::to<zview>(zview &obj, zview const &default_value) const
375 {
376  bool const null{is_null()};
377  if (null)
378  obj = default_value;
379  else
380  obj = zview{c_str(), size()};
381  return not null;
382 }
383 
384 
385 template<> inline zview field::as<zview>() const
386 {
387  if (is_null())
388  PQXX_UNLIKELY
389  internal::throw_null_conversion(type_name<zview>);
390  return zview{c_str(), size()};
391 }
392 
393 
394 template<> inline zview field::as<zview>(zview const &default_value) const
395 {
396  return is_null() ? default_value : zview{c_str(), size()};
397 }
398 
399 
400 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
401 class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
402 {
403 public:
404  using char_type = CHAR;
405  using traits_type = TRAITS;
406  using int_type = typename traits_type::int_type;
407  using pos_type = typename traits_type::pos_type;
408  using off_type = typename traits_type::off_type;
409  using openmode = std::ios::openmode;
410  using seekdir = std::ios::seekdir;
411 
412  explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
413 
414 protected:
415  virtual int sync() override { return traits_type::eof(); }
416 
418  {
419  return traits_type::eof();
420  }
421  virtual pos_type seekpos(pos_type, openmode) override
422  {
423  return traits_type::eof();
424  }
425  virtual int_type overflow(int_type) override { return traits_type::eof(); }
426  virtual int_type underflow() override { return traits_type::eof(); }
427 
428 private:
429  field const &m_field;
430 
431  int_type initialize()
432  {
433  auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
434  this->setg(g, g, g + std::size(m_field));
435  return int_type(std::size(m_field));
436  }
437 };
438 
439 
441 
449 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
450 class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
451 {
452  using super = std::basic_istream<CHAR, TRAITS>;
453 
454 public:
455  using char_type = CHAR;
456  using traits_type = TRAITS;
457  using int_type = typename traits_type::int_type;
458  using pos_type = typename traits_type::pos_type;
459  using off_type = typename traits_type::off_type;
460 
461  basic_fieldstream(field const &f) : super{nullptr}, m_buf{f}
462  {
463  super::init(&m_buf);
464  }
465 
466 private:
468 };
469 
471 
473 
493 template<typename CHAR>
494 inline std::basic_ostream<CHAR> &
495 operator<<(std::basic_ostream<CHAR> &s, field const &value)
496 {
497  s.write(value.c_str(), std::streamsize(std::size(value)));
498  return s;
499 }
500 
501 
503 
506 template<typename T> inline T from_string(field const &value)
507 {
508  if (value.is_null())
509  {
510  if constexpr (nullness<T>::has_null)
511  return nullness<T>::null();
512  else
513  internal::throw_null_conversion(type_name<T>);
514  }
515  else
516  {
517  return from_string<T>(value.view());
518  }
519 }
520 
521 
523 
529 template<>
530 inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
531 {
532  if (not value.is_null())
533  throw conversion_error{
534  "Extracting non-null field into nullptr_t variable."};
535  return nullptr;
536 }
537 
538 
540 template<> PQXX_LIBEXPORT std::string to_string(field const &value);
541 } // namespace pqxx
542 #endif
T as() const
Return value as object of given type, or throw exception if null.
Definition: field.hxx:222
Low-level array parser.
Definition: array.hxx:47
TRAITS traits_type
Definition: field.hxx:405
T as(T const &default_value) const
Return value as object of given type, or default value if null.
Definition: field.hxx:208
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
Definition: field.hxx:401
std::ios::openmode openmode
Definition: field.hxx:409
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
Reference to one row in a result.
Definition: row.hxx:46
constexpr size_type size() const noexcept
Definition: row.hxx:108
PQXX_PURE bool is_null() const noexcept
Is this field&#39;s value null?
Definition: field.cxx:71
virtual pos_type seekoff(off_type, seekdir, openmode) override
Definition: field.hxx:417
TRAITS traits_type
Definition: field.hxx:456
Reference to a field in a result set.
Definition: field.hxx:34
std::size_t field_size_type
Number of bytes in a field of database data.
Definition: types.hxx:40
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:533
field(result const &r, result_size_type row_num, row_size_type col_num) noexcept
Definition: field.hxx:270
field_size_type size_type
Definition: field.hxx:37
typename traits_type::int_type int_type
Definition: field.hxx:457
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition: field.hxx:164
typename traits_type::off_type off_type
Definition: field.hxx:459
bool operator>>(T &obj) const
Read value into obj; or leave obj untouched and return false if null.
Definition: field.hxx:178
T from_string(field const &value)
Convert a field&#39;s value to type T.
Definition: field.hxx:506
PQXX_PURE std::string_view view() const &
Read as string_view, or an empty one if null.
Definition: field.hxx:114
virtual pos_type seekpos(pos_type, openmode) override
Definition: field.hxx:421
int row_size_type
Number of fields in a row of database data.
Definition: types.hxx:34
typename traits_type::pos_type pos_type
Definition: field.hxx:458
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition: strconv.cxx:253
auto to(T &obj) 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, leave obj untouched and return false.
Definition: field.hxx:142
std::ios::seekdir seekdir
Definition: field.hxx:410
typename traits_type::off_type off_type
Definition: field.hxx:408
typename traits_type::pos_type pos_type
Definition: field.hxx:407
PQXX_PURE char const * c_str() const &
Read as plain C string.
Definition: field.cxx:65
result_size_type size_type
Definition: result.hxx:76
constexpr result::size_type idx() const noexcept
Definition: field.hxx:264
CHAR char_type
Definition: field.hxx:404
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:192
virtual int sync() override
Definition: field.hxx:415
array_parser as_array() const &
Parse the field as an SQL array.
Definition: field.hxx:255
constexpr row_size_type col() const noexcept
Definition: field.hxx:265
constexpr result const & home() const noexcept
Definition: field.hxx:263
virtual int_type underflow() override
Definition: field.hxx:426
Result set containing data returned by a query or command.
Definition: result.hxx:73
field_streambuf(field const &f)
Definition: field.hxx:412
basic_fieldstream(field const &f)
Definition: field.hxx:461
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:37
virtual int_type overflow(int_type) override
Definition: field.hxx:425
row_size_type m_col
Definition: field.hxx:280
static TYPE null()
Return a null value.
Input stream that gets its data from a result field.
Definition: field.hxx:450
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:187
PQXX_PURE constexpr row_size_type num() const noexcept
Return row number. The first row is row 0, the second is row 1, etc.
Definition: field.hxx:99
Traits describing a type&#39;s "null value," if any.
Definition: strconv.hxx:92
int result_size_type
Number of rows in a result set.
Definition: types.hxx:28
typename traits_type::int_type int_type
Definition: field.hxx:406
constexpr bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:370
CHAR char_type
Definition: field.hxx:455