libpqxx  4.0.1
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-2012, 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 #ifdef PQXX_HAVE_STREAMBUF
26 #include <streambuf>
27 #else
28 #include <streambuf.h>
29 #endif
30 
31 #include "pqxx/dbtransaction"
32 
33 
34 namespace pqxx
35 {
36 
37 class largeobjectaccess;
38 
40 
47 class PQXX_LIBEXPORT largeobject
48 {
49 public:
50  typedef long size_type;
51 
53  largeobject() throw (); //[t48]
54 
56 
58  explicit largeobject(dbtransaction &T); //[t48]
59 
61 
65  explicit largeobject(oid O) throw () : m_ID(O) {} //[t48]
66 
68 
72  largeobject(dbtransaction &T, const PGSTD::string &File); //[t53]
73 
75 
79  largeobject(const largeobjectaccess &O) throw (); //[t50]
80 
82 
86  oid id() const throw () { return m_ID; } //[t48]
87 
96 
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 
118  bool operator>(const largeobject &other) const //[t51]
119  { return m_ID > other.m_ID; }
121 
123 
127  void to_file(dbtransaction &T, const PGSTD::string &File) const; //[t52]
128 
130 
134  void remove(dbtransaction &T) const; //[t48]
135 
136 protected:
137  static internal::pq::PGconn * PQXX_PURE RawConnection(const dbtransaction &T);
138 
139  PGSTD::string Reason(int err) const;
140 
141 private:
142  oid m_ID;
143 };
144 
145 
146 // TODO: New hierarchy with separate read / write / mixed-mode access
147 
149 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
150 {
151 public:
153  typedef long off_type;
155 
157 
161  typedef PGSTD::ios::openmode openmode;
162 
164 
168  typedef PGSTD::ios::seekdir seekdir;
169 
171 
175  explicit largeobjectaccess(dbtransaction &T,
176  openmode mode =
177  PGSTD::ios::in |
178  PGSTD::ios::out); //[t51]
179 
181 
188  oid O,
189  openmode mode =
190  PGSTD::ios::in |
191  PGSTD::ios::out); //[t52]
192 
194 
200  largeobject O,
201  openmode mode = PGSTD::ios::in | PGSTD::ios::out); //[t50]
202 
204 
210  const PGSTD::string &File,
211  openmode mode =
212  PGSTD::ios::in | PGSTD::ios::out); //[t55]
213 
214  ~largeobjectaccess() throw () { close(); }
215 
217 
220  using largeobject::id;
221 
223 
226  void to_file(const PGSTD::string &File) const //[t54]
227  { largeobject::to_file(m_Trans, File); }
228 
229 #ifdef PQXX_BROKEN_USING_DECL
230 
231 
235  void to_file(dbtransaction &T, const PGSTD::string &F) const
236  { largeobject::to_file(T, F); }
237 #else
238  using largeobject::to_file;
239 #endif
240 
245 
246 
250  void write(const char Buf[], size_type Len); //[t51]
251 
253 
256  void write(const PGSTD::string &Buf) //[t50]
257  { write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
258 
260 
266  size_type read(char Buf[], size_type Len); //[t50]
267 
269 
272  size_type seek(size_type dest, seekdir dir); //[t51]
273 
275 
278  size_type tell() const; //[t50]
280 
290 
291 
299  pos_type cseek(off_type dest, seekdir dir) throw (); //[t50]
300 
302 
308  off_type cwrite(const char Buf[], size_type Len) throw (); //[t50]
309 
311 
317  off_type cread(char Buf[], size_type Len) throw (); //[t50]
318 
320 
324  pos_type ctell() const throw (); //[t50]
326 
331 
332  void process_notice(const PGSTD::string &) throw (); //[t50]
334 
335  using largeobject::remove;
336 
337  using largeobject::operator==;
338  using largeobject::operator!=;
339  using largeobject::operator<;
340  using largeobject::operator<=;
341  using largeobject::operator>;
342  using largeobject::operator>=;
343 
344 private:
345  PGSTD::string PQXX_PRIVATE Reason(int err) const;
346  internal::pq::PGconn *RawConnection() const
347  { return largeobject::RawConnection(m_Trans); }
348 
349  void open(openmode mode);
350  void close() throw ();
351 
352  dbtransaction &m_Trans;
353  int m_fd;
354 
355  // Not allowed:
356  largeobjectaccess();
357  largeobjectaccess(const largeobjectaccess &);
358  largeobjectaccess operator=(const largeobjectaccess &);
359 };
360 
361 
363 
371 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
373 #ifdef PQXX_HAVE_STREAMBUF
374  public PGSTD::basic_streambuf<CHAR, TRAITS>
375 #else
376  public PGSTD::streambuf
377 #endif
378 {
379  typedef long size_type;
380 public:
381  typedef CHAR char_type;
382  typedef TRAITS traits_type;
383  typedef typename traits_type::int_type int_type;
384 #ifdef PQXX_HAVE_STREAMBUF
385  typedef typename traits_type::pos_type pos_type;
386  typedef typename traits_type::off_type off_type;
387 #else
388  typedef streamoff off_type;
389  typedef streampos pos_type;
390 #endif
393 
395  largeobject O,
396  openmode mode = PGSTD::ios::in | PGSTD::ios::out,
397  size_type BufSize=512) : //[t48]
398  m_BufSize(BufSize),
399  m_Obj(T, O, mode),
400  m_G(0),
401  m_P(0)
402  { initialize(mode); }
403 
405  oid O,
406  openmode mode = PGSTD::ios::in | PGSTD::ios::out,
407  size_type BufSize=512) : //[t48]
408  m_BufSize(BufSize),
409  m_Obj(T, O, mode),
410  m_G(0),
411  m_P(0)
412  { initialize(mode); }
413 
414  virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; }
415 
416 
418  void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
419 
420 #ifdef PQXX_HAVE_STREAMBUF
421 protected:
422 #endif
423  virtual int sync()
424  {
425  // setg() sets eback, gptr, egptr
426  this->setg(this->eback(), this->eback(), this->egptr());
427  return overflow(EoF());
428  }
429 
430 protected:
431  virtual pos_type seekoff(off_type offset,
432  seekdir dir,
433  openmode)
434  {
435  return AdjustEOF(m_Obj.cseek(largeobjectaccess::off_type(offset), dir));
436  }
437 
438  virtual pos_type seekpos(pos_type pos, openmode)
439  {
440  const largeobjectaccess::pos_type newpos = m_Obj.cseek(
442  PGSTD::ios::beg);
443  return AdjustEOF(newpos);
444  }
445 
446  virtual int_type overflow(int_type ch = EoF())
447  {
448  char *const pp = this->pptr();
449  if (!pp) return EoF();
450  char *const pb = this->pbase();
451  int_type res = 0;
452 
453  if (pp > pb) res = int_type(AdjustEOF(m_Obj.cwrite(pb, pp-pb)));
454  this->setp(m_P, m_P + m_BufSize);
455 
456  // Write that one more character, if it's there.
457  if (ch != EoF())
458  {
459  *this->pptr() = char(ch);
460  this->pbump(1);
461  }
462  return res;
463  }
464 
465  virtual int_type underflow()
466  {
467  if (!this->gptr()) return EoF();
468  char *const eb = this->eback();
469  const int_type res(static_cast<int_type>(
470  AdjustEOF(m_Obj.cread(this->eback(), m_BufSize))));
471  this->setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
472  return (!res || (res == EoF())) ? EoF() : *eb;
473  }
474 
475 private:
477  static int_type EoF() { return traits_type::eof(); }
478 
480  template<typename INTYPE>
481  static PGSTD::streampos AdjustEOF(INTYPE pos)
482  { return (pos==-1) ? PGSTD::streampos(EoF()) : PGSTD::streampos(pos); }
483 
484  void initialize(openmode mode)
485  {
486  if (mode & PGSTD::ios::in)
487  {
488  m_G = new char_type[unsigned(m_BufSize)];
489  this->setg(m_G, m_G, m_G);
490  }
491  if (mode & PGSTD::ios::out)
492  {
493  m_P = new char_type[unsigned(m_BufSize)];
494  this->setp(m_P, m_P + m_BufSize);
495  }
496  }
497 
498  const size_type m_BufSize;
499  largeobjectaccess m_Obj;
500 
501  // Get & put buffers
502  char_type *m_G, *m_P;
503 };
504 
505 
507 
515 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
517 #ifdef PQXX_HAVE_STREAMBUF
518  public PGSTD::basic_istream<CHAR, TRAITS>
519 #else
520  public PGSTD::istream
521 #endif
522 {
523 #ifdef PQXX_HAVE_STREAMBUF
524  typedef PGSTD::basic_istream<CHAR, TRAITS> super;
525 #else
526  typedef PGSTD::istream super;
527 #endif
528 
529 public:
530  typedef CHAR char_type;
531  typedef TRAITS traits_type;
532  typedef typename traits_type::int_type int_type;
533  typedef typename traits_type::pos_type pos_type;
534  typedef typename traits_type::off_type off_type;
535 
537 
543  largeobject O,
544  largeobject::size_type BufSize=512) : //[t57]
545  super(0),
546  m_Buf(T, O, PGSTD::ios::in, BufSize)
547  { super::init(&m_Buf); }
548 
550 
556  oid O,
557  largeobject::size_type BufSize=512) : //[t48]
558  super(0),
559  m_Buf(T, O, PGSTD::ios::in, BufSize)
560  { super::init(&m_Buf); }
561 
562 private:
564 };
565 
567 
568 
570 
578 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
580 #ifdef PQXX_HAVE_STREAMBUF
581  public PGSTD::basic_ostream<CHAR, TRAITS>
582 #else
583  public PGSTD::ostream
584 #endif
585 {
586 #ifdef PQXX_HAVE_STREAMBUF
587  typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
588 #else
589  typedef PGSTD::ostream super;
590 #endif
591 public:
592  typedef CHAR char_type;
593  typedef TRAITS traits_type;
594  typedef typename traits_type::int_type int_type;
595  typedef typename traits_type::pos_type pos_type;
596  typedef typename traits_type::off_type off_type;
597 
599 
605  largeobject O,
606  largeobject::size_type BufSize=512) : //[t48]
607  super(0),
608  m_Buf(T, O, PGSTD::ios::out, BufSize)
609  { super::init(&m_Buf); }
610 
612 
618  oid O,
619  largeobject::size_type BufSize=512) : //[t57]
620  super(0),
621  m_Buf(T, O, PGSTD::ios::out, BufSize)
622  { super::init(&m_Buf); }
623 
625  {
626  try
627  {
628 #ifdef PQXX_HAVE_STREAMBUF
629  m_Buf.pubsync(); m_Buf.pubsync();
630 #else
631  m_Buf.sync(); m_Buf.sync();
632 #endif
633  }
634  catch (const PGSTD::exception &e)
635  {
636  m_Buf.process_notice(e.what());
637  }
638  }
639 
640 private:
642 };
643 
645 
646 
648 
656 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
658 #ifdef PQXX_HAVE_STREAMBUF
659  public PGSTD::basic_iostream<CHAR, TRAITS>
660 #else
661  public PGSTD::iostream
662 #endif
663 {
664 #ifdef PQXX_HAVE_STREAMBUF
665  typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
666 #else
667  typedef PGSTD::iostream super;
668 #endif
669 
670 public:
671  typedef CHAR char_type;
672  typedef TRAITS traits_type;
673  typedef typename traits_type::int_type int_type;
674  typedef typename traits_type::pos_type pos_type;
675  typedef typename traits_type::off_type off_type;
676 
678 
684  largeobject O,
685  largeobject::size_type BufSize=512) : //[t59]
686  super(0),
687  m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
688  { super::init(&m_Buf); }
689 
691 
697  oid O,
698  largeobject::size_type BufSize=512) : //[t59]
699  super(0),
700  m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
701  { super::init(&m_Buf); }
702 
704  {
705  try
706  {
707 #ifdef PQXX_HAVE_STREAMBUF
708  m_Buf.pubsync(); m_Buf.pubsync();
709 #else
710  m_Buf.sync(); m_Buf.sync();
711 #endif
712  }
713  catch (const PGSTD::exception &e)
714  {
715  m_Buf.process_notice(e.what());
716  }
717  }
718 
719 private:
721 };
722 
724 
725 } // namespace pqxx
726 
727 #include "pqxx/compiler-internal-post.hxx"
728 
729 #endif
730