libpqxx  7.6.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-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 "pqxx/compiler-public.hxx"
17 #include "pqxx/internal/compiler-internal-pre.hxx"
18 
19 #include <optional>
20 
21 #include "pqxx/array.hxx"
22 #include "pqxx/composite.hxx"
23 #include "pqxx/result.hxx"
24 #include "pqxx/strconv.hxx"
25 #include "pqxx/types.hxx"
26 
27 namespace pqxx
28 {
30 
33 class PQXX_LIBEXPORT field
34 {
35 public:
37 
39 
43  [[deprecated(
44  "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept;
45 
47  [[deprecated(
48  "Do not construct fields yourself. Get them from the row.")]] field() =
49  default;
50 
55 
72  [[nodiscard]] PQXX_PURE bool operator==(field const &) const;
73 
75 
77  [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const
78  {
79  return not operator==(rhs);
80  }
82 
87  [[nodiscard]] PQXX_PURE char const *name() const;
89 
91  [[nodiscard]] oid PQXX_PURE type() const;
92 
94  [[nodiscard]] PQXX_PURE oid table() const;
95 
97  PQXX_PURE row_size_type num() const { return col(); }
98 
100  [[nodiscard]] PQXX_PURE row_size_type table_column() const;
102 
107  [[nodiscard]] PQXX_PURE std::string_view view() const
109  {
110  return std::string_view(c_str(), size());
111  }
112 
114 
123  [[nodiscard]] PQXX_PURE char const *c_str() const;
124 
126  [[nodiscard]] PQXX_PURE bool is_null() const noexcept;
127 
129  [[nodiscard]] PQXX_PURE size_type size() const noexcept;
130 
132 
135  template<typename T>
136  auto to(T &obj) const -> typename std::enable_if_t<
137  (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
138  bool>
139  {
140  if (is_null())
141  {
142  return false;
143  }
144  else
145  {
146  auto const bytes{c_str()};
147  from_string(bytes, obj);
148  return true;
149  }
150  }
151 
153 
158  template<typename... T> bool composite_to(T &...fields) const
159  {
160  if (is_null())
161  {
162  return false;
163  }
164  else
165  {
166  parse_composite(m_home.m_encoding, view(), fields...);
167  return true;
168  }
169  }
170 
172  template<typename T> bool operator>>(T &obj) const { return to(obj); }
173 
175 
185  template<typename T>
186  auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<
187  (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
188  bool>
189  {
190  bool const null{is_null()};
191  if (null)
192  obj = default_value;
193  else
194  obj = from_string<T>(this->view());
195  return not null;
196  }
197 
199 
202  template<typename T> T as(T const &default_value) const
203  {
204  if (is_null())
205  return default_value;
206  else
207  return from_string<T>(this->view());
208  }
209 
211 
216  template<typename T> T as() const
217  {
218  if (is_null())
219  {
220  if constexpr (not nullness<T>::has_null)
221  PQXX_UNLIKELY
222  internal::throw_null_conversion(type_name<T>);
223  else return nullness<T>::null();
224  }
225  else
226  {
227  return from_string<T>(this->view());
228  }
229  }
230 
232 
235  template<typename T, template<typename> class O = std::optional>
236  constexpr O<T> get() const
237  {
238  return as<O<T>>();
239  }
240 
242 
249  {
250  return array_parser{c_str(), m_home.m_encoding};
251  }
253 
254 
255 protected:
256  result const &home() const noexcept { return m_home; }
257  result::size_type idx() const noexcept { return m_row; }
258  row_size_type col() const noexcept { return m_col; }
259 
265 
266 private:
267  result m_home;
268  result::size_type m_row;
269 };
270 
271 
272 template<> inline bool field::to<std::string>(std::string &obj) const
273 {
274  bool const null{is_null()};
275  if (not null)
276  obj = std::string{view()};
277  return not null;
278 }
279 
280 
281 template<>
282 inline bool field::to<std::string>(
283  std::string &obj, std::string const &default_value) const
284 {
285  bool const null{is_null()};
286  if (null)
287  obj = default_value;
288  else
289  obj = std::string{view()};
290  return not null;
291 }
292 
293 
295 
300 template<> inline bool field::to<char const *>(char const *&obj) const
301 {
302  bool const null{is_null()};
303  if (not null)
304  obj = c_str();
305  return not null;
306 }
307 
308 
309 template<> inline bool field::to<std::string_view>(std::string_view &obj) const
310 {
311  bool const null{is_null()};
312  if (not null)
313  obj = view();
314  return not null;
315 }
316 
317 
318 template<>
319 inline bool field::to<std::string_view>(
320  std::string_view &obj, std::string_view const &default_value) const
321 {
322  bool const null{is_null()};
323  if (null)
324  obj = default_value;
325  else
326  obj = view();
327  return not null;
328 }
329 
330 
331 template<> inline std::string_view field::as<std::string_view>() const
332 {
333  if (is_null())
334  PQXX_UNLIKELY
335  internal::throw_null_conversion(type_name<std::string_view>);
336  return view();
337 }
338 
339 
340 template<>
341 inline std::string_view
342 field::as<std::string_view>(std::string_view const &default_value) const
343 {
344  return is_null() ? default_value : view();
345 }
346 
347 
348 template<> inline bool field::to<zview>(zview &obj) const
349 {
350  bool const null{is_null()};
351  if (not null)
352  obj = zview{c_str(), size()};
353  return not null;
354 }
355 
356 
357 template<>
358 inline bool field::to<zview>(zview &obj, zview const &default_value) const
359 {
360  bool const null{is_null()};
361  if (null)
362  obj = default_value;
363  else
364  obj = zview{c_str(), size()};
365  return not null;
366 }
367 
368 
369 template<> inline zview field::as<zview>() const
370 {
371  if (is_null())
372  PQXX_UNLIKELY
373  internal::throw_null_conversion(type_name<zview>);
374  return zview{c_str(), size()};
375 }
376 
377 
378 template<> inline zview field::as<zview>(zview const &default_value) const
379 {
380  return is_null() ? default_value : zview{c_str(), size()};
381 }
382 
383 
384 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
385 class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
386 {
387 public:
388  using char_type = CHAR;
389  using traits_type = TRAITS;
390  using int_type = typename traits_type::int_type;
391  using pos_type = typename traits_type::pos_type;
392  using off_type = typename traits_type::off_type;
393  using openmode = std::ios::openmode;
394  using seekdir = std::ios::seekdir;
395 
396  explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
397 
398 protected:
399  virtual int sync() override { return traits_type::eof(); }
400 
402  {
403  return traits_type::eof();
404  }
405  virtual pos_type seekpos(pos_type, openmode) override
406  {
407  return traits_type::eof();
408  }
409  virtual int_type overflow(int_type) override { return traits_type::eof(); }
410  virtual int_type underflow() override { return traits_type::eof(); }
411 
412 private:
413  field const &m_field;
414 
415  int_type initialize()
416  {
417  auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
418  this->setg(g, g, g + std::size(m_field));
419  return int_type(std::size(m_field));
420  }
421 };
422 
423 
425 
433 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
434 class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
435 {
436  using super = std::basic_istream<CHAR, TRAITS>;
437 
438 public:
439  using char_type = CHAR;
440  using traits_type = TRAITS;
441  using int_type = typename traits_type::int_type;
442  using pos_type = typename traits_type::pos_type;
443  using off_type = typename traits_type::off_type;
444 
445  basic_fieldstream(field const &f) : super{nullptr}, m_buf{f}
446  {
447  super::init(&m_buf);
448  }
449 
450 private:
452 };
453 
455 
457 
477 template<typename CHAR>
478 inline std::basic_ostream<CHAR> &
479 operator<<(std::basic_ostream<CHAR> &s, field const &value)
480 {
481  s.write(value.c_str(), std::streamsize(std::size(value)));
482  return s;
483 }
484 
485 
487 
490 template<typename T> inline T from_string(field const &value)
491 {
492  if (value.is_null())
493  {
494  if constexpr (nullness<T>::has_null)
495  return nullness<T>::null();
496  else
497  PQXX_UNLIKELY
498  internal::throw_null_conversion(type_name<T>);
499  }
500  else
501  {
502  return from_string<T>(value.view());
503  }
504 }
505 
506 
508 
514 template<>
515 inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
516 {
517  if (not value.is_null())
518  throw conversion_error{
519  "Extracting non-null field into nullptr_t variable."};
520  return nullptr;
521 }
522 
523 
525 template<> PQXX_LIBEXPORT std::string to_string(field const &value);
526 } // namespace pqxx
527 
528 #include "pqxx/internal/compiler-internal-post.hxx"
529 #endif
CHAR char_type
Definition: field.hxx:439
PQXX_PURE char const * c_str() const
Read as plain C string.
Definition: field.cxx:60
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition: field.hxx:158
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:39
typename traits_type::off_type off_type
Definition: field.hxx:443
CHAR char_type
Definition: field.hxx:388
typename traits_type::pos_type pos_type
Definition: field.hxx:391
PQXX_PURE bool is_null() const noexcept
Is this field&#39;s value null?
Definition: field.cxx:66
virtual int sync() override
Definition: field.hxx:399
row_size_type col() const noexcept
Definition: field.hxx:258
std::size_t field_size_type
Number of bytes in a field of database data.
Definition: types.hxx:36
row_size_type m_col
Definition: field.hxx:264
T as(T const &default_value) const
Return value as object of given type, or default value if null.
Definition: field.hxx:202
virtual int_type underflow() override
Definition: field.hxx:410
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:507
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:33
array_parser as_array() const
Parse the field as an SQL array.
Definition: field.hxx:248
bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:357
TRAITS traits_type
Definition: field.hxx:389
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
int row_size_type
Number of fields in a row of database data.
Definition: types.hxx:30
field_size_type size_type
Definition: field.hxx:36
void throw_null_conversion(std::string const &type)
Definition: strconv.cxx:243
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:97
TRAITS traits_type
Definition: field.hxx:440
T from_string(field const &value)
Convert a field&#39;s value to type T.
Definition: field.hxx:490
typename traits_type::int_type int_type
Definition: field.hxx:390
typename traits_type::int_type int_type
Definition: field.hxx:441
std::ios::openmode openmode
Definition: field.hxx:393
Low-level array parser.
Definition: array.hxx:46
Reference to a field in a result set.
Definition: field.hxx:33
PQXX_PURE std::string_view view() const
Read as string_view, or an empty one if null.
Definition: field.hxx:108
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:178
static TYPE null()
Return a null value.
virtual pos_type seekpos(pos_type, openmode) override
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:186
PQXX_PURE bool operator!=(field const &rhs) const
Byte-by-byte comparison (all nulls are considered equal)
Definition: field.hxx:77
field_streambuf(field const &f)
Definition: field.hxx:396
bool operator>>(T &obj) const
Read value into obj; or leave obj untouched and return false if null.
Definition: field.hxx:172
Input stream that gets its data from a result field.
Definition: field.hxx:434
result const & home() const noexcept
Definition: field.hxx:256
Traits describing a type&#39;s "null value," if any.
Definition: strconv.hxx:90
result::size_type idx() const noexcept
Definition: field.hxx:257
virtual pos_type seekoff(off_type, seekdir, openmode) override
Definition: field.hxx:401
Reference to one row in a result.
Definition: row.hxx:45
typename traits_type::off_type off_type
Definition: field.hxx:392
T as() const
Return value as object of given type, or throw exception if null.
Definition: field.hxx:216
typename traits_type::pos_type pos_type
Definition: field.hxx:442
Definition: field.hxx:385
virtual int_type overflow(int_type) override
Definition: field.hxx:409
Result set containing data returned by a query or command.
Definition: result.hxx:70
basic_fieldstream(field const &f)
Definition: field.hxx:445
result_size_type size_type
Definition: result.hxx:73
std::ios::seekdir seekdir
Definition: field.hxx:394
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:136