mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-30 09:48:54 +00:00
736 lines
23 KiB
C++
736 lines
23 KiB
C++
/* Large Objects interface. Deprecated; use blob instead.
|
|
*
|
|
* DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
|
|
*
|
|
* Copyright (c) 2000-2022, 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
|
|
{
|
|
/// Identity of a large object.
|
|
/** @deprecated Use the @ref blob class instead.
|
|
*
|
|
* Encapsulates the identity of a large object.
|
|
*
|
|
* A largeobject must be accessed only from within a backend transaction, but
|
|
* the object's identity remains valid as long as the object exists.
|
|
*/
|
|
class PQXX_LIBEXPORT largeobject
|
|
{
|
|
public:
|
|
using size_type = large_object_size_type;
|
|
|
|
/// Refer to a nonexistent large object (similar to what a null pointer
|
|
/// does).
|
|
[[deprecated("Use blob instead.")]] largeobject() noexcept = default;
|
|
|
|
/// Create new large object.
|
|
/** @param t Backend transaction in which the object is to be created.
|
|
*/
|
|
[[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t);
|
|
|
|
/// Wrap object with given oid.
|
|
/** Convert combination of a transaction and object identifier into a
|
|
* large object identity. Does not affect the database.
|
|
* @param o Object identifier for the given object.
|
|
*/
|
|
[[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept :
|
|
m_id{o}
|
|
{}
|
|
|
|
/// Import large object from a local file.
|
|
/** Creates a large object containing the data found in the given file.
|
|
* @param t Backend transaction in which the large object is to be created.
|
|
* @param file A filename on the client program's filesystem.
|
|
*/
|
|
[[deprecated("Use blob instead.")]] largeobject(
|
|
dbtransaction &t, std::string_view file);
|
|
|
|
/// Take identity of an opened large object.
|
|
/** Copy identity of already opened large object. Note that this may be done
|
|
* as an implicit conversion.
|
|
* @param o Already opened large object to copy identity from.
|
|
*/
|
|
[[deprecated("Use blob instead.")]] largeobject(
|
|
largeobjectaccess const &o) noexcept;
|
|
|
|
/// Object identifier.
|
|
/** The number returned by this function identifies the large object in the
|
|
* database we're connected to (or oid_none is returned if we refer to the
|
|
* null object).
|
|
*/
|
|
[[nodiscard]] oid id() const noexcept { return m_id; }
|
|
|
|
/**
|
|
* @name Identity comparisons
|
|
*
|
|
* These operators compare the object identifiers of large objects. This has
|
|
* nothing to do with the objects' actual contents; use them only for keeping
|
|
* track of containers of references to large objects and such.
|
|
*/
|
|
//@{
|
|
/// Compare object identities
|
|
/** @warning Only valid between large objects in the same database. */
|
|
[[nodiscard]] bool operator==(largeobject const &other) const
|
|
{
|
|
return m_id == other.m_id;
|
|
}
|
|
/// Compare object identities
|
|
/** @warning Only valid between large objects in the same database. */
|
|
[[nodiscard]] bool operator!=(largeobject const &other) const
|
|
{
|
|
return m_id != other.m_id;
|
|
}
|
|
/// Compare object identities
|
|
/** @warning Only valid between large objects in the same database. */
|
|
[[nodiscard]] bool operator<=(largeobject const &other) const
|
|
{
|
|
return m_id <= other.m_id;
|
|
}
|
|
/// Compare object identities
|
|
/** @warning Only valid between large objects in the same database. */
|
|
[[nodiscard]] bool operator>=(largeobject const &other) const
|
|
{
|
|
return m_id >= other.m_id;
|
|
}
|
|
/// Compare object identities
|
|
/** @warning Only valid between large objects in the same database. */
|
|
[[nodiscard]] bool operator<(largeobject const &other) const
|
|
{
|
|
return m_id < other.m_id;
|
|
}
|
|
/// Compare object identities
|
|
/** @warning Only valid between large objects in the same database. */
|
|
[[nodiscard]] bool operator>(largeobject const &other) const
|
|
{
|
|
return m_id > other.m_id;
|
|
}
|
|
//@}
|
|
|
|
/// Export large object's contents to a local file
|
|
/** Writes the data stored in the large object to the given file.
|
|
* @param t Transaction in which the object is to be accessed
|
|
* @param file A filename on the client's filesystem
|
|
*/
|
|
void to_file(dbtransaction &t, std::string_view file) const;
|
|
|
|
/// Delete large object from database
|
|
/** Unlike its low-level equivalent cunlink, this will throw an exception if
|
|
* deletion fails.
|
|
* @param t Transaction in which the object is to be deleted
|
|
*/
|
|
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;
|
|
};
|
|
|
|
|
|
/// Accessor for large object's contents.
|
|
/** @deprecated Use the `blob` class instead.
|
|
*/
|
|
class PQXX_LIBEXPORT largeobjectaccess : private largeobject
|
|
{
|
|
public:
|
|
using largeobject::size_type;
|
|
using off_type = size_type;
|
|
using pos_type = size_type;
|
|
|
|
/// Open mode: `in`, `out` (can be combined using "bitwise or").
|
|
/** According to the C++ standard, these should be in `std::ios_base`. We
|
|
* take them from derived class `std::ios` instead, which is easier on the
|
|
* eyes.
|
|
*
|
|
* Historical note: taking it from std::ios was originally a workaround for a
|
|
* problem with gcc 2.95.
|
|
*/
|
|
using openmode = std::ios::openmode;
|
|
|
|
/// Default open mode: in, out, binary.
|
|
static constexpr auto default_mode{
|
|
std::ios::in | std::ios::out | std::ios::binary};
|
|
|
|
/// Seek direction: `beg`, `cur`, `end`.
|
|
using seekdir = std::ios::seekdir;
|
|
|
|
/// Create new large object and open it.
|
|
/**
|
|
* @param t Backend transaction in which the object is to be created.
|
|
* @param mode Access mode, defaults to ios_base::in | ios_base::out |
|
|
* ios_base::binary.
|
|
*/
|
|
[[deprecated("Use blob instead.")]] explicit largeobjectaccess(
|
|
dbtransaction &t, openmode mode = default_mode);
|
|
|
|
/// Open large object with given oid.
|
|
/** Convert combination of a transaction and object identifier into a
|
|
* large object identity. Does not affect the database.
|
|
* @param t Transaction in which the object is to be accessed.
|
|
* @param o Object identifier for the given object.
|
|
* @param mode Access mode, defaults to ios_base::in | ios_base::out |
|
|
* ios_base::binary.
|
|
*/
|
|
[[deprecated("Use blob instead.")]] largeobjectaccess(
|
|
dbtransaction &t, oid o, openmode mode = default_mode);
|
|
|
|
/// Open given large object.
|
|
/** Open a large object with the given identity for reading and/or writing.
|
|
* @param t Transaction in which the object is to be accessed.
|
|
* @param o Identity for the large object to be accessed.
|
|
* @param mode Access mode, defaults to ios_base::in | ios_base::out |
|
|
* ios_base::binary.
|
|
*/
|
|
[[deprecated("Use blob instead.")]] largeobjectaccess(
|
|
dbtransaction &t, largeobject o, openmode mode = default_mode);
|
|
|
|
/// Import large object from a local file and open it.
|
|
/** Creates a large object containing the data found in the given file.
|
|
* @param t Backend transaction in which the large object is to be created.
|
|
* @param file A filename on the client program's filesystem.
|
|
* @param mode Access mode, defaults to ios_base::in | ios_base::out.
|
|
*/
|
|
[[deprecated("Use blob instead.")]] largeobjectaccess(
|
|
dbtransaction &t, std::string_view file, openmode mode = default_mode);
|
|
|
|
~largeobjectaccess() noexcept { close(); }
|
|
|
|
/// Object identifier.
|
|
/** The number returned by this function uniquely identifies the large object
|
|
* in the context of the database we're connected to.
|
|
*/
|
|
using largeobject::id;
|
|
|
|
/// Export large object's contents to a local file.
|
|
/** Writes the data stored in the large object to the given file.
|
|
* @param file A filename on the client's filesystem.
|
|
*/
|
|
void to_file(std::string_view file) const
|
|
{
|
|
largeobject::to_file(m_trans, file);
|
|
}
|
|
|
|
using largeobject::to_file;
|
|
|
|
/**
|
|
* @name High-level access to object contents.
|
|
*/
|
|
//@{
|
|
/// Write data to large object.
|
|
/** @warning The size of a write is currently limited to 2GB.
|
|
*
|
|
* @param buf Data to write.
|
|
* @param len Number of bytes from Buf to write.
|
|
*/
|
|
void write(char const buf[], std::size_t len);
|
|
|
|
/// Write string to large object.
|
|
/** If not all bytes could be written, an exception is thrown.
|
|
* @param buf Data to write; no terminating zero is written.
|
|
*/
|
|
void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }
|
|
|
|
/// Read data from large object.
|
|
/** Throws an exception if an error occurs while reading.
|
|
* @param buf Location to store the read data in.
|
|
* @param len Number of bytes to try and read.
|
|
* @return Number of bytes read, which may be less than the number requested
|
|
* if the end of the large object is reached.
|
|
*/
|
|
size_type read(char buf[], std::size_t len);
|
|
|
|
/// Seek in large object's data stream.
|
|
/** Throws an exception if an error occurs.
|
|
* @return The new position in the large object
|
|
*/
|
|
size_type seek(size_type dest, seekdir dir);
|
|
|
|
/// Report current position in large object's data stream.
|
|
/** Throws an exception if an error occurs.
|
|
* @return The current position in the large object.
|
|
*/
|
|
[[nodiscard]] size_type tell() const;
|
|
//@}
|
|
|
|
/**
|
|
* @name Low-level access to object contents.
|
|
*
|
|
* These functions provide a more "C-like" access interface, returning
|
|
* special values instead of throwing exceptions on error. These functions
|
|
* are generally best avoided in favour of the high-level access functions,
|
|
* which behave more like C++ functions should.
|
|
*
|
|
* Due to libpq's underlying API, some operations are limited to "int"
|
|
* sizes, typically 2 GB, even though a large object can grow much larger.
|
|
*/
|
|
//@{
|
|
/// Seek in large object's data stream.
|
|
/** Does not throw exception in case of error; inspect return value and
|
|
* `errno` instead.
|
|
* @param dest Offset to go to.
|
|
* @param dir Origin to which dest is relative: ios_base::beg (from beginning
|
|
* of the object), ios_base::cur (from current access position), or
|
|
* ios_base;:end (from end of object).
|
|
* @return New position in large object, or -1 if an error occurred.
|
|
*/
|
|
pos_type cseek(off_type dest, seekdir dir) noexcept;
|
|
|
|
/// Write to large object's data stream.
|
|
/** Does not throw exception in case of error; inspect return value and
|
|
* `errno` instead.
|
|
* @param buf Data to write.
|
|
* @param len Number of bytes to write.
|
|
* @return Number of bytes actually written, or -1 if an error occurred.
|
|
*/
|
|
off_type cwrite(char const buf[], std::size_t len) noexcept;
|
|
|
|
/// Read from large object's data stream.
|
|
/** Does not throw exception in case of error; inspect return value and
|
|
* `errno` instead.
|
|
* @param buf Area where incoming bytes should be stored.
|
|
* @param len Number of bytes to read.
|
|
* @return Number of bytes actually read, or -1 if an error occurred..
|
|
*/
|
|
off_type cread(char buf[], std::size_t len) noexcept;
|
|
|
|
/// Report current position in large object's data stream.
|
|
/** Does not throw exception in case of error; inspect return value and
|
|
* `errno` instead.
|
|
* @return Current position in large object, of -1 if an error occurred.
|
|
*/
|
|
[[nodiscard]] pos_type ctell() const noexcept;
|
|
//@}
|
|
|
|
/**
|
|
* @name Error/warning output
|
|
*/
|
|
//@{
|
|
/// Issue message to transaction's notice processor.
|
|
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;
|
|
};
|
|
|
|
|
|
/// Streambuf to use large objects in standard I/O streams.
|
|
/** @deprecated Access large objects directly using the @ref blob class.
|
|
*
|
|
* The standard streambuf classes provide uniform access to data storage such
|
|
* as files or string buffers, so they can be accessed using standard input or
|
|
* output streams. This streambuf implementation provided similar access to
|
|
* large objects, so they could be read and written using the same stream
|
|
* classes.
|
|
*
|
|
* This functionality was considered too fragile and complex, so it has been
|
|
* replaced with a single, much simpler class.
|
|
*/
|
|
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;
|
|
|
|
/// Default open mode: in, out, binary.
|
|
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;
|
|
}
|
|
|
|
/// For use by large object stream classes.
|
|
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:
|
|
/// Shortcut for traits_type::eof().
|
|
static int_type eof() { return traits_type::eof(); }
|
|
|
|
/// Helper: change error position of -1 to EOF (probably a no-op).
|
|
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;
|
|
|
|
/// Get & put buffers.
|
|
char_type *m_g, *m_p;
|
|
};
|
|
|
|
|
|
/// Input stream that gets its data from a large object.
|
|
/** @deprecated Access large objects directly using the @ref blob class.
|
|
*
|
|
* This class worked like any other istream, but to read data from a large
|
|
* object. It supported all formatting and streaming operations of
|
|
* `std::istream`.
|
|
*
|
|
* This functionality was considered too fragile and complex, so it has been
|
|
* replaced with a single, much simpler class.
|
|
*/
|
|
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"
|
|
/// Create a basic_ilostream.
|
|
/**
|
|
* @param t Transaction in which this stream is to exist.
|
|
* @param o Large object to access.
|
|
* @param buf_size Size of buffer to use internally (optional).
|
|
*/
|
|
[[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"
|
|
|
|
/// Create a basic_ilostream.
|
|
/**
|
|
* @param t Transaction in which this stream is to exist.
|
|
* @param o Identifier of a large object to access.
|
|
* @param buf_size Size of buffer to use internally (optional).
|
|
*/
|
|
[[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>;
|
|
|
|
|
|
/// Output stream that writes data back to a large object.
|
|
/** @deprecated Access large objects directly using the @ref blob class.
|
|
*
|
|
* This worked like any other ostream, but to write data to a large object.
|
|
* It supported all formatting and streaming operations of `std::ostream`.
|
|
*
|
|
* This functionality was considered too fragile and complex, so it has been
|
|
* replaced with a single, much simpler class.
|
|
*/
|
|
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"
|
|
/// Create a basic_olostream.
|
|
/**
|
|
* @param t transaction in which this stream is to exist.
|
|
* @param o a large object to access.
|
|
* @param buf_size size of buffer to use internally (optional).
|
|
*/
|
|
[[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"
|
|
|
|
/// Create a basic_olostream.
|
|
/**
|
|
* @param t transaction in which this stream is to exist.
|
|
* @param o a large object to access.
|
|
* @param buf_size size of buffer to use internally (optional).
|
|
*/
|
|
[[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>;
|
|
|
|
|
|
/// Stream that reads and writes a large object.
|
|
/** @deprecated Access large objects directly using the @ref blob class.
|
|
*
|
|
* This worked like a std::iostream, but to read data from, or write data to, a
|
|
* large object. It supported all formatting and streaming operations of
|
|
* `std::iostream`.
|
|
*
|
|
* This functionality was considered too fragile and complex, so it has been
|
|
* replaced with a single, much simpler class.
|
|
*/
|
|
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;
|
|
|
|
/// Create a basic_lostream.
|
|
/**
|
|
* @param t Transaction in which this stream is to exist.
|
|
* @param o Large object to access.
|
|
* @param buf_size Size of buffer to use internally (optional).
|
|
*/
|
|
[[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);
|
|
}
|
|
|
|
/// Create a basic_lostream.
|
|
/**
|
|
* @param t Transaction in which this stream is to exist.
|
|
* @param o Large object to access.
|
|
* @param buf_size Size of buffer to use internally (optional).
|
|
*/
|
|
[[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
|