Loading...
Searching...
No Matches
result.hxx
/* Definitions for the pqxx::result class and support classes.
*
* pqxx::result represents the set of result rows from a database query.
*
* DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.
*
* Copyright (c) 2000-2024, Jeroen T. Vermeulen.
*
* See COPYING for copyright license. If you did not receive a file called
* COPYING with this source code, please notify the distributor of this
* mistake, or contact the author.
*/
#ifndef PQXX_H_RESULT
#define PQXX_H_RESULT
#if !defined(PQXX_HEADER_PRE)
# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
#endif
#include <functional>
#include <ios>
#include <list>
#include <memory>
#include <stdexcept>
#include "pqxx/except.hxx"
#include "pqxx/types.hxx"
#include "pqxx/util.hxx"
#include "pqxx/zview.hxx"
#include "pqxx/internal/encodings.hxx"
namespace pqxx::internal
{
PQXX_LIBEXPORT void clear_result(pq::PGresult const *) noexcept;
} // namespace pqxx::internal
namespace pqxx::internal::gate
{
class result_connection;
class result_creation;
class result_pipeline;
class result_row;
class result_sql_cursor;
} // namespace pqxx::internal::gate
namespace pqxx::internal
{
// 9.0: Remove this, just use the notice handler in connection/result.
struct notice_waiters
{
std::function<void(zview)> notice_handler;
std::list<errorhandler *> errorhandlers;
notice_waiters() = default;
notice_waiters(notice_waiters const &) = delete;
notice_waiters(notice_waiters &&) = delete;
notice_waiters &operator=(notice_waiters const &) = delete;
notice_waiters &operator=(notice_waiters &&) = delete;
};
} // namespace pqxx::internal
namespace pqxx
{
class PQXX_LIBEXPORT result
{
public:
using size_type = result_size_type;
using difference_type = result_difference_type;
using reference = row;
using const_iterator = const_result_iterator;
using pointer = const_iterator;
using iterator = const_iterator;
using const_reverse_iterator = const_reverse_result_iterator;
using reverse_iterator = const_reverse_iterator;
result() noexcept :
m_data{}, m_query{}, m_encoding{internal::encoding_group::MONOBYTE}
{}
result(result const &rhs) noexcept = default;
result(result &&rhs) noexcept = default;
result &operator=(result const &rhs) noexcept = default;
result &operator=(result &&rhs) noexcept = default;
[[nodiscard]] bool operator==(result const &) const noexcept;
[[nodiscard]] bool operator!=(result const &rhs) const noexcept
{
return not operator==(rhs);
}
template<typename... TYPE> auto iter() const;
[[nodiscard]] const_reverse_iterator rbegin() const;
[[nodiscard]] const_reverse_iterator crbegin() const;
[[nodiscard]] const_reverse_iterator rend() const;
[[nodiscard]] const_reverse_iterator crend() const;
[[nodiscard]] const_iterator begin() const noexcept;
[[nodiscard]] const_iterator cbegin() const noexcept;
[[nodiscard]] inline const_iterator end() const noexcept;
[[nodiscard]] inline const_iterator cend() const noexcept;
[[nodiscard]] reference front() const noexcept;
[[nodiscard]] reference back() const noexcept;
[[nodiscard]] PQXX_PURE size_type size() const noexcept;
[[nodiscard]] PQXX_PURE bool empty() const noexcept;
[[nodiscard]] size_type capacity() const noexcept { return size(); }
void swap(result &) noexcept;
[[nodiscard]] row operator[](size_type i) const noexcept;
#if defined(PQXX_HAVE_MULTIDIM)
[[nodiscard]] field
operator[](size_type row_num, row_size_type col_num) const noexcept;
#endif // PQXX_HAVE_MULTIDIM
row at(size_type) const;
field at(size_type, row_size_type) const;
void clear() noexcept
{
m_data.reset();
m_query = nullptr;
}
[[nodiscard]] PQXX_PURE row_size_type columns() const noexcept;
[[nodiscard]] row_size_type column_number(zview name) const;
[[nodiscard]] char const *column_name(row_size_type number) const &;
[[nodiscard]] int column_storage(row_size_type number) const;
[[nodiscard]] int column_type_modifier(row_size_type number) const noexcept;
[[nodiscard]] oid column_type(row_size_type col_num) const;
[[nodiscard]] oid column_type(zview col_name) const
{
return column_type(column_number(col_name));
}
[[nodiscard]] oid column_table(row_size_type col_num) const;
[[nodiscard]] oid column_table(zview col_name) const
{
return column_table(column_number(col_name));
}
[[nodiscard]] row_size_type table_column(row_size_type col_num) const;
[[nodiscard]] row_size_type table_column(zview col_name) const
{
return table_column(column_number(col_name));
}
[[nodiscard]] PQXX_PURE std::string const &query() const & noexcept;
[[nodiscard]] PQXX_PURE oid inserted_oid() const;
[[nodiscard]] PQXX_PURE size_type affected_rows() const;
// C++20: Concept like std::invocable, but without specifying param types.
template<typename CALLABLE> inline void for_each(CALLABLE &&func) const;
result expect_rows(size_type n) const
{
auto const sz{size()};
if (sz != n)
{
// TODO: See whether result contains a generated statement.
if (not m_query or m_query->empty())
throw unexpected_rows{pqxx::internal::concat(
"Expected ", n, " row(s) from query, got ", sz, ".")};
else
throw unexpected_rows{pqxx::internal::concat(
"Expected ", n, " row(s) from query '", *m_query, "', got ", sz,
".")};
}
return *this;
}
row one_row() const;
std::optional<row> opt_row() const;
result no_rows() const
{
expect_rows(0);
return *this;
}
result expect_columns(row_size_type cols) const
{
auto const actual{columns()};
if (actual != cols)
{
// TODO: See whether result contains a generated statement.
if (not m_query or m_query->empty())
throw usage_error{pqxx::internal::concat(
"Expected 1 column from query, got ", actual, ".")};
else
throw usage_error{pqxx::internal::concat(
"Expected 1 column from query '", *m_query, "', got ", actual, ".")};
}
return *this;
}
field one_field() const;
private:
using data_pointer = std::shared_ptr<internal::pq::PGresult const>;
data_pointer m_data;
friend class pqxx::internal::gate::result_pipeline;
PQXX_PURE std::shared_ptr<std::string const> query_ptr() const noexcept
{
return m_query;
}
std::shared_ptr<std::string const> m_query;
std::shared_ptr<pqxx::internal::notice_waiters> m_notice_waiters;
internal::encoding_group m_encoding;
static std::string const s_empty_string;
friend class pqxx::field;
PQXX_PURE char const *
get_value(size_type row, row_size_type col) const noexcept;
PQXX_PURE bool get_is_null(size_type row, row_size_type col) const noexcept;
PQXX_PURE
field_size_type get_length(size_type, row_size_type) const noexcept;
friend class pqxx::internal::gate::result_creation;
result(
std::shared_ptr<internal::pq::PGresult> const &rhs,
std::shared_ptr<std::string> const &query,
std::shared_ptr<pqxx::internal::notice_waiters> const &waiters,
internal::encoding_group enc);
PQXX_PRIVATE void check_status(std::string_view desc = ""sv) const;
friend class pqxx::internal::gate::result_connection;
friend class pqxx::internal::gate::result_row;
bool operator!() const noexcept { return m_data.get() == nullptr; }
operator bool() const noexcept { return m_data.get() != nullptr; }
[[noreturn]] PQXX_PRIVATE PQXX_COLD void
throw_sql_error(std::string const &Err, std::string const &Query) const;
PQXX_PRIVATE PQXX_PURE int errorposition() const;
PQXX_PRIVATE std::string status_error() const;
friend class pqxx::internal::gate::result_sql_cursor;
PQXX_PURE char const *cmd_status() const noexcept;
};
} // namespace pqxx
#endif
pqxx::internal::gate::result_connection
Definition result-connection.hxx:6
pqxx::internal::gate::result_creation
Definition result-creation.hxx:6
pqxx::internal::gate::result_pipeline
Definition result-pipeline.hxx:6
pqxx::internal::gate::result_sql_cursor
Definition result-sql_cursor.hxx:6
pqxx::result::columns
PQXX_PURE row_size_type columns() const noexcept
Number of columns in result.
Definition result.cxx:507
pqxx::result::column_type
oid column_type(row_size_type col_num) const
Return column's type, as an OID from the system catalogue.
pqxx::result::table_column
row_size_type table_column(zview col_name) const
What column in its table did this column come from?
Definition result.hxx:255
pqxx::result::operator=
result & operator=(result &&rhs) noexcept=default
Assign one result to another, invaliding the old one.
pqxx::result::operator==
bool operator==(result const &) const noexcept
Compare two results for equality.
Definition result.cxx:63
pqxx::result::column_table
oid column_table(row_size_type col_num) const
What table did this column come from?
pqxx::result::operator!=
bool operator!=(result const &rhs) const noexcept
Compare two results for inequality.
Definition result.hxx:130
pqxx::result::expect_rows
result expect_rows(size_type n) const
Check that result contains exactly n rows.
Definition result.hxx:321
pqxx::result::clear
void clear() noexcept
Let go of the result's data.
Definition result.hxx:195
pqxx::result::table_column
row_size_type table_column(row_size_type col_num) const
What column in its table did this column come from?
pqxx::result::column_number
row_size_type column_number(zview name) const
Number of given column (throws exception if it doesn't exist).
Definition result.cxx:427
pqxx::result::expect_columns
result expect_columns(row_size_type cols) const
Expect that result consists of exactly cols columns.
Definition result.hxx:363
pqxx::result::column_table
oid column_table(zview col_name) const
What table did this column come from?
Definition result.hxx:246
pqxx::result::operator=
result & operator=(result const &rhs) noexcept=default
Assign one result to another.
pqxx::result::no_rows
result no_rows() const
Expect that result contains no rows. Return result for convenience.
Definition result.hxx:353
pqxx::zview
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
pqxx::unexpected_rows
Query returned an unexpected number of rows.
Definition except.hxx:343
pqxx::usage_error
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
pqxx::internal
Internal items for libpqxx' own use. Do not use these yourself.
Definition encodings.cxx:33
pqxx::internal::concat
std::string concat(TYPE... item)
Efficiently combine a bunch of items into one big string.
Definition concat.hxx:31
pqxx::internal::clear_result
PQXX_LIBEXPORT void clear_result(pq::PGresult const *) noexcept
C++ wrapper for libpq's PQclear.
Definition result.cxx:42
pqxx
The home of all libpqxx classes, functions, templates, etc.
Definition array.cxx:27
pqxx::oid
unsigned int oid
PostgreSQL database row identifier.
Definition libpq-forward.hxx:33
pqxx::result_size_type
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
pqxx::row_size_type
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
pqxx::result_difference_type
int result_difference_type
Difference between result sizes.
Definition types.hxx:31