libpqxx
The C++ client library for PostgreSQL
result_iter.hxx
Go to the documentation of this file.
1 
9 #ifndef PQXX_INTERNAL_RESULT_ITER_HXX
10 #define PQXX_INTERNAL_RESULT_ITER_HXX
11 
12 #include <memory>
13 
15 #include "pqxx/strconv.hxx"
16 
17 namespace pqxx
18 {
19 class result;
20 } // namespace pqxx
21 
22 
23 namespace pqxx::internal
24 {
25 // TODO: Replace with generator?
26 // TODO: Separate type for `end()` iterator.
28 
30 template<typename... TYPE> class result_iter final
31 {
32 public:
33  using value_type = std::tuple<TYPE...>;
34 
36  result_iter() = default;
37  result_iter(result_iter const &) = delete;
38  result_iter(result_iter &&) = delete;
39  ~result_iter() = default;
40 
41  result_iter &operator=(result_iter const &) = delete;
43 
44  explicit result_iter(result const &home, sl loc = sl::current()) :
45  m_home{&home}, m_size{std::size(home)}
46  {
47  if (not std::empty(home))
48  read(loc);
49  }
50 
52  {
53  PQXX_ASSUME(m_home != nullptr);
54  PQXX_ASSUME(m_index <= m_size);
55  // TODO: Would be nice to get at least the result's creation location.
56  sl const loc{sl::current()};
57  ++m_index;
58  if (m_index >= m_size)
59  m_home = nullptr;
60  else if (m_home != nullptr) [[likely]]
61  read(loc);
62  return *this;
63  }
64 
66  bool operator==(result_iter const &rhs) const noexcept
67  {
68  return m_home == rhs.m_home;
69  }
70  bool operator!=(result_iter const &rhs) const noexcept
71  {
72  return not(*this == rhs);
73  }
74 
75  value_type const &operator*() const noexcept { return m_value; }
76 
77 private:
78  void read(sl loc) { (*m_home)[m_index].convert(m_value, loc); }
79 
80  result const *m_home{nullptr};
81  result::size_type m_index{0};
82  result::size_type m_size{0};
83  value_type m_value;
84 };
85 
86 
88 template<typename... TYPE> class result_iteration final
89 {
90 public:
91  using iterator = result_iter<TYPE...>;
92 
93  explicit result_iteration(result home) : m_home{std::move(home)}
94  {
95  m_home.expect_columns(sizeof...(TYPE));
96  }
97 
98  [[nodiscard]] iterator begin() const
99  {
100  if (std::empty(m_home))
101  return end();
102  else
103  return iterator{m_home};
104  }
105  [[nodiscard]] iterator end() const { return {}; }
106 
107 private:
108  // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
109  pqxx::result const m_home;
110 };
111 } // namespace pqxx::internal
112 
113 
114 template<typename... TYPE> inline auto pqxx::result::iter() const
115 {
116  return pqxx::internal::result_iteration<TYPE...>{*this};
117 }
118 
119 
120 // A for_each iteration of a result.
121 //
122 // This is a strange place to define an inline member function on result, but
123 // ordering of definitions leaves no better place for it.
124 template<typename CALLABLE>
125 inline void pqxx::result::for_each(CALLABLE &&func, sl loc) const
126 {
127  using args_tuple = internal::args_t<decltype(func)>;
128  constexpr auto sz{std::tuple_size_v<args_tuple>};
129  static_assert(
130  sz > 0,
131  "Callback for for_each must take parameters, one for each column in the "
132  "result.");
133 
134  auto const cols{this->columns()};
135  if (sz != cols)
136  throw usage_error{
137  std::format(
138  "Callback to for_each takes {} parameter(s), but result set has {} "
139  "field(s).",
140  sz, cols),
141  loc};
142 
144  for (auto const r : *this)
145  std::apply(
146  func, pqxx::internal::gate::row_ref_result{r}.as_tuple<pass_tuple>(loc));
147 }
148 #endif
Definition: row_ref-result.hxx:15
Iterator for looped unpacking of a result.
Definition: result_iter.hxx:31
result_iter()=default
Construct an "end" iterator.
value_type const & operator*() const noexcept
Definition: result_iter.hxx:75
result_iter & operator=(result_iter &&)=delete
bool operator==(result_iter const &rhs) const noexcept
Comparison only works for comparing to end().
Definition: result_iter.hxx:66
result_iter(result_iter &&)=delete
result_iter(result_iter const &)=delete
result_iter(result const &home, sl loc=sl::current())
Definition: result_iter.hxx:44
result_iter & operator=(result_iter const &)=delete
std::tuple< TYPE... > value_type
Definition: result_iter.hxx:33
result_iter & operator++()
Definition: result_iter.hxx:51
bool operator!=(result_iter const &rhs) const noexcept
Definition: result_iter.hxx:70
Iterator for implementing pqxx::result::iter().
Definition: result_iter.hxx:89
iterator end() const
Definition: result_iter.hxx:105
iterator begin() const
Definition: result_iter.hxx:98
result_iteration(result home)
Definition: result_iter.hxx:93
Result set containing data returned by a query or command.
Definition: result.hxx:101
void for_each(CALLABLE &&func, sl=sl::current()) const
Run func on each row, passing the row's fields as parameters.
Definition: result_iter.hxx:125
result_size_type size_type
Definition: result.hxx:103
result const & expect_columns(row_size_type cols, sl loc=sl::current()) const
Expect that result consists of exactly cols columns.
Definition: result.hxx:476
auto iter() const
Iterate rows, reading them directly into a tuple of "TYPE...".
Definition: result_iter.hxx:114
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:580
#define PQXX_ASSUME(condition)
Definition: header-pre.hxx:228
Private namespace for libpqxx's internal use; do not access.
Definition: connection.cxx:333
decltype(strip_types(std::declval< TYPES... >())) strip_types_t
Take a tuple type and apply std::remove_cvref_t to its component types.
Definition: util.hxx:612
decltype(args_f(std::declval< CALLABLE >())) args_t
A callable's parameter types, as a tuple.
Definition: util.hxx:598
The home of all libpqxx classes, functions, templates, etc.
Definition: array.cxx:26
std::source_location sl
Convenience alias for std::source_location. It's just too long.
Definition: types.hxx:38
format
Format code: is data text or binary?
Definition: types.hxx:121