11#ifndef PQXX_H_LARGEOBJECT
12#define PQXX_H_LARGEOBJECT
14#if !defined(PQXX_HEADER_PRE)
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
20#include "pqxx/dbtransaction.hxx"
33class PQXX_LIBEXPORT largeobject
40 [[deprecated(
"Use blob instead.")]] largeobject() noexcept = default;
45 [[deprecated(
"Use blob instead.")]] explicit largeobject(dbtransaction &t);
52 [[deprecated(
"Use blob instead.")]] explicit largeobject(oid o) noexcept :
61 [[deprecated(
"Use blob instead.")]] largeobject(
62 dbtransaction &t, std::string_view file);
69 [[deprecated(
"Use blob instead.")]] largeobject(
70 largeobjectaccess
const &o)
noexcept;
77 [[nodiscard]]
oid id() const noexcept {
return m_id; }
89 [[nodiscard]]
bool operator==(largeobject
const &other)
const
91 return m_id == other.m_id;
95 [[nodiscard]]
bool operator!=(largeobject
const &other)
const
97 return m_id != other.m_id;
101 [[nodiscard]]
bool operator<=(largeobject
const &other)
const
103 return m_id <= other.m_id;
107 [[nodiscard]]
bool operator>=(largeobject
const &other)
const
109 return m_id >= other.m_id;
113 [[nodiscard]]
bool operator<(largeobject
const &other)
const
115 return m_id < other.m_id;
119 [[nodiscard]]
bool operator>(largeobject
const &other)
const
121 return m_id > other.m_id;
130 void to_file(dbtransaction &t, std::string_view file)
const;
137 void remove(dbtransaction &t)
const;
140 PQXX_PURE
static internal::pq::PGconn *
141 raw_connection(dbtransaction
const &T);
143 PQXX_PRIVATE std::string reason(connection
const &,
int err)
const;
153class PQXX_LIBEXPORT largeobjectaccess :
private largeobject
156 using largeobject::size_type;
157 using off_type = size_type;
158 using pos_type = size_type;
168 using openmode = std::ios::openmode;
171 static constexpr auto default_mode{
172 std::ios::in | std::ios::out | std::ios::binary};
175 using seekdir = std::ios::seekdir;
183 [[deprecated(
"Use blob instead.")]]
explicit largeobjectaccess(
184 dbtransaction &t, openmode mode = default_mode);
194 [[deprecated(
"Use blob instead.")]] largeobjectaccess(
195 dbtransaction &t, oid o, openmode mode = default_mode);
204 [[deprecated(
"Use blob instead.")]] largeobjectaccess(
205 dbtransaction &t, largeobject o, openmode mode = default_mode);
213 [[deprecated(
"Use blob instead.")]] largeobjectaccess(
214 dbtransaction &t, std::string_view file, openmode mode = default_mode);
216 ~largeobjectaccess() noexcept { close(); }
222 using largeobject::id;
228 void to_file(std::string_view file)
const
230 largeobject::to_file(m_trans, file);
233 using largeobject::to_file;
245 void write(
char const buf[], std::size_t len);
251 void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }
260 size_type read(
char buf[], std::size_t len);
266 size_type seek(size_type dest, seekdir dir);
272 [[nodiscard]] size_type tell()
const;
296 pos_type cseek(off_type dest, seekdir dir)
noexcept;
305 off_type cwrite(
char const buf[], std::size_t len)
noexcept;
314 off_type cread(
char buf[], std::size_t len)
noexcept;
321 [[nodiscard]] pos_type ctell() const noexcept;
329 void process_notice(zview) noexcept;
332 using largeobject::remove;
334 using largeobject::operator==;
335 using largeobject::operator!=;
336 using largeobject::operator<;
337 using largeobject::operator<=;
338 using largeobject::operator>;
339 using largeobject::operator>=;
341 largeobjectaccess() = delete;
342 largeobjectaccess(largeobjectaccess const &) = delete;
343 largeobjectaccess operator=(largeobjectaccess const &) = delete;
346 PQXX_PRIVATE std::
string reason(
int err) const;
347 internal::pq::PGconn *raw_connection()
const
349 return largeobject::raw_connection(m_trans);
352 PQXX_PRIVATE
void open(openmode mode);
353 void close() noexcept;
355 dbtransaction &m_trans;
372template<typename CHAR =
char, typename TRAITS = std::char_traits<CHAR>>
373class largeobject_streambuf : public std::basic_streambuf<CHAR, TRAITS>
375 using size_type = largeobject::size_type;
378 using char_type = CHAR;
379 using traits_type = TRAITS;
380 using int_type =
typename traits_type::int_type;
381 using pos_type =
typename traits_type::pos_type;
382 using off_type =
typename traits_type::off_type;
383 using openmode = largeobjectaccess::openmode;
384 using seekdir = largeobjectaccess::seekdir;
388 std::ios::in | std::ios::out | std::ios::binary};
390#include "pqxx/internal/ignore-deprecated-pre.hxx"
392 dbtransaction &t, largeobject o, openmode mode = default_mode,
393 size_type buf_size = 512) :
394 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
398#include "pqxx/internal/ignore-deprecated-post.hxx"
402 size_type buf_size = 512) :
403 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
418 virtual int sync()
override
421 this->setg(this->eback(), this->eback(), this->egptr());
422 return overflow(eof());
425 virtual pos_type seekoff(off_type offset, seekdir dir, openmode)
override
427 return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
430 virtual pos_type seekpos(pos_type pos, openmode)
override
432 largeobjectaccess::pos_type
const newpos{
433 m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};
434 return adjust_eof(newpos);
437 virtual int_type overflow(int_type ch)
override
439 auto *
const pp{this->pptr()};
442 auto *
const pb{this->pbase()};
447 auto const write_sz{pp - pb};
448 auto const written_sz{
449 m_obj.cwrite(pb,
static_cast<std::size_t
>(pp - pb))};
450 if (internal::cmp_less_equal(written_sz, 0))
451 throw internal_error{
452 "pqxx::largeobject: write failed "
453 "(is transaction still valid on write or flush?), "
454 "libpq reports error"};
455 else if (write_sz != written_sz)
456 throw internal_error{
457 "pqxx::largeobject: write failed "
458 "(is transaction still valid on write or flush?), " +
459 std::to_string(written_sz) +
"/" + std::to_string(write_sz) +
461 auto const out{adjust_eof(written_sz)};
463 if constexpr (std::is_arithmetic_v<
decltype(out)>)
464 res = check_cast<int_type>(out,
"largeobject position"sv);
468 this->setp(m_p, m_p + m_bufsize);
473 *this->pptr() =
static_cast<char_type
>(ch);
479 virtual int_type overflow() {
return overflow(eof()); }
481 virtual int_type underflow()
override
483 if (this->gptr() ==
nullptr)
485 auto *
const eb{this->eback()};
486 auto const res{adjust_eof(
487 m_obj.cread(this->eback(),
static_cast<std::size_t
>(m_bufsize)))};
489 eb, eb, eb + (res == eof() ? 0 :
static_cast<std::size_t
>(res)));
490 return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);
495 static int_type eof() {
return traits_type::eof(); }
498 template<
typename INTYPE>
static std::streampos adjust_eof(INTYPE pos)
500 bool const at_eof{pos == -1};
501 if constexpr (std::is_arithmetic_v<std::streampos>)
503 return check_cast<std::streampos>(
504 (at_eof ? eof() : pos),
"large object seek"sv);
508 return std::streampos(at_eof ? eof() : pos);
512 void initialize(openmode mode)
514 if ((mode & std::ios::in) != 0)
516 m_g =
new char_type[unsigned(m_bufsize)];
517 this->setg(m_g, m_g, m_g);
519 if ((mode & std::ios::out) != 0)
521 m_p =
new char_type[unsigned(m_bufsize)];
522 this->setp(m_p, m_p + m_bufsize);
526 size_type
const m_bufsize;
527 largeobjectaccess m_obj;
530 char_type *m_g, *m_p;
544template<
typename CHAR =
char,
typename TRAITS = std::
char_traits<CHAR>>
547 using super = std::basic_istream<CHAR, TRAITS>;
550 using char_type = CHAR;
551 using traits_type = TRAITS;
552 using int_type =
typename traits_type::int_type;
553 using pos_type =
typename traits_type::pos_type;
554 using off_type =
typename traits_type::off_type;
556#include "pqxx/internal/ignore-deprecated-pre.hxx"
564 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
566 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
570#include "pqxx/internal/ignore-deprecated-post.hxx"
579 dbtransaction &t,
oid o, largeobject::size_type buf_size = 512) :
581 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
590using ilostream = basic_ilostream<char>;
602template<
typename CHAR =
char,
typename TRAITS = std::
char_traits<CHAR>>
605 using super = std::basic_ostream<CHAR, TRAITS>;
608 using char_type = CHAR;
609 using traits_type = TRAITS;
610 using int_type =
typename traits_type::int_type;
611 using pos_type =
typename traits_type::pos_type;
612 using off_type =
typename traits_type::off_type;
614#include "pqxx/internal/ignore-deprecated-pre.hxx"
622 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
624 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
628#include "pqxx/internal/ignore-deprecated-post.hxx"
637 dbtransaction &t,
oid o, largeobject::size_type buf_size = 512) :
639 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
651 catch (std::exception
const &e)
653 m_buf.process_notice(e.what());
658 largeobject_streambuf<CHAR, TRAITS> m_buf;
661using olostream = basic_olostream<char>;
674template<
typename CHAR =
char,
typename TRAITS = std::
char_traits<CHAR>>
677 using super = std::basic_iostream<CHAR, TRAITS>;
680 using char_type = CHAR;
681 using traits_type = TRAITS;
682 using int_type =
typename traits_type::int_type;
683 using pos_type =
typename traits_type::pos_type;
684 using off_type =
typename traits_type::off_type;
693 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
696 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
708 dbtransaction &t,
oid o, largeobject::size_type buf_size = 512) :
711 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
723 catch (std::exception
const &e)
725 m_buf.process_notice(e.what());
730 largeobject_streambuf<CHAR, TRAITS> m_buf;
733using lostream = basic_lostream<char>;
basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
End a code block started by "ignore-deprecated-pre.hxx".
Definition largeobject.hxx:578
basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition largeobject.hxx:563
Stream that reads and writes a large object.
Definition largeobject.hxx:676
basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition largeobject.hxx:692
basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition largeobject.hxx:707
Output stream that writes data back to a large object.
Definition largeobject.hxx:604
basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition largeobject.hxx:621
basic_olostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
End a code block started by "ignore-deprecated-pre.hxx".
Definition largeobject.hxx:636
Accessor for large object's contents.
Definition largeobject.hxx:374
static constexpr auto default_mode
Default open mode: in, out, binary.
Definition largeobject.hxx:387
largeobject_streambuf(dbtransaction &t, oid o, openmode mode=default_mode, size_type buf_size=512)
End a code block started by "ignore-deprecated-pre.hxx".
Definition largeobject.hxx:400
void process_notice(zview const &s)
For use by large object stream classes.
Definition largeobject.hxx:415
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
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
int64_t large_object_size_type
Number of bytes in a large object.
Definition types.hxx:43
constexpr oid oid_none
The "null" oid.
Definition util.hxx:447