libpqxx  7.7.4
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 #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 
87 
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 
239 
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 
287 
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 
328  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;
342  largeobjectaccess(largeobjectaccess const &) = 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)
416  {
417  m_obj.process_notice(s);
418  }
419 
420 protected:
421  virtual int sync() override
422  {
423  // setg() sets eback, gptr, egptr.
424  this->setg(this->eback(), this->eback(), this->egptr());
425  return overflow(eof());
426  }
427 
428  virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
429  {
430  return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
431  }
432 
433  virtual pos_type seekpos(pos_type pos, openmode) override
434  {
435  largeobjectaccess::pos_type const newpos{
436  m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};
437  return adjust_eof(newpos);
438  }
439 
440  virtual int_type overflow(int_type ch) override
441  {
442  auto *const pp{this->pptr()};
443  if (pp == nullptr)
444  return eof();
445  auto *const pb{this->pbase()};
446  int_type res{0};
447 
448  if (pp > pb)
449  {
450  auto const write_sz{pp - pb};
451  auto const written_sz{
452  m_obj.cwrite(pb, static_cast<std::size_t>(pp - pb))};
453  if (internal::cmp_less_equal(written_sz, 0))
454  throw internal_error{
455  "pqxx::largeobject: write failed "
456  "(is transaction still valid on write or flush?), "
457  "libpq reports error"};
458  else if (write_sz != written_sz)
459  throw internal_error{
460  "pqxx::largeobject: write failed "
461  "(is transaction still valid on write or flush?), " +
462  std::to_string(written_sz) + "/" + std::to_string(write_sz) +
463  " bytes written"};
464  auto const out{adjust_eof(written_sz)};
465 
466  if constexpr (std::is_arithmetic_v<decltype(out)>)
467  res = check_cast<int_type>(out, "largeobject position"sv);
468  else
469  res = int_type(out);
470  }
471  this->setp(m_p, m_p + m_bufsize);
472 
473  // Write that one more character, if it's there.
474  if (ch != eof())
475  {
476  *this->pptr() = static_cast<char_type>(ch);
477  this->pbump(1);
478  }
479  return res;
480  }
481 
482  virtual int_type overflow()
483  {
484  return overflow(eof());
485  }
486 
487  virtual int_type underflow() override
488  {
489  if (this->gptr() == nullptr)
490  return eof();
491  auto *const eb{this->eback()};
492  auto const res{adjust_eof(
493  m_obj.cread(this->eback(), static_cast<std::size_t>(m_bufsize)))};
494  this->setg(
495  eb, eb, eb + (res == eof() ? 0 : static_cast<std::size_t>(res)));
496  return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);
497  }
498 
499 private:
501  static int_type eof()
502  {
503  return traits_type::eof();
504  }
505 
507  template<typename INTYPE> static std::streampos adjust_eof(INTYPE pos)
508  {
509  bool const at_eof{pos == -1};
510  if constexpr (std::is_arithmetic_v<std::streampos>)
511  {
512  return check_cast<std::streampos>(
513  (at_eof ? eof() : pos), "large object seek"sv);
514  }
515  else
516  {
517  return std::streampos(at_eof ? eof() : pos);
518  }
519  }
520 
521  void initialize(openmode mode)
522  {
523  if ((mode & std::ios::in) != 0)
524  {
525  m_g = new char_type[unsigned(m_bufsize)];
526  this->setg(m_g, m_g, m_g);
527  }
528  if ((mode & std::ios::out) != 0)
529  {
530  m_p = new char_type[unsigned(m_bufsize)];
531  this->setp(m_p, m_p + m_bufsize);
532  }
533  }
534 
535  size_type const m_bufsize;
536  largeobjectaccess m_obj;
537 
539  char_type *m_g, *m_p;
540 };
541 
542 
544 
553 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
554 class basic_ilostream : public std::basic_istream<CHAR, TRAITS>
555 {
556  using super = std::basic_istream<CHAR, TRAITS>;
557 
558 public:
559  using char_type = CHAR;
560  using traits_type = TRAITS;
561  using int_type = typename traits_type::int_type;
562  using pos_type = typename traits_type::pos_type;
563  using off_type = typename traits_type::off_type;
564 
565 #include "pqxx/internal/ignore-deprecated-pre.hxx"
567 
572  [[deprecated("Use blob instead.")]] basic_ilostream(
573  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
574  super{nullptr},
575  m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
576  {
577  super::init(&m_buf);
578  }
579 #include "pqxx/internal/ignore-deprecated-post.hxx"
580 
582 
587  [[deprecated("Use blob instead.")]] basic_ilostream(
588  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
589  super{nullptr},
590  m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
591  {
592  super::init(&m_buf);
593  }
594 
595 private:
597 };
598 
600 
601 
603 
611 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
612 class basic_olostream : public std::basic_ostream<CHAR, TRAITS>
613 {
614  using super = std::basic_ostream<CHAR, TRAITS>;
615 
616 public:
617  using char_type = CHAR;
618  using traits_type = TRAITS;
619  using int_type = typename traits_type::int_type;
620  using pos_type = typename traits_type::pos_type;
621  using off_type = typename traits_type::off_type;
622 
623 #include "pqxx/internal/ignore-deprecated-pre.hxx"
625 
630  [[deprecated("Use blob instead.")]] basic_olostream(
631  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
632  super{nullptr},
633  m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
634  {
635  super::init(&m_buf);
636  }
637 #include "pqxx/internal/ignore-deprecated-post.hxx"
638 
640 
645  [[deprecated("Use blob instead.")]] basic_olostream(
646  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
647  super{nullptr},
648  m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
649  {
650  super::init(&m_buf);
651  }
652 
654  {
655  try
656  {
657  m_buf.pubsync();
658  m_buf.pubsync();
659  }
660  catch (std::exception const &e)
661  {
662  m_buf.process_notice(e.what());
663  }
664  }
665 
666 private:
668 };
669 
671 
672 
674 
683 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
684 class basic_lostream : public std::basic_iostream<CHAR, TRAITS>
685 {
686  using super = std::basic_iostream<CHAR, TRAITS>;
687 
688 public:
689  using char_type = CHAR;
690  using traits_type = TRAITS;
691  using int_type = typename traits_type::int_type;
692  using pos_type = typename traits_type::pos_type;
693  using off_type = typename traits_type::off_type;
694 
696 
701  [[deprecated("Use blob instead.")]] basic_lostream(
702  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
703  super{nullptr},
704  m_buf{
705  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
706  {
707  super::init(&m_buf);
708  }
709 
711 
716  [[deprecated("Use blob instead.")]] basic_lostream(
717  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
718  super{nullptr},
719  m_buf{
720  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
721  {
722  super::init(&m_buf);
723  }
724 
726  {
727  try
728  {
729  m_buf.pubsync();
730  m_buf.pubsync();
731  }
732  catch (std::exception const &e)
733  {
734  m_buf.process_notice(e.what());
735  }
736  }
737 
738 private:
740 };
741 
743 } // namespace pqxx
744 #endif
basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition: largeobject.hxx:630
virtual int_type underflow() override
Definition: largeobject.hxx:487
Abstract transaction base class: bracket transactions on the database.
Definition: dbtransaction.hxx:53
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
largeobjectaccess::seekdir seekdir
Definition: largeobject.hxx:384
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:175
typename traits_type::int_type int_type
Definition: largeobject.hxx:619
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:587
Connection to a database.
Definition: connection.hxx:184
largeobject_streambuf(dbtransaction &t, largeobject o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:391
virtual pos_type seekpos(pos_type pos, openmode) override
Definition: largeobject.hxx:433
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
~basic_lostream()
Definition: largeobject.hxx:725
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:692
std::ios::openmode openmode
Open mode: in, out (can be combined using "bitwise or").
Definition: largeobject.hxx:168
Input stream that gets its data from a large object.
Definition: largeobject.hxx:554
void to_file(std::string_view file) const
Export large object&#39;s contents to a local file.
Definition: largeobject.hxx:228
void process_notice(zview const &s)
For use by large object stream classes.
Definition: largeobject.hxx:415
Identity of a large object.
Definition: largeobject.hxx:33
static PQXX_PURE internal::pq::PGconn * raw_connection(dbtransaction const &T)
Definition: largeobject.cxx:139
int64_t large_object_size_type
Number of bytes in a large object.
Definition: types.hxx:43
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
Definition: largeobject.hxx:428
CHAR char_type
Definition: largeobject.hxx:617
virtual ~largeobject_streambuf() noexcept
Definition: largeobject.hxx:408
virtual int sync() override
Definition: largeobject.hxx:421
Stream that reads and writes a large object.
Definition: largeobject.hxx:684
typename traits_type::off_type off_type
Definition: largeobject.hxx:563
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:373
typename traits_type::off_type off_type
Definition: largeobject.hxx:621
constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_less_equal, or workaround if not available.
Definition: util.hxx:101
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:344
size_type off_type
Definition: largeobject.hxx:157
TRAITS traits_type
Definition: largeobject.hxx:379
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:645
virtual int_type overflow()
Definition: largeobject.hxx:482
void to_file(dbtransaction &t, std::string_view file) const
Export large object&#39;s contents to a local file.
Definition: largeobject.cxx:107
~basic_olostream()
Definition: largeobject.hxx:653
bool operator!=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:95
void remove(dbtransaction &t) const
Delete large object from database.
Definition: largeobject.cxx:123
CHAR char_type
Definition: largeobject.hxx:559
basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:572
large_object_size_type size_type
Definition: largeobject.hxx:36
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:562
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:383
bool operator==(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:89
size_type pos_type
Definition: largeobject.hxx:158
bool operator>=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:107
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:620
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:381
bool operator<(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:113
Definition: blob.hxx:52
TRAITS traits_type
Definition: largeobject.hxx:618
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:37
TRAITS traits_type
Definition: largeobject.hxx:690
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:154
typename traits_type::off_type off_type
Definition: largeobject.hxx:693
typename traits_type::int_type int_type
Definition: largeobject.hxx:561
TRAITS traits_type
Definition: largeobject.hxx:560
oid id() const noexcept
Object identifier.
Definition: largeobject.hxx:77
virtual int_type overflow(int_type ch) override
Definition: largeobject.hxx:440
CHAR char_type
Definition: largeobject.hxx:689
basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition: largeobject.hxx:716
basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition: largeobject.hxx:701
bool operator>(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:119
bool operator<=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:101
typename traits_type::off_type off_type
Definition: largeobject.hxx:382
Output stream that writes data back to a large object.
Definition: largeobject.hxx:612
typename traits_type::int_type int_type
Definition: largeobject.hxx:691
Internal error in libpqxx library.
Definition: except.hxx:166
Accessor for large object&#39;s contents.
Definition: largeobject.hxx:153
CHAR char_type
Definition: largeobject.hxx:378
std::string to_string(TYPE const &value)
Convert a value to a readable string that PostgreSQL will understand.
typename traits_type::int_type int_type
Definition: largeobject.hxx:380
~largeobjectaccess() noexcept
Definition: largeobject.hxx:216
void write(std::string_view buf)
Write string to large object.
Definition: largeobject.hxx:251