libpqxx  7.7.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 #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  [[deprecated("Use blob instead.")]] largeobject_streambuf(
391  dbtransaction &t, largeobject o, openmode mode = default_mode,
392  size_type buf_size = 512) :
393  m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
394  {
395  initialize(mode);
396  }
397 
398  [[deprecated("Use blob instead.")]] largeobject_streambuf(
399  dbtransaction &t, oid o, openmode mode = default_mode,
400  size_type buf_size = 512) :
401  m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
402  {
403  initialize(mode);
404  }
405 
406  virtual ~largeobject_streambuf() noexcept
407  {
408  delete[] m_p;
409  delete[] m_g;
410  }
411 
413  void process_notice(zview const &s) { m_obj.process_notice(s); }
414 
415 protected:
416  virtual int sync() override
417  {
418  // setg() sets eback, gptr, egptr.
419  this->setg(this->eback(), this->eback(), this->egptr());
420  return overflow(eof());
421  }
422 
423  virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
424  {
425  return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
426  }
427 
428  virtual pos_type seekpos(pos_type pos, openmode) override
429  {
430  largeobjectaccess::pos_type const newpos{
431  m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};
432  return adjust_eof(newpos);
433  }
434 
435  virtual int_type overflow(int_type ch) override
436  {
437  auto *const pp{this->pptr()};
438  if (pp == nullptr)
439  return eof();
440  auto *const pb{this->pbase()};
441  int_type res{0};
442 
443  if (pp > pb)
444  {
445  auto const write_sz{pp - pb};
446  auto const written_sz{
447  m_obj.cwrite(pb, static_cast<std::size_t>(pp - pb))};
448  if (internal::cmp_less_equal(written_sz, 0))
449  throw internal_error{
450  "pqxx::largeobject: write failed "
451  "(is transaction still valid on write or flush?), "
452  "libpq reports error"};
453  else if (write_sz != written_sz)
454  throw internal_error{
455  "pqxx::largeobject: write failed "
456  "(is transaction still valid on write or flush?), " +
457  std::to_string(written_sz) + "/" + std::to_string(write_sz) +
458  " bytes written"};
459  auto const out{adjust_eof(written_sz)};
460 
461  if constexpr (std::is_arithmetic_v<decltype(out)>)
462  res = check_cast<int_type>(out, "largeobject position"sv);
463  else
464  res = int_type(out);
465  }
466  this->setp(m_p, m_p + m_bufsize);
467 
468  // Write that one more character, if it's there.
469  if (ch != eof())
470  {
471  *this->pptr() = static_cast<char_type>(ch);
472  this->pbump(1);
473  }
474  return res;
475  }
476 
477  virtual int_type overflow() { return overflow(eof()); }
478 
479  virtual int_type underflow() override
480  {
481  if (this->gptr() == nullptr)
482  return eof();
483  auto *const eb{this->eback()};
484  auto const res{adjust_eof(
485  m_obj.cread(this->eback(), static_cast<std::size_t>(m_bufsize)))};
486  this->setg(
487  eb, eb, eb + (res == eof() ? 0 : static_cast<std::size_t>(res)));
488  return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);
489  }
490 
491 private:
493  static int_type eof() { return traits_type::eof(); }
494 
496  template<typename INTYPE> static std::streampos adjust_eof(INTYPE pos)
497  {
498  bool const at_eof{pos == -1};
499  if constexpr (std::is_arithmetic_v<std::streampos>)
500  {
501  return check_cast<std::streampos>(
502  (at_eof ? eof() : pos), "large object seek"sv);
503  }
504  else
505  {
506  return std::streampos(at_eof ? eof() : pos);
507  }
508  }
509 
510  void initialize(openmode mode)
511  {
512  if ((mode & std::ios::in) != 0)
513  {
514  m_g = new char_type[unsigned(m_bufsize)];
515  this->setg(m_g, m_g, m_g);
516  }
517  if ((mode & std::ios::out) != 0)
518  {
519  m_p = new char_type[unsigned(m_bufsize)];
520  this->setp(m_p, m_p + m_bufsize);
521  }
522  }
523 
524  size_type const m_bufsize;
525  largeobjectaccess m_obj;
526 
528  char_type *m_g, *m_p;
529 };
530 
531 
533 
542 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
543 class basic_ilostream : public std::basic_istream<CHAR, TRAITS>
544 {
545  using super = std::basic_istream<CHAR, TRAITS>;
546 
547 public:
548  using char_type = CHAR;
549  using traits_type = TRAITS;
550  using int_type = typename traits_type::int_type;
551  using pos_type = typename traits_type::pos_type;
552  using off_type = typename traits_type::off_type;
553 
555 
560  [[deprecated("Use blob instead.")]] basic_ilostream(
561  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
562  super{nullptr},
563  m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
564  {
565  super::init(&m_buf);
566  }
567 
569 
574  [[deprecated("Use blob instead.")]] basic_ilostream(
575  dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
576  super{nullptr},
577  m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
578  {
579  super::init(&m_buf);
580  }
581 
582 private:
584 };
585 
587 
588 
590 
598 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
599 class basic_olostream : public std::basic_ostream<CHAR, TRAITS>
600 {
601  using super = std::basic_ostream<CHAR, TRAITS>;
602 
603 public:
604  using char_type = CHAR;
605  using traits_type = TRAITS;
606  using int_type = typename traits_type::int_type;
607  using pos_type = typename traits_type::pos_type;
608  using off_type = typename traits_type::off_type;
609 
611 
616  [[deprecated("Use blob instead.")]] basic_olostream(
617  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
618  super{nullptr},
619  m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
620  {
621  super::init(&m_buf);
622  }
623 
625 
630  [[deprecated("Use blob instead.")]] basic_olostream(
631  dbtransaction &t, oid 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 
639  {
640  try
641  {
642  m_buf.pubsync();
643  m_buf.pubsync();
644  }
645  catch (std::exception const &e)
646  {
647  m_buf.process_notice(e.what());
648  }
649  }
650 
651 private:
653 };
654 
656 
657 
659 
668 template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
669 class basic_lostream : public std::basic_iostream<CHAR, TRAITS>
670 {
671  using super = std::basic_iostream<CHAR, TRAITS>;
672 
673 public:
674  using char_type = CHAR;
675  using traits_type = TRAITS;
676  using int_type = typename traits_type::int_type;
677  using pos_type = typename traits_type::pos_type;
678  using off_type = typename traits_type::off_type;
679 
681 
686  [[deprecated("Use blob instead.")]] basic_lostream(
687  dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
688  super{nullptr},
689  m_buf{
690  t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
691  {
692  super::init(&m_buf);
693  }
694 
696 
701  [[deprecated("Use blob instead.")]] basic_lostream(
702  dbtransaction &t, oid 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  {
712  try
713  {
714  m_buf.pubsync();
715  m_buf.pubsync();
716  }
717  catch (std::exception const &e)
718  {
719  m_buf.process_notice(e.what());
720  }
721  }
722 
723 private:
725 };
726 
728 } // namespace pqxx
729 #endif
basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition: largeobject.hxx:616
virtual int_type underflow() override
Definition: largeobject.hxx:479
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:606
basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:574
Connection to a database.
Definition: connection.hxx:185
largeobject_streambuf(dbtransaction &t, largeobject o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:390
virtual pos_type seekpos(pos_type pos, openmode) override
Definition: largeobject.hxx:428
largeobject_streambuf(dbtransaction &t, oid o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:398
~basic_lostream()
Definition: largeobject.hxx:710
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:677
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:543
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:413
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:423
CHAR char_type
Definition: largeobject.hxx:604
virtual ~largeobject_streambuf() noexcept
Definition: largeobject.hxx:406
virtual int sync() override
Definition: largeobject.hxx:416
Stream that reads and writes a large object.
Definition: largeobject.hxx:669
typename traits_type::off_type off_type
Definition: largeobject.hxx:552
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:373
typename traits_type::off_type off_type
Definition: largeobject.hxx:608
constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_less_equal, or workaround if not available.
Definition: util.hxx:92
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:335
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)
Create a basic_olostream.
Definition: largeobject.hxx:630
virtual int_type overflow()
Definition: largeobject.hxx:477
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:638
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:548
basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:560
large_object_size_type size_type
Definition: largeobject.hxx:36
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:551
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:607
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:605
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:37
TRAITS traits_type
Definition: largeobject.hxx:675
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:145
typename traits_type::off_type off_type
Definition: largeobject.hxx:678
typename traits_type::int_type int_type
Definition: largeobject.hxx:550
TRAITS traits_type
Definition: largeobject.hxx:549
oid id() const noexcept
Object identifier.
Definition: largeobject.hxx:77
virtual int_type overflow(int_type ch) override
Definition: largeobject.hxx:435
CHAR char_type
Definition: largeobject.hxx:674
basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition: largeobject.hxx:701
basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition: largeobject.hxx:686
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:599
typename traits_type::int_type int_type
Definition: largeobject.hxx:676
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