libpqxx  7.7.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-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 #include <optional>
17 
18 #include "pqxx/array.hxx"
19 #include "pqxx/composite.hxx"
20 #include "pqxx/result.hxx"
21 #include "pqxx/strconv.hxx"
22 #include "pqxx/types.hxx"
23 
24 namespace pqxx
25 {
27 
30 class PQXX_LIBEXPORT field
31 {
32 public:
34 
36 
40  [[deprecated(
41  "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept;
42 
44  [[deprecated(
45  "Do not construct fields yourself. Get them from the row.")]] field() =
46  default;
47 
52 
69  [[nodiscard]] PQXX_PURE bool operator==(field const &) const;
70 
72 
74  [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const
75  {
76  return not operator==(rhs);
77  }
79 
84  [[nodiscard]] PQXX_PURE char const *name() const &;
86 
88  [[nodiscard]] oid PQXX_PURE type() const;
89 
91  [[nodiscard]] PQXX_PURE oid table() const;
92 
94  PQXX_PURE row_size_type num() const { return col(); }
95 
97  [[nodiscard]] PQXX_PURE row_size_type table_column() const;
99 
104  [[nodiscard]] PQXX_PURE std::string_view view() const &
106  {
107  return std::string_view(c_str(), size());
108  }
109 
111 
120  [[nodiscard]] PQXX_PURE char const *c_str() const &;
121 
123  [[nodiscard]] PQXX_PURE bool is_null() const noexcept;
124 
126  [[nodiscard]] PQXX_PURE size_type size() const noexcept;
127 
129 
132  template<typename T>
133  auto to(T &obj) const -> typename std::enable_if_t<
134  (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
135  bool>
136  {
137  if (is_null())
138  {
139  return false;
140  }
141  else
142  {
143  auto const bytes{c_str()};
144  from_string(bytes, obj);
145  return true;
146  }
147  }
148 
150 
155  template<typename... T> bool composite_to(T &...fields) const
156  {
157  if (is_null())
158  {
159  return false;
160  }
161  else
162  {
163  parse_composite(m_home.m_encoding, view(), fields...);
164  return true;
165  }
166  }
167 
169  template<typename T> bool operator>>(T &obj) const { return to(obj); }
170 
172 
182  template<typename T>
183  auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<
184  (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
185  bool>
186  {
187  bool const null{is_null()};
188  if (null)
189  obj = default_value;
190  else
191  obj = from_string<T>(this->view());
192  return not null;
193  }
194 
196 
199  template<typename T> T as(T const &default_value) const
200  {
201  if (is_null())
202  return default_value;
203  else
204  return from_string<T>(this->view());
205  }
206 
208 
213  template<typename T> T as() const
214  {
215  if (is_null())
216  {
217  if constexpr (not nullness<T>::has_null)
218  internal::throw_null_conversion(type_name<T>);
219  else
220  return nullness<T>::null();
221  }
222  else
223  {
224  return from_string<T>(this->view());
225  }
226  }
227 
229 
232  template<typename T, template<typename> class O = std::optional>
233  constexpr O<T> get() const
234  {
235  return as<O<T>>();
236  }
237 
239 
246  {
247  return array_parser{c_str(), m_home.m_encoding};
248  }
250 
251 
252 protected:
253  result const &home() const noexcept { return m_home; }
254  result::size_type idx() const noexcept { return m_row; }
255  row_size_type col() const noexcept { return m_col; }
256 
257  // TODO: Create gates.
258  friend class pqxx::result;
259  friend class pqxx::row;
260  field(result const &r, result_size_type row_num, row_size_type col_num) :
261  m_col{col_num}, m_home{r}, m_row{row_num}
262  {}
263 
269 
270 private:
271  result m_home;
272  result::size_type m_row;
273 };
274 
275 
276 template<> inline bool field::to<std::string>(std::string &obj) const
277 {
278  bool const null{is_null()};
279  if (not null)
280  obj = std::string{view()};
281  return not null;
282 }
283 
284 
285 template<>
286 inline bool field::to<std::string>(
287  std::string &obj, std::string const &default_value) const
288 {
289  bool const null{is_null()};
290  if (null)
291  obj = default_value;
292  else
293  obj = std::string{view()};
294  return not null;
295 }
296 
297 
299 
304 template<> inline bool field::to<char const *>(char const *&obj) const
305 {
306  bool const null{is_null()};
307  if (not null)
308  obj = c_str();
309  return not null;
310 }
311 
312 
313 template<> inline bool field::to<std::string_view>(std::string_view &obj) const
314 {
315  bool const null{is_null()};
316  if (not null)
317  obj = view();
318  return not null;
319 }
320 
321 
322 template<>
323 inline bool field::to<std::string_view>(
324  std::string_view &obj, std::string_view const &default_value) const
325 {
326  bool const null{is_null()};
327  if (null)
328  obj = default_value;
329  else
330  obj = view();
331  return not null;
332 }
333 
334 
335 template<> inline std::string_view field::as<std::string_view>() const
336 {
337  if (is_null())
338  PQXX_UNLIKELY
339  internal::throw_null_conversion(type_name<std::string_view>);
340  return view();
341 }
342 
343 
344 template<>
345 inline std::string_view
346 field::as<std::string_view>(std::string_view const &default_value) const
347 {
348  return is_null() ? default_value : view();
349 }
350 
351 
352 template<> inline bool field::to<zview>(zview &obj) const
353 {
354  bool const null{is_null()};
355  if (not null)
356  obj = zview{c_str(), size()};
357  return not null;
358 }
359 
360 
361 template<>
362 inline bool field::to<zview>(zview &obj, zview const &default_value) const
363 {
364  bool const null{is_null()};
365  if (null)
366  obj = default_value;
367  else
368  obj = zview{c_str(), size()};
369  return not null;
370 }
371 
372 
373 template<> inline zview field::as<zview>() const
374 {
375  if (is_null())
376  PQXX_UNLIKELY
377  internal::throw_null_conversion(type_name<zview>);
378  return zview{c_str(), size()};
379 }
380 
381 
382 template<> inline zview field::as<zview>(zview const &default_value) const
383 {
384  return is_null() ? default_value : zview{c_str(), size()};
385 }
386 
387 
388 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
389 class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
390 {
391 public:
392  using char_type = CHAR;
393  using traits_type = TRAITS;
394  using int_type = typename traits_type::int_type;
395  using pos_type = typename traits_type::pos_type;
396  using off_type = typename traits_type::off_type;
397  using openmode = std::ios::openmode;
398  using seekdir = std::ios::seekdir;
399 
400  explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
401 
402 protected:
403  virtual int sync() override { return traits_type::eof(); }
404 
406  {
407  return traits_type::eof();
408  }
409  virtual pos_type seekpos(pos_type, openmode) override
410  {
411  return traits_type::eof();
412  }
413  virtual int_type overflow(int_type) override { return traits_type::eof(); }
414  virtual int_type underflow() override { return traits_type::eof(); }
415 
416 private:
417  field const &m_field;
418 
419  int_type initialize()
420  {
421  auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
422  this->setg(g, g, g + std::size(m_field));
423  return int_type(std::size(m_field));
424  }
425 };
426 
427 
429 
437 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
438 class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
439 {
440  using super = std::basic_istream<CHAR, TRAITS>;
441 
442 public:
443  using char_type = CHAR;
444  using traits_type = TRAITS;
445  using int_type = typename traits_type::int_type;
446  using pos_type = typename traits_type::pos_type;
447  using off_type = typename traits_type::off_type;
448 
449  basic_fieldstream(field const &f) : super{nullptr}, m_buf{f}
450  {
451  super::init(&m_buf);
452  }
453 
454 private:
456 };
457 
459 
461 
481 template<typename CHAR>
482 inline std::basic_ostream<CHAR> &
483 operator<<(std::basic_ostream<CHAR> &s, field const &value)
484 {
485  s.write(value.c_str(), std::streamsize(std::size(value)));
486  return s;
487 }
488 
489 
491 
494 template<typename T> inline T from_string(field const &value)
495 {
496  if (value.is_null())
497  {
498  if constexpr (nullness<T>::has_null)
499  return nullness<T>::null();
500  else
501  internal::throw_null_conversion(type_name<T>);
502  }
503  else
504  {
505  return from_string<T>(value.view());
506  }
507 }
508 
509 
511 
517 template<>
518 inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
519 {
520  if (not value.is_null())
521  throw conversion_error{
522  "Extracting non-null field into nullptr_t variable."};
523  return nullptr;
524 }
525 
526 
528 template<> PQXX_LIBEXPORT std::string to_string(field const &value);
529 } // namespace pqxx
530 #endif
virtual int_type overflow(int_type) override
Definition: field.hxx:413
result const & home() const noexcept
Definition: field.hxx:253
int row_size_type
Number of fields in a row of database data.
Definition: types.hxx:30
size_type size() const noexcept
Definition: row.hxx:100
result::size_type idx() const noexcept
Definition: field.hxx:254
Reference to a field in a result set.
Definition: field.hxx:30
array_parser as_array() const &
Parse the field as an SQL array.
Definition: field.hxx:245
typename traits_type::int_type int_type
Definition: field.hxx:445
typename traits_type::off_type off_type
Definition: field.hxx:447
Result set containing data returned by a query or command.
Definition: result.hxx:67
row_size_type m_col
Definition: field.hxx:268
virtual pos_type seekpos(pos_type, openmode) override
Definition: field.hxx:409
bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:364
PQXX_PURE std::string_view view() const &
Read as string_view, or an empty one if null.
Definition: field.hxx:105
Input stream that gets its data from a result field.
Definition: field.hxx:438
static TYPE null()
Return a null value.
typename traits_type::pos_type pos_type
Definition: field.hxx:446
typename traits_type::off_type off_type
Definition: field.hxx:396
typename traits_type::pos_type pos_type
Definition: field.hxx:395
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition: field.hxx:155
CHAR char_type
Definition: field.hxx:392
bool operator>>(T &obj) const
Read value into obj; or leave obj untouched and return false if null.
Definition: field.hxx:169
TRAITS traits_type
Definition: field.hxx:393
TRAITS traits_type
Definition: field.hxx:444
PQXX_PURE char const * c_str() const &
Read as plain C string.
Definition: field.cxx:60
result_size_type size_type
Definition: result.hxx:70
PQXX_PURE row_size_type num() const
Return row number. The first row is row 0, the second is row 1, etc.
Definition: field.hxx:94
virtual int_type underflow() override
Definition: field.hxx:414
field_size_type size_type
Definition: field.hxx:33
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition: strconv.cxx:252
PQXX_PURE bool is_null() const noexcept
Is this field&#39;s value null?
Definition: field.cxx:66
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:31
row_size_type col() const noexcept
Definition: field.hxx:255
int result_size_type
Number of rows in a result set.
Definition: types.hxx:24
field(result const &r, result_size_type row_num, row_size_type col_num)
Definition: field.hxx:260
Low-level array parser.
Definition: array.hxx:43
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:37
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:175
std::size_t field_size_type
Number of bytes in a field of database data.
Definition: types.hxx:36
typename traits_type::int_type int_type
Definition: field.hxx:394
CHAR char_type
Definition: field.hxx:443
Traits describing a type&#39;s "null value," if any.
Definition: strconv.hxx:88
Definition: field.hxx:389
std::ios::seekdir seekdir
Definition: field.hxx:398
std::ios::openmode openmode
Definition: field.hxx:397
Reference to one row in a result.
Definition: row.hxx:42
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:22
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:528
virtual pos_type seekoff(off_type, seekdir, openmode) override
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:199
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:133
basic_fieldstream(field const &f)
Definition: field.hxx:449
T as() const
Return value as object of given type, or throw exception if null.
Definition: field.hxx:213
T from_string(field const &value)
Convert a field&#39;s value to type T.
Definition: field.hxx:494
virtual int sync() override
Definition: field.hxx:403
PQXX_PURE bool operator!=(field const &rhs) const
Byte-by-byte comparison (all nulls are considered equal)
Definition: field.hxx:74
field_streambuf(field const &f)
Definition: field.hxx:400
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:183