libpqxx  7.9.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-2024, 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 #if !defined(PQXX_HEADER_PRE)
15 # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
16 #endif
17 
18 #include <streambuf>
19 
20 #include "pqxx/dbtransaction.hxx"
21 
22 
23 namespace pqxx
24 {
26 
33 class PQXX_LIBEXPORT largeobject
34 {
35 public:
37 
40  [[deprecated("Use blob instead.")]] largeobject() noexcept = default;
41 
43 
45  [[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t);
46 
48 
52  [[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept :
53  m_id{o}
54  {}
55 
57 
61  [[deprecated("Use blob instead.")]] largeobject(
62  dbtransaction &t, std::string_view file);
63 
65 
69  [[deprecated("Use blob instead.")]] largeobject(
70  largeobjectaccess const &o) noexcept;
71 
73 
77  [[nodiscard]] oid id() const noexcept { return m_id; }
78 
88 
89  [[nodiscard]] bool operator==(largeobject const &other) const
90  {
91  return m_id == other.m_id;
92  }
94 
95  [[nodiscard]] bool operator!=(largeobject const &other) const
96  {
97  return m_id != other.m_id;
98  }
100 
101  [[nodiscard]] bool operator<=(largeobject const &other) const
102  {
103  return m_id <= other.m_id;
104  }
106 
107  [[nodiscard]] bool operator>=(largeobject const &other) const
108  {
109  return m_id >= other.m_id;
110  }
112 
113  [[nodiscard]] bool operator<(largeobject const &other) const
114  {
115  return m_id < other.m_id;
116  }
118 
119  [[nodiscard]] bool operator>(largeobject const &other) const
120  {
121  return m_id > other.m_id;
122  }
124 
126 
130  void to_file(dbtransaction &t, std::string_view file) const;
131 
133 
137  void remove(dbtransaction &t) const;
138 
139 protected:
140  PQXX_PURE static internal::pq::PGconn *
141  raw_connection(dbtransaction const &T);
142 
143  PQXX_PRIVATE std::string reason(connection const &, int err) const;
144 
145 private:
146  oid m_id = oid_none;
147 };
148 
149 
151 
153 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
154 {
155 public:
159 
161 
168  using openmode = std::ios::openmode;
169 
171  static constexpr auto default_mode{
172  std::ios::in | std::ios::out | std::ios::binary};
173 
175  using seekdir = std::ios::seekdir;
176 
178 
183  [[deprecated("Use blob instead.")]] explicit largeobjectaccess(
184  dbtransaction &t, openmode mode = default_mode);
185 
187 
194  [[deprecated("Use blob instead.")]] largeobjectaccess(
195  dbtransaction &t, oid o, openmode mode = default_mode);
196 
198 
204  [[deprecated("Use blob instead.")]] largeobjectaccess(
205  dbtransaction &t, largeobject o, openmode mode = default_mode);
206 
208 
213  [[deprecated("Use blob instead.")]] largeobjectaccess(
214  dbtransaction &t, std::string_view file, openmode mode = default_mode);
215 
216  ~largeobjectaccess() noexcept { close(); }
217 
219 
222  using largeobject::id;
223 
225 
228  void to_file(std::string_view file) const
229  {
230  largeobject::to_file(m_trans, file);
231  }
232 
233  using largeobject::to_file;
234 
240 
245  void write(char const buf[], std::size_t len);
246 
248 
251  void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }
252 
254 
260  size_type read(char buf[], std::size_t len);
261 
263 
266  size_type seek(size_type dest, seekdir dir);
267 
269 
272  [[nodiscard]] size_type tell() const;
274 
288 
296  pos_type cseek(off_type dest, seekdir dir) noexcept;
297 
299 
305  off_type cwrite(char const buf[], std::size_t len) noexcept;
306 
308 
314  off_type cread(char buf[], std::size_t len) noexcept;
315 
317 
321  [[nodiscard]] pos_type ctell() const noexcept;
323 
329  void process_notice(zview) noexcept;
331 
332  using largeobject::remove;
333 
334  using largeobject::operator==;
335  using largeobject::operator!=;
336  using largeobject::operator<;
337  using largeobject::operator<=;
338  using largeobject::operator>;
339  using largeobject::operator>=;
340 
341  largeobjectaccess() = delete;
343  largeobjectaccess operator=(largeobjectaccess const &) = delete;
344 
345 private:
346  PQXX_PRIVATE std::string reason(int err) const;
347  internal::pq::PGconn *raw_connection() const
348  {
349  return largeobject::raw_connection(m_trans);
350  }
351 
352  PQXX_PRIVATE void open(openmode mode);
353  void close() noexcept;
354 
355  dbtransaction &m_trans;
356  int m_fd = -1;
357 };
358 
359 
361 
372 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
373 class largeobject_streambuf : public std::basic_streambuf<CHAR, TRAITS>
374 {
375  using size_type = largeobject::size_type;
376 
377 public:
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;
385 
387  static constexpr auto default_mode{
388  std::ios::in | std::ios::out | std::ios::binary};
389 
390 #include "pqxx/internal/ignore-deprecated-pre.hxx"
391  [[deprecated("Use blob instead.")]] largeobject_streambuf(
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}
395  {
396  initialize(mode);
397  }
398 #include "pqxx/internal/ignore-deprecated-post.hxx"
399 
400  [[deprecated("Use blob instead.")]] largeobject_streambuf(
401  dbtransaction &t, oid o, openmode mode = default_mode,
402  size_type buf_size = 512) :
403  m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
404  {
405  initialize(mode);
406  }
407 
408  virtual ~largeobject_streambuf() noexcept
409  {
410  delete[] m_p;
411  delete[] m_g;
412  }
413 
415  void process_notice(zview const &s) { m_obj.process_notice(s); }
416 
417 protected:
418  virtual int sync() override
419  {
420  // setg() sets eback, gptr, egptr.
421  this->setg(this->eback(), this->eback(), this->egptr());
422  return overflow(eof());
423  }
424 
425  virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
426  {
427  return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
428  }
429 
430  virtual pos_type seekpos(pos_type pos, openmode) override
431  {
432  largeobjectaccess::pos_type const newpos{
433  m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};
434  return adjust_eof(newpos);
435  }
436 
437  virtual int_type overflow(int_type ch) override
438  {
439  auto *const pp{this->pptr()};
440  if (pp == nullptr)
441  return eof();
442  auto *const pb{this->pbase()};
443  int_type res{0};
444 
445  if (pp > pb)
446  {
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) +
460  " bytes written"};
461  auto const out{adjust_eof(written_sz)};
462 
463  if constexpr (std::is_arithmetic_v<decltype(out)>)
464  res = check_cast<int_type>(out, "largeobject position"sv);
465  else
466  res = int_type(out);
467  }
468  this->setp(m_p, m_p + m_bufsize);
469 
470  // Write that one more character, if it's there.
471  if (ch != eof())
472  {
473  *this->pptr() = static_cast<char_type>(ch);
474  this->pbump(1);
475  }
476  return res;
477  }
478 
479  virtual int_type overflow() { return overflow(eof()); }
480 
481  virtual int_type underflow() override
482  {
483  if (this->gptr() == nullptr)
484  return eof();
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)))};
488  this->setg(
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);
491  }
492 
493 private:
495  static int_type eof() { return traits_type::eof(); }
496 
498  template<typename INTYPE> static std::streampos adjust_eof(INTYPE pos)
499  {
500  bool const at_eof{pos == -1};
501  if constexpr (std::is_arithmetic_v<std::streampos>)
502  {
503  return check_cast<std::streampos>(
504  (at_eof ? eof() : pos), "large object seek"sv);
505  }
506  else
507  {
508  return std::streampos(at_eof ? eof() : pos);
509  }
510  }
511 
512  void initialize(openmode mode)
513  {
514  if ((mode & std::ios::in) != 0)
515  {
516  m_g = new char_type[unsigned(m_bufsize)];
517  this->setg(m_g, m_g, m_g);
518  }
519  if ((mode & std::ios::out) != 0)
520  {
521  m_p = new char_type[unsigned(m_bufsize)];
522  this->setp(m_p, m_p + m_bufsize);
523  }
524  }
525 
526  size_type const m_bufsize;
527  largeobjectaccess m_obj;
528 
530  char_type *m_g, *m_p;
531 };
532 
533 
535 
544 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
545 class basic_ilostream : public std::basic_istream<CHAR, TRAITS>
546 {
547  using super = std::basic_istream<CHAR, TRAITS>;
548 
549 public:
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;
555 
556 #include "pqxx/internal/ignore-deprecated-pre.hxx"
558 
563  [[deprecated("Use blob instead.")]] basic_ilostream(
564  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
565  super{nullptr},
566  m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
567  {
568  super::init(&m_buf);
569  }
570 #include "pqxx/internal/ignore-deprecated-post.hxx"
571 
573 
578  [[deprecated("Use blob instead.")]] basic_ilostream(
579  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
580  super{nullptr},
581  m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
582  {
583  super::init(&m_buf);
584  }
585 
586 private:
588 };
589 
591 
592 
594 
602 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
603 class basic_olostream : public std::basic_ostream<CHAR, TRAITS>
604 {
605  using super = std::basic_ostream<CHAR, TRAITS>;
606 
607 public:
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;
613 
614 #include "pqxx/internal/ignore-deprecated-pre.hxx"
616 
621  [[deprecated("Use blob instead.")]] basic_olostream(
622  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
623  super{nullptr},
624  m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
625  {
626  super::init(&m_buf);
627  }
628 #include "pqxx/internal/ignore-deprecated-post.hxx"
629 
631 
636  [[deprecated("Use blob instead.")]] basic_olostream(
637  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
638  super{nullptr},
639  m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
640  {
641  super::init(&m_buf);
642  }
643 
645  {
646  try
647  {
648  m_buf.pubsync();
649  m_buf.pubsync();
650  }
651  catch (std::exception const &e)
652  {
653  m_buf.process_notice(e.what());
654  }
655  }
656 
657 private:
659 };
660 
662 
663 
665 
674 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
675 class basic_lostream : public std::basic_iostream<CHAR, TRAITS>
676 {
677  using super = std::basic_iostream<CHAR, TRAITS>;
678 
679 public:
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;
685 
687 
692  [[deprecated("Use blob instead.")]] basic_lostream(
693  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
694  super{nullptr},
695  m_buf{
696  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
697  {
698  super::init(&m_buf);
699  }
700 
702 
707  [[deprecated("Use blob instead.")]] basic_lostream(
708  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
709  super{nullptr},
710  m_buf{
711  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
712  {
713  super::init(&m_buf);
714  }
715 
717  {
718  try
719  {
720  m_buf.pubsync();
721  m_buf.pubsync();
722  }
723  catch (std::exception const &e)
724  {
725  m_buf.process_notice(e.what());
726  }
727  }
728 
729 private:
731 };
732 
734 } // namespace pqxx
735 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:33
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:445
int64_t large_object_size_type
Number of bytes in a large object.
Definition: types.hxx:43
constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_less_equal, or workaround if not available.
Definition: util.hxx:98
Definition: blob.hxx:55
Connection to a database.
Definition: connection.hxx:233
Abstract transaction base class: bracket transactions on the database.
Definition: dbtransaction.hxx:54
Internal error in libpqxx library.
Definition: except.hxx:242
Identity of a large object.
Definition: largeobject.hxx:34
bool operator==(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:89
bool operator>=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:107
static PQXX_PURE internal::pq::PGconn * raw_connection(dbtransaction const &T)
Definition: largeobject.cxx:139
bool operator<=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:101
large_object_size_type size_type
Definition: largeobject.hxx:36
bool operator<(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:113
largeobject() noexcept=default
void to_file(dbtransaction &t, std::string_view file) const
Export large object's contents to a local file.
Definition: largeobject.cxx:107
bool operator!=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:95
bool operator>(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:119
oid id() const noexcept
Object identifier.
Definition: largeobject.hxx:77
Accessor for large object's contents.
Definition: largeobject.hxx:154
size_type pos_type
Definition: largeobject.hxx:158
std::ios::openmode openmode
Open mode: in, out (can be combined using "bitwise or").
Definition: largeobject.hxx:168
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:175
void to_file(std::string_view file) const
Export large object's contents to a local file.
Definition: largeobject.hxx:228
~largeobjectaccess() noexcept
Definition: largeobject.hxx:216
void write(std::string_view buf)
Write string to large object.
Definition: largeobject.hxx:251
size_type off_type
Definition: largeobject.hxx:157
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:374
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
Definition: largeobject.hxx:425
virtual int_type overflow(int_type ch) override
Definition: largeobject.hxx:437
TRAITS traits_type
Definition: largeobject.hxx:379
typename traits_type::int_type int_type
Definition: largeobject.hxx:380
virtual pos_type seekpos(pos_type pos, openmode) override
Definition: largeobject.hxx:430
largeobject_streambuf(dbtransaction &t, oid o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:400
CHAR char_type
Definition: largeobject.hxx:378
typename traits_type::off_type off_type
Definition: largeobject.hxx:382
virtual int_type overflow()
Definition: largeobject.hxx:479
virtual ~largeobject_streambuf() noexcept
Definition: largeobject.hxx:408
void process_notice(zview const &s)
For use by large object stream classes.
Definition: largeobject.hxx:415
virtual int sync() override
Definition: largeobject.hxx:418
largeobjectaccess::seekdir seekdir
Definition: largeobject.hxx:384
virtual int_type underflow() override
Definition: largeobject.hxx:481
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:383
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:381
largeobject_streambuf(dbtransaction &t, largeobject o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:391
Input stream that gets its data from a large object.
Definition: largeobject.hxx:546
basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:578
CHAR char_type
Definition: largeobject.hxx:550
basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:563
typename traits_type::int_type int_type
Definition: largeobject.hxx:552
TRAITS traits_type
Definition: largeobject.hxx:551
typename traits_type::off_type off_type
Definition: largeobject.hxx:554
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:553
Output stream that writes data back to a large object.
Definition: largeobject.hxx:604
typename traits_type::off_type off_type
Definition: largeobject.hxx:612
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:611
basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition: largeobject.hxx:621
typename traits_type::int_type int_type
Definition: largeobject.hxx:610
~basic_olostream()
Definition: largeobject.hxx:644
CHAR char_type
Definition: largeobject.hxx:608
basic_olostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition: largeobject.hxx:636
TRAITS traits_type
Definition: largeobject.hxx:609
Stream that reads and writes a large object.
Definition: largeobject.hxx:676
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:683
~basic_lostream()
Definition: largeobject.hxx:716
typename traits_type::int_type int_type
Definition: largeobject.hxx:682
typename traits_type::off_type off_type
Definition: largeobject.hxx:684
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
TRAITS traits_type
Definition: largeobject.hxx:681
CHAR char_type
Definition: largeobject.hxx:680
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:38