00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pqxx/libcompiler.h"
00020
00021 #ifdef PQXX_HAVE_STREAMBUF
00022 #include <streambuf>
00023 #else
00024 #include <streambuf.h>
00025 #endif
00026
00027 #include "pqxx/dbtransaction"
00028
00029
00030 namespace pqxx
00031 {
00032
00033 class largeobjectaccess;
00034
00036
00043 class PQXX_LIBEXPORT largeobject
00044 {
00045 public:
00046 typedef long size_type;
00047
00049 largeobject() throw ();
00050
00052
00054 explicit largeobject(dbtransaction &T);
00055
00057
00061 explicit largeobject(oid O) throw () : m_ID(O) {}
00062
00064
00068 largeobject(dbtransaction &T, const PGSTD::string &File);
00069
00071
00075 largeobject(const largeobjectaccess &O) throw ();
00076
00078
00082 oid id() const throw () { return m_ID; }
00083
00092
00093
00094 bool operator==(const largeobject &other) const
00095 { return m_ID == other.m_ID; }
00097
00098 bool operator!=(const largeobject &other) const
00099 { return m_ID != other.m_ID; }
00101
00102 bool operator<=(const largeobject &other) const
00103 { return m_ID <= other.m_ID; }
00105
00106 bool operator>=(const largeobject &other) const
00107 { return m_ID >= other.m_ID; }
00109
00110 bool operator<(const largeobject &other) const
00111 { return m_ID < other.m_ID; }
00113
00114 bool operator>(const largeobject &other) const
00115 { return m_ID > other.m_ID; }
00117
00119
00123 void to_file(dbtransaction &T, const PGSTD::string &File) const;
00124
00126
00130 void remove(dbtransaction &T) const;
00131
00132 protected:
00133 static internal::pq::PGconn *RawConnection(const dbtransaction &T)
00134 {
00135 return T.conn().RawConnection();
00136 }
00137
00138 PGSTD::string Reason(int err) const;
00139
00140 private:
00141 oid m_ID;
00142 };
00143
00144
00145
00146
00148 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
00149 {
00150 public:
00151 using largeobject::size_type;
00152 typedef long off_type;
00153 typedef size_type pos_type;
00154
00156
00160 typedef PGSTD::ios::openmode openmode;
00161
00163
00167 typedef PGSTD::ios::seekdir seekdir;
00168
00170
00174 explicit largeobjectaccess(dbtransaction &T,
00175 openmode mode =
00176 PGSTD::ios::in |
00177 PGSTD::ios::out);
00178
00180
00186 largeobjectaccess(dbtransaction &T,
00187 oid O,
00188 openmode mode =
00189 PGSTD::ios::in |
00190 PGSTD::ios::out);
00191
00193
00198 largeobjectaccess(dbtransaction &T,
00199 largeobject O,
00200 openmode mode = PGSTD::ios::in | PGSTD::ios::out);
00201
00203
00208 largeobjectaccess(dbtransaction &T,
00209 const PGSTD::string &File,
00210 openmode mode =
00211 PGSTD::ios::in | PGSTD::ios::out);
00212
00213 ~largeobjectaccess() throw () { close(); }
00214
00216
00219 using largeobject::id;
00220
00222
00225 void to_file(const PGSTD::string &File) const
00226 { largeobject::to_file(m_Trans, File); }
00227
00228 #ifdef PQXX_BROKEN_USING_DECL
00229
00230
00234 void to_file(dbtransaction &T, const PGSTD::string &F) const
00235 { largeobject::to_file(T, F); }
00236 #else
00237 using largeobject::to_file;
00238 #endif
00239
00244
00245
00249 void write(const char Buf[], size_type Len);
00250
00252
00255 void write(const PGSTD::string &Buf)
00256 { write(Buf.c_str(), Buf.size()); }
00257
00259
00265 size_type read(char Buf[], size_type Len);
00266
00268
00271 size_type seek(size_type dest, seekdir dir);
00272
00274
00277 size_type tell() const;
00279
00289
00290
00298 pos_type cseek(off_type dest, seekdir dir) throw ();
00299
00301
00307 off_type cwrite(const char Buf[], size_type Len) throw ();
00308
00310
00316 off_type cread(char Buf[], size_type Len) throw ();
00317
00319
00323 pos_type ctell() const throw ();
00325
00330
00331 void process_notice(const PGSTD::string &) throw ();
00333
00334 using largeobject::remove;
00335
00336 using largeobject::operator==;
00337 using largeobject::operator!=;
00338 using largeobject::operator<;
00339 using largeobject::operator<=;
00340 using largeobject::operator>;
00341 using largeobject::operator>=;
00342
00343 private:
00344 PGSTD::string PQXX_PRIVATE Reason(int err) const;
00345 internal::pq::PGconn *RawConnection() const
00346 { return largeobject::RawConnection(m_Trans); }
00347
00348 void open(openmode mode);
00349 void close() throw ();
00350
00351 dbtransaction &m_Trans;
00352 int m_fd;
00353
00354
00355 largeobjectaccess();
00356 largeobjectaccess(const largeobjectaccess &);
00357 largeobjectaccess operator=(const largeobjectaccess &);
00358 };
00359
00360
00362
00370 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00371 class largeobject_streambuf :
00372 #ifdef PQXX_HAVE_STREAMBUF
00373 public PGSTD::basic_streambuf<CHAR, TRAITS>
00374 #else
00375 public PGSTD::streambuf
00376 #endif
00377 {
00378 typedef long size_type;
00379 public:
00380 typedef CHAR char_type;
00381 typedef TRAITS traits_type;
00382 typedef typename traits_type::int_type int_type;
00383 #ifdef PQXX_HAVE_STREAMBUF
00384 typedef typename traits_type::pos_type pos_type;
00385 typedef typename traits_type::off_type off_type;
00386 #else
00387 typedef streamoff off_type;
00388 typedef streampos pos_type;
00389 #endif
00390 typedef largeobjectaccess::openmode openmode;
00391 typedef largeobjectaccess::seekdir seekdir;
00392
00393 largeobject_streambuf(dbtransaction &T,
00394 largeobject O,
00395 openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00396 size_type BufSize=512) :
00397 m_BufSize(BufSize),
00398 m_Obj(T, O),
00399 m_G(0),
00400 m_P(0)
00401 { initialize(mode); }
00402
00403 largeobject_streambuf(dbtransaction &T,
00404 oid O,
00405 openmode mode = PGSTD::ios::in | PGSTD::ios::out,
00406 size_type BufSize=512) :
00407 m_BufSize(BufSize),
00408 m_Obj(T, O),
00409 m_G(0),
00410 m_P(0)
00411 { initialize(mode); }
00412
00413 virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; }
00414
00415
00417 void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); }
00418
00419 #ifdef PQXX_HAVE_STREAMBUF
00420 protected:
00421 #endif
00422 virtual int sync()
00423 {
00424
00425 setg(this->eback(), this->eback(), this->egptr());
00426 return overflow(EoF());
00427 }
00428
00429 protected:
00430 virtual pos_type seekoff(off_type offset,
00431 seekdir dir,
00432 openmode)
00433 { return AdjustEOF(m_Obj.cseek(offset, dir)); }
00434
00435 virtual pos_type seekpos(pos_type pos, openmode)
00436 { return AdjustEOF(m_Obj.cseek(pos, PGSTD::ios::beg)); }
00437
00438 virtual int_type overflow(int_type ch = EoF())
00439 {
00440 char *const pp = this->pptr();
00441 if (!pp) return EoF();
00442 char *const pb = this->pbase();
00443 int_type res = 0;
00444
00445 if (pp > pb) res = AdjustEOF(m_Obj.cwrite(pb, pp-pb));
00446 setp(m_P, m_P + m_BufSize);
00447
00448
00449 if (ch != EoF())
00450 {
00451 *this->pptr() = char(ch);
00452 this->pbump(1);
00453 }
00454 return res;
00455 }
00456
00457 virtual int_type underflow()
00458 {
00459 if (!this->gptr()) return EoF();
00460 char *const eb = this->eback();
00461 const int res = AdjustEOF(m_Obj.cread(this->eback(), m_BufSize));
00462 setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
00463 return (!res || (res == EoF())) ? EoF() : *eb;
00464 }
00465
00466 private:
00468 static int_type EoF() { return traits_type::eof(); }
00469
00471 static PGSTD::streampos AdjustEOF(int pos) { return (pos==-1) ? EoF() : pos; }
00472
00473 void initialize(openmode mode)
00474 {
00475 if (mode & PGSTD::ios::in)
00476 {
00477 m_G = new char_type[m_BufSize];
00478 setg(m_G, m_G, m_G);
00479 }
00480 if (mode & PGSTD::ios::out)
00481 {
00482 m_P = new char_type[m_BufSize];
00483 setp(m_P, m_P + m_BufSize);
00484 }
00485 }
00486
00487 const size_type m_BufSize;
00488 largeobjectaccess m_Obj;
00489
00490
00491 char_type *m_G, *m_P;
00492 };
00493
00494
00496
00504 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00505 class basic_ilostream :
00506 #ifdef PQXX_HAVE_STREAMBUF
00507 public PGSTD::basic_istream<CHAR, TRAITS>
00508 #else
00509 public PGSTD::istream
00510 #endif
00511 {
00512 #ifdef PQXX_HAVE_STREAMBUF
00513 typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00514 #else
00515 typedef PGSTD::istream super;
00516 #endif
00517
00518 public:
00519 typedef CHAR char_type;
00520 typedef TRAITS traits_type;
00521 typedef typename traits_type::int_type int_type;
00522 typedef typename traits_type::pos_type pos_type;
00523 typedef typename traits_type::off_type off_type;
00524
00526
00531 basic_ilostream(dbtransaction &T,
00532 largeobject O,
00533 largeobject::size_type BufSize=512) :
00534 super(0),
00535 m_Buf(T, O, PGSTD::ios::in, BufSize)
00536 { super::init(&m_Buf); }
00537
00539
00544 basic_ilostream(dbtransaction &T,
00545 oid O,
00546 largeobject::size_type BufSize=512) :
00547 super(0),
00548 m_Buf(T, O, PGSTD::ios::in, BufSize)
00549 { super::init(&m_Buf); }
00550
00551 private:
00552 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00553 };
00554
00555 typedef basic_ilostream<char> ilostream;
00556
00557
00559
00567 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00568 class basic_olostream :
00569 #ifdef PQXX_HAVE_STREAMBUF
00570 public PGSTD::basic_ostream<CHAR, TRAITS>
00571 #else
00572 public PGSTD::ostream
00573 #endif
00574 {
00575 #ifdef PQXX_HAVE_STREAMBUF
00576 typedef PGSTD::basic_ostream<CHAR, TRAITS> super;
00577 #else
00578 typedef PGSTD::ostream super;
00579 #endif
00580 public:
00581 typedef CHAR char_type;
00582 typedef TRAITS traits_type;
00583 typedef typename traits_type::int_type int_type;
00584 typedef typename traits_type::pos_type pos_type;
00585 typedef typename traits_type::off_type off_type;
00586
00588
00593 basic_olostream(dbtransaction &T,
00594 largeobject O,
00595 largeobject::size_type BufSize=512) :
00596 super(0),
00597 m_Buf(T, O, PGSTD::ios::out, BufSize)
00598 { super::init(&m_Buf); }
00599
00601
00606 basic_olostream(dbtransaction &T,
00607 oid O,
00608 largeobject::size_type BufSize=512) :
00609 super(0),
00610 m_Buf(T, O, PGSTD::ios::out, BufSize)
00611 { super::init(&m_Buf); }
00612
00613 ~basic_olostream()
00614 {
00615 try
00616 {
00617 #ifdef PQXX_HAVE_STREAMBUF
00618 m_Buf.pubsync(); m_Buf.pubsync();
00619 #else
00620 m_Buf.sync(); m_Buf.sync();
00621 #endif
00622 }
00623 catch (const PGSTD::exception &e)
00624 {
00625 m_Buf.process_notice(e.what());
00626 }
00627 }
00628
00629 private:
00630 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00631 };
00632
00633 typedef basic_olostream<char> olostream;
00634
00635
00637
00645 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00646 class basic_lostream :
00647 #ifdef PQXX_HAVE_STREAMBUF
00648 public PGSTD::basic_iostream<CHAR, TRAITS>
00649 #else
00650 public PGSTD::iostream
00651 #endif
00652 {
00653 #ifdef PQXX_HAVE_STREAMBUF
00654 typedef PGSTD::basic_iostream<CHAR, TRAITS> super;
00655 #else
00656 typedef PGSTD::iostream super;
00657 #endif
00658
00659 public:
00660 typedef CHAR char_type;
00661 typedef TRAITS traits_type;
00662 typedef typename traits_type::int_type int_type;
00663 typedef typename traits_type::pos_type pos_type;
00664 typedef typename traits_type::off_type off_type;
00665
00667
00672 basic_lostream(dbtransaction &T,
00673 largeobject O,
00674 largeobject::size_type BufSize=512) :
00675 super(0),
00676 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00677 { super::init(&m_Buf); }
00678
00680
00685 basic_lostream(dbtransaction &T,
00686 oid O,
00687 largeobject::size_type BufSize=512) :
00688 super(0),
00689 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize)
00690 { super::init(&m_Buf); }
00691
00692 ~basic_lostream()
00693 {
00694 try
00695 {
00696 #ifdef PQXX_HAVE_STREAMBUF
00697 m_Buf.pubsync(); m_Buf.pubsync();
00698 #else
00699 m_Buf.sync(); m_Buf.sync();
00700 #endif
00701 }
00702 catch (const PGSTD::exception &e)
00703 {
00704 m_Buf.process_notice(e.what());
00705 }
00706 }
00707
00708 private:
00709 largeobject_streambuf<CHAR,TRAITS> m_Buf;
00710 };
00711
00712 typedef basic_lostream<char> lostream;
00713
00714 }