libpqxx
largeobject.hxx
1 
13 #ifndef PQXX_H_LARGEOBJECT
14 #define PQXX_H_LARGEOBJECT
15 
16 #include "pqxx/compiler-public.hxx"
17 #include "pqxx/compiler-internal-pre.hxx"
18 
19 #include <streambuf>
20 
21 #include "pqxx/dbtransaction.hxx"
22 
23 
24 namespace pqxx
25 {
27 
34 class PQXX_LIBEXPORT largeobject
35 {
36 public:
38 
40  largeobject() noexcept =default; //[t48]
41 
43 
45  explicit largeobject(dbtransaction &T); //[t48]
46 
48 
52  explicit largeobject(oid O) noexcept : m_id{O} {} //[t48]
53 
55 
59  largeobject(dbtransaction &T, const std::string &File); //[t53]
60 
62 
66  largeobject(const largeobjectaccess &O) noexcept; //[t50]
67 
69 
73  oid id() const noexcept { return m_id; } //[t48]
74 
83 
85  bool operator==(const largeobject &other) const //[t51]
86  { return m_id == other.m_id; }
88 
89  bool operator!=(const largeobject &other) const //[t51]
90  { return m_id != other.m_id; }
92 
93  bool operator<=(const largeobject &other) const //[t51]
94  { return m_id <= other.m_id; }
96 
97  bool operator>=(const largeobject &other) const //[t51]
98  { return m_id >= other.m_id; }
100 
101  bool operator<(const largeobject &other) const //[t51]
102  { return m_id < other.m_id; }
104 
105  bool operator>(const largeobject &other) const //[t51]
106  { return m_id > other.m_id; }
108 
110 
114  void to_file(dbtransaction &T, const std::string &File) const; //[t52]
115 
117 
121  void remove(dbtransaction &T) const; //[t48]
122 
123 protected:
124  PQXX_PURE static internal::pq::PGconn *raw_connection(
125  const dbtransaction &T);
126 
127  PQXX_PRIVATE std::string reason(const connection_base &, int err) const;
128 
129 private:
130  oid m_id = oid_none;
131 };
132 
133 
134 // TODO: New hierarchy with separate read / write / mixed-mode access
135 
137 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
138 {
139 public:
141  using off_type = long;
143 
145 
149  using openmode = std::ios::openmode;
150 
152 
156  using seekdir = std::ios::seekdir;
157 
159 
163  explicit largeobjectaccess( //[t51]
164  dbtransaction &T,
165  openmode mode=std::ios::in|std::ios::out);
166 
168 
174  largeobjectaccess( //[t52]
175  dbtransaction &T,
176  oid O,
177  openmode mode=std::ios::in|std::ios::out);
178 
180 
185  largeobjectaccess( //[t50]
186  dbtransaction &T,
187  largeobject O,
188  openmode mode=std::ios::in|std::ios::out);
189 
191 
196  largeobjectaccess( //[t55]
197  dbtransaction &T,
198  const std::string &File,
199  openmode mode=std::ios::in|std::ios::out);
200 
201  ~largeobjectaccess() noexcept { close(); }
202 
204 
207  using largeobject::id;
208 
210 
213  void to_file(const std::string &File) const //[t54]
214  { largeobject::to_file(m_trans, File); }
215 
216  using largeobject::to_file;
217 
222 
227  void write(const char Buf[], size_type Len); //[t51]
228 
230 
233  void write(const std::string &Buf) //[t50]
234  { write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
235 
237 
243  size_type read(char Buf[], size_type Len); //[t50]
244 
246 
249  size_type seek(size_type dest, seekdir dir); //[t51]
250 
252 
255  size_type tell() const; //[t50]
257 
267 
276  pos_type cseek(off_type dest, seekdir dir) noexcept; //[t50]
277 
279 
285  off_type cwrite(const char Buf[], size_type Len) noexcept; //[t50]
286 
288 
294  off_type cread(char Buf[], size_type Len) noexcept; //[t50]
295 
297 
301  pos_type ctell() const noexcept; //[t50]
303 
308  void process_notice(const std::string &) noexcept; //[t50]
311 
312  using largeobject::remove;
313 
314  using largeobject::operator==;
315  using largeobject::operator!=;
316  using largeobject::operator<;
317  using largeobject::operator<=;
318  using largeobject::operator>;
319  using largeobject::operator>=;
320 
321 private:
322  PQXX_PRIVATE std::string reason(int err) const;
323  internal::pq::PGconn *raw_connection() const
324  { return largeobject::raw_connection(m_trans); }
325 
326  PQXX_PRIVATE void open(openmode mode);
327  void close() noexcept;
328 
329  dbtransaction &m_trans;
330  int m_fd = -1;
331 
332  largeobjectaccess() =delete;
333  largeobjectaccess(const largeobjectaccess &) =delete;
334  largeobjectaccess operator=(const largeobjectaccess &) =delete;
335 };
336 
337 
339 
347 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
349  public std::basic_streambuf<CHAR, TRAITS>
350 {
351  using size_type = long;
352 public:
353  using char_type = CHAR;
354  using traits_type = TRAITS;
355  using int_type = typename traits_type::int_type;
356  using pos_type = typename traits_type::pos_type;
357  using off_type = typename traits_type::off_type;
360 
362  dbtransaction &T,
363  largeobject O,
364  openmode mode=std::ios::in|std::ios::out,
365  size_type BufSize=512) :
366  m_bufsize{BufSize},
367  m_obj{T, O, mode},
368  m_g{nullptr},
369  m_p{nullptr}
370  { initialize(mode); }
371 
373  dbtransaction &T,
374  oid O,
375  openmode mode=std::ios::in|std::ios::out,
376  size_type BufSize=512) :
377  m_bufsize{BufSize},
378  m_obj{T, O, mode},
379  m_g{nullptr},
380  m_p{nullptr}
381  { initialize(mode); }
382 
383  virtual ~largeobject_streambuf() noexcept
384  { delete [] m_p; delete [] m_g; }
385 
386 
388  void process_notice(const std::string &s) { m_obj.process_notice(s); }
389 
390 protected:
391  virtual int sync() override
392  {
393  // setg() sets eback, gptr, egptr
394  this->setg(this->eback(), this->eback(), this->egptr());
395  return overflow(EoF());
396  }
397 
398  virtual pos_type seekoff(
399  off_type offset,
400  seekdir dir,
401  openmode)
402  override
403  {
404  return AdjustEOF(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
405  }
406 
407  virtual pos_type seekpos(pos_type pos, openmode) override
408  {
409  const largeobjectaccess::pos_type newpos = m_obj.cseek(
411  std::ios::beg);
412  return AdjustEOF(newpos);
413  }
414 
415  virtual int_type overflow(int_type ch = EoF()) override
416  {
417  char *const pp = this->pptr();
418  if (pp == nullptr) return EoF();
419  char *const pb = this->pbase();
420  int_type res = 0;
421 
422  if (pp > pb) res = int_type(AdjustEOF(m_obj.cwrite(pb, pp-pb)));
423  this->setp(m_p, m_p + m_bufsize);
424 
425  // Write that one more character, if it's there.
426  if (ch != EoF())
427  {
428  *this->pptr() = char(ch);
429  this->pbump(1);
430  }
431  return res;
432  }
433 
434  virtual int_type underflow() override
435  {
436  if (this->gptr() == nullptr) return EoF();
437  auto *const eb{this->eback()};
438  auto const res = AdjustEOF(
439  m_obj.cread(this->eback(), static_cast<std::size_t>(m_bufsize)));
440  this->setg(
441  eb, eb, eb + (res == EoF() ? 0 : static_cast<std::size_t>(res)));
442  return (res == EoF() || res == 0) ? EoF() : traits_type::to_int_type(*eb);
443  }
444 
445 private:
447  static int_type EoF() { return traits_type::eof(); }
448 
450  template<typename INTYPE>
451  static std::streampos AdjustEOF(INTYPE pos)
452  { return (pos==-1) ? std::streampos(EoF()) : std::streampos(pos); }
453 
454  void initialize(openmode mode)
455  {
456  if (mode & std::ios::in)
457  {
458  m_g = new char_type[unsigned(m_bufsize)];
459  this->setg(m_g, m_g, m_g);
460  }
461  if (mode & std::ios::out)
462  {
463  m_p = new char_type[unsigned(m_bufsize)];
464  this->setp(m_p, m_p + m_bufsize);
465  }
466  }
467 
468  const size_type m_bufsize;
469  largeobjectaccess m_obj;
470 
472  char_type *m_g, *m_p;
473 };
474 
475 
477 
485 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
487  public std::basic_istream<CHAR, TRAITS>
488 {
489  using super = std::basic_istream<CHAR, TRAITS>;
490 
491 public:
492  using char_type = CHAR;
493  using traits_type = TRAITS;
494  using int_type = typename traits_type::int_type;
495  using pos_type = typename traits_type::pos_type;
496  using off_type = typename traits_type::off_type;
497 
499 
505  dbtransaction &T,
506  largeobject O,
507  largeobject::size_type BufSize=512) :
508  super{nullptr},
509  m_buf{T, O, std::ios::in, BufSize}
510  { super::init(&m_buf); }
511 
513 
519  dbtransaction &T,
520  oid O,
521  largeobject::size_type BufSize=512) :
522  super{nullptr},
523  m_buf{T, O, std::ios::in, BufSize}
524  { super::init(&m_buf); }
525 
526 private:
528 };
529 
531 
532 
534 
542 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
544  public std::basic_ostream<CHAR, TRAITS>
545 {
546  using super = std::basic_ostream<CHAR, TRAITS>;
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 
561  dbtransaction &T,
562  largeobject O,
563  largeobject::size_type BufSize=512) :
564  super{nullptr},
565  m_buf{T, O, std::ios::out, BufSize}
566  { super::init(&m_buf); }
567 
569 
575  dbtransaction &T,
576  oid O,
577  largeobject::size_type BufSize=512) :
578  super{nullptr},
579  m_buf{T, O, std::ios::out, BufSize}
580  { super::init(&m_buf); }
581 
583  {
584  try
585  {
586  m_buf.pubsync(); m_buf.pubsync();
587  }
588  catch (const std::exception &e)
589  {
590  m_buf.process_notice(e.what());
591  }
592  }
593 
594 private:
596 };
597 
599 
600 
602 
610 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
612  public std::basic_iostream<CHAR, TRAITS>
613 {
614  using super = std::basic_iostream<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 
624 
629  basic_lostream( //[t59]
630  dbtransaction &T,
631  largeobject O,
632  largeobject::size_type BufSize=512) :
633  super{nullptr},
634  m_buf{T, O, std::ios::in | std::ios::out, BufSize}
635  { super::init(&m_buf); }
636 
638 
643  basic_lostream( //[t59]
644  dbtransaction &T,
645  oid O,
646  largeobject::size_type BufSize=512) :
647  super{nullptr},
648  m_buf{T, O, std::ios::in | std::ios::out, BufSize}
649  { super::init(&m_buf); }
650 
652  {
653  try
654  {
655  m_buf.pubsync(); m_buf.pubsync();
656  }
657  catch (const std::exception &e)
658  {
659  m_buf.process_notice(e.what());
660  }
661  }
662 
663 private:
665 };
666 
668 
669 } // namespace pqxx
670 
671 #include "pqxx/compiler-internal-post.hxx"
672 
673 #endif
typename traits_type::off_type off_type
Definition: largeobject.hxx:357
~largeobjectaccess() noexcept
Definition: largeobject.hxx:201
CHAR char_type
Definition: largeobject.hxx:548
long off_type
Definition: largeobject.hxx:141
void to_file(dbtransaction &T, const std::string &File) const
Export large object&#39;s contents to a local file.
Definition: largeobject.cxx:106
virtual pos_type seekpos(pos_type pos, openmode) override
Definition: largeobject.hxx:407
bool operator>(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:105
CHAR char_type
Definition: largeobject.hxx:617
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
Definition: largeobject.hxx:398
void process_notice(const std::string &s)
For use by large object stream classes.
Definition: largeobject.hxx:388
bool operator<=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:93
TRAITS traits_type
Definition: largeobject.hxx:354
Input stream that gets its data from a large object.
Definition: largeobject.hxx:486
std::ios::openmode openmode
Open mode: in, out (can be combined with the "or" operator)
Definition: largeobject.hxx:149
basic_lostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:643
typename traits_type::int_type int_type
Definition: largeobject.hxx:355
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:495
connection_base abstract base class; represents a connection to a database.
Definition: connection_base.hxx:139
largeobjectaccess::seekdir seekdir
Definition: largeobject.hxx:359
TRAITS traits_type
Definition: largeobject.hxx:549
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:77
typename traits_type::int_type int_type
Definition: largeobject.hxx:550
TRAITS traits_type
Definition: largeobject.hxx:493
Identity of a large object.
Definition: largeobject.hxx:34
basic_olostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:574
basic_lostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:629
CHAR char_type
Definition: largeobject.hxx:353
bool operator<(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:101
Stream that reads and writes a large object.
Definition: largeobject.hxx:611
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:620
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:348
Abstract base class responsible for bracketing a backend transaction.
Definition: dbtransaction.hxx:62
virtual int sync() override
Definition: largeobject.hxx:391
typename traits_type::off_type off_type
Definition: largeobject.hxx:496
basic_ilostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:518
virtual ~largeobject_streambuf() noexcept
Definition: largeobject.hxx:383
typename traits_type::off_type off_type
Definition: largeobject.hxx:552
largeobject_streambuf(dbtransaction &T, largeobject O, openmode mode=std::ios::in|std::ios::out, size_type BufSize=512)
Definition: largeobject.hxx:361
largeobject_streambuf(dbtransaction &T, oid O, openmode mode=std::ios::in|std::ios::out, size_type BufSize=512)
Definition: largeobject.hxx:372
Output stream that writes data back to a large object.
Definition: largeobject.hxx:543
virtual int_type underflow() override
Definition: largeobject.hxx:434
Accessor for large object&#39;s contents.
Definition: largeobject.hxx:137
typename traits_type::off_type off_type
Definition: largeobject.hxx:621
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:156
bool operator!=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:89
static PQXX_PURE internal::pq::PGconn * raw_connection(const dbtransaction &T)
Definition: largeobject.cxx:134
basic_ilostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:504
void remove(dbtransaction &T) const
Delete large object from database.
Definition: largeobject.cxx:121
TRAITS traits_type
Definition: largeobject.hxx:618
long large_object_size_type
Number of bytes in a large object. (Unusual: it&#39;s signed.)
Definition: types.hxx:33
size_type pos_type
Definition: largeobject.hxx:142
~basic_lostream()
Definition: largeobject.hxx:651
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
void write(const std::string &Buf)
Write string to large object.
Definition: largeobject.hxx:233
typename traits_type::int_type int_type
Definition: largeobject.hxx:619
basic_olostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:560
typename traits_type::int_type int_type
Definition: largeobject.hxx:494
~basic_olostream()
Definition: largeobject.hxx:582
bool operator==(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:85
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:356
void to_file(const std::string &File) const
Export large object&#39;s contents to a local file.
Definition: largeobject.hxx:213
large_object_size_type size_type
Definition: largeobject.hxx:37
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:551
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:358
CHAR char_type
Definition: largeobject.hxx:492
oid id() const noexcept
Object identifier.
Definition: largeobject.hxx:73
bool operator>=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:97
virtual int_type overflow(int_type ch=EoF()) override
Definition: largeobject.hxx:415