libpqxx  7.7.3
row.hxx
1 /* Definitions for the pqxx::result class and support classes.
2  *
3  * pqxx::result represents the set of result rows from a database query.
4  *
5  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result 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_ROW
14 #define PQXX_H_ROW
15 
16 #if !defined(PQXX_HEADER_PRE)
17 # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
18 #endif
19 
20 #include "pqxx/except.hxx"
21 #include "pqxx/field.hxx"
22 #include "pqxx/result.hxx"
23 
24 #include "pqxx/internal/concat.hxx"
25 
26 namespace pqxx::internal
27 {
28 template<typename... T> class result_iter;
29 } // namespace pqxx::internal
30 
31 
32 namespace pqxx
33 {
35 
46 class PQXX_LIBEXPORT row
47 {
48 public:
53  using reference = field;
57 
58  row() noexcept = default;
59  row(row &&) noexcept = default;
60  row(row const &) noexcept = default;
61  row &operator=(row const &) noexcept = default;
62  row &operator=(row &&) noexcept = default;
63 
68  [[nodiscard]] PQXX_PURE bool operator==(row const &) const noexcept;
69  [[nodiscard]] bool operator!=(row const &rhs) const noexcept
70  {
71  return not operator==(rhs);
72  }
74 
75  [[nodiscard]] const_iterator begin() const noexcept;
76  [[nodiscard]] const_iterator cbegin() const noexcept;
77  [[nodiscard]] const_iterator end() const noexcept;
78  [[nodiscard]] const_iterator cend() const noexcept;
79 
84  [[nodiscard]] reference front() const noexcept;
85  [[nodiscard]] reference back() const noexcept;
86 
87  // TODO: noexcept. Breaks ABI.
88  [[nodiscard]] const_reverse_row_iterator rbegin() const;
89  // TODO: noexcept. Breaks ABI.
90  [[nodiscard]] const_reverse_row_iterator crbegin() const;
91  // TODO: noexcept. Breaks ABI.
92  [[nodiscard]] const_reverse_row_iterator rend() const;
93  // TODO: noexcept. Breaks ABI.
94  [[nodiscard]] const_reverse_row_iterator crend() const;
95 
96  [[nodiscard]] reference operator[](size_type) const noexcept;
100  [[nodiscard]] reference operator[](zview col_name) const;
101 
102  reference at(size_type) const;
106  reference at(zview col_name) const;
107 
108  [[nodiscard]] constexpr size_type size() const noexcept
109  {
110  return m_end - m_begin;
111  }
112 
113  [[deprecated("Swap iterators, not rows.")]] void swap(row &) noexcept;
114 
116  [[nodiscard]] constexpr result::size_type rownumber() const noexcept
117  {
118  return m_index;
119  }
120 
125  [[nodiscard]] size_type column_number(zview col_name) const;
127 
129  [[nodiscard]] oid column_type(size_type) const;
130 
132  [[nodiscard]] oid column_type(zview col_name) const
133  {
134  return column_type(column_number(col_name));
135  }
136 
138  [[nodiscard]] oid column_table(size_type col_num) const;
139 
141  [[nodiscard]] oid column_table(zview col_name) const
142  {
143  return column_table(column_number(col_name));
144  }
145 
147 
154  [[nodiscard]] size_type table_column(size_type) const;
155 
157  [[nodiscard]] size_type table_column(zview col_name) const
158  {
159  return table_column(column_number(col_name));
160  }
162 
163  [[nodiscard]] constexpr result::size_type num() const noexcept
164  {
165  return rownumber();
166  }
167 
179  [[deprecated("Row slicing is going away. File a bug if you need it.")]] row
180  slice(size_type sbegin, size_type send) const;
181 
183  [[nodiscard, deprecated("Row slicing is going away.")]] PQXX_PURE bool
184  empty() const noexcept;
185 
187 
189  template<typename Tuple> void to(Tuple &t) const
190  {
191  check_size(std::tuple_size_v<Tuple>);
192  convert(t);
193  }
194 
195  template<typename... TYPE> std::tuple<TYPE...> as() const
196  {
197  check_size(sizeof...(TYPE));
198  using seq = std::make_index_sequence<sizeof...(TYPE)>;
199  return get_tuple<std::tuple<TYPE...>>(seq{});
200  }
201 
202 protected:
203  friend class const_row_iterator;
204  friend class result;
205  row(result const &r, result_size_type index, size_type cols) noexcept;
206 
208  void check_size(size_type expected) const
209  {
210  if (size() != expected)
211  throw usage_error{internal::concat(
212  "Tried to extract ", expected, " field(s) from a row of ", size(),
213  ".")};
214  }
215 
217 
220  template<typename TUPLE> TUPLE as_tuple() const
221  {
222  using seq = std::make_index_sequence<std::tuple_size_v<TUPLE>>;
223  return get_tuple<TUPLE>(seq{});
224  }
225 
226  template<typename... T> friend class pqxx::internal::result_iter;
228  template<typename Tuple> void convert(Tuple &t) const
229  {
230  extract_fields(t, std::make_index_sequence<std::tuple_size_v<Tuple>>{});
231  }
232 
233  friend class field;
234 
237 
239 
243  result::size_type m_index = 0;
244 
245  // TODO: Remove m_begin and (if possible) m_end when we remove slice().
247  size_type m_begin = 0;
249  size_type m_end = 0;
250 
251 private:
252  template<typename Tuple, std::size_t... indexes>
253  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
254  {
255  (extract_value<Tuple, indexes>(t), ...);
256  }
257 
258  template<typename Tuple, std::size_t index>
259  void extract_value(Tuple &t) const;
260 
262  template<typename TUPLE, std::size_t... indexes>
263  auto get_tuple(std::index_sequence<indexes...>) const
264  {
265  return std::make_tuple(get_field<TUPLE, indexes>()...);
266  }
267 
269  template<typename TUPLE, std::size_t index> auto get_field() const
270  {
271  return (*this)[index].as<std::tuple_element_t<index, TUPLE>>();
272  }
273 };
274 
275 
277 class PQXX_LIBEXPORT const_row_iterator : public field
278 {
279 public:
280  using iterator_category = std::random_access_iterator_tag;
281  using value_type = field const;
282  using pointer = field const *;
285  using reference = field;
286 
287 #include "pqxx/internal/ignore-deprecated-pre.hxx"
288  const_row_iterator() = default;
289 #include "pqxx/internal/ignore-deprecated-post.hxx"
290  const_row_iterator(row const &t, row_size_type c) noexcept :
291  field{t.m_result, t.m_index, c}
292  {}
293  const_row_iterator(field const &F) noexcept : field{F} {}
294  const_row_iterator(const_row_iterator const &) noexcept = default;
295  const_row_iterator(const_row_iterator &&) noexcept = default;
296 
301  [[nodiscard]] constexpr pointer operator->() const noexcept { return this; }
302  [[nodiscard]] reference operator*() const noexcept { return {*this}; }
304 
309  const_row_iterator &operator=(const_row_iterator const &) noexcept = default;
310  const_row_iterator &operator=(const_row_iterator &&) noexcept = default;
311 
312  // TODO: noexcept. Breaks ABI.
313  const_row_iterator operator++(int);
315  {
316  ++m_col;
317  return *this;
318  }
319  // TODO: noexcept. Breaks ABI.
320  const_row_iterator operator--(int);
322  {
323  --m_col;
324  return *this;
325  }
326 
328  {
329  m_col = size_type(difference_type(m_col) + i);
330  return *this;
331  }
333  {
334  m_col = size_type(difference_type(m_col) - i);
335  return *this;
336  }
338 
343  [[nodiscard]] constexpr bool
344  operator==(const_row_iterator const &i) const noexcept
345  {
346  return col() == i.col();
347  }
348  [[nodiscard]] constexpr bool
349  operator!=(const_row_iterator const &i) const noexcept
350  {
351  return col() != i.col();
352  }
353  [[nodiscard]] constexpr bool
354  operator<(const_row_iterator const &i) const noexcept
355  {
356  return col() < i.col();
357  }
358  [[nodiscard]] constexpr bool
359  operator<=(const_row_iterator const &i) const noexcept
360  {
361  return col() <= i.col();
362  }
363  [[nodiscard]] constexpr bool
364  operator>(const_row_iterator const &i) const noexcept
365  {
366  return col() > i.col();
367  }
368  [[nodiscard]] constexpr bool
369  operator>=(const_row_iterator const &i) const noexcept
370  {
371  return col() >= i.col();
372  }
374 
379  [[nodiscard]] inline const_row_iterator
380  operator+(difference_type) const noexcept;
381 
382  friend const_row_iterator
383  operator+(difference_type, const_row_iterator const &) noexcept;
384 
385  [[nodiscard]] inline const_row_iterator
386  operator-(difference_type) const noexcept;
387  [[nodiscard]] inline difference_type
388  operator-(const_row_iterator const &) const noexcept;
390 };
391 
392 
394 class PQXX_LIBEXPORT const_reverse_row_iterator : private const_row_iterator
395 {
396 public:
404 
405  const_reverse_row_iterator() noexcept = default;
407  default;
409 
410  explicit const_reverse_row_iterator(super const &rhs) noexcept :
411  const_row_iterator{rhs}
412  {
413  super::operator--();
414  }
415 
416  [[nodiscard]] PQXX_PURE iterator_type base() const noexcept;
417 
422  using iterator_type::operator->;
423  using iterator_type::operator*;
425 
432  {
433  iterator_type::operator=(r);
434  return *this;
435  }
437  {
438  iterator_type::operator--();
439  return *this;
440  }
441  // TODO: noexcept. Breaks ABI.
442  const_reverse_row_iterator operator++(int);
444  {
445  iterator_type::operator++();
446  return *this;
447  }
448  const_reverse_row_iterator operator--(int);
449  // TODO: noexcept. Breaks ABI.
451  {
452  iterator_type::operator-=(i);
453  return *this;
454  }
456  {
457  iterator_type::operator+=(i);
458  return *this;
459  }
461 
466  [[nodiscard]] const_reverse_row_iterator
467  operator+(difference_type i) const noexcept
468  {
469  return const_reverse_row_iterator{base() - i};
470  }
471  [[nodiscard]] const_reverse_row_iterator
473  {
474  return const_reverse_row_iterator{base() + i};
475  }
476  [[nodiscard]] difference_type
477  operator-(const_reverse_row_iterator const &rhs) const noexcept
478  {
479  return rhs.const_row_iterator::operator-(*this);
480  }
482 
487  [[nodiscard]] bool
488  operator==(const_reverse_row_iterator const &rhs) const noexcept
489  {
490  return iterator_type::operator==(rhs);
491  }
492  [[nodiscard]] bool
493  operator!=(const_reverse_row_iterator const &rhs) const noexcept
494  {
495  return !operator==(rhs);
496  }
497 
498  [[nodiscard]] constexpr bool
499  operator<(const_reverse_row_iterator const &rhs) const noexcept
500  {
501  return iterator_type::operator>(rhs);
502  }
503  [[nodiscard]] constexpr bool
504  operator<=(const_reverse_row_iterator const &rhs) const noexcept
505  {
506  return iterator_type::operator>=(rhs);
507  }
508  [[nodiscard]] constexpr bool
509  operator>(const_reverse_row_iterator const &rhs) const noexcept
510  {
511  return iterator_type::operator<(rhs);
512  }
513  [[nodiscard]] constexpr bool
514  operator>=(const_reverse_row_iterator const &rhs) const noexcept
515  {
516  return iterator_type::operator<=(rhs);
517  }
519 };
520 
521 
524 {
525  // TODO:: More direct route to home().columns()?
526  return {
527  row{home(), idx(), home().columns()},
528  size_type(difference_type(col()) + o)};
529 }
530 
533 {
534  return i + o;
535 }
536 
537 inline const_row_iterator
539 {
540  // TODO:: More direct route to home().columns()?
541  return {
542  row{home(), idx(), home().columns()},
543  size_type(difference_type(col()) - o)};
544 }
545 
548 {
549  return difference_type(num() - i.num());
550 }
551 
552 
553 template<typename Tuple, std::size_t index>
554 inline void row::extract_value(Tuple &t) const
555 {
556  using field_type = strip_t<decltype(std::get<index>(t))>;
557  field const f{m_result, m_index, index};
558  std::get<index>(t) = from_string<field_type>(f);
559 }
560 } // namespace pqxx
561 #endif
bool operator==(const_reverse_row_iterator const &rhs) const noexcept
Definition: row.hxx:488
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
const_row_iterator & operator+=(difference_type i) noexcept
Definition: row.hxx:327
const_reverse_row_iterator & operator=(const_reverse_row_iterator const &r) noexcept
Definition: row.hxx:431
const_row_iterator & operator--() noexcept
Definition: row.hxx:321
Reference to one row in a result.
Definition: row.hxx:46
const_row_iterator & operator-=(difference_type i) noexcept
Definition: row.hxx:332
const_reverse_row_iterator & operator+=(difference_type i) noexcept
Definition: row.hxx:450
oid column_table(zview col_name) const
What table did this column come from?
Definition: row.hxx:141
constexpr size_type size() const noexcept
Definition: row.hxx:108
void convert(Tuple &t) const
Convert entire row to tuple fields, without checking row size.
Definition: row.hxx:228
std::tuple< TYPE... > as() const
Definition: row.hxx:195
field const value_type
Definition: row.hxx:281
const_reverse_row_iterator & operator--() noexcept
Definition: row.hxx:443
Reverse iterator for a row. Use as row::const_reverse_iterator.
Definition: row.hxx:394
constexpr bool operator!=(const_row_iterator const &i) const noexcept
Definition: row.hxx:349
Reference to a field in a result set.
Definition: field.hxx:34
Definition: row.hxx:28
const_row_iterator(row const &t, row_size_type c) noexcept
End a code block started by "ignore-deprecated-pre.hxx".
Definition: row.hxx:290
field const * pointer
Definition: row.hxx:282
int row_difference_type
Difference between row sizes.
Definition: types.hxx:37
field_size_type size_type
Definition: field.hxx:37
void check_size(size_type expected) const
Throw usage_error if row size is not expected.
Definition: row.hxx:208
TUPLE as_tuple() const
Convert to a given tuple of values, don&#39;t check sizes.
Definition: row.hxx:220
row_size_type size_type
Definition: row.hxx:49
const_row_iterator operator+(const_row_iterator::difference_type o, const_row_iterator const &i) noexcept
Definition: row.hxx:531
size_type table_column(zview col_name) const
What column number in its table did this result column come from?
Definition: row.hxx:157
const_reverse_row_iterator operator-(difference_type i) noexcept
Definition: row.hxx:472
int row_size_type
Number of fields in a row of database data.
Definition: types.hxx:34
std::random_access_iterator_tag iterator_category
Definition: row.hxx:280
row_difference_type difference_type
Definition: row.hxx:284
result m_result
Result set of which this is one row.
Definition: row.hxx:236
constexpr result::size_type rownumber() const noexcept
Row number, assuming this is a real row and not end()/rend().
Definition: row.hxx:116
const_reverse_row_iterator & operator-=(difference_type i) noexcept
Definition: row.hxx:455
constexpr pointer operator->() const noexcept
Definition: row.hxx:301
bool operator!=(const_reverse_row_iterator const &rhs) const noexcept
Definition: row.hxx:493
result_size_type size_type
Definition: result.hxx:76
const_row_iterator operator-(difference_type) const noexcept
Definition: row.hxx:538
const_reverse_row_iterator operator+(difference_type i) const noexcept
Definition: row.hxx:467
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:173
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: types.hxx:91
constexpr bool operator>(const_row_iterator const &i) const noexcept
Definition: row.hxx:364
constexpr row_size_type col() const noexcept
Definition: field.hxx:265
difference_type operator-(const_reverse_row_iterator const &rhs) const noexcept
Definition: row.hxx:477
const_row_iterator(field const &F) noexcept
Definition: row.hxx:293
oid column_type(zview col_name) const
Return a column&#39;s type.
Definition: row.hxx:132
Result set containing data returned by a query or command.
Definition: result.hxx:73
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:37
Internal items for libpqxx&#39; own use. Do not use these yourself.
Definition: composite.hxx:82
constexpr bool operator>(const_reverse_row_iterator const &rhs) const noexcept
Definition: row.hxx:509
constexpr bool operator>=(const_row_iterator const &i) const noexcept
Definition: row.hxx:369
const_row_iterator operator+(difference_type) const noexcept
Definition: row.hxx:523
reference operator*() const noexcept
Definition: row.hxx:302
Iterator for fields in a row. Use as row::const_iterator.
Definition: row.hxx:277
const_reverse_row_iterator operator++() noexcept
Definition: row.hxx:436
constexpr result::size_type num() const noexcept
Definition: row.hxx:163
void to(Tuple &t) const
Extract entire row&#39;s values into a tuple.
Definition: row.hxx:189
row_difference_type difference_type
Definition: row.hxx:50
const_row_iterator & operator++() noexcept
Definition: row.hxx:314
constexpr bool operator==(const_row_iterator const &i) const noexcept
Definition: row.hxx:344
int result_size_type
Number of rows in a result set.
Definition: types.hxx:28
constexpr bool operator>=(const_reverse_row_iterator const &rhs) const noexcept
Definition: row.hxx:514