libpqxx  5.0
largeobject.hxx
1 /*-------------------------------------------------------------------------
2  *
3  * FILE
4  * pqxx/largeobject.hxx
5  *
6  * DESCRIPTION
7  * libpqxx's Large Objects interface
8  * Allows access to large objects directly, or through I/O streams
9  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
10  *
11  * Copyright (c) 2003-2015, Jeroen T. Vermeulen <jtv@xs4all.nl>
12  *
13  * See COPYING for copyright license. If you did not receive a file called
14  * COPYING with this source code, please notify the distributor of this mistake,
15  * or contact the author.
16  *
17  *-------------------------------------------------------------------------
18  */
19 #ifndef PQXX_H_LARGEOBJECT
20 #define PQXX_H_LARGEOBJECT
21 
22 #include "pqxx/compiler-public.hxx"
23 #include "pqxx/compiler-internal-pre.hxx"
24 
25 #include <streambuf>
26 
27 #include "pqxx/dbtransaction"
28 
29 
30 namespace pqxx
31 {
32 
33 class largeobjectaccess;
34 
36 
43 class PQXX_LIBEXPORT largeobject
44 {
45 public:
46  typedef long size_type;
47 
49  largeobject() PQXX_NOEXCEPT; //[t48]
50 
52 
54  explicit largeobject(dbtransaction &T); //[t48]
55 
57 
61  explicit largeobject(oid O) PQXX_NOEXCEPT : m_ID(O) {} //[t48]
62 
64 
68  largeobject(dbtransaction &T, const std::string &File); //[t53]
69 
71 
75  largeobject(const largeobjectaccess &O) PQXX_NOEXCEPT; //[t50]
76 
78 
82  oid id() const PQXX_NOEXCEPT { return m_ID; } //[t48]
83 
92 
94  bool operator==(const largeobject &other) const //[t51]
95  { return m_ID == other.m_ID; }
97 
98  bool operator!=(const largeobject &other) const //[t51]
99  { return m_ID != other.m_ID; }
101 
102  bool operator<=(const largeobject &other) const //[t51]
103  { return m_ID <= other.m_ID; }
105 
106  bool operator>=(const largeobject &other) const //[t51]
107  { return m_ID >= other.m_ID; }
109 
110  bool operator<(const largeobject &other) const //[t51]
111  { return m_ID < other.m_ID; }
113 
114  bool operator>(const largeobject &other) const //[t51]
115  { return m_ID > other.m_ID; }
117 
119 
123  void to_file(dbtransaction &T, const std::string &File) const; //[t52]
124 
126 
130  void remove(dbtransaction &T) const; //[t48]
131 
132 protected:
133  PQXX_PURE static internal::pq::PGconn *RawConnection(const dbtransaction &T);
134 
135  std::string Reason(int err) const;
136 
137 private:
138  oid m_ID;
139 };
140 
141 
142 // TODO: New hierarchy with separate read / write / mixed-mode access
143 
145 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
146 {
147 public:
149  typedef long off_type;
151 
153 
157  typedef std::ios::openmode openmode;
158 
160 
164  typedef std::ios::seekdir seekdir;
165 
167 
171  explicit largeobjectaccess(dbtransaction &T,
172  openmode mode=std::ios::in|std::ios::out); //[t51]
173 
175 
182  oid O,
183  openmode mode=std::ios::in|std::ios::out); //[t52]
184 
186 
192  largeobject O,
193  openmode mode=std::ios::in|std::ios::out); //[t50]
194 
196 
202  const std::string &File,
203  openmode mode=std::ios::in|std::ios::out); //[t55]
204 
205  ~largeobjectaccess() PQXX_NOEXCEPT { close(); }
206 
208 
211  using largeobject::id;
212 
214 
217  void to_file(const std::string &File) const //[t54]
218  { largeobject::to_file(m_Trans, File); }
219 
220  using largeobject::to_file;
221 
226 
231  void write(const char Buf[], size_type Len); //[t51]
232 
234 
237  void write(const std::string &Buf) //[t50]
238  { write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
239 
241 
247  size_type read(char Buf[], size_type Len); //[t50]
248 
250 
253  size_type seek(size_type dest, seekdir dir); //[t51]
254 
256 
259  size_type tell() const; //[t50]
261 
271 
280  pos_type cseek(off_type dest, seekdir dir) PQXX_NOEXCEPT; //[t50]
281 
283 
289  off_type cwrite(const char Buf[], size_type Len) PQXX_NOEXCEPT; //[t50]
290 
292 
298  off_type cread(char Buf[], size_type Len) PQXX_NOEXCEPT; //[t50]
299 
301 
305  pos_type ctell() const PQXX_NOEXCEPT; //[t50]
307 
312  void process_notice(const std::string &) PQXX_NOEXCEPT; //[t50]
315 
316  using largeobject::remove;
317 
318  using largeobject::operator==;
319  using largeobject::operator!=;
320  using largeobject::operator<;
321  using largeobject::operator<=;
322  using largeobject::operator>;
323  using largeobject::operator>=;
324 
325 private:
326  PQXX_PRIVATE std::string Reason(int err) const;
327  internal::pq::PGconn *RawConnection() const
328  { return largeobject::RawConnection(m_Trans); }
329 
330  void open(openmode mode);
331  void close() PQXX_NOEXCEPT;
332 
333  dbtransaction &m_Trans;
334  int m_fd;
335 
336  // Not allowed:
337  largeobjectaccess() PQXX_DELETED_OP;
338  largeobjectaccess(const largeobjectaccess &) PQXX_DELETED_OP;
339  largeobjectaccess operator=(const largeobjectaccess &) PQXX_DELETED_OP;
340 };
341 
342 
344 
352 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
354  public std::basic_streambuf<CHAR, TRAITS>
355 {
356  typedef long size_type;
357 public:
358  typedef CHAR char_type;
359  typedef TRAITS traits_type;
360  typedef typename traits_type::int_type int_type;
361  typedef typename traits_type::pos_type pos_type;
362  typedef typename traits_type::off_type off_type;
365 
367  largeobject O,
368  openmode mode=std::ios::in|std::ios::out,
369  size_type BufSize=512) : //[t48]
370  m_BufSize(BufSize),
371  m_Obj(T, O, mode),
372  m_G(0),
373  m_P(0)
374  { initialize(mode); }
375 
377  oid O,
378  openmode mode=std::ios::in|std::ios::out,
379  size_type BufSize=512) : //[t48]
380  m_BufSize(BufSize),
381  m_Obj(T, O, mode),
382  m_G(0),
383  m_P(0)
384  { initialize(mode); }
385 
386  virtual ~largeobject_streambuf() PQXX_NOEXCEPT
387  { delete [] m_P; delete [] m_G; }
388 
389 
391  void process_notice(const std::string &s) { m_Obj.process_notice(s); }
392 
393 protected:
394  virtual int sync() PQXX_OVERRIDE
395  {
396  // setg() sets eback, gptr, egptr
397  this->setg(this->eback(), this->eback(), this->egptr());
398  return overflow(EoF());
399  }
400 
401 protected:
402  virtual pos_type seekoff(off_type offset,
403  seekdir dir,
404  openmode) PQXX_OVERRIDE
405  {
406  return AdjustEOF(m_Obj.cseek(largeobjectaccess::off_type(offset), dir));
407  }
408 
409  virtual pos_type seekpos(pos_type pos, openmode) PQXX_OVERRIDE
410  {
411  const largeobjectaccess::pos_type newpos = m_Obj.cseek(
413  std::ios::beg);
414  return AdjustEOF(newpos);
415  }
416 
417  virtual int_type overflow(int_type ch = EoF()) PQXX_OVERRIDE
418  {
419  char *const pp = this->pptr();
420  if (!pp) return EoF();
421  char *const pb = this->pbase();
422  int_type res = 0;
423 
424  if (pp > pb) res = int_type(AdjustEOF(m_Obj.cwrite(pb, pp-pb)));
425  this->setp(m_P, m_P + m_BufSize);
426 
427  // Write that one more character, if it's there.
428  if (ch != EoF())
429  {
430  *this->pptr() = char(ch);
431  this->pbump(1);
432  }
433  return res;
434  }
435 
436  virtual int_type underflow() PQXX_OVERRIDE
437  {
438  if (!this->gptr()) return EoF();
439  char *const eb = this->eback();
440  const int_type res(static_cast<int_type>(
441  AdjustEOF(m_Obj.cread(this->eback(), m_BufSize))));
442  this->setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
443  return (!res || (res == EoF())) ? EoF() : *eb;
444  }
445 
446 private:
448  static int_type EoF() { return traits_type::eof(); }
449 
451  template<typename INTYPE>
452  static std::streampos AdjustEOF(INTYPE pos)
453  { return (pos==-1) ? std::streampos(EoF()) : std::streampos(pos); }
454 
455  void initialize(openmode mode)
456  {
457  if (mode & std::ios::in)
458  {
459  m_G = new char_type[unsigned(m_BufSize)];
460  this->setg(m_G, m_G, m_G);
461  }
462  if (mode & std::ios::out)
463  {
464  m_P = new char_type[unsigned(m_BufSize)];
465  this->setp(m_P, m_P + m_BufSize);
466  }
467  }
468 
469  const size_type m_BufSize;
470  largeobjectaccess m_Obj;
471 
472  // Get & put buffers
473  char_type *m_G, *m_P;
474 };
475 
476 
478 
486 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
488  public std::basic_istream<CHAR, TRAITS>
489 {
490  typedef std::basic_istream<CHAR, TRAITS> super;
491 
492 public:
493  typedef CHAR char_type;
494  typedef TRAITS traits_type;
495  typedef typename traits_type::int_type int_type;
496  typedef typename traits_type::pos_type pos_type;
497  typedef typename traits_type::off_type off_type;
498 
500 
506  largeobject O,
507  largeobject::size_type BufSize=512) : //[t57]
508  super(0),
509  m_Buf(T, O, std::ios::in, BufSize)
510  { super::init(&m_Buf); }
511 
513 
519  oid O,
520  largeobject::size_type BufSize=512) : //[t48]
521  super(0),
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  typedef std::basic_ostream<CHAR, TRAITS> super;
546 public:
547  typedef CHAR char_type;
548  typedef TRAITS traits_type;
549  typedef typename traits_type::int_type int_type;
550  typedef typename traits_type::pos_type pos_type;
551  typedef typename traits_type::off_type off_type;
552 
554 
560  largeobject O,
561  largeobject::size_type BufSize=512) : //[t48]
562  super(0),
563  m_Buf(T, O, std::ios::out, BufSize)
564  { super::init(&m_Buf); }
565 
567 
573  oid O,
574  largeobject::size_type BufSize=512) : //[t57]
575  super(0),
576  m_Buf(T, O, std::ios::out, BufSize)
577  { super::init(&m_Buf); }
578 
580  {
581  try
582  {
583  m_Buf.pubsync(); m_Buf.pubsync();
584  }
585  catch (const std::exception &e)
586  {
587  m_Buf.process_notice(e.what());
588  }
589  }
590 
591 private:
593 };
594 
596 
597 
599 
607 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR> >
609  public std::basic_iostream<CHAR, TRAITS>
610 {
611  typedef std::basic_iostream<CHAR, TRAITS> super;
612 
613 public:
614  typedef CHAR char_type;
615  typedef TRAITS traits_type;
616  typedef typename traits_type::int_type int_type;
617  typedef typename traits_type::pos_type pos_type;
618  typedef typename traits_type::off_type off_type;
619 
621 
627  largeobject O,
628  largeobject::size_type BufSize=512) : //[t59]
629  super(0),
630  m_Buf(T, O, std::ios::in | std::ios::out, BufSize)
631  { super::init(&m_Buf); }
632 
634 
640  oid O,
641  largeobject::size_type BufSize=512) : //[t59]
642  super(0),
643  m_Buf(T, O, std::ios::in | std::ios::out, BufSize)
644  { super::init(&m_Buf); }
645 
647  {
648  try
649  {
650  m_Buf.pubsync(); m_Buf.pubsync();
651  }
652  catch (const std::exception &e)
653  {
654  m_Buf.process_notice(e.what());
655  }
656  }
657 
658 private:
660 };
661 
663 
664 } // namespace pqxx
665 
666 #include "pqxx/compiler-internal-post.hxx"
667 
668 #endif
669 
void process_notice(const std::string &s)
For use by large object stream classes.
Definition: largeobject.hxx:391
virtual int_type underflow() PQXX_OVERRIDE
Definition: largeobject.hxx:436
traits_type::off_type off_type
Definition: largeobject.hxx:551
virtual pos_type seekpos(pos_type pos, openmode) PQXX_OVERRIDE
Definition: largeobject.hxx:409
traits_type::pos_type pos_type
Definition: largeobject.hxx:496
std::ios::openmode openmode
Open mode: in, out (can be combined with the &quot;or&quot; operator)
Definition: largeobject.hxx:157
Accessor for large object&#39;s contents.
Definition: largeobject.hxx:145
traits_type::int_type int_type
Definition: largeobject.hxx:495
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:164
basic_ilostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:518
~largeobjectaccess() PQXX_NOEXCEPT
Definition: largeobject.hxx:205
bool operator!=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:98
basic_olostream< char > olostream
Definition: largeobject.hxx:595
TRAITS traits_type
Definition: largeobject.hxx:494
oid id() const PQXX_NOEXCEPT
Object identifier.
Definition: largeobject.hxx:82
CHAR char_type
Definition: largeobject.hxx:547
basic_ilostream< char > ilostream
Definition: largeobject.hxx:529
basic_ilostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:505
bool operator<(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:110
traits_type::pos_type pos_type
Definition: largeobject.hxx:361
long size_type
Definition: largeobject.hxx:46
bool operator==(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:94
long off_type
Definition: largeobject.hxx:149
basic_olostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:572
~basic_lostream()
Definition: largeobject.hxx:646
traits_type::pos_type pos_type
Definition: largeobject.hxx:617
Output stream that writes data back to a large object.
Definition: largeobject.hxx:542
Input stream that gets its data from a large object.
Definition: largeobject.hxx:487
basic_lostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:626
TRAITS traits_type
Definition: largeobject.hxx:359
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:353
traits_type::off_type off_type
Definition: largeobject.hxx:497
traits_type::off_type off_type
Definition: largeobject.hxx:618
basic_lostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:639
CHAR char_type
Definition: largeobject.hxx:493
~basic_olostream()
Definition: largeobject.hxx:579
TRAITS traits_type
Definition: largeobject.hxx:548
traits_type::int_type int_type
Definition: largeobject.hxx:549
basic_olostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:559
largeobject_streambuf(dbtransaction &T, largeobject O, openmode mode=std::ios::in|std::ios::out, size_type BufSize=512)
Definition: largeobject.hxx:366
traits_type::int_type int_type
Definition: largeobject.hxx:360
traits_type::int_type int_type
Definition: largeobject.hxx:616
CHAR char_type
Definition: largeobject.hxx:358
Stream that reads and writes a large object.
Definition: largeobject.hxx:608
traits_type::off_type off_type
Definition: largeobject.hxx:362
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:363
Identity of a large object.
Definition: largeobject.hxx:43
void to_file(dbtransaction &T, const std::string &File) const
Export large object&#39;s contents to a local file.
Definition: largeobject.cxx:115
TRAITS traits_type
Definition: largeobject.hxx:615
bool operator>(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:114
CHAR char_type
Definition: largeobject.hxx:614
largeobjectaccess::seekdir seekdir
Definition: largeobject.hxx:364
Definition: dbtransaction.hxx:68
virtual int_type overflow(int_type ch=EoF()) PQXX_OVERRIDE
Definition: largeobject.hxx:417
traits_type::pos_type pos_type
Definition: largeobject.hxx:550
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) PQXX_OVERRIDE
Definition: largeobject.hxx:402
bool operator<=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:102
void write(const std::string &Buf)
Write string to large object.
Definition: largeobject.hxx:237
largeobject_streambuf(dbtransaction &T, oid O, openmode mode=std::ios::in|std::ios::out, size_type BufSize=512)
Definition: largeobject.hxx:376
virtual int sync() PQXX_OVERRIDE
Definition: largeobject.hxx:394
static PQXX_PURE internal::pq::PGconn * RawConnection(const dbtransaction &T)
Definition: largeobject.cxx:141
size_type pos_type
Definition: largeobject.hxx:150
basic_lostream< char > lostream
Definition: largeobject.hxx:662
bool operator>=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:106
void to_file(const std::string &File) const
Export large object&#39;s contents to a local file.
Definition: largeobject.hxx:217
virtual ~largeobject_streambuf() PQXX_NOEXCEPT
Definition: largeobject.hxx:386