libpqxx  7.6.1
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 "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  [[deprecated("Use blob instead.")]] largeobject() noexcept = default;
40 
42 
44  [[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t);
45 
47 
51  [[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept :
52  m_id{o}
53  {}
54 
56 
60  [[deprecated("Use blob instead.")]] largeobject(
61  dbtransaction &t, std::string_view file);
62 
64 
68  [[deprecated("Use blob instead.")]] largeobject(
69  largeobjectaccess const &o) noexcept;
70 
72 
76  [[nodiscard]] oid id() const noexcept { return m_id; }
77 
87 
88  [[nodiscard]] bool operator==(largeobject const &other) const
89  {
90  return m_id == other.m_id;
91  }
93 
94  [[nodiscard]] bool operator!=(largeobject const &other) const
95  {
96  return m_id != other.m_id;
97  }
99 
100  [[nodiscard]] bool operator<=(largeobject const &other) const
101  {
102  return m_id <= other.m_id;
103  }
105 
106  [[nodiscard]] bool operator>=(largeobject const &other) const
107  {
108  return m_id >= other.m_id;
109  }
111 
112  [[nodiscard]] bool operator<(largeobject const &other) const
113  {
114  return m_id < other.m_id;
115  }
117 
118  [[nodiscard]] bool operator>(largeobject const &other) const
119  {
120  return m_id > other.m_id;
121  }
123 
125 
129  void to_file(dbtransaction &t, std::string_view file) const;
130 
132 
136  void remove(dbtransaction &t) const;
137 
138 protected:
139  PQXX_PURE static internal::pq::PGconn *
140  raw_connection(dbtransaction const &T);
141 
142  PQXX_PRIVATE std::string reason(connection const &, int err) const;
143 
144 private:
145  oid m_id = oid_none;
146 };
147 
148 
150 
152 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
153 {
154 public:
158 
160 
167  using openmode = std::ios::openmode;
168 
170  static constexpr auto default_mode{
171  std::ios::in | std::ios::out | std::ios::binary};
172 
174  using seekdir = std::ios::seekdir;
175 
177 
182  [[deprecated("Use blob instead.")]] explicit largeobjectaccess(
183  dbtransaction &t, openmode mode = default_mode);
184 
186 
193  [[deprecated("Use blob instead.")]] largeobjectaccess(
194  dbtransaction &t, oid o, openmode mode = default_mode);
195 
197 
203  [[deprecated("Use blob instead.")]] largeobjectaccess(
204  dbtransaction &t, largeobject o, openmode mode = default_mode);
205 
207 
212  [[deprecated("Use blob instead.")]] largeobjectaccess(
213  dbtransaction &t, std::string_view file, openmode mode = default_mode);
214 
215  ~largeobjectaccess() noexcept { close(); }
216 
218 
221  using largeobject::id;
222 
224 
227  void to_file(std::string_view file) const
228  {
229  largeobject::to_file(m_trans, file);
230  }
231 
232  using largeobject::to_file;
233 
239 
244  void write(char const buf[], std::size_t len);
245 
247 
250  void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }
251 
253 
259  size_type read(char buf[], std::size_t len);
260 
262 
265  size_type seek(size_type dest, seekdir dir);
266 
268 
271  [[nodiscard]] size_type tell() const;
273 
287 
295  pos_type cseek(off_type dest, seekdir dir) noexcept;
296 
298 
304  off_type cwrite(char const buf[], std::size_t len) noexcept;
305 
307 
313  off_type cread(char buf[], std::size_t len) noexcept;
314 
316 
320  [[nodiscard]] pos_type ctell() const noexcept;
322 
328  void process_notice(zview) noexcept;
330 
331  using largeobject::remove;
332 
333  using largeobject::operator==;
334  using largeobject::operator!=;
335  using largeobject::operator<;
336  using largeobject::operator<=;
337  using largeobject::operator>;
338  using largeobject::operator>=;
339 
340  largeobjectaccess() = delete;
342  largeobjectaccess operator=(largeobjectaccess const &) = delete;
343 
344 private:
345  PQXX_PRIVATE std::string reason(int err) const;
346  internal::pq::PGconn *raw_connection() const
347  {
348  return largeobject::raw_connection(m_trans);
349  }
350 
351  PQXX_PRIVATE void open(openmode mode);
352  void close() noexcept;
353 
354  dbtransaction &m_trans;
355  int m_fd = -1;
356 };
357 
358 
360 
371 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
372 class largeobject_streambuf : public std::basic_streambuf<CHAR, TRAITS>
373 {
374  using size_type = largeobject::size_type;
375 
376 public:
377  using char_type = CHAR;
378  using traits_type = TRAITS;
379  using int_type = typename traits_type::int_type;
380  using pos_type = typename traits_type::pos_type;
381  using off_type = typename traits_type::off_type;
384 
386  static constexpr auto default_mode{
387  std::ios::in | std::ios::out | std::ios::binary};
388 
389  [[deprecated("Use blob instead.")]] largeobject_streambuf(
390  dbtransaction &t, largeobject o, openmode mode = default_mode,
391  size_type buf_size = 512) :
392  m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
393  {
394  initialize(mode);
395  }
396 
397  [[deprecated("Use blob instead.")]] largeobject_streambuf(
398  dbtransaction &t, oid o, openmode mode = default_mode,
399  size_type buf_size = 512) :
400  m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
401  {
402  initialize(mode);
403  }
404 
405  virtual ~largeobject_streambuf() noexcept
406  {
407  delete[] m_p;
408  delete[] m_g;
409  }
410 
412  void process_notice(zview const &s) { m_obj.process_notice(s); }
413 
414 protected:
415  virtual int sync() override
416  {
417  // setg() sets eback, gptr, egptr.
418  this->setg(this->eback(), this->eback(), this->egptr());
419  return overflow(eof());
420  }
421 
422  virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
423  {
424  return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
425  }
426 
427  virtual pos_type seekpos(pos_type pos, openmode) override
428  {
429  largeobjectaccess::pos_type const newpos{
430  m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};
431  return adjust_eof(newpos);
432  }
433 
434  virtual int_type overflow(int_type ch) override
435  {
436  auto *const pp{this->pptr()};
437  if (pp == nullptr)
438  return eof();
439  auto *const pb{this->pbase()};
440  int_type res{0};
441 
442  if (pp > pb)
443  {
444  auto const write_sz{pp - pb};
445  auto const written_sz{
446  m_obj.cwrite(pb, static_cast<std::size_t>(pp - pb))};
447  if (written_sz <= static_cast<off_type>(0))
448  throw internal_error{
449  "pqxx::largeobject: write failed "
450  "(is transaction still valid on write or flush?), "
451  "libpq reports error"};
452  else if (write_sz != written_sz)
453  throw internal_error{
454  "pqxx::largeobject: write failed "
455  "(is transaction still valid on write or flush?), " +
456  std::to_string(written_sz) + "/" + std::to_string(write_sz) +
457  " bytes written"};
458  auto const out{adjust_eof(written_sz)};
459 
460  if constexpr (std::is_arithmetic_v<decltype(out)>)
461  res = check_cast<int_type>(out, "largeobject position"sv);
462  else
463  res = int_type(out);
464  }
465  this->setp(m_p, m_p + m_bufsize);
466 
467  // Write that one more character, if it's there.
468  if (ch != eof())
469  {
470  *this->pptr() = static_cast<char_type>(ch);
471  this->pbump(1);
472  }
473  return res;
474  }
475 
476  virtual int_type overflow() { return overflow(eof()); }
477 
478  virtual int_type underflow() override
479  {
480  if (this->gptr() == nullptr)
481  return eof();
482  auto *const eb{this->eback()};
483  auto const res{adjust_eof(
484  m_obj.cread(this->eback(), static_cast<std::size_t>(m_bufsize)))};
485  this->setg(
486  eb, eb, eb + (res == eof() ? 0 : static_cast<std::size_t>(res)));
487  return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);
488  }
489 
490 private:
492  static int_type eof() { return traits_type::eof(); }
493 
495  template<typename INTYPE> static std::streampos adjust_eof(INTYPE pos)
496  {
497  bool const at_eof{pos == -1};
498  if constexpr (std::is_arithmetic_v<std::streampos>)
499  {
500  return check_cast<std::streampos>(
501  (at_eof ? eof() : pos), "large object seek"sv);
502  }
503  else
504  {
505  return std::streampos(at_eof ? eof() : pos);
506  }
507  }
508 
509  void initialize(openmode mode)
510  {
511  if ((mode & std::ios::in) != 0)
512  {
513  m_g = new char_type[unsigned(m_bufsize)];
514  this->setg(m_g, m_g, m_g);
515  }
516  if ((mode & std::ios::out) != 0)
517  {
518  m_p = new char_type[unsigned(m_bufsize)];
519  this->setp(m_p, m_p + m_bufsize);
520  }
521  }
522 
523  size_type const m_bufsize;
524  largeobjectaccess m_obj;
525 
527  char_type *m_g, *m_p;
528 };
529 
530 
532 
541 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
542 class basic_ilostream : public std::basic_istream<CHAR, TRAITS>
543 {
544  using super = std::basic_istream<CHAR, TRAITS>;
545 
546 public:
547  using char_type = CHAR;
548  using traits_type = TRAITS;
549  using int_type = typename traits_type::int_type;
550  using pos_type = typename traits_type::pos_type;
551  using off_type = typename traits_type::off_type;
552 
554 
559  [[deprecated("Use blob instead.")]] basic_ilostream(
560  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
561  super{nullptr},
562  m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
563  {
564  super::init(&m_buf);
565  }
566 
568 
573  [[deprecated("Use blob instead.")]] basic_ilostream(
574  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
575  super{nullptr},
576  m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
577  {
578  super::init(&m_buf);
579  }
580 
581 private:
583 };
584 
586 
587 
589 
597 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
598 class basic_olostream : public std::basic_ostream<CHAR, TRAITS>
599 {
600  using super = std::basic_ostream<CHAR, TRAITS>;
601 
602 public:
603  using char_type = CHAR;
604  using traits_type = TRAITS;
605  using int_type = typename traits_type::int_type;
606  using pos_type = typename traits_type::pos_type;
607  using off_type = typename traits_type::off_type;
608 
610 
615  [[deprecated("Use blob instead.")]] basic_olostream(
616  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
617  super{nullptr},
618  m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
619  {
620  super::init(&m_buf);
621  }
622 
624 
629  [[deprecated("Use blob instead.")]] basic_olostream(
630  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
631  super{nullptr},
632  m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
633  {
634  super::init(&m_buf);
635  }
636 
638  {
639  try
640  {
641  m_buf.pubsync();
642  m_buf.pubsync();
643  }
644  catch (std::exception const &e)
645  {
646  m_buf.process_notice(e.what());
647  }
648  }
649 
650 private:
652 };
653 
655 
656 
658 
667 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
668 class basic_lostream : public std::basic_iostream<CHAR, TRAITS>
669 {
670  using super = std::basic_iostream<CHAR, TRAITS>;
671 
672 public:
673  using char_type = CHAR;
674  using traits_type = TRAITS;
675  using int_type = typename traits_type::int_type;
676  using pos_type = typename traits_type::pos_type;
677  using off_type = typename traits_type::off_type;
678 
680 
685  [[deprecated("Use blob instead.")]] basic_lostream(
686  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
687  super{nullptr},
688  m_buf{
689  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
690  {
691  super::init(&m_buf);
692  }
693 
695 
700  [[deprecated("Use blob instead.")]] basic_lostream(
701  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
702  super{nullptr},
703  m_buf{
704  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
705  {
706  super::init(&m_buf);
707  }
708 
710  {
711  try
712  {
713  m_buf.pubsync();
714  m_buf.pubsync();
715  }
716  catch (std::exception const &e)
717  {
718  m_buf.process_notice(e.what());
719  }
720  }
721 
722 private:
724 };
725 
727 } // namespace pqxx
728 
729 #include "pqxx/internal/compiler-internal-post.hxx"
730 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:268
int64_t large_object_size_type
Number of bytes in a large object.
Definition: types.hxx:39
Definition: blob.hxx:52
Connection to a database.
Definition: connection.hxx:181
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:88
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:106
bool operator<=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:100
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:112
largeobject() noexcept=default
bool operator!=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:94
bool operator>(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:118
oid id() const noexcept
Object identifier.
Definition: largeobject.hxx:76
Accessor for large object's contents.
Definition: largeobject.hxx:153
size_type pos_type
Definition: largeobject.hxx:157
std::ios::openmode openmode
Open mode: in, out (can be combined using "bitwise or").
Definition: largeobject.hxx:167
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:174
void to_file(std::string_view file) const
Export large object's contents to a local file.
Definition: largeobject.hxx:227
~largeobjectaccess() noexcept
Definition: largeobject.hxx:215
void write(std::string_view buf)
Write string to large object.
Definition: largeobject.hxx:250
size_type off_type
Definition: largeobject.hxx:156
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:373
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
Definition: largeobject.hxx:422
virtual int_type overflow(int_type ch) override
Definition: largeobject.hxx:434
TRAITS traits_type
Definition: largeobject.hxx:378
typename traits_type::int_type int_type
Definition: largeobject.hxx:379
virtual pos_type seekpos(pos_type pos, openmode) override
Definition: largeobject.hxx:427
largeobject_streambuf(dbtransaction &t, oid o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:397
CHAR char_type
Definition: largeobject.hxx:377
typename traits_type::off_type off_type
Definition: largeobject.hxx:381
virtual int_type overflow()
Definition: largeobject.hxx:476
virtual ~largeobject_streambuf() noexcept
Definition: largeobject.hxx:405
void process_notice(zview const &s)
For use by large object stream classes.
Definition: largeobject.hxx:412
virtual int sync() override
Definition: largeobject.hxx:415
largeobjectaccess::seekdir seekdir
Definition: largeobject.hxx:383
virtual int_type underflow() override
Definition: largeobject.hxx:478
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:382
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:380
largeobject_streambuf(dbtransaction &t, largeobject o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:389
Input stream that gets its data from a large object.
Definition: largeobject.hxx:543
basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:573
CHAR char_type
Definition: largeobject.hxx:547
basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:559
typename traits_type::int_type int_type
Definition: largeobject.hxx:549
TRAITS traits_type
Definition: largeobject.hxx:548
typename traits_type::off_type off_type
Definition: largeobject.hxx:551
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:550
Output stream that writes data back to a large object.
Definition: largeobject.hxx:599
typename traits_type::off_type off_type
Definition: largeobject.hxx:607
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:606
basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition: largeobject.hxx:615
typename traits_type::int_type int_type
Definition: largeobject.hxx:605
~basic_olostream()
Definition: largeobject.hxx:637
CHAR char_type
Definition: largeobject.hxx:603
basic_olostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition: largeobject.hxx:629
TRAITS traits_type
Definition: largeobject.hxx:604
Stream that reads and writes a large object.
Definition: largeobject.hxx:669
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:676
~basic_lostream()
Definition: largeobject.hxx:709
typename traits_type::int_type int_type
Definition: largeobject.hxx:675
typename traits_type::off_type off_type
Definition: largeobject.hxx:677
basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition: largeobject.hxx:685
basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition: largeobject.hxx:700
TRAITS traits_type
Definition: largeobject.hxx:674
CHAR char_type
Definition: largeobject.hxx:673
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:40