libpqxx
The C++ client library for PostgreSQL
cursor.hxx
Go to the documentation of this file.
1 /* Definition of the iterator/container-style cursor classes.
2  *
3  * C++-style wrappers for SQL cursors.
4  *
5  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead.
6  *
7  * Copyright (c) 2000-2026, 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_CURSOR_HXX
14 #define PQXX_CURSOR_HXX
15 
16 #if !defined(PQXX_HEADER_PRE)
17 # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
18 #endif
19 
20 #include <limits>
21 #include <stdexcept>
22 
23 #include "pqxx/result.hxx"
25 
26 
27 namespace pqxx
28 {
30 
42 {
43 public:
46 
48 
52  {
56  random_access
57  };
58 
60 
64  {
68  update
69  };
70 
72 
88  {
92  loose
93  };
94 
95  cursor_base() = delete;
96  cursor_base(cursor_base const &) = delete;
97  cursor_base(cursor_base &&) = delete;
98 
99  // Really weird: gcc complains that this accesses deprecated m_name.
101  ~cursor_base() = default;
103 
104  cursor_base &operator=(cursor_base const &) = delete;
106 
111 
113 
116  [[nodiscard]] static constexpr difference_type all() noexcept
117  {
118  return (std::numeric_limits<int>::max)() - 1;
119  }
120 
122 
124  [[nodiscard]] static constexpr difference_type next() noexcept { return 1; }
125 
127 
129  [[nodiscard]] static constexpr difference_type prior() noexcept
130  {
131  return -1;
132  }
133 
135 
137  [[nodiscard]] static constexpr difference_type backward_all() noexcept
138  {
139  return (std::numeric_limits<int>::min)() + 1;
140  }
141 
143 
145 
150  [[nodiscard]] constexpr std::string const &name() const noexcept
151  {
153  return m_name;
155  }
156 
157 protected:
158  cursor_base(
159  connection &, std::string_view Name, bool embellish_name = true,
160  sl loc = sl::current());
161 
163  [[nodiscard]] sl created_loc() const
164  {
166  return m_created_loc;
168  }
169 
170  // NOLINTBEGIN(
171  // cppcoreguidelines-non-private-member-variables-in-classes,
172  // misc-non-private-member-variables-in-classes
173  // )
174 
175  [[deprecated(
176  "This will become private. Use name() instead.")]] std::string const
178 
180  [[deprecated("This will become private. Use created_loc() instead.")]] sl
182 
183  // NOLINTEND(
184  // cppcoreguidelines-non-private-member-variables-in-classes,
185  // misc-non-private-member-variables-in-classes
186  // )
187 };
188 } // namespace pqxx
189 
190 
192 
193 
194 namespace pqxx
195 {
197 
203 template<cursor_base::update_policy up, cursor_base::ownership_policy op>
204 class stateless_cursor final
205 {
206 public:
209 
211 
220  transaction_base &tx, std::string_view query, std::string_view cname,
221  bool hold, sl loc = sl::current()) :
222  m_cur{tx, query, cname, cursor_base::random_access,
223  up, op, hold, loc}
224  {}
225 
227 
234  transaction_base &tx, std::string_view adopted_cursor,
235  sl loc = sl::current()) :
236  m_cur{tx, adopted_cursor, op}
237  {
238  // Put cursor in known position
239  m_cur.move(cursor_base::backward_all(), loc);
240  }
241 
244  ~stateless_cursor() = default;
245 
248 
250 
255  void close(sl loc = sl::current()) { m_cur.close(loc); }
256 
258 
261  [[nodiscard]] size_type size(sl loc = sl::current())
262  {
263  return internal::obtain_stateless_cursor_size(m_cur, loc);
264  }
265 
267 
279  difference_type begin_pos, difference_type end_pos, sl loc = sl::current())
280  {
282  m_cur, result::difference_type(size()), begin_pos, end_pos, loc);
283  }
284 
286  [[nodiscard]] constexpr std::string const &name() const noexcept
287  {
288  return m_cur.name();
289  }
290 
291 private:
292  internal::sql_cursor m_cur;
293 };
294 
295 
296 class icursor_iterator;
297 } // namespace pqxx
298 
299 
300 namespace pqxx::internal::gate
301 {
302 class icursor_iterator_icursorstream;
303 class icursorstream_icursor_iterator;
304 } // namespace pqxx::internal::gate
305 
306 
307 namespace pqxx
308 {
310 
326 {
327 public:
330 
332 
344  transaction_base &context, std::string_view query,
345  std::string_view basename, difference_type sstride = 1,
346  sl = sl::current());
347 
349 
374  transaction_base &context, field const &cname, difference_type sstride = 1,
375  cursor_base::ownership_policy op = cursor_base::owned, sl = sl::current());
376 
377  // NOLINTBEGIN(google-explicit-constructor,hicpp-explicit-conversions)
378 
380  constexpr operator bool() const & noexcept { return not m_done; }
381 
382  // NOLINTEND(google-explicit-constructor,hicpp-explicit-conversions)
383 
385 
393  icursorstream &get(result &res, sl loc = sl::current())
394  {
395  res = fetchblock(loc);
396  return *this;
397  }
399 
407  icursorstream &operator>>(result &res) { return get(res); }
408 
410 
416  icursorstream &ignore(std::streamsize n = 1, sl = sl::current()) &;
417 
419 
422  void set_stride(difference_type stride, sl = sl::current()) &;
423  [[nodiscard]] constexpr difference_type stride() const noexcept
424  {
425  return m_stride;
426  }
427 
429  [[nodiscard]] PQXX_PURE sl created_loc() const noexcept
430  {
431  return m_cur.created_loc();
432  }
433 
434 private:
435  result fetchblock(sl);
436 
438  size_type forward(size_type n = 1);
439  void insert_iterator(icursor_iterator *) noexcept;
440  void remove_iterator(icursor_iterator *) const noexcept;
441 
442  void service_iterators(difference_type, sl);
443 
444  internal::sql_cursor m_cur;
445 
446  mutable icursor_iterator *m_iterators = nullptr;
447 
448  difference_type m_stride;
449  difference_type m_realpos, m_reqpos;
450 
451  bool m_done = false;
452 };
453 
454 
456 
483 {
484 public:
485  using iterator_category = std::input_iterator_tag;
487  using pointer = result const *;
488  using reference = result const &;
492 
493  icursor_iterator() noexcept;
494  explicit icursor_iterator(istream_type &) noexcept;
495  icursor_iterator(icursor_iterator const &) noexcept;
497  ~icursor_iterator() noexcept;
498 
499  icursor_iterator &operator=(icursor_iterator &&) = delete;
500 
501  result const &operator*() const noexcept
502  {
503  refresh(created_loc());
504  return m_here;
505  }
506  PQXX_RETURNS_NONNULL result const *operator->() const noexcept
507  {
508  refresh(created_loc());
509  return &m_here;
510  }
511  icursor_iterator &operator++();
512  icursor_iterator operator++(int) &;
513  icursor_iterator &operator+=(difference_type);
514  icursor_iterator &operator=(icursor_iterator const &) noexcept;
515 
516  [[nodiscard]] bool operator==(icursor_iterator const &rhs) const;
517  [[nodiscard]] bool operator!=(icursor_iterator const &rhs) const noexcept
518  {
519  return not operator==(rhs);
520  }
521  [[nodiscard]] bool operator<(icursor_iterator const &rhs) const;
522  [[nodiscard]] bool operator>(icursor_iterator const &rhs) const
523  {
524  return rhs < *this;
525  }
526  [[nodiscard]] bool operator<=(icursor_iterator const &rhs) const
527  {
528  return not(*this > rhs);
529  }
530  [[nodiscard]] bool operator>=(icursor_iterator const &rhs) const
531  {
532  return not(*this < rhs);
533  }
534 
535 private:
536  void refresh(sl) const;
537 
539  [[nodiscard]] difference_type pos() const noexcept { return m_pos; }
540  void fill(result const &);
541 
543 
549  [[nodiscard]] PQXX_PURE sl created_loc(sl loc = sl::current()) const noexcept
550  {
551  return (m_stream == nullptr) ? loc : m_stream->created_loc();
552  }
553 
562  [[nodiscard]] sl
563  best_location(icursor_iterator const &other, sl loc = sl::current()) const
564  {
565  if (m_stream != nullptr)
566  return created_loc();
567  else
568  return other.created_loc(loc);
569  }
570 
571  icursorstream *m_stream{nullptr};
572  result m_here;
573  difference_type m_pos;
574 
575  icursor_iterator *m_prev{nullptr}, *m_next{nullptr};
576 };
577 } // namespace pqxx
578 #endif
Connection to a database.
Definition: connection.hxx:273
Common definitions for cursor types.
Definition: cursor.hxx:42
cursor_base & operator=(cursor_base const &)=delete
~cursor_base()=default
cursor_base(cursor_base &&)=delete
result_size_type size_type
Definition: cursor.hxx:44
constexpr std::string const & name() const noexcept
Name of underlying SQL cursor.
Definition: cursor.hxx:150
static constexpr difference_type next() noexcept
Special value: read one row only.
Definition: cursor.hxx:124
cursor_base(cursor_base const &)=delete
static constexpr difference_type all() noexcept
Special value: read until end.
Definition: cursor.hxx:116
static constexpr difference_type prior() noexcept
Special value: read backwards, one row only.
Definition: cursor.hxx:129
cursor_base & operator=(cursor_base &&)=delete
cursor_base()=delete
access_policy
Cursor access-pattern policy.
Definition: cursor.hxx:52
@ forward_only
Cursor can move forward only.
Definition: cursor.hxx:54
ownership_policy
Cursor destruction policy.
Definition: cursor.hxx:88
@ owned
Destroy SQL cursor when cursor object is closed at end of transaction.
Definition: cursor.hxx:90
update_policy
Cursor update policy.
Definition: cursor.hxx:64
@ read_only
Cursor can be used to read data but not to write.
Definition: cursor.hxx:66
result_difference_type difference_type
Definition: cursor.hxx:45
sl m_created_loc
The std::source_location for where this cursor was created.
Definition: cursor.hxx:181
sl created_loc() const
The std::source_location for where this cursor was created.
Definition: cursor.hxx:163
std::string const m_name
Definition: cursor.hxx:177
static constexpr difference_type backward_all() noexcept
Special value: read backwards from current position back to origin.
Definition: cursor.hxx:137
Reference to a field in a result set.
Definition: field.hxx:309
Approximate istream_iterator for icursorstream.
Definition: cursor.hxx:483
bool operator!=(icursor_iterator const &rhs) const noexcept
Definition: cursor.hxx:517
result const * pointer
Definition: cursor.hxx:487
bool operator>=(icursor_iterator const &rhs) const
Definition: cursor.hxx:530
bool operator>(icursor_iterator const &rhs) const
Definition: cursor.hxx:522
PQXX_RETURNS_NONNULL result const * operator->() const noexcept
Definition: cursor.hxx:506
result const & reference
Definition: cursor.hxx:488
istream_type::difference_type difference_type
Definition: cursor.hxx:491
std::input_iterator_tag iterator_category
Definition: cursor.hxx:485
bool operator<=(icursor_iterator const &rhs) const
Definition: cursor.hxx:526
istream_type::size_type size_type
Definition: cursor.hxx:490
Simple read-only cursor represented as a stream of results.
Definition: cursor.hxx:326
PQXX_PURE sl created_loc() const noexcept
The `std::source_location for where this stream was created.
Definition: cursor.hxx:429
cursor_base::size_type size_type
Definition: cursor.hxx:328
icursorstream & operator>>(result &res)
Read new value into given result object; same as get(result&).
Definition: cursor.hxx:407
cursor_base::difference_type difference_type
Definition: cursor.hxx:329
icursorstream & get(result &res, sl loc=sl::current())
Read new value into given result object; same as operator >>.
Definition: cursor.hxx:393
constexpr difference_type stride() const noexcept
Definition: cursor.hxx:423
Definition: icursor_iterator-icursorstream.hxx:10
Definition: icursorstream-icursor_iterator.hxx:10
Cursor with SQL positioning semantics.
Definition: sql_cursor.hxx:32
difference_type move(difference_type rows, difference_type &displacement, sl)
Definition: sql_cursor.cxx:286
void close(sl loc)
Definition: sql_cursor.cxx:194
Result set containing data returned by a query or command.
Definition: result.hxx:101
result_difference_type difference_type
Definition: result.hxx:104
"Stateless cursor" class: easy API for retrieving parts of result sets
Definition: cursor.hxx:205
void close(sl loc=sl::current())
Close this cursor.
Definition: cursor.hxx:255
result retrieve(difference_type begin_pos, difference_type end_pos, sl loc=sl::current())
Retrieve rows from begin_pos (inclusive) to end_pos (exclusive)
Definition: cursor.hxx:278
stateless_cursor & operator=(stateless_cursor const &)=delete
stateless_cursor(stateless_cursor const &)=delete
stateless_cursor(transaction_base &tx, std::string_view adopted_cursor, sl loc=sl::current())
Adopt an existing scrolling SQL cursor.
Definition: cursor.hxx:233
stateless_cursor(stateless_cursor &&)=default
size_type size(sl loc=sl::current())
Number of rows in cursor's result set.
Definition: cursor.hxx:261
result_size_type size_type
Definition: cursor.hxx:207
result_difference_type difference_type
Definition: cursor.hxx:208
constexpr std::string const & name() const noexcept
Return this cursor's name.
Definition: cursor.hxx:286
stateless_cursor(transaction_base &tx, std::string_view query, std::string_view cname, bool hold, sl loc=sl::current())
Create cursor.
Definition: cursor.hxx:219
stateless_cursor & operator=(stateless_cursor &&)=default
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:151
#define PQXX_LIBEXPORT
Definition: header-pre.hxx:206
#define PQXX_PURE
Definition: header-pre.hxx:64
#define PQXX_RETURNS_NONNULL
Definition: header-pre.hxx:119
Definition: connection.hxx:94
PQXX_LIBEXPORT result_size_type obtain_stateless_cursor_size(sql_cursor &, sl)
Definition: cursor.cxx:36
PQXX_LIBEXPORT result stateless_cursor_retrieve(sql_cursor &, result::difference_type size, result::difference_type begin_pos, result::difference_type end_pos, sl)
Definition: cursor.cxx:44
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
int result_difference_type
Difference between result sizes.
Definition: types.hxx:80
int result_size_type
Number of rows in a result set.
Definition: types.hxx:77
constexpr bool operator==(char const lhs[], pqxx::zview rhs) noexcept
Disambiguating comparison operator: leave it to std::string_view.
Definition: zview.hxx:203