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 
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 
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 
88  [[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 
108 
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)
226  internal::throw_null_conversion(type_name<T>);
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 
260 protected:
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 
280 private:
281  result m_home;
282  result::size_type m_row;
283 };
284 
285 
286 template<> 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 
295 template<>
296 inline 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 
314 template<> 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 
323 template<> 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 
332 template<>
333 inline 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 
345 template<> 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 
354 template<>
355 inline std::string_view
356 field::as<std::string_view>(std::string_view const &default_value) const
357 {
358  return is_null() ? default_value : view();
359 }
360 
361 
362 template<> 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 
371 template<>
372 inline 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 
383 template<> 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 
392 template<> inline zview field::as<zview>(zview const &default_value) const
393 {
394  return is_null() ? default_value : zview{c_str(), size()};
395 }
396 
397 
398 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
399 class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
400 {
401 public:
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 
412 protected:
413  virtual int sync() override { return traits_type::eof(); }
414 
416  {
417  return traits_type::eof();
418  }
419  virtual pos_type seekpos(pos_type, openmode) override
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 
426 private:
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 
452 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
453 class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
454 {
455  using super = std::basic_istream<CHAR, TRAITS>;
456 
457 public:
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 
471 private:
472  field_streambuf<CHAR, TRAITS> m_buf;
473 };
474 
475 
478 
479 
481 
505 template<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 
520 template<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
527  internal::throw_null_conversion(type_name<T>);
528  }
529  else
530  {
531  return from_string<T>(value.view());
532  }
533 }
534 
535 
537 
543 template<>
544 inline 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 
554 template<> PQXX_LIBEXPORT std::string to_string(field const &value);
555 } // namespace pqxx
556 #endif
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition: field.hxx:163
Input stream that gets its data from a result field.
Definition: field.hxx:453
Result set containing data returned by a query or command.
Definition: result.hxx:72
T as(T const &default_value) const
Return value as object of given type, or default value if null.
Definition: field.hxx:207
typename traits_type::pos_type pos_type
Definition: field.hxx:461
constexpr result const & home() const noexcept
Definition: field.hxx:261
std::ios::seekdir seekdir
Definition: field.hxx:408
basic_fieldstream(field const &f)
Definition: field.hxx:464
result_size_type size_type
Definition: result.hxx:75
TRAITS traits_type
Definition: field.hxx:403
typename traits_type::pos_type pos_type
Definition: field.hxx:405
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
Low-level array parser.
Definition: array.hxx:526
typename traits_type::int_type int_type
Definition: field.hxx:404
Reference to a field in a result set.
Definition: field.hxx:34
constexpr row_size_type col() const noexcept
Definition: field.hxx:263
Reference to one row in a result.
Definition: row.hxx:46
field_size_type size_type
Definition: field.hxx:37
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:32
virtual pos_type seekoff(off_type, seekdir, openmode) override
Definition: field.hxx:415
int row_size_type
Number of fields in a row of database data.
Definition: types.hxx:34
int result_size_type
Number of rows in a result set.
Definition: types.hxx:28
virtual int_type overflow(int_type) override
Definition: field.hxx:423
PQXX_PURE std::string_view view() const &
Read as string_view, or an empty one if null.
Definition: field.hxx:113
Traits describing a type's "null value," if any.
Definition: strconv.hxx:92
typename traits_type::int_type int_type
Definition: field.hxx:460
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition: strconv.cxx:253
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:282
constexpr size_type size() const noexcept
Definition: row.hxx:104
STL namespace.
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:37
CHAR char_type
Definition: field.hxx:458
typename traits_type::off_type off_type
Definition: field.hxx:406
constexpr result::size_type idx() const noexcept
Definition: field.hxx:262
virtual int sync() override
Definition: field.hxx:413
row_size_type m_col
Definition: field.hxx:278
T from_string(field const &value)
Convert a field's value to type T.
Definition: field.hxx:520
std::ios::openmode openmode
Definition: field.hxx:407
field_streambuf(field const &f)
Definition: field.hxx:410
bool operator>>(T &obj) const
Read value into obj; or leave obj untouched and return false if null.
Definition: field.hxx:177
virtual int_type underflow() override
Definition: field.hxx:424
array_parser as_array() const &noexcept
Parse the field as an SQL array.
Definition: field.hxx:253
typename traits_type::off_type off_type
Definition: field.hxx:462
CHAR char_type
Definition: field.hxx:402
std::size_t field_size_type
Number of bytes in a field of database data.
Definition: types.hxx:40
static TYPE null()
Return a null value.
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
PQXX_PURE bool is_null() const noexcept
Is this field's value null?
Definition: field.cxx:71
PQXX_PURE char const * c_str() const &
Read as plain C string.
Definition: field.cxx:65
TRAITS traits_type
Definition: field.hxx:459
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:549
T as() const
Return value as object of given type, or throw exception if null.
Definition: field.hxx:221
constexpr bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:518
Definition: field.hxx:399
field(result const &r, result_size_type row_num, row_size_type col_num) noexcept
Definition: field.hxx:268
virtual pos_type seekpos(pos_type, openmode) override
Definition: field.hxx:419