libpqxx  7.5.2
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-2021, 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 "pqxx/compiler-public.hxx"
15 #include "pqxx/internal/compiler-internal-pre.hxx"
16 
17 #include <streambuf>
18 
19 #include "pqxx/dbtransaction.hxx"
20 
21 
22 namespace pqxx
23 {
25 
32 class PQXX_LIBEXPORT largeobject
33 {
34 public:
36 
39  PQXX_DEPRECATED("Use blob instead.") largeobject() noexcept = default;
40 
42 
44  PQXX_DEPRECATED("Use blob instead.") explicit largeobject(dbtransaction &t);
45 
47 
51  PQXX_DEPRECATED("Use blob instead.")
52  explicit largeobject(oid o) noexcept : m_id{o} {}
53 
55 
59  PQXX_DEPRECATED("Use blob instead.")
60  largeobject(dbtransaction &t, std::string_view file);
61 
63 
67  PQXX_DEPRECATED("Use blob instead.")
68  largeobject(largeobjectaccess const &o) noexcept;
69 
71 
75  [[nodiscard]] oid id() const noexcept { return m_id; }
76 
86 
87  [[nodiscard]] bool operator==(largeobject const &other) const
88  {
89  return m_id == other.m_id;
90  }
92 
93  [[nodiscard]] bool operator!=(largeobject const &other) const
94  {
95  return m_id != other.m_id;
96  }
98 
99  [[nodiscard]] bool operator<=(largeobject const &other) const
100  {
101  return m_id <= other.m_id;
102  }
104 
105  [[nodiscard]] bool operator>=(largeobject const &other) const
106  {
107  return m_id >= other.m_id;
108  }
110 
111  [[nodiscard]] bool operator<(largeobject const &other) const
112  {
113  return m_id < other.m_id;
114  }
116 
117  [[nodiscard]] bool operator>(largeobject const &other) const
118  {
119  return m_id > other.m_id;
120  }
122 
124 
128  void to_file(dbtransaction &t, std::string_view file) const;
129 
131 
135  void remove(dbtransaction &t) const;
136 
137 protected:
138  PQXX_PURE static internal::pq::PGconn *
139  raw_connection(dbtransaction const &T);
140 
141  PQXX_PRIVATE std::string reason(connection const &, int err) const;
142 
143 private:
144  oid m_id = oid_none;
145 };
146 
147 
149 
151 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
152 {
153 public:
157 
159 
166  using openmode = std::ios::openmode;
167 
169  static constexpr auto default_mode{
170  std::ios::in | std::ios::out | std::ios::binary};
171 
173  using seekdir = std::ios::seekdir;
174 
176 
181  PQXX_DEPRECATED("Use blob instead.")
182  explicit largeobjectaccess(dbtransaction &t, openmode mode = default_mode);
183 
185 
192  PQXX_DEPRECATED("Use blob instead.")
193  largeobjectaccess(dbtransaction &t, oid o, openmode mode = default_mode);
194 
196 
202  PQXX_DEPRECATED("Use blob instead.")
204  dbtransaction &t, largeobject o, openmode mode = default_mode);
205 
207 
212  PQXX_DEPRECATED("Use blob instead.")
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(buf.data(), 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  PQXX_DEPRECATED("Use blob instead.")
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 
399  PQXX_DEPRECATED("Use blob instead.")
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 (written_sz <= static_cast<off_type>(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 
557 
562  PQXX_DEPRECATED("Use blob instead.")
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 
572 
577  PQXX_DEPRECATED("Use blob instead.")
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:
587  largeobject_streambuf<CHAR, TRAITS> m_buf;
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 
615 
620  PQXX_DEPRECATED("Use blob instead.")
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 
630 
635  PQXX_DEPRECATED("Use blob instead.")
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  PQXX_DEPRECATED("Use blob instead.")
694  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
695  super{nullptr},
696  m_buf{
697  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
698  {
699  super::init(&m_buf);
700  }
701 
703 
708  PQXX_DEPRECATED("Use blob instead.")
710  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
711  super{nullptr},
712  m_buf{
713  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
714  {
715  super::init(&m_buf);
716  }
717 
719  {
720  try
721  {
722  m_buf.pubsync();
723  m_buf.pubsync();
724  }
725  catch (std::exception const &e)
726  {
727  m_buf.process_notice(e.what());
728  }
729  }
730 
731 private:
733 };
734 
736 } // namespace pqxx
737 
738 #include "pqxx/internal/compiler-internal-post.hxx"
739 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:215
int64_t large_object_size_type
Number of bytes in a large object.
Definition: types.hxx:33
Definition: blob.hxx:44
Connection to a database.
Definition: connection.hxx:184
Abstract transaction base class: bracket transactions on the database.
Definition: dbtransaction.hxx:53
Internal error in libpqxx library.
Definition: except.hxx:158
Identity of a large object.
Definition: largeobject.hxx:33
bool operator==(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:87
static PQXX_PURE internal::pq::PGconn * raw_connection(dbtransaction const &T)
Definition: largeobject.cxx:133
bool operator>=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:105
bool operator<=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:99
void to_file(dbtransaction &t, std::string_view file) const
Export large object's contents to a local file.
Definition: largeobject.cxx:101
large_object_size_type size_type
Definition: largeobject.hxx:35
bool operator<(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:111
bool operator!=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:93
bool operator>(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:117
oid id() const noexcept
Object identifier.
Definition: largeobject.hxx:75
Accessor for large object's contents.
Definition: largeobject.hxx:152
size_type pos_type
Definition: largeobject.hxx:156
std::ios::openmode openmode
Open mode: in, out (can be combined using "bitwise or").
Definition: largeobject.hxx:166
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:173
void to_file(std::string_view file) const
Export large object's contents to a local file.
Definition: largeobject.hxx:228
void write(std::string_view buf)
Write string to large object.
Definition: largeobject.hxx:251
size_type off_type
Definition: largeobject.hxx:155
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
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
Input stream that gets its data from a large object.
Definition: largeobject.hxx:546
CHAR char_type
Definition: largeobject.hxx:550
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
typename traits_type::int_type int_type
Definition: largeobject.hxx:610
~basic_olostream()
Definition: largeobject.hxx:644
CHAR char_type
Definition: largeobject.hxx:608
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:718
typename traits_type::int_type int_type
Definition: largeobject.hxx:682
typename traits_type::off_type off_type
Definition: largeobject.hxx:684
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