field.hxx
/* Definitions for the pqxx::field class.
*
* pqxx::field refers to a field in a query result.
*
* DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.
*
* Copyright (c) 2000-2023, 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_FIELD
#define PQXX_H_FIELD
#if !defined(PQXX_HEADER_PRE)
# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
#endif
#include <optional>
#include "pqxx/array.hxx"
#include "pqxx/composite.hxx"
#include "pqxx/result.hxx"
#include "pqxx/strconv.hxx"
#include "pqxx/types.hxx"
namespace pqxx
{
class PQXX_LIBEXPORT field
{
public:
using size_type = field_size_type;
[[deprecated(
"Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept;
[[deprecated(
"Do not construct fields yourself. Get them from the "
"row.")]] field() noexcept = default;
[[nodiscard]] PQXX_PURE bool operator==(field const &) const noexcept;
[[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept
{
return not operator==(rhs);
}
[[nodiscard]] PQXX_PURE char const *name() const &;
[[nodiscard]] oid PQXX_PURE type() const;
[[nodiscard]] PQXX_PURE oid table() const;
PQXX_PURE constexpr row_size_type num() const noexcept { return col(); }
[[nodiscard]] PQXX_PURE row_size_type table_column() const;
[[nodiscard]] PQXX_PURE std::string_view view() const &
{
return std::string_view(c_str(), size());
}
[[nodiscard]] PQXX_PURE char const *c_str() const &;
[[nodiscard]] PQXX_PURE bool is_null() const noexcept;
[[nodiscard]] PQXX_PURE size_type size() const noexcept;
template<typename T>
auto to(T &obj) const -> typename std::enable_if_t<
(not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
bool>
{
if (is_null())
{
return false;
}
else
{
auto const bytes{c_str()};
from_string(bytes, obj);
return true;
}
}
template<typename... T> bool composite_to(T &...fields) const
{
if (is_null())
{
return false;
}
else
{
parse_composite(m_home.m_encoding, view(), fields...);
return true;
}
}
template<typename T> bool operator>>(T &obj) const { return to(obj); }
template<typename T>
auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<
(not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
bool>
{
bool const null{is_null()};
if (null)
obj = default_value;
else
obj = from_string<T>(this->view());
return not null;
}
template<typename T> T as(T const &default_value) const
{
if (is_null())
return default_value;
else
return from_string<T>(this->view());
}
template<typename T> T as() const
{
if (is_null())
{
if constexpr (not nullness<T>::has_null)
internal::throw_null_conversion(type_name<T>);
else
return nullness<T>::null();
}
else
{
return from_string<T>(this->view());
}
}
template<typename T, template<typename> class O = std::optional>
constexpr O<T> get() const
{
return as<O<T>>();
}
array_parser as_array() const &noexcept
{
return array_parser{c_str(), m_home.m_encoding};
}
protected:
constexpr result const &home() const noexcept { return m_home; }
constexpr result::size_type idx() const noexcept { return m_row; }
constexpr row_size_type col() const noexcept { return m_col; }
// TODO: Create gates.
friend class pqxx::result;
friend class pqxx::row;
field(
result const &r, result_size_type row_num, row_size_type col_num) noexcept
:
m_col{col_num}, m_home{r}, m_row{row_num}
{}
row_size_type m_col;
private:
result m_home;
result::size_type m_row;
};
template<> inline bool field::to<std::string>(std::string &obj) const
{
bool const null{is_null()};
if (not null)
obj = std::string{view()};
return not null;
}
template<>
inline bool field::to<std::string>(
std::string &obj, std::string const &default_value) const
{
bool const null{is_null()};
if (null)
obj = default_value;
else
obj = std::string{view()};
return not null;
}
template<> inline bool field::to<char const *>(char const *&obj) const
{
bool const null{is_null()};
if (not null)
obj = c_str();
return not null;
}
template<> inline bool field::to<std::string_view>(std::string_view &obj) const
{
bool const null{is_null()};
if (not null)
obj = view();
return not null;
}
template<>
inline bool field::to<std::string_view>(
std::string_view &obj, std::string_view const &default_value) const
{
bool const null{is_null()};
if (null)
obj = default_value;
else
obj = view();
return not null;
}
template<> inline std::string_view field::as<std::string_view>() const
{
if (is_null())
PQXX_UNLIKELY
internal::throw_null_conversion(type_name<std::string_view>);
return view();
}
template<>
inline std::string_view
field::as<std::string_view>(std::string_view const &default_value) const
{
return is_null() ? default_value : view();
}
template<> inline bool field::to<zview>(zview &obj) const
{
bool const null{is_null()};
if (not null)
obj = zview{c_str(), size()};
return not null;
}
template<>
inline bool field::to<zview>(zview &obj, zview const &default_value) const
{
bool const null{is_null()};
if (null)
obj = default_value;
else
obj = zview{c_str(), size()};
return not null;
}
template<> inline zview field::as<zview>() const
{
if (is_null())
PQXX_UNLIKELY
internal::throw_null_conversion(type_name<zview>);
return zview{c_str(), size()};
}
template<> inline zview field::as<zview>(zview const &default_value) const
{
return is_null() ? default_value : zview{c_str(), size()};
}
template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
{
public:
using char_type = CHAR;
using traits_type = TRAITS;
using int_type = typename traits_type::int_type;
using pos_type = typename traits_type::pos_type;
using off_type = typename traits_type::off_type;
using openmode = std::ios::openmode;
using seekdir = std::ios::seekdir;
explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
protected:
virtual int sync() override { return traits_type::eof(); }
virtual pos_type seekoff(off_type, seekdir, openmode) override
{
return traits_type::eof();
}
virtual pos_type seekpos(pos_type, openmode) override
{
return traits_type::eof();
}
virtual int_type overflow(int_type) override { return traits_type::eof(); }
virtual int_type underflow() override { return traits_type::eof(); }
private:
field const &m_field;
int_type initialize()
{
auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
this->setg(g, g, g + std::size(m_field));
return int_type(std::size(m_field));
}
};
template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
{
using super = std::basic_istream<CHAR, TRAITS>;
public:
using char_type = CHAR;
using traits_type = TRAITS;
using int_type = typename traits_type::int_type;
using pos_type = typename traits_type::pos_type;
using off_type = typename traits_type::off_type;
[[deprecated("Use field::as<...>() or field::c_str().")]] basic_fieldstream(
field const &f) :
super{nullptr}, m_buf{f}
{
super::init(&m_buf);
}
private:
field_streambuf<CHAR, TRAITS> m_buf;
};
using fieldstream = basic_fieldstream<char>;
template<typename CHAR>
[[deprecated(
"Do this by hand, probably with better error checking.")]] inline std::
basic_ostream<CHAR> &
operator<<(std::basic_ostream<CHAR> &s, field const &value)
{
s.write(value.c_str(), std::streamsize(std::size(value)));
return s;
}
template<typename T> inline T from_string(field const &value)
{
if (value.is_null())
{
if constexpr (nullness<T>::has_null)
return nullness<T>::null();
else
internal::throw_null_conversion(type_name<T>);
}
else
{
return from_string<T>(value.view());
}
}
template<>
inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
{
if (not value.is_null())
throw conversion_error{
"Extracting non-null field into nullptr_t variable."};
return nullptr;
}
template<> PQXX_LIBEXPORT std::string to_string(field const &value);
} // namespace pqxx
#endif
pqxx
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
pqxx::operator<<
std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field const &value)
Write a result field to any type of stream.
Definition field.hxx:509
pqxx::row_size_type
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
pqxx::field_size_type
std::size_t field_size_type
Number of bytes in a field of database data.
Definition types.hxx:40
pqxx::result_size_type
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
pqxx::parse_composite
void parse_composite(pqxx::internal::encoding_group enc, std::string_view text, T &...fields)
Parse a string representation of a value of a composite type.
Definition composite.hxx:35
pqxx::from_string< std::nullptr_t >
std::nullptr_t from_string< std::nullptr_t >(field const &value)
Convert a field's value to nullptr_t.
Definition field.hxx:544
pqxx::to_string
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
pqxx::from_string
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:520
pqxx::internal::throw_null_conversion
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition strconv.cxx:253
pqxx::array_parser
Low-level array parser.
Definition array.hxx:527
pqxx::conversion_error
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
pqxx::field
Reference to a field in a result set.
Definition field.hxx:35
pqxx::field::home
constexpr result const & home() const noexcept
Definition field.hxx:261
pqxx::field::size
PQXX_PURE size_type size() const noexcept
Return number of bytes taken up by the field's value.
Definition field.cxx:77
pqxx::field::as
T as(T const &default_value) const
Return value as object of given type, or default value if null.
Definition field.hxx:207
pqxx::field::m_col
row_size_type m_col
Definition field.hxx:278
pqxx::field::as_array
array_parser as_array() const &noexcept
Parse the field as an SQL array.
Definition field.hxx:253
pqxx::field::to
auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<(not std::is_pointer< T >::value or std::is_same< T, char const * >::value), bool >
Read value into obj; or if null, use default value and return false.
Definition field.hxx:191
pqxx::field::size_type
field_size_type size_type
Definition field.hxx:37
pqxx::field::operator>>
bool operator>>(T &obj) const
Read value into obj; or leave obj untouched and return false if null.
Definition field.hxx:177
pqxx::field::c_str
PQXX_PURE char const * c_str() const &
Read as plain C string.
Definition field.cxx:65
pqxx::field::as
T as() const
Return value as object of given type, or throw exception if null.
Definition field.hxx:221
pqxx::field::field
field(result const &r, result_size_type row_num, row_size_type col_num) noexcept
Definition field.hxx:268
pqxx::field::col
constexpr row_size_type col() const noexcept
Definition field.hxx:263
pqxx::field::view
PQXX_PURE std::string_view view() const &
Read as string_view, or an empty one if null.
Definition field.hxx:113
pqxx::field::composite_to
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition field.hxx:163
pqxx::field::field
field() noexcept=default
Constructor. Do not call this yourself; libpqxx will do it for you.
pqxx::field::is_null
PQXX_PURE bool is_null() const noexcept
Is this field's value null?
Definition field.cxx:71
pqxx::field::get
constexpr O< T > get() const
Return value wrapped in some optional type (empty for nulls).
Definition field.hxx:241
pqxx::field::idx
constexpr result::size_type idx() const noexcept
Definition field.hxx:262
pqxx::field_streambuf
Definition field.hxx:400
pqxx::field_streambuf::traits_type
TRAITS traits_type
Definition field.hxx:403
pqxx::field_streambuf::off_type
typename traits_type::off_type off_type
Definition field.hxx:406
pqxx::field_streambuf::field_streambuf
field_streambuf(field const &f)
Definition field.hxx:410
pqxx::field_streambuf::seekoff
virtual pos_type seekoff(off_type, seekdir, openmode) override
Definition field.hxx:415
pqxx::field_streambuf::seekpos
virtual pos_type seekpos(pos_type, openmode) override
Definition field.hxx:419
pqxx::field_streambuf::openmode
std::ios::openmode openmode
Definition field.hxx:407
pqxx::field_streambuf::overflow
virtual int_type overflow(int_type) override
Definition field.hxx:423
pqxx::field_streambuf::pos_type
typename traits_type::pos_type pos_type
Definition field.hxx:405
pqxx::field_streambuf::sync
virtual int sync() override
Definition field.hxx:413
pqxx::field_streambuf::int_type
typename traits_type::int_type int_type
Definition field.hxx:404
pqxx::field_streambuf::underflow
virtual int_type underflow() override
Definition field.hxx:424
pqxx::field_streambuf::char_type
CHAR char_type
Definition field.hxx:402
pqxx::field_streambuf::seekdir
std::ios::seekdir seekdir
Definition field.hxx:408
pqxx::basic_fieldstream
Input stream that gets its data from a result field.
Definition field.hxx:454
pqxx::basic_fieldstream::traits_type
TRAITS traits_type
Definition field.hxx:459
pqxx::basic_fieldstream::basic_fieldstream
basic_fieldstream(field const &f)
Definition field.hxx:464
pqxx::basic_fieldstream::pos_type
typename traits_type::pos_type pos_type
Definition field.hxx:461
pqxx::basic_fieldstream::off_type
typename traits_type::off_type off_type
Definition field.hxx:462
pqxx::basic_fieldstream::int_type
typename traits_type::int_type int_type
Definition field.hxx:460
pqxx::basic_fieldstream::char_type
CHAR char_type
Definition field.hxx:458
pqxx::result
Result set containing data returned by a query or command.
Definition result.hxx:73
pqxx::result::size_type
result_size_type size_type
Definition result.hxx:75
pqxx::row
Reference to one row in a result.
Definition row.hxx:47
pqxx::nullness
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
pqxx::nullness::null
static TYPE null()
Return a null value.
pqxx::zview
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38