Loading...
Searching...
No Matches
largeobject.hxx
/* Large Objects interface. Deprecated; use blob instead.
*
* DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject 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_LARGEOBJECT
#define PQXX_H_LARGEOBJECT
#if !defined(PQXX_HEADER_PRE)
# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
#endif
#include <streambuf>
#include "pqxx/dbtransaction.hxx"
namespace pqxx
{
class PQXX_LIBEXPORT largeobject
{
public:
using size_type = large_object_size_type;
[[deprecated("Use blob instead.")]] largeobject() noexcept = default;
[[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t);
[[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept :
m_id{o}
{}
[[deprecated("Use blob instead.")]] largeobject(
dbtransaction &t, std::string_view file);
[[deprecated("Use blob instead.")]] largeobject(
largeobjectaccess const &o) noexcept;
[[nodiscard]] oid id() const noexcept { return m_id; }
[[nodiscard]] bool operator==(largeobject const &other) const
{
return m_id == other.m_id;
}
[[nodiscard]] bool operator!=(largeobject const &other) const
{
return m_id != other.m_id;
}
[[nodiscard]] bool operator<=(largeobject const &other) const
{
return m_id <= other.m_id;
}
[[nodiscard]] bool operator>=(largeobject const &other) const
{
return m_id >= other.m_id;
}
[[nodiscard]] bool operator<(largeobject const &other) const
{
return m_id < other.m_id;
}
[[nodiscard]] bool operator>(largeobject const &other) const
{
return m_id > other.m_id;
}
void to_file(dbtransaction &t, std::string_view file) const;
void remove(dbtransaction &t) const;
protected:
PQXX_PURE static internal::pq::PGconn *
raw_connection(dbtransaction const &T);
PQXX_PRIVATE std::string reason(connection const &, int err) const;
private:
oid m_id = oid_none;
};
class PQXX_LIBEXPORT largeobjectaccess : private largeobject
{
public:
using largeobject::size_type;
using off_type = size_type;
using pos_type = size_type;
using openmode = std::ios::openmode;
static constexpr auto default_mode{
std::ios::in | std::ios::out | std::ios::binary};
using seekdir = std::ios::seekdir;
[[deprecated("Use blob instead.")]] explicit largeobjectaccess(
dbtransaction &t, openmode mode = default_mode);
[[deprecated("Use blob instead.")]] largeobjectaccess(
dbtransaction &t, oid o, openmode mode = default_mode);
[[deprecated("Use blob instead.")]] largeobjectaccess(
dbtransaction &t, largeobject o, openmode mode = default_mode);
[[deprecated("Use blob instead.")]] largeobjectaccess(
dbtransaction &t, std::string_view file, openmode mode = default_mode);
~largeobjectaccess() noexcept { close(); }
using largeobject::id;
void to_file(std::string_view file) const
{
largeobject::to_file(m_trans, file);
}
using largeobject::to_file;
void write(char const buf[], std::size_t len);
void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }
size_type read(char buf[], std::size_t len);
size_type seek(size_type dest, seekdir dir);
[[nodiscard]] size_type tell() const;
pos_type cseek(off_type dest, seekdir dir) noexcept;
off_type cwrite(char const buf[], std::size_t len) noexcept;
off_type cread(char buf[], std::size_t len) noexcept;
[[nodiscard]] pos_type ctell() const noexcept;
void process_notice(zview) noexcept;
using largeobject::remove;
using largeobject::operator==;
using largeobject::operator!=;
using largeobject::operator<;
using largeobject::operator<=;
using largeobject::operator>;
using largeobject::operator>=;
largeobjectaccess() = delete;
largeobjectaccess(largeobjectaccess const &) = delete;
largeobjectaccess operator=(largeobjectaccess const &) = delete;
private:
PQXX_PRIVATE std::string reason(int err) const;
internal::pq::PGconn *raw_connection() const
{
return largeobject::raw_connection(m_trans);
}
PQXX_PRIVATE void open(openmode mode);
void close() noexcept;
dbtransaction &m_trans;
int m_fd = -1;
};
template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
class largeobject_streambuf : public std::basic_streambuf<CHAR, TRAITS>
{
using size_type = largeobject::size_type;
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 = largeobjectaccess::openmode;
using seekdir = largeobjectaccess::seekdir;
static constexpr auto default_mode{
std::ios::in | std::ios::out | std::ios::binary};
#include "pqxx/internal/ignore-deprecated-pre.hxx"
[[deprecated("Use blob instead.")]] largeobject_streambuf(
dbtransaction &t, largeobject o, openmode mode = default_mode,
size_type buf_size = 512) :
m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
{
initialize(mode);
}
#include "pqxx/internal/ignore-deprecated-post.hxx"
[[deprecated("Use blob instead.")]] largeobject_streambuf(
dbtransaction &t, oid o, openmode mode = default_mode,
size_type buf_size = 512) :
m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
{
initialize(mode);
}
virtual ~largeobject_streambuf() noexcept
{
delete[] m_p;
delete[] m_g;
}
void process_notice(zview const &s) { m_obj.process_notice(s); }
protected:
virtual int sync() override
{
// setg() sets eback, gptr, egptr.
this->setg(this->eback(), this->eback(), this->egptr());
return overflow(eof());
}
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
{
return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
}
virtual pos_type seekpos(pos_type pos, openmode) override
{
largeobjectaccess::pos_type const newpos{
m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};
return adjust_eof(newpos);
}
virtual int_type overflow(int_type ch) override
{
auto *const pp{this->pptr()};
if (pp == nullptr)
return eof();
auto *const pb{this->pbase()};
int_type res{0};
if (pp > pb)
{
auto const write_sz{pp - pb};
auto const written_sz{
m_obj.cwrite(pb, static_cast<std::size_t>(pp - pb))};
if (internal::cmp_less_equal(written_sz, 0))
throw internal_error{
"pqxx::largeobject: write failed "
"(is transaction still valid on write or flush?), "
"libpq reports error"};
else if (write_sz != written_sz)
throw internal_error{
"pqxx::largeobject: write failed "
"(is transaction still valid on write or flush?), " +
std::to_string(written_sz) + "/" + std::to_string(write_sz) +
" bytes written"};
auto const out{adjust_eof(written_sz)};
if constexpr (std::is_arithmetic_v<decltype(out)>)
res = check_cast<int_type>(out, "largeobject position"sv);
else
res = int_type(out);
}
this->setp(m_p, m_p + m_bufsize);
// Write that one more character, if it's there.
if (ch != eof())
{
*this->pptr() = static_cast<char_type>(ch);
this->pbump(1);
}
return res;
}
virtual int_type overflow() { return overflow(eof()); }
virtual int_type underflow() override
{
if (this->gptr() == nullptr)
return eof();
auto *const eb{this->eback()};
auto const res{adjust_eof(
m_obj.cread(this->eback(), static_cast<std::size_t>(m_bufsize)))};
this->setg(
eb, eb, eb + (res == eof() ? 0 : static_cast<std::size_t>(res)));
return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);
}
private:
static int_type eof() { return traits_type::eof(); }
template<typename INTYPE> static std::streampos adjust_eof(INTYPE pos)
{
bool const at_eof{pos == -1};
if constexpr (std::is_arithmetic_v<std::streampos>)
{
return check_cast<std::streampos>(
(at_eof ? eof() : pos), "large object seek"sv);
}
else
{
return std::streampos(at_eof ? eof() : pos);
}
}
void initialize(openmode mode)
{
if ((mode & std::ios::in) != 0)
{
m_g = new char_type[unsigned(m_bufsize)];
this->setg(m_g, m_g, m_g);
}
if ((mode & std::ios::out) != 0)
{
m_p = new char_type[unsigned(m_bufsize)];
this->setp(m_p, m_p + m_bufsize);
}
}
size_type const m_bufsize;
largeobjectaccess m_obj;
char_type *m_g, *m_p;
};
template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
class basic_ilostream : 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;
#include "pqxx/internal/ignore-deprecated-pre.hxx"
[[deprecated("Use blob instead.")]] basic_ilostream(
dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
super{nullptr},
m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
{
super::init(&m_buf);
}
#include "pqxx/internal/ignore-deprecated-post.hxx"
[[deprecated("Use blob instead.")]] basic_ilostream(
dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
super{nullptr},
m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
{
super::init(&m_buf);
}
private:
largeobject_streambuf<CHAR, TRAITS> m_buf;
};
using ilostream = basic_ilostream<char>;
template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
class basic_olostream : public std::basic_ostream<CHAR, TRAITS>
{
using super = std::basic_ostream<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;
#include "pqxx/internal/ignore-deprecated-pre.hxx"
[[deprecated("Use blob instead.")]] basic_olostream(
dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
super{nullptr},
m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
{
super::init(&m_buf);
}
#include "pqxx/internal/ignore-deprecated-post.hxx"
[[deprecated("Use blob instead.")]] basic_olostream(
dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
super{nullptr},
m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
{
super::init(&m_buf);
}
~basic_olostream()
{
try
{
m_buf.pubsync();
m_buf.pubsync();
}
catch (std::exception const &e)
{
m_buf.process_notice(e.what());
}
}
private:
largeobject_streambuf<CHAR, TRAITS> m_buf;
};
using olostream = basic_olostream<char>;
template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
class basic_lostream : public std::basic_iostream<CHAR, TRAITS>
{
using super = std::basic_iostream<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 blob instead.")]] basic_lostream(
dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
super{nullptr},
m_buf{
t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
{
super::init(&m_buf);
}
[[deprecated("Use blob instead.")]] basic_lostream(
dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
super{nullptr},
m_buf{
t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
{
super::init(&m_buf);
}
~basic_lostream()
{
try
{
m_buf.pubsync();
m_buf.pubsync();
}
catch (std::exception const &e)
{
m_buf.process_notice(e.what());
}
}
private:
largeobject_streambuf<CHAR, TRAITS> m_buf;
};
using lostream = basic_lostream<char>;
} // namespace pqxx
#endif
pqxx::basic_ilostream
Input stream that gets its data from a large object.
Definition largeobject.hxx:546
pqxx::basic_ilostream::basic_ilostream
basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition largeobject.hxx:578
pqxx::basic_ilostream::basic_ilostream
basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition largeobject.hxx:563
pqxx::basic_lostream
Stream that reads and writes a large object.
Definition largeobject.hxx:676
pqxx::basic_lostream::basic_lostream
basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition largeobject.hxx:692
pqxx::basic_lostream::basic_lostream
basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition largeobject.hxx:707
pqxx::basic_olostream
Output stream that writes data back to a large object.
Definition largeobject.hxx:604
pqxx::basic_olostream::basic_olostream
basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition largeobject.hxx:621
pqxx::basic_olostream::basic_olostream
basic_olostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition largeobject.hxx:636
pqxx::blob
Definition blob.hxx:55
pqxx::connection
Connection to a database.
Definition connection.hxx:279
pqxx::largeobject_streambuf
Streambuf to use large objects in standard I/O streams.
Definition largeobject.hxx:374
pqxx::largeobject_streambuf::process_notice
void process_notice(zview const &s)
For use by large object stream classes.
Definition largeobject.hxx:415
pqxx::largeobject
Identity of a large object.
Definition largeobject.hxx:34
pqxx::largeobject::operator==
bool operator==(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:89
pqxx::largeobject::operator>=
bool operator>=(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:107
pqxx::largeobject::operator<=
bool operator<=(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:101
pqxx::largeobject::operator<
bool operator<(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:113
pqxx::largeobject::largeobject
largeobject() noexcept=default
pqxx::largeobject::operator!=
bool operator!=(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:95
pqxx::largeobject::operator>
bool operator>(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:119
pqxx::largeobject::id
oid id() const noexcept
Object identifier.
Definition largeobject.hxx:77
pqxx::largeobjectaccess
Accessor for large object's contents.
Definition largeobject.hxx:154
pqxx::largeobjectaccess::openmode
std::ios::openmode openmode
Open mode: in, out (can be combined using "bitwise or").
Definition largeobject.hxx:168
pqxx::largeobjectaccess::seekdir
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition largeobject.hxx:175
pqxx::largeobjectaccess::to_file
void to_file(std::string_view file) const
Export large object's contents to a local file.
Definition largeobject.hxx:228
pqxx::largeobjectaccess::write
void write(std::string_view buf)
Write string to large object.
Definition largeobject.hxx:251
pqxx::zview
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
pqxx::dbtransaction
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
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::oid_none
constexpr oid oid_none
The "null" oid.
Definition util.hxx:447
pqxx::large_object_size_type
int64_t large_object_size_type
Number of bytes in a large object.
Definition types.hxx:43