libpqxx  7.7.0
largeobject.hxx
1 /* Large Objects interface. Deprecated; use blob instead.
2  *
3  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
4  *
5  * Copyright (c) 2000-2022, Jeroen T. Vermeulen.
6  *
7  * See COPYING for copyright license. If you did not receive a file called
8  * COPYING with this source code, please notify the distributor of this
9  * mistake, or contact the author.
10  */
11 #ifndef PQXX_H_LARGEOBJECT
12 #define PQXX_H_LARGEOBJECT
13 
14 #include <streambuf>
15 
16 #include "pqxx/dbtransaction.hxx"
17 
18 
19 namespace pqxx
20 {
22 
29 class PQXX_LIBEXPORT largeobject
30 {
31 public:
33 
36  [[deprecated("Use blob instead.")]] largeobject() noexcept = default;
37 
39 
41  [[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t);
42 
44 
48  [[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept :
49  m_id{o}
50  {}
51 
53 
57  [[deprecated("Use blob instead.")]] largeobject(
58  dbtransaction &t, std::string_view file);
59 
61 
65  [[deprecated("Use blob instead.")]] largeobject(
66  largeobjectaccess const &o) noexcept;
67 
69 
73  [[nodiscard]] oid id() const noexcept { return m_id; }
74 
83 
85  [[nodiscard]] bool operator==(largeobject const &other) const
86  {
87  return m_id == other.m_id;
88  }
90 
91  [[nodiscard]] bool operator!=(largeobject const &other) const
92  {
93  return m_id != other.m_id;
94  }
96 
97  [[nodiscard]] bool operator<=(largeobject const &other) const
98  {
99  return m_id <= other.m_id;
100  }
102 
103  [[nodiscard]] bool operator>=(largeobject const &other) const
104  {
105  return m_id >= other.m_id;
106  }
108 
109  [[nodiscard]] bool operator<(largeobject const &other) const
110  {
111  return m_id < other.m_id;
112  }
114 
115  [[nodiscard]] bool operator>(largeobject const &other) const
116  {
117  return m_id > other.m_id;
118  }
120 
122 
126  void to_file(dbtransaction &t, std::string_view file) const;
127 
129 
133  void remove(dbtransaction &t) const;
134 
135 protected:
136  PQXX_PURE static internal::pq::PGconn *
137  raw_connection(dbtransaction const &T);
138 
139  PQXX_PRIVATE std::string reason(connection const &, int err) const;
140 
141 private:
142  oid m_id = oid_none;
143 };
144 
145 
147 
149 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
150 {
151 public:
155 
157 
164  using openmode = std::ios::openmode;
165 
167  static constexpr auto default_mode{
168  std::ios::in | std::ios::out | std::ios::binary};
169 
171  using seekdir = std::ios::seekdir;
172 
174 
179  [[deprecated("Use blob instead.")]] explicit largeobjectaccess(
180  dbtransaction &t, openmode mode = default_mode);
181 
183 
190  [[deprecated("Use blob instead.")]] largeobjectaccess(
191  dbtransaction &t, oid o, openmode mode = default_mode);
192 
194 
200  [[deprecated("Use blob instead.")]] largeobjectaccess(
201  dbtransaction &t, largeobject o, openmode mode = default_mode);
202 
204 
209  [[deprecated("Use blob instead.")]] largeobjectaccess(
210  dbtransaction &t, std::string_view file, openmode mode = default_mode);
211 
212  ~largeobjectaccess() noexcept { close(); }
213 
215 
218  using largeobject::id;
219 
221 
224  void to_file(std::string_view file) const
225  {
226  largeobject::to_file(m_trans, file);
227  }
228 
229  using largeobject::to_file;
230 
235 
241  void write(char const buf[], std::size_t len);
242 
244 
247  void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }
248 
250 
256  size_type read(char buf[], std::size_t len);
257 
259 
262  size_type seek(size_type dest, seekdir dir);
263 
265 
268  [[nodiscard]] size_type tell() const;
270 
283 
292  pos_type cseek(off_type dest, seekdir dir) noexcept;
293 
295 
301  off_type cwrite(char const buf[], std::size_t len) noexcept;
302 
304 
310  off_type cread(char buf[], std::size_t len) noexcept;
311 
313 
317  [[nodiscard]] pos_type ctell() const noexcept;
319 
324  void process_notice(zview) noexcept;
327 
328  using largeobject::remove;
329 
330  using largeobject::operator==;
331  using largeobject::operator!=;
332  using largeobject::operator<;
333  using largeobject::operator<=;
334  using largeobject::operator>;
335  using largeobject::operator>=;
336 
337  largeobjectaccess() = delete;
338  largeobjectaccess(largeobjectaccess const &) = delete;
339  largeobjectaccess operator=(largeobjectaccess const &) = delete;
340 
341 private:
342  PQXX_PRIVATE std::string reason(int err) const;
343  internal::pq::PGconn *raw_connection() const
344  {
345  return largeobject::raw_connection(m_trans);
346  }
347 
348  PQXX_PRIVATE void open(openmode mode);
349  void close() noexcept;
350 
351  dbtransaction &m_trans;
352  int m_fd = -1;
353 };
354 
355 
357 
368 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
369 class largeobject_streambuf : public std::basic_streambuf<CHAR, TRAITS>
370 {
371  using size_type = largeobject::size_type;
372 
373 public:
374  using char_type = CHAR;
375  using traits_type = TRAITS;
376  using int_type = typename traits_type::int_type;
377  using pos_type = typename traits_type::pos_type;
378  using off_type = typename traits_type::off_type;
381 
383  static constexpr auto default_mode{
384  std::ios::in | std::ios::out | std::ios::binary};
385 
386  [[deprecated("Use blob instead.")]] largeobject_streambuf(
387  dbtransaction &t, largeobject o, openmode mode = default_mode,
388  size_type buf_size = 512) :
389  m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
390  {
391  initialize(mode);
392  }
393 
394  [[deprecated("Use blob instead.")]] largeobject_streambuf(
395  dbtransaction &t, oid o, openmode mode = default_mode,
396  size_type buf_size = 512) :
397  m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
398  {
399  initialize(mode);
400  }
401 
402  virtual ~largeobject_streambuf() noexcept
403  {
404  delete[] m_p;
405  delete[] m_g;
406  }
407 
409  void process_notice(zview const &s) { m_obj.process_notice(s); }
410 
411 protected:
412  virtual int sync() override
413  {
414  // setg() sets eback, gptr, egptr.
415  this->setg(this->eback(), this->eback(), this->egptr());
416  return overflow(eof());
417  }
418 
419  virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
420  {
421  return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
422  }
423 
424  virtual pos_type seekpos(pos_type pos, openmode) override
425  {
426  largeobjectaccess::pos_type const newpos{
427  m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};
428  return adjust_eof(newpos);
429  }
430 
431  virtual int_type overflow(int_type ch) override
432  {
433  auto *const pp{this->pptr()};
434  if (pp == nullptr)
435  return eof();
436  auto *const pb{this->pbase()};
437  int_type res{0};
438 
439  if (pp > pb)
440  {
441  auto const write_sz{pp - pb};
442  auto const written_sz{
443  m_obj.cwrite(pb, static_cast<std::size_t>(pp - pb))};
444  if (internal::cmp_less_equal(written_sz, 0))
445  throw internal_error{
446  "pqxx::largeobject: write failed "
447  "(is transaction still valid on write or flush?), "
448  "libpq reports error"};
449  else if (write_sz != written_sz)
450  throw internal_error{
451  "pqxx::largeobject: write failed "
452  "(is transaction still valid on write or flush?), " +
453  std::to_string(written_sz) + "/" + std::to_string(write_sz) +
454  " bytes written"};
455  auto const out{adjust_eof(written_sz)};
456 
457  if constexpr (std::is_arithmetic_v<decltype(out)>)
458  res = check_cast<int_type>(out, "largeobject position"sv);
459  else
460  res = int_type(out);
461  }
462  this->setp(m_p, m_p + m_bufsize);
463 
464  // Write that one more character, if it's there.
465  if (ch != eof())
466  {
467  *this->pptr() = static_cast<char_type>(ch);
468  this->pbump(1);
469  }
470  return res;
471  }
472 
473  virtual int_type overflow() { return overflow(eof()); }
474 
475  virtual int_type underflow() override
476  {
477  if (this->gptr() == nullptr)
478  return eof();
479  auto *const eb{this->eback()};
480  auto const res{adjust_eof(
481  m_obj.cread(this->eback(), static_cast<std::size_t>(m_bufsize)))};
482  this->setg(
483  eb, eb, eb + (res == eof() ? 0 : static_cast<std::size_t>(res)));
484  return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);
485  }
486 
487 private:
489  static int_type eof() { return traits_type::eof(); }
490 
492  template<typename INTYPE> static std::streampos adjust_eof(INTYPE pos)
493  {
494  bool const at_eof{pos == -1};
495  if constexpr (std::is_arithmetic_v<std::streampos>)
496  {
497  return check_cast<std::streampos>(
498  (at_eof ? eof() : pos), "large object seek"sv);
499  }
500  else
501  {
502  return std::streampos(at_eof ? eof() : pos);
503  }
504  }
505 
506  void initialize(openmode mode)
507  {
508  if ((mode & std::ios::in) != 0)
509  {
510  m_g = new char_type[unsigned(m_bufsize)];
511  this->setg(m_g, m_g, m_g);
512  }
513  if ((mode & std::ios::out) != 0)
514  {
515  m_p = new char_type[unsigned(m_bufsize)];
516  this->setp(m_p, m_p + m_bufsize);
517  }
518  }
519 
520  size_type const m_bufsize;
521  largeobjectaccess m_obj;
522 
524  char_type *m_g, *m_p;
525 };
526 
527 
529 
538 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
539 class basic_ilostream : public std::basic_istream<CHAR, TRAITS>
540 {
541  using super = std::basic_istream<CHAR, TRAITS>;
542 
543 public:
544  using char_type = CHAR;
545  using traits_type = TRAITS;
546  using int_type = typename traits_type::int_type;
547  using pos_type = typename traits_type::pos_type;
548  using off_type = typename traits_type::off_type;
549 
551 
556  [[deprecated("Use blob instead.")]] basic_ilostream(
557  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
558  super{nullptr},
559  m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
560  {
561  super::init(&m_buf);
562  }
563 
565 
570  [[deprecated("Use blob instead.")]] basic_ilostream(
571  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
572  super{nullptr},
573  m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
574  {
575  super::init(&m_buf);
576  }
577 
578 private:
579  largeobject_streambuf<CHAR, TRAITS> m_buf;
580 };
581 
583 
584 
586 
594 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
595 class basic_olostream : public std::basic_ostream<CHAR, TRAITS>
596 {
597  using super = std::basic_ostream<CHAR, TRAITS>;
598 
599 public:
600  using char_type = CHAR;
601  using traits_type = TRAITS;
602  using int_type = typename traits_type::int_type;
603  using pos_type = typename traits_type::pos_type;
604  using off_type = typename traits_type::off_type;
605 
607 
612  [[deprecated("Use blob instead.")]] basic_olostream(
613  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
614  super{nullptr},
615  m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
616  {
617  super::init(&m_buf);
618  }
619 
621 
626  [[deprecated("Use blob instead.")]] basic_olostream(
627  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
628  super{nullptr},
629  m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
630  {
631  super::init(&m_buf);
632  }
633 
635  {
636  try
637  {
638  m_buf.pubsync();
639  m_buf.pubsync();
640  }
641  catch (std::exception const &e)
642  {
643  m_buf.process_notice(e.what());
644  }
645  }
646 
647 private:
649 };
650 
652 
653 
655 
664 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
665 class basic_lostream : public std::basic_iostream<CHAR, TRAITS>
666 {
667  using super = std::basic_iostream<CHAR, TRAITS>;
668 
669 public:
670  using char_type = CHAR;
671  using traits_type = TRAITS;
672  using int_type = typename traits_type::int_type;
673  using pos_type = typename traits_type::pos_type;
674  using off_type = typename traits_type::off_type;
675 
677 
682  [[deprecated("Use blob instead.")]] basic_lostream(
683  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
684  super{nullptr},
685  m_buf{
686  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
687  {
688  super::init(&m_buf);
689  }
690 
692 
697  [[deprecated("Use blob instead.")]] basic_lostream(
698  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
699  super{nullptr},
700  m_buf{
701  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
702  {
703  super::init(&m_buf);
704  }
705 
707  {
708  try
709  {
710  m_buf.pubsync();
711  m_buf.pubsync();
712  }
713  catch (std::exception const &e)
714  {
715  m_buf.process_notice(e.what());
716  }
717  }
718 
719 private:
721 };
722 
724 } // namespace pqxx
725 #endif
typename traits_type::off_type off_type
Definition: largeobject.hxx:378
std::string to_string(TYPE const &value)
Convert a value to a readable string that PostgreSQL will understand.
bool operator>(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:115
bool operator<=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:97
typename traits_type::int_type int_type
Definition: largeobject.hxx:672
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:547
~basic_olostream()
Definition: largeobject.hxx:634
Definition: blob.hxx:48
virtual int_type overflow(int_type ch) override
Definition: largeobject.hxx:431
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
Definition: largeobject.hxx:419
basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition: largeobject.hxx:682
basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:556
Input stream that gets its data from a large object.
Definition: largeobject.hxx:539
Identity of a large object.
Definition: largeobject.hxx:29
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:37
void process_notice(zview const &s)
For use by large object stream classes.
Definition: largeobject.hxx:409
virtual int_type underflow() override
Definition: largeobject.hxx:475
constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs)
C++20 std::cmp_less_equal, or workaround if not available.
Definition: util.hxx:84
typename traits_type::int_type int_type
Definition: largeobject.hxx:602
typename traits_type::int_type int_type
Definition: largeobject.hxx:546
Stream that reads and writes a large object.
Definition: largeobject.hxx:665
oid id() const noexcept
Object identifier.
Definition: largeobject.hxx:73
TRAITS traits_type
Definition: largeobject.hxx:545
typename traits_type::off_type off_type
Definition: largeobject.hxx:674
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:369
Abstract transaction base class: bracket transactions on the database.
Definition: dbtransaction.hxx:49
CHAR char_type
Definition: largeobject.hxx:544
TRAITS traits_type
Definition: largeobject.hxx:601
void to_file(dbtransaction &t, std::string_view file) const
Export large object&#39;s contents to a local file.
Definition: largeobject.cxx:104
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:328
Internal error in libpqxx library.
Definition: except.hxx:154
largeobjectaccess::seekdir seekdir
Definition: largeobject.hxx:380
bool operator>=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:103
Output stream that writes data back to a large object.
Definition: largeobject.hxx:595
CHAR char_type
Definition: largeobject.hxx:374
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:673
~largeobjectaccess() noexcept
Definition: largeobject.hxx:212
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:379
TO check_cast(FROM value, std::string_view description)
Cast a numeric value to another type, or throw if it underflows/overflows.
Definition: util.hxx:136
void write(std::string_view buf)
Write string to large object.
Definition: largeobject.hxx:247
static PQXX_PURE internal::pq::PGconn * raw_connection(dbtransaction const &T)
Definition: largeobject.cxx:136
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:377
typename traits_type::int_type int_type
Definition: largeobject.hxx:376
TRAITS traits_type
Definition: largeobject.hxx:375
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:22
bool operator!=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:91
virtual int sync() override
Definition: largeobject.hxx:412
largeobject_streambuf(dbtransaction &t, oid o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:394
size_type off_type
Definition: largeobject.hxx:153
bool operator==(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:85
basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition: largeobject.hxx:697
virtual int_type overflow()
Definition: largeobject.hxx:473
basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:570
typename traits_type::off_type off_type
Definition: largeobject.hxx:548
basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition: largeobject.hxx:612
virtual ~largeobject_streambuf() noexcept
Definition: largeobject.hxx:402
TRAITS traits_type
Definition: largeobject.hxx:671
void to_file(std::string_view file) const
Export large object&#39;s contents to a local file.
Definition: largeobject.hxx:224
STL namespace.
largeobject_streambuf(dbtransaction &t, largeobject o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:386
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:603
typename traits_type::off_type off_type
Definition: largeobject.hxx:604
size_type pos_type
Definition: largeobject.hxx:154
std::ios::openmode openmode
Open mode: in, out (can be combined using "bitwise or").
Definition: largeobject.hxx:164
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:171
basic_olostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition: largeobject.hxx:626
CHAR char_type
Definition: largeobject.hxx:670
large_object_size_type size_type
Definition: largeobject.hxx:32
bool operator<(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:109
Accessor for large object&#39;s contents.
Definition: largeobject.hxx:149
CHAR char_type
Definition: largeobject.hxx:600
int64_t large_object_size_type
Number of bytes in a large object.
Definition: types.hxx:39
~basic_lostream()
Definition: largeobject.hxx:706
Connection to a database.
Definition: connection.hxx:180
virtual pos_type seekpos(pos_type pos, openmode) override
Definition: largeobject.hxx:424