libpqxx 4.0
|
00001 /*------------------------------------------------------------------------- 00002 * 00003 * FILE 00004 * pqxx/largeobject.hxx 00005 * 00006 * DESCRIPTION 00007 * libpqxx's Large Objects interface 00008 * Allows access to large objects directly, or through I/O streams 00009 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead. 00010 * 00011 * Copyright (c) 2003-2011, Jeroen T. Vermeulen <jtv@xs4all.nl> 00012 * 00013 * See COPYING for copyright license. If you did not receive a file called 00014 * COPYING with this source code, please notify the distributor of this mistake, 00015 * or contact the author. 00016 * 00017 *------------------------------------------------------------------------- 00018 */ 00019 #ifndef PQXX_H_LARGEOBJECT 00020 #define PQXX_H_LARGEOBJECT 00021 00022 #include "pqxx/compiler-public.hxx" 00023 #include "pqxx/compiler-internal-pre.hxx" 00024 00025 #ifdef PQXX_HAVE_STREAMBUF 00026 #include <streambuf> 00027 #else 00028 #include <streambuf.h> 00029 #endif 00030 00031 #include "pqxx/dbtransaction" 00032 00033 00034 namespace pqxx 00035 { 00036 00037 class largeobjectaccess; 00038 00040 00047 class PQXX_LIBEXPORT largeobject 00048 { 00049 public: 00050 typedef long size_type; 00051 00053 largeobject() throw (); //[t48] 00054 00056 00058 explicit largeobject(dbtransaction &T); //[t48] 00059 00061 00065 explicit largeobject(oid O) throw () : m_ID(O) {} //[t48] 00066 00068 00072 largeobject(dbtransaction &T, const PGSTD::string &File); //[t53] 00073 00075 00079 largeobject(const largeobjectaccess &O) throw (); //[t50] 00080 00082 00086 oid id() const throw () { return m_ID; } //[t48] 00087 00096 00097 00098 bool operator==(const largeobject &other) const //[t51] 00099 { return m_ID == other.m_ID; } 00101 00102 bool operator!=(const largeobject &other) const //[t51] 00103 { return m_ID != other.m_ID; } 00105 00106 bool operator<=(const largeobject &other) const //[t51] 00107 { return m_ID <= other.m_ID; } 00109 00110 bool operator>=(const largeobject &other) const //[t51] 00111 { return m_ID >= other.m_ID; } 00113 00114 bool operator<(const largeobject &other) const //[t51] 00115 { return m_ID < other.m_ID; } 00117 00118 bool operator>(const largeobject &other) const //[t51] 00119 { return m_ID > other.m_ID; } 00121 00123 00127 void to_file(dbtransaction &T, const PGSTD::string &File) const; //[t52] 00128 00130 00134 void remove(dbtransaction &T) const; //[t48] 00135 00136 protected: 00137 static internal::pq::PGconn * PQXX_PURE RawConnection(const dbtransaction &T); 00138 00139 PGSTD::string Reason(int err) const; 00140 00141 private: 00142 oid m_ID; 00143 }; 00144 00145 00146 // TODO: New hierarchy with separate read / write / mixed-mode access 00147 00149 class PQXX_LIBEXPORT largeobjectaccess : private largeobject 00150 { 00151 public: 00152 using largeobject::size_type; 00153 typedef long off_type; 00154 typedef size_type pos_type; 00155 00157 00161 typedef PGSTD::ios::openmode openmode; 00162 00164 00168 typedef PGSTD::ios::seekdir seekdir; 00169 00171 00175 explicit largeobjectaccess(dbtransaction &T, 00176 openmode mode = 00177 PGSTD::ios::in | 00178 PGSTD::ios::out); //[t51] 00179 00181 00187 largeobjectaccess(dbtransaction &T, 00188 oid O, 00189 openmode mode = 00190 PGSTD::ios::in | 00191 PGSTD::ios::out); //[t52] 00192 00194 00199 largeobjectaccess(dbtransaction &T, 00200 largeobject O, 00201 openmode mode = PGSTD::ios::in | PGSTD::ios::out); //[t50] 00202 00204 00209 largeobjectaccess(dbtransaction &T, 00210 const PGSTD::string &File, 00211 openmode mode = 00212 PGSTD::ios::in | PGSTD::ios::out); //[t55] 00213 00214 ~largeobjectaccess() throw () { close(); } 00215 00217 00220 using largeobject::id; 00221 00223 00226 void to_file(const PGSTD::string &File) const //[t54] 00227 { largeobject::to_file(m_Trans, File); } 00228 00229 #ifdef PQXX_BROKEN_USING_DECL 00230 00231 00235 void to_file(dbtransaction &T, const PGSTD::string &F) const 00236 { largeobject::to_file(T, F); } 00237 #else 00238 using largeobject::to_file; 00239 #endif 00240 00245 00246 00250 void write(const char Buf[], size_type Len); //[t51] 00251 00253 00256 void write(const PGSTD::string &Buf) //[t50] 00257 { write(Buf.c_str(), static_cast<size_type>(Buf.size())); } 00258 00260 00266 size_type read(char Buf[], size_type Len); //[t50] 00267 00269 00272 size_type seek(size_type dest, seekdir dir); //[t51] 00273 00275 00278 size_type tell() const; //[t50] 00280 00290 00291 00299 pos_type cseek(off_type dest, seekdir dir) throw (); //[t50] 00300 00302 00308 off_type cwrite(const char Buf[], size_type Len) throw (); //[t50] 00309 00311 00317 off_type cread(char Buf[], size_type Len) throw (); //[t50] 00318 00320 00324 pos_type ctell() const throw (); //[t50] 00326 00331 00332 void process_notice(const PGSTD::string &) throw (); //[t50] 00334 00335 using largeobject::remove; 00336 00337 using largeobject::operator==; 00338 using largeobject::operator!=; 00339 using largeobject::operator<; 00340 using largeobject::operator<=; 00341 using largeobject::operator>; 00342 using largeobject::operator>=; 00343 00344 private: 00345 PGSTD::string PQXX_PRIVATE Reason(int err) const; 00346 internal::pq::PGconn *RawConnection() const 00347 { return largeobject::RawConnection(m_Trans); } 00348 00349 void open(openmode mode); 00350 void close() throw (); 00351 00352 dbtransaction &m_Trans; 00353 int m_fd; 00354 00355 // Not allowed: 00356 largeobjectaccess(); 00357 largeobjectaccess(const largeobjectaccess &); 00358 largeobjectaccess operator=(const largeobjectaccess &); 00359 }; 00360 00361 00363 00371 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 00372 class largeobject_streambuf : 00373 #ifdef PQXX_HAVE_STREAMBUF 00374 public PGSTD::basic_streambuf<CHAR, TRAITS> 00375 #else 00376 public PGSTD::streambuf 00377 #endif 00378 { 00379 typedef long size_type; 00380 public: 00381 typedef CHAR char_type; 00382 typedef TRAITS traits_type; 00383 typedef typename traits_type::int_type int_type; 00384 #ifdef PQXX_HAVE_STREAMBUF 00385 typedef typename traits_type::pos_type pos_type; 00386 typedef typename traits_type::off_type off_type; 00387 #else 00388 typedef streamoff off_type; 00389 typedef streampos pos_type; 00390 #endif 00391 typedef largeobjectaccess::openmode openmode; 00392 typedef largeobjectaccess::seekdir seekdir; 00393 00394 largeobject_streambuf(dbtransaction &T, 00395 largeobject O, 00396 openmode mode = PGSTD::ios::in | PGSTD::ios::out, 00397 size_type BufSize=512) : //[t48] 00398 m_BufSize(BufSize), 00399 m_Obj(T, O), 00400 m_G(0), 00401 m_P(0) 00402 { initialize(mode); } 00403 00404 largeobject_streambuf(dbtransaction &T, 00405 oid O, 00406 openmode mode = PGSTD::ios::in | PGSTD::ios::out, 00407 size_type BufSize=512) : //[t48] 00408 m_BufSize(BufSize), 00409 m_Obj(T, O), 00410 m_G(0), 00411 m_P(0) 00412 { initialize(mode); } 00413 00414 virtual ~largeobject_streambuf() throw () { delete [] m_P; delete [] m_G; } 00415 00416 00418 void process_notice(const PGSTD::string &s) { m_Obj.process_notice(s); } 00419 00420 #ifdef PQXX_HAVE_STREAMBUF 00421 protected: 00422 #endif 00423 virtual int sync() 00424 { 00425 // setg() sets eback, gptr, egptr 00426 this->setg(this->eback(), this->eback(), this->egptr()); 00427 return overflow(EoF()); 00428 } 00429 00430 protected: 00431 virtual pos_type seekoff(off_type offset, 00432 seekdir dir, 00433 openmode) 00434 { 00435 return AdjustEOF(m_Obj.cseek(largeobjectaccess::off_type(offset), dir)); 00436 } 00437 00438 virtual pos_type seekpos(pos_type pos, openmode) 00439 { 00440 const largeobjectaccess::pos_type newpos = m_Obj.cseek( 00441 largeobjectaccess::off_type(pos), 00442 PGSTD::ios::beg); 00443 return AdjustEOF(newpos); 00444 } 00445 00446 virtual int_type overflow(int_type ch = EoF()) 00447 { 00448 char *const pp = this->pptr(); 00449 if (!pp) return EoF(); 00450 char *const pb = this->pbase(); 00451 int_type res = 0; 00452 00453 if (pp > pb) res = int_type(AdjustEOF(m_Obj.cwrite(pb, pp-pb))); 00454 this->setp(m_P, m_P + m_BufSize); 00455 00456 // Write that one more character, if it's there. 00457 if (ch != EoF()) 00458 { 00459 *this->pptr() = char(ch); 00460 this->pbump(1); 00461 } 00462 return res; 00463 } 00464 00465 virtual int_type underflow() 00466 { 00467 if (!this->gptr()) return EoF(); 00468 char *const eb = this->eback(); 00469 const int_type res(static_cast<int_type>( 00470 AdjustEOF(m_Obj.cread(this->eback(), m_BufSize)))); 00471 this->setg(eb, eb, eb + ((res==EoF()) ? 0 : res)); 00472 return (!res || (res == EoF())) ? EoF() : *eb; 00473 } 00474 00475 private: 00477 static int_type EoF() { return traits_type::eof(); } 00478 00480 template<typename INTYPE> 00481 static PGSTD::streampos AdjustEOF(INTYPE pos) 00482 { return (pos==-1) ? PGSTD::streampos(EoF()) : PGSTD::streampos(pos); } 00483 00484 void initialize(openmode mode) 00485 { 00486 if (mode & PGSTD::ios::in) 00487 { 00488 m_G = new char_type[unsigned(m_BufSize)]; 00489 this->setg(m_G, m_G, m_G); 00490 } 00491 if (mode & PGSTD::ios::out) 00492 { 00493 m_P = new char_type[unsigned(m_BufSize)]; 00494 this->setp(m_P, m_P + m_BufSize); 00495 } 00496 } 00497 00498 const size_type m_BufSize; 00499 largeobjectaccess m_Obj; 00500 00501 // Get & put buffers 00502 char_type *m_G, *m_P; 00503 }; 00504 00505 00507 00515 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 00516 class basic_ilostream : 00517 #ifdef PQXX_HAVE_STREAMBUF 00518 public PGSTD::basic_istream<CHAR, TRAITS> 00519 #else 00520 public PGSTD::istream 00521 #endif 00522 { 00523 #ifdef PQXX_HAVE_STREAMBUF 00524 typedef PGSTD::basic_istream<CHAR, TRAITS> super; 00525 #else 00526 typedef PGSTD::istream super; 00527 #endif 00528 00529 public: 00530 typedef CHAR char_type; 00531 typedef TRAITS traits_type; 00532 typedef typename traits_type::int_type int_type; 00533 typedef typename traits_type::pos_type pos_type; 00534 typedef typename traits_type::off_type off_type; 00535 00537 00542 basic_ilostream(dbtransaction &T, 00543 largeobject O, 00544 largeobject::size_type BufSize=512) : //[t57] 00545 super(0), 00546 m_Buf(T, O, PGSTD::ios::in, BufSize) 00547 { super::init(&m_Buf); } 00548 00550 00555 basic_ilostream(dbtransaction &T, 00556 oid O, 00557 largeobject::size_type BufSize=512) : //[t48] 00558 super(0), 00559 m_Buf(T, O, PGSTD::ios::in, BufSize) 00560 { super::init(&m_Buf); } 00561 00562 private: 00563 largeobject_streambuf<CHAR,TRAITS> m_Buf; 00564 }; 00565 00566 typedef basic_ilostream<char> ilostream; 00567 00568 00570 00578 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 00579 class basic_olostream : 00580 #ifdef PQXX_HAVE_STREAMBUF 00581 public PGSTD::basic_ostream<CHAR, TRAITS> 00582 #else 00583 public PGSTD::ostream 00584 #endif 00585 { 00586 #ifdef PQXX_HAVE_STREAMBUF 00587 typedef PGSTD::basic_ostream<CHAR, TRAITS> super; 00588 #else 00589 typedef PGSTD::ostream super; 00590 #endif 00591 public: 00592 typedef CHAR char_type; 00593 typedef TRAITS traits_type; 00594 typedef typename traits_type::int_type int_type; 00595 typedef typename traits_type::pos_type pos_type; 00596 typedef typename traits_type::off_type off_type; 00597 00599 00604 basic_olostream(dbtransaction &T, 00605 largeobject O, 00606 largeobject::size_type BufSize=512) : //[t48] 00607 super(0), 00608 m_Buf(T, O, PGSTD::ios::out, BufSize) 00609 { super::init(&m_Buf); } 00610 00612 00617 basic_olostream(dbtransaction &T, 00618 oid O, 00619 largeobject::size_type BufSize=512) : //[t57] 00620 super(0), 00621 m_Buf(T, O, PGSTD::ios::out, BufSize) 00622 { super::init(&m_Buf); } 00623 00624 ~basic_olostream() 00625 { 00626 try 00627 { 00628 #ifdef PQXX_HAVE_STREAMBUF 00629 m_Buf.pubsync(); m_Buf.pubsync(); 00630 #else 00631 m_Buf.sync(); m_Buf.sync(); 00632 #endif 00633 } 00634 catch (const PGSTD::exception &e) 00635 { 00636 m_Buf.process_notice(e.what()); 00637 } 00638 } 00639 00640 private: 00641 largeobject_streambuf<CHAR,TRAITS> m_Buf; 00642 }; 00643 00644 typedef basic_olostream<char> olostream; 00645 00646 00648 00656 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> > 00657 class basic_lostream : 00658 #ifdef PQXX_HAVE_STREAMBUF 00659 public PGSTD::basic_iostream<CHAR, TRAITS> 00660 #else 00661 public PGSTD::iostream 00662 #endif 00663 { 00664 #ifdef PQXX_HAVE_STREAMBUF 00665 typedef PGSTD::basic_iostream<CHAR, TRAITS> super; 00666 #else 00667 typedef PGSTD::iostream super; 00668 #endif 00669 00670 public: 00671 typedef CHAR char_type; 00672 typedef TRAITS traits_type; 00673 typedef typename traits_type::int_type int_type; 00674 typedef typename traits_type::pos_type pos_type; 00675 typedef typename traits_type::off_type off_type; 00676 00678 00683 basic_lostream(dbtransaction &T, 00684 largeobject O, 00685 largeobject::size_type BufSize=512) : //[t59] 00686 super(0), 00687 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize) 00688 { super::init(&m_Buf); } 00689 00691 00696 basic_lostream(dbtransaction &T, 00697 oid O, 00698 largeobject::size_type BufSize=512) : //[t59] 00699 super(0), 00700 m_Buf(T, O, PGSTD::ios::in | PGSTD::ios::out, BufSize) 00701 { super::init(&m_Buf); } 00702 00703 ~basic_lostream() 00704 { 00705 try 00706 { 00707 #ifdef PQXX_HAVE_STREAMBUF 00708 m_Buf.pubsync(); m_Buf.pubsync(); 00709 #else 00710 m_Buf.sync(); m_Buf.sync(); 00711 #endif 00712 } 00713 catch (const PGSTD::exception &e) 00714 { 00715 m_Buf.process_notice(e.what()); 00716 } 00717 } 00718 00719 private: 00720 largeobject_streambuf<CHAR,TRAITS> m_Buf; 00721 }; 00722 00723 typedef basic_lostream<char> lostream; 00724 00725 } // namespace pqxx 00726 00727 #include "pqxx/compiler-internal-post.hxx" 00728 00729 #endif 00730