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  char *const eb = this->eback();
438  const int_type res(static_cast<int_type>(
439  AdjustEOF(m_obj.cread(this->eback(), m_bufsize))));
440  this->setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
441  return ((res == 0) or (res == EoF())) ? EoF() : *eb;
442  }
443 
444 private:
446  static int_type EoF() { return traits_type::eof(); }
447 
449  template<typename INTYPE>
450  static std::streampos AdjustEOF(INTYPE pos)
451  { return (pos==-1) ? std::streampos(EoF()) : std::streampos(pos); }
452 
453  void initialize(openmode mode)
454  {
455  if (mode & std::ios::in)
456  {
457  m_g = new char_type[unsigned(m_bufsize)];
458  this->setg(m_g, m_g, m_g);
459  }
460  if (mode & std::ios::out)
461  {
462  m_p = new char_type[unsigned(m_bufsize)];
463  this->setp(m_p, m_p + m_bufsize);
464  }
465  }
466 
467  const size_type m_bufsize;
468  largeobjectaccess m_obj;
469 
471  char_type *m_g, *m_p;
472 };
473 
474 
476 
484 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
486  public std::basic_istream<CHAR, TRAITS>
487 {
488  using super = std::basic_istream<CHAR, TRAITS>;
489 
490 public:
491  using char_type = CHAR;
492  using traits_type = TRAITS;
493  using int_type = typename traits_type::int_type;
494  using pos_type = typename traits_type::pos_type;
495  using off_type = typename traits_type::off_type;
496 
498 
504  dbtransaction &T,
505  largeobject O,
506  largeobject::size_type BufSize=512) :
507  super{nullptr},
508  m_buf{T, O, std::ios::in, BufSize}
509  { super::init(&m_buf); }
510 
512 
518  dbtransaction &T,
519  oid O,
520  largeobject::size_type BufSize=512) :
521  super{nullptr},
522  m_buf{T, O, std::ios::in, BufSize}
523  { super::init(&m_buf); }
524 
525 private:
527 };
528 
530 
531 
533 
541 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
543  public std::basic_ostream<CHAR, TRAITS>
544 {
545  using super = std::basic_ostream<CHAR, TRAITS>;
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 
560  dbtransaction &T,
561  largeobject O,
562  largeobject::size_type BufSize=512) :
563  super{nullptr},
564  m_buf{T, O, std::ios::out, BufSize}
565  { super::init(&m_buf); }
566 
568 
574  dbtransaction &T,
575  oid O,
576  largeobject::size_type BufSize=512) :
577  super{nullptr},
578  m_buf{T, O, std::ios::out, BufSize}
579  { super::init(&m_buf); }
580 
582  {
583  try
584  {
585  m_buf.pubsync(); m_buf.pubsync();
586  }
587  catch (const std::exception &e)
588  {
589  m_buf.process_notice(e.what());
590  }
591  }
592 
593 private:
595 };
596 
598 
599 
601 
609 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
611  public std::basic_iostream<CHAR, TRAITS>
612 {
613  using super = std::basic_iostream<CHAR, TRAITS>;
614 
615 public:
616  using char_type = CHAR;
617  using traits_type = TRAITS;
618  using int_type = typename traits_type::int_type;
619  using pos_type = typename traits_type::pos_type;
620  using off_type = typename traits_type::off_type;
621 
623 
628  basic_lostream( //[t59]
629  dbtransaction &T,
630  largeobject O,
631  largeobject::size_type BufSize=512) :
632  super{nullptr},
633  m_buf{T, O, std::ios::in | std::ios::out, BufSize}
634  { super::init(&m_buf); }
635 
637 
642  basic_lostream( //[t59]
643  dbtransaction &T,
644  oid O,
645  largeobject::size_type BufSize=512) :
646  super{nullptr},
647  m_buf{T, O, std::ios::in | std::ios::out, BufSize}
648  { super::init(&m_buf); }
649 
651  {
652  try
653  {
654  m_buf.pubsync(); m_buf.pubsync();
655  }
656  catch (const std::exception &e)
657  {
658  m_buf.process_notice(e.what());
659  }
660  }
661 
662 private:
664 };
665 
667 
668 } // namespace pqxx
669 
670 #include "pqxx/compiler-internal-post.hxx"
671 
672 #endif
typename traits_type::off_type off_type
Definition: largeobject.hxx:357
~largeobjectaccess() noexcept
Definition: largeobject.hxx:201
CHAR char_type
Definition: largeobject.hxx:547
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:616
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:485
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:642
typename traits_type::int_type int_type
Definition: largeobject.hxx:355
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:494
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:548
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:77
typename traits_type::int_type int_type
Definition: largeobject.hxx:549
TRAITS traits_type
Definition: largeobject.hxx:492
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:573
basic_lostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:628
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:610
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:619
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:495
basic_ilostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:517
virtual ~largeobject_streambuf() noexcept
Definition: largeobject.hxx:383
typename traits_type::off_type off_type
Definition: largeobject.hxx:551
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:542
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:620
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:503
void remove(dbtransaction &T) const
Delete large object from database.
Definition: largeobject.cxx:121
TRAITS traits_type
Definition: largeobject.hxx:617
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:650
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:618
basic_olostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:559
typename traits_type::int_type int_type
Definition: largeobject.hxx:493
~basic_olostream()
Definition: largeobject.hxx:581
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:550
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:358
CHAR char_type
Definition: largeobject.hxx:491
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