libpqxx
The C++ client library for PostgreSQL
Loading...
Searching...
No Matches
result.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-2024, 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_RESULT
14#define PQXX_H_RESULT
15
16#if !defined(PQXX_HEADER_PRE)
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
18#endif
19
20#include <functional>
21#include <ios>
22#include <list>
23#include <memory>
24#include <stdexcept>
25
26#include "pqxx/except.hxx"
27#include "pqxx/types.hxx"
28#include "pqxx/util.hxx"
29#include "pqxx/zview.hxx"
30
31#include "pqxx/internal/encodings.hxx"
32
33
34namespace pqxx::internal
35{
36PQXX_LIBEXPORT void clear_result(pq::PGresult const *) noexcept;
37} // namespace pqxx::internal
38
39
40namespace pqxx::internal::gate
41{
42class result_connection;
43class result_creation;
44class result_pipeline;
45class result_row;
46class result_sql_cursor;
47} // namespace pqxx::internal::gate
48
49
50namespace pqxx::internal
51{
52// 9.0: Remove this, just use the notice handler in connection/result.
55{
56 std::function<void(zview)> notice_handler;
57 std::list<errorhandler *> errorhandlers;
58
59 notice_waiters() = default;
60 notice_waiters(notice_waiters const &) = delete;
61 notice_waiters(notice_waiters &&) = delete;
62 notice_waiters &operator=(notice_waiters const &) = delete;
63 notice_waiters &operator=(notice_waiters &&) = delete;
64};
65} // namespace pqxx::internal
66
67
68namespace pqxx
69{
71
91class PQXX_LIBEXPORT result
92{
93public:
94 using size_type = result_size_type;
95 using difference_type = result_difference_type;
96 using reference = row;
97 using const_iterator = const_result_iterator;
98 using pointer = const_iterator;
99 using iterator = const_iterator;
100 using const_reverse_iterator = const_reverse_result_iterator;
101 using reverse_iterator = const_reverse_iterator;
102
103 result() noexcept :
104 m_data{}, m_query{}, m_encoding{internal::encoding_group::MONOBYTE}
105 {}
106
107 result(result const &rhs) noexcept = default;
108 result(result &&rhs) noexcept = default;
109
111
114 result &operator=(result const &rhs) noexcept = default;
115
117 result &operator=(result &&rhs) noexcept = default;
118
128 [[nodiscard]] bool operator==(result const &) const noexcept;
130 [[nodiscard]] bool operator!=(result const &rhs) const noexcept
131 {
132 return not operator==(rhs);
133 }
135
137
143 template<typename... TYPE> auto iter() const;
144
145 [[nodiscard]] const_reverse_iterator rbegin() const;
146 [[nodiscard]] const_reverse_iterator crbegin() const;
147 [[nodiscard]] const_reverse_iterator rend() const;
148 [[nodiscard]] const_reverse_iterator crend() const;
149
150 [[nodiscard]] const_iterator begin() const noexcept;
151 [[nodiscard]] const_iterator cbegin() const noexcept;
152 [[nodiscard]] inline const_iterator end() const noexcept;
153 [[nodiscard]] inline const_iterator cend() const noexcept;
154
155 [[nodiscard]] reference front() const noexcept;
156 [[nodiscard]] reference back() const noexcept;
157
158 [[nodiscard]] PQXX_PURE size_type size() const noexcept;
159 [[nodiscard]] PQXX_PURE bool empty() const noexcept;
160 [[nodiscard]] size_type capacity() const noexcept { return size(); }
161
163
167 void swap(result &) noexcept;
168
170
174 [[nodiscard]] row operator[](size_type i) const noexcept;
175
176#if defined(PQXX_HAVE_MULTIDIM)
177 [[nodiscard]] field
178 operator[](size_type row_num, row_size_type col_num) const noexcept;
179#endif // PQXX_HAVE_MULTIDIM
180
182 row at(size_type) const;
183
185 field at(size_type, row_size_type) const;
186
188
195 void clear() noexcept
196 {
197 m_data.reset();
198 m_query = nullptr;
199 }
200
206 [[nodiscard]] PQXX_PURE row_size_type columns() const noexcept;
207
209 [[nodiscard]] row_size_type column_number(zview name) const;
210
212 [[nodiscard]] char const *column_name(row_size_type number) const &;
213
215
218 [[nodiscard]] int column_storage(row_size_type number) const;
219
221
231 [[nodiscard]] int column_type_modifier(row_size_type number) const noexcept;
232
234 [[nodiscard]] oid column_type(row_size_type col_num) const;
235
237 [[nodiscard]] oid column_type(zview col_name) const
238 {
239 return column_type(column_number(col_name));
240 }
241
243 [[nodiscard]] oid column_table(row_size_type col_num) const;
244
246 [[nodiscard]] oid column_table(zview col_name) const
247 {
248 return column_table(column_number(col_name));
249 }
250
252 [[nodiscard]] row_size_type table_column(row_size_type col_num) const;
253
255 [[nodiscard]] row_size_type table_column(zview col_name) const
256 {
257 return table_column(column_number(col_name));
258 }
260
262 [[nodiscard]] PQXX_PURE std::string const &query() const & noexcept;
263
265
268 [[nodiscard]] PQXX_PURE oid inserted_oid() const;
269
271
274 [[nodiscard]] PQXX_PURE size_type affected_rows() const;
275
276 // C++20: Concept like std::invocable, but without specifying param types.
278
315 template<typename CALLABLE> inline void for_each(CALLABLE &&func) const;
316
318
321 result expect_rows(size_type n) const
322 {
323 auto const sz{size()};
324 if (sz != n)
325 {
326 // TODO: See whether result contains a generated statement.
327 if (not m_query or m_query->empty())
329 "Expected ", n, " row(s) from query, got ", sz, ".")};
330 else
332 "Expected ", n, " row(s) from query '", *m_query, "', got ", sz,
333 ".")};
334 }
335 return *this;
336 }
337
339
342 row one_row() const;
343
345
350 std::optional<row> opt_row() const;
351
354 {
355 expect_rows(0);
356 return *this;
357 }
358
360
364 {
365 auto const actual{columns()};
366 if (actual != cols)
367 {
368 // TODO: See whether result contains a generated statement.
369 if (not m_query or m_query->empty())
371 "Expected 1 column from query, got ", actual, ".")};
372 else
374 "Expected 1 column from query '", *m_query, "', got ", actual, ".")};
375 }
376 return *this;
377 }
378
380
383 field one_field() const;
384
385private:
386 using data_pointer = std::shared_ptr<internal::pq::PGresult const>;
387
389 data_pointer m_data;
390
392 PQXX_PURE std::shared_ptr<std::string const> query_ptr() const noexcept
393 {
394 return m_query;
395 }
396
398 std::shared_ptr<std::string const> m_query;
399
401
405 std::shared_ptr<pqxx::internal::notice_waiters> m_notice_waiters;
406
407 internal::encoding_group m_encoding;
408
409 static std::string const s_empty_string;
410
411 friend class pqxx::field;
412 PQXX_PURE char const *
413 get_value(size_type row, row_size_type col) const noexcept;
414 PQXX_PURE bool get_is_null(size_type row, row_size_type col) const noexcept;
415 PQXX_PURE
416 field_size_type get_length(size_type, row_size_type) const noexcept;
417
419 result(
420 std::shared_ptr<internal::pq::PGresult> const &rhs,
421 std::shared_ptr<std::string> const &query,
422 std::shared_ptr<pqxx::internal::notice_waiters> const &waiters,
423 internal::encoding_group enc);
424
425 PQXX_PRIVATE void check_status(std::string_view desc = ""sv) const;
426
428 friend class pqxx::internal::gate::result_row;
429 bool operator!() const noexcept { return m_data.get() == nullptr; }
430 operator bool() const noexcept { return m_data.get() != nullptr; }
431
432 [[noreturn]] PQXX_PRIVATE PQXX_COLD void
433 throw_sql_error(std::string const &Err, std::string const &Query) const;
434 PQXX_PRIVATE PQXX_PURE int errorposition() const;
435 PQXX_PRIVATE std::string status_error() const;
436
438 PQXX_PURE char const *cmd_status() const noexcept;
439};
440} // namespace pqxx
441#endif
Definition result-connection.hxx:6
Definition result-creation.hxx:6
Definition result-pipeline.hxx:6
Definition result-sql_cursor.hxx:6
Result set containing data returned by a query or command.
Definition result.hxx:92
row_size_type table_column(zview col_name) const
What column in its table did this column come from?
Definition result.hxx:255
result & operator=(result &&rhs) noexcept=default
Assign one result to another, invaliding the old one.
oid column_table(row_size_type col_num) const
What table did this column come from?
bool operator!=(result const &rhs) const noexcept
Compare two results for inequality.
Definition result.hxx:130
void clear() noexcept
Let go of the result's data.
Definition result.hxx:195
row_size_type table_column(row_size_type col_num) const
What column in its table did this column come from?
result expect_columns(row_size_type cols) const
Expect that result consists of exactly cols columns.
Definition result.hxx:363
oid column_table(zview col_name) const
What table did this column come from?
Definition result.hxx:246
result & operator=(result const &rhs) noexcept=default
Assign one result to another.
result no_rows() const
Expect that result contains no rows. Return result for convenience.
Definition result.hxx:353
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
Query returned an unexpected number of rows.
Definition except.hxx:343
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
Internal items for libpqxx' own use. Do not use these yourself.
Definition encodings.cxx:33
std::string concat(TYPE... item)
Efficiently combine a bunch of items into one big string.
Definition concat.hxx:31
PQXX_LIBEXPORT void clear_result(pq::PGresult const *) noexcept
C++ wrapper for libpq's PQclear.
Definition result.cxx:42
The home of all libpqxx classes, functions, templates, etc.
Definition array.cxx:27
unsigned int oid
PostgreSQL database row identifier.
Definition libpq-forward.hxx:33
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
int result_difference_type
Difference between result sizes.
Definition types.hxx:31
Various callbacks waiting for a notice to come in.
Definition result.hxx:55