00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef PQXX_HAVE_IOS
00020 #include <ios>
00021 #endif
00022
00023 #include <stdexcept>
00024
00025 #include "pqxx/util"
00026
00027
00028
00029
00030
00031
00032
00033
00034 namespace pqxx
00035 {
00036
00038
00045 class PQXX_LIBEXPORT result
00046 {
00047 public:
00048 result() throw () : m_Result(0), m_l(this), m_r(this) {}
00049 result(const result &rhs) throw () :
00050 m_Result(0), m_l(this), m_r(this) { MakeRef(rhs); }
00051 ~result() { LoseRef(); }
00052
00053 result &operator=(const result &) throw ();
00054
00055 typedef unsigned long size_type;
00056 typedef signed long difference_type;
00057 class field;
00058 class const_fielditerator;
00059
00061
00071 class PQXX_LIBEXPORT tuple
00072 {
00073 public:
00074 typedef unsigned int size_type;
00075 typedef signed int difference_type;
00076 typedef const_fielditerator const_iterator;
00077
00078 tuple(const result *r, result::size_type i) throw () :
00079 m_Home(r), m_Index(i) {}
00080 ~tuple() throw () {}
00081
00082 inline const_iterator begin() const throw ();
00083 inline const_iterator end() const throw ();
00084
00085 #ifdef PQXX_HAVE_REVERSE_ITERATOR
00086 typedef PGSTD::reverse_iterator<const_iterator> const_reverse_iterator;
00087 const_reverse_iterator rbegin() const
00088 { return const_reverse_iterator(end()); }
00089 const_reverse_iterator rend() const
00090 { return const_reverse_iterator(begin()); }
00091 #endif
00092
00093 inline field operator[](size_type) const throw ();
00094 inline field operator[](int i) const throw ()
00095 { return operator[](size_type(i)); }
00096 field operator[](const char[]) const;
00097 field operator[](const PGSTD::string &s) const
00098 { return operator[](s.c_str()); }
00099 field at(size_type) const throw (PGSTD::out_of_range);
00100 field at(int i) const throw (PGSTD::out_of_range)
00101 { return at(size_type(i)); }
00102 field at(const char[]) const;
00103 field at(const PGSTD::string &s) const { return at(s.c_str()); }
00104
00105 inline size_type size() const throw ();
00106
00107 result::size_type rownumber() const throw () { return m_Index; }
00108
00110 size_type column_number(const PGSTD::string &ColName) const
00111 { return m_Home->column_number(ColName); }
00112
00114 size_type column_number(const char ColName[]) const
00115 { return m_Home->column_number(ColName); }
00116
00118 oid column_type(size_type ColNum) const
00119 { return m_Home->column_type(ColNum); }
00120
00122 oid column_type(int ColNum) const
00123 { return column_type(size_type(ColNum)); }
00124
00126 oid column_type(const PGSTD::string &ColName) const
00127 { return column_type(column_number(ColName)); }
00128
00130 oid column_type(const char ColName[]) const
00131 { return column_type(column_number(ColName)); }
00132
00133 result::size_type num() const { return rownumber(); }
00134
00135 #ifdef PQXX_HAVE_PQFTABLE
00136 oid column_table(size_type ColNum) const
00137 { return m_Home->column_table(ColNum); }
00138 oid column_table(int ColNum) const
00139 { return column_table(size_type(ColNum)); }
00140 oid column_table(const PGSTD::string &ColName) const
00141 { return column_table(column_number(ColName)); }
00142 #endif
00143
00144
00145 #ifdef PQXX_DEPRECATED_HEADERS
00146
00147 result::size_type Row() const { return rownumber(); }
00148
00150 size_type ColumnNumber(const PGSTD::string &ColName) const
00151 { return m_Home->ColumnNumber(ColName); }
00152
00154 size_type ColumnNumber(const char ColName[]) const
00155 { return m_Home->ColumnNumber(ColName); }
00156 #endif
00157
00158
00159 protected:
00160 friend class field;
00161 const result *m_Home;
00162 result::size_type m_Index;
00163
00164
00165 tuple();
00166 };
00167
00169
00172 class PQXX_LIBEXPORT field
00173 {
00174 public:
00175 typedef size_t size_type;
00176
00178
00182 field(const tuple &T, tuple::size_type C) throw () :
00183 m_tup(T), m_col(C) {}
00184
00186
00191 const char *c_str() const {return home()->GetValue(idx(),col());}
00192
00194 inline const char *name() const;
00195
00197 oid type() const
00198 { return home()->column_type(col()); }
00199
00200 #ifdef PQXX_HAVE_PQFTABLE
00201
00202
00204 oid table() const { return home()->column_table(col()); }
00205 #endif
00206
00208
00217 template<typename T> bool to(T &Obj) const
00218 {
00219 if (is_null())
00220 return false;
00221
00222 try
00223 {
00224 from_string(c_str(), Obj);
00225 }
00226 catch (const PGSTD::exception &e)
00227 {
00228 throw PGSTD::domain_error("Error reading field " +
00229 PGSTD::string(name()) +
00230 ": " +
00231 e.what());
00232 }
00233 return true;
00234 }
00235
00237 template<typename T> bool operator>>(T &Obj) const
00238 { return to(Obj); }
00239
00240 #ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00241
00242 template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00243
00245
00248 template<> bool to<const char *>(const char *&Obj) const;
00249 #endif
00250
00251
00253 template<typename T> bool to(T &Obj, const T &Default) const
00254 {
00255 const bool NotNull = to(Obj);
00256 if (!NotNull)
00257 Obj = Default;
00258 return NotNull;
00259 }
00260
00262
00265 template<typename T> T as(const T &Default) const
00266 {
00267 T Obj;
00268 to(Obj, Default);
00269 return Obj;
00270 }
00271
00273 template<typename T> T as() const
00274 {
00275 T Obj;
00276 const bool NotNull = to(Obj);
00277 if (!NotNull) throw PGSTD::domain_error("Attempt to read null field");
00278 return Obj;
00279 }
00280
00281 bool is_null() const { return home()->GetIsNull(idx(),col()); }
00282
00283 size_type size() const { return home()->GetLength(idx(),col()); }
00284
00285 tuple::size_type num() const { return col(); }
00286
00287 #ifdef PQXX_DEPRECATED_HEADERS
00288
00289 const char *Name() const {return name();}
00290 #endif
00291
00292 private:
00293 const result *home() const throw () { return m_tup.m_Home; }
00294 result::size_type idx() const throw () { return m_tup.m_Index; }
00295
00296 protected:
00297 const tuple::size_type col() const throw () { return m_col; }
00298 tuple m_tup;
00299 tuple::size_type m_col;
00300 };
00301
00303
00307 class PQXX_LIBEXPORT const_iterator :
00308 public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00309 const tuple,
00310 result::size_type>,
00311 public tuple
00312 {
00313 public:
00314 typedef result::size_type size_type;
00315 typedef result::difference_type difference_type;
00316
00317 const_iterator() throw () : tuple(0,0) {}
00318 const_iterator(const tuple &t) throw () : tuple(t) {}
00319
00326 pointer operator->() const { return this; }
00327 reference operator*() const { return *operator->(); }
00328
00329 const_iterator operator++(int);
00330 const_iterator &operator++() { ++m_Index; return *this; }
00331 const_iterator operator--(int);
00332 const_iterator &operator--() { --m_Index; return *this; }
00333
00334 const_iterator &operator+=(difference_type i)
00335 { m_Index+=i; return *this; }
00336 const_iterator &operator-=(difference_type i)
00337 { m_Index-=i; return *this; }
00338
00339 bool operator==(const const_iterator &i) const
00340 {return m_Index==i.m_Index;}
00341 bool operator!=(const const_iterator &i) const
00342 {return m_Index!=i.m_Index;}
00343 bool operator<(const const_iterator &i) const
00344 {return m_Index<i.m_Index;}
00345 bool operator<=(const const_iterator &i) const
00346 {return m_Index<=i.m_Index;}
00347 bool operator>(const const_iterator &i) const
00348 {return m_Index>i.m_Index;}
00349 bool operator>=(const const_iterator &i) const
00350 {return m_Index>=i.m_Index;}
00351
00352 inline const_iterator operator+(difference_type) const;
00353
00354 friend const_iterator operator+(difference_type, const_iterator);
00355
00356 inline const_iterator operator-(difference_type) const;
00357
00358 inline difference_type operator-(const_iterator) const;
00359
00360 private:
00361 friend class result;
00362 const_iterator(const result *r, result::size_type i) : tuple(r, i) {}
00363 };
00364
00365 class PQXX_LIBEXPORT const_fielditerator :
00366 public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00367 const field,
00368 tuple::size_type>,
00369 public field
00370 {
00371 typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
00372 const field,
00373 tuple::size_type> it;
00374 public:
00375 typedef tuple::size_type size_type;
00376 typedef tuple::difference_type difference_type;
00377 using it::pointer;
00378 using it::reference;
00379
00380 const_fielditerator(const tuple &T, tuple::size_type C) throw () :
00381 field(T, C) {}
00382 const_fielditerator(const field &F) throw () : field(F) {}
00383
00384 pointer operator->() const { return this; }
00385 reference operator*() const { return *operator->(); }
00386
00387 const_fielditerator operator++(int);
00388 const_fielditerator &operator++() { ++m_col; return *this; }
00389 const_fielditerator operator--(int);
00390 const_fielditerator &operator--() { --m_col; return *this; }
00391
00392 const_fielditerator &operator+=(difference_type i)
00393 { m_col+=i; return *this; }
00394 const_fielditerator &operator-=(difference_type i)
00395 { m_col-=i; return *this; }
00396
00397 bool operator==(const const_fielditerator &i) const
00398 {return col()==i.col();}
00399 bool operator!=(const const_fielditerator &i) const
00400 {return col()!=i.col();}
00401 bool operator<(const const_fielditerator &i) const
00402 {return col()<i.col();}
00403 bool operator<=(const const_fielditerator &i) const
00404 {return col()<=i.col();}
00405 bool operator>(const const_fielditerator &i) const
00406 {return col()>i.col();}
00407 bool operator>=(const const_fielditerator &i) const
00408 {return col()>=i.col();}
00409
00410 inline const_fielditerator operator+(difference_type) const;
00411
00412 friend const_fielditerator operator+(difference_type,
00413 const_fielditerator);
00414
00415 inline const_fielditerator operator-(difference_type) const;
00416
00417 inline difference_type operator-(const_fielditerator) const;
00418 };
00419
00420
00421 #ifdef PQXX_HAVE_REVERSE_ITERATOR
00422 typedef PGSTD::reverse_iterator<const_iterator> const_reverse_iterator;
00423 const_reverse_iterator rbegin() const
00424 { return const_reverse_iterator(end()); }
00425 const_reverse_iterator rend() const
00426 { return const_reverse_iterator(begin()); }
00427 #endif
00428
00429 const_iterator begin() const { return const_iterator(this, 0); }
00430 inline const_iterator end() const;
00431
00432 size_type size() const
00433 { return m_Result ? PQXXPQ::PQntuples(m_Result) : 0; }
00434 bool empty() const
00435 { return !m_Result || !PQXXPQ::PQntuples(m_Result); }
00436 size_type capacity() const { return size(); }
00437
00438 void swap(result &other) throw ();
00439
00440 const tuple operator[](size_type i) const throw ()
00441 { return tuple(this, i); }
00442 const tuple at(size_type) const throw (PGSTD::out_of_range);
00443
00444 void clear() throw () { LoseRef(); }
00445
00447 tuple::size_type columns() const throw ()
00448 { return PQnfields(m_Result); }
00449
00451 tuple::size_type column_number(const char ColName[]) const;
00452
00454 tuple::size_type column_number(const PGSTD::string &Name) const
00455 {return column_number(Name.c_str());}
00456
00458 const char *column_name(tuple::size_type Number) const;
00459
00461 inline oid column_type(tuple::size_type ColNum) const;
00463 inline oid column_type(int ColNum) const
00464 { return column_type(tuple::size_type(ColNum)); }
00465
00467 oid column_type(const PGSTD::string &ColName) const
00468 { return column_type(column_number(ColName)); }
00469
00471 oid column_type(const char ColName[]) const
00472 { return column_type(column_number(ColName)); }
00473
00474 #ifdef PQXX_HAVE_PQFTABLE
00475
00476 oid column_table(tuple::size_type ColNum) const;
00478 oid column_table(int ColNum) const
00479 { return column_table(tuple::size_type(ColNum)); }
00480
00482 oid column_table(const PGSTD::string &ColName) const
00483 { return column_table(column_number(ColName)); }
00484 #endif
00485
00487
00489 oid inserted_oid() const { return PQoidValue(m_Result); }
00490
00491
00493
00494 size_type affected_rows() const;
00495
00496
00497 #ifdef PQXX_DEPRECATED_HEADERS
00498
00499 typedef tuple Tuple;
00501 typedef field Field;
00503 oid InsertedOid() const { return inserted_oid(); }
00505 size_type AffectedRows() const { return affected_rows(); }
00507 tuple::size_type Columns() const { return columns(); }
00509 tuple::size_type ColumnNumber(const char Name[]) const
00510 {return PQfnumber(m_Result,Name);}
00512 tuple::size_type ColumnNumber(const PGSTD::string &Name) const
00513 {return ColumnNumber(Name.c_str());}
00515 const char *ColumnName(tuple::size_type Number) const
00516 {return PQfname(m_Result,Number);}
00517 #endif
00518
00519
00520 private:
00521 internal::pq::PGresult *m_Result;
00522 mutable const result *m_l, *m_r;
00523
00524 friend class result::field;
00525 const char *GetValue(size_type Row, tuple::size_type Col) const;
00526 bool GetIsNull(size_type Row, tuple::size_type Col) const;
00527 field::size_type GetLength(size_type Row, tuple::size_type Col) const;
00528
00529 friend class connection_base;
00530 friend class pipeline;
00531 explicit result(internal::pq::PGresult *rhs) throw () :
00532 m_Result(0), m_l(this), m_r(this) {MakeRef(rhs);}
00533 result &operator=(internal::pq::PGresult *) throw ();
00534 bool operator!() const throw () { return !m_Result; }
00535 operator bool() const throw () { return m_Result != 0; }
00536 void CheckStatus(const PGSTD::string &Query) const;
00537 void CheckStatus(const char Query[]) const;
00538 int errorposition() const throw ();
00539 PGSTD::string StatusError() const;
00540
00541 friend class Cursor;
00542 const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00543
00544
00545 void MakeRef(internal::pq::PGresult *) throw ();
00546 void MakeRef(const result &) throw ();
00547 void LoseRef() throw ();
00548 };
00549
00550
00552
00569 template<typename STREAM>
00570 inline STREAM &operator<<(STREAM &S, const pqxx::result::field &F)
00571 {
00572 S.write(F.c_str(), F.size());
00573 return S;
00574 }
00575
00576
00578 template<typename T>
00579 inline void from_string(const result::field &F, T &Obj)
00580 { from_string(F.c_str(), Obj); }
00581
00583 template<>
00584 inline PGSTD::string to_string(const result::field &Obj)
00585 { return to_string(Obj.c_str()); }
00586
00587
00588
00589 inline result::tuple::const_iterator
00590 result::tuple::begin() const throw ()
00591 { return tuple::const_iterator(*this, 0); }
00592
00593 inline result::tuple::const_iterator
00594 result::tuple::end() const throw ()
00595 { return tuple::const_iterator(*this, size()); }
00596
00597 inline result::field
00598 result::tuple::operator[](result::tuple::size_type i) const throw ()
00599 { return field(*this, i); }
00600
00601 inline result::tuple::size_type result::tuple::size() const throw ()
00602 { return m_Home->columns(); }
00603
00604 inline const char *result::field::name() const
00605 { return home()->column_name(col()); }
00606
00608 template<>
00609 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
00610 {
00611 if (is_null()) return false;
00612 Obj = c_str();
00613 return true;
00614 }
00615
00617
00620 template<>
00621 inline bool result::field::to<const char *>(const char *&Obj) const
00622 {
00623 if (is_null()) return false;
00624 Obj = c_str();
00625 return true;
00626 }
00627
00628
00629 inline result::const_iterator
00630 result::const_iterator::operator+(difference_type o) const
00631 {
00632 return const_iterator(m_Home, m_Index + o);
00633 }
00634
00635 inline result::const_iterator
00636 operator+(result::const_iterator::difference_type o,
00637 result::const_iterator i)
00638 {
00639 return i + o;
00640 }
00641
00642 inline result::const_iterator
00643 result::const_iterator::operator-(difference_type o) const
00644 {
00645 return const_iterator(m_Home, m_Index - o);
00646 }
00647
00648 inline result::const_iterator::difference_type
00649 result::const_iterator::operator-(const_iterator i) const
00650 {
00651 return num()-i.num();
00652 }
00653
00654 inline result::const_iterator result::end() const
00655 {
00656 return const_iterator(this, size());
00657 }
00658
00659 inline oid result::column_type(tuple::size_type ColNum) const
00660 {
00661 const oid T = PQftype(m_Result, ColNum);
00662 if (T == oid_none)
00663 throw PGSTD::invalid_argument(
00664 "Attempt to retrieve type of nonexistant column " +
00665 to_string(ColNum) + " "
00666 "of query result");
00667 return T;
00668 }
00669
00670
00671 inline result::const_fielditerator
00672 result::const_fielditerator::operator+(difference_type o) const
00673 {
00674 return const_fielditerator(m_tup, col() + o);
00675 }
00676
00677 inline result::const_fielditerator
00678 operator+(result::const_fielditerator::difference_type o,
00679 result::const_fielditerator i)
00680 {
00681 return i + o;
00682 }
00683
00684 inline result::const_fielditerator
00685 result::const_fielditerator::operator-(difference_type o) const
00686 {
00687 return const_fielditerator(m_tup, col() - o);
00688 }
00689
00690 inline result::const_fielditerator::difference_type
00691 result::const_fielditerator::operator-(const_fielditerator i) const
00692 {
00693 return num()-i.num();
00694 }
00695
00696
00697
00698 #ifdef PQXX_HAVE_PQFTABLE
00699 inline oid result::column_table(tuple::size_type ColNum) const
00700 {
00701 const oid T = PQftable(m_Result, ColNum);
00702
00703
00704
00705
00706
00707 if ((T == oid_none) &&
00708 (ColNum >= columns()))
00709 throw PGSTD::invalid_argument("Attempt to retrieve table ID for column " +
00710 to_string(ColNum) + " "
00711 "out of " + to_string(columns()));
00712 return T;
00713 }
00714 #endif
00715
00716
00717 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00718 class field_streambuf :
00719 #ifdef PQXX_HAVE_STREAMBUF
00720 public PGSTD::basic_streambuf<CHAR, TRAITS>
00721 #else
00722 public PGSTD::streambuf
00723 #endif
00724 {
00725 public:
00726 typedef CHAR char_type;
00727 typedef TRAITS traits_type;
00728 typedef typename traits_type::int_type int_type;
00729 #ifdef PQXX_HAVE_STREAMBUF
00730 typedef typename traits_type::pos_type pos_type;
00731 typedef typename traits_type::off_type off_type;
00732 #else
00733 typedef streamoff off_type;
00734 typedef streampos pos_type;
00735 #endif
00736 typedef PGSTD::ios::openmode openmode;
00737 typedef PGSTD::ios::seekdir seekdir;
00738
00739 explicit field_streambuf(const result::field &F) :
00740 m_Field(F)
00741 {
00742 initialize();
00743 }
00744
00745 #ifdef PQXX_HAVE_STREAMBUF
00746 protected:
00747 #endif
00748 virtual int sync() { return traits_type::eof(); }
00749
00750 protected:
00751 virtual pos_type seekoff(off_type, seekdir, openmode)
00752 {
00753 return traits_type::eof();
00754 }
00755
00756 virtual pos_type seekpos(pos_type, openmode) {return traits_type::eof();}
00757
00758 virtual int_type overflow(int_type) { return traits_type::eof(); }
00759
00760 virtual int_type underflow() { return traits_type::eof(); }
00761
00762 private:
00763 const result::field &m_Field;
00764
00765 int_type initialize()
00766 {
00767 char_type *G =
00768 reinterpret_cast<char_type *>(const_cast<char *>(m_Field.c_str()));
00769 setg(G, G, G + m_Field.size());
00770 return m_Field.size();
00771 }
00772 };
00773
00774
00776
00790 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00791 class basic_fieldstream :
00792 #ifdef PQXX_HAVE_STREAMBUF
00793 public PGSTD::basic_istream<CHAR, TRAITS>
00794 #else
00795 public PGSTD::istream
00796 #endif
00797 {
00798 #ifdef PQXX_HAVE_STREAMBUF
00799 typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00800 #else
00801 typedef PGSTD::istream super;
00802 #endif
00803
00804 public:
00805 typedef CHAR char_type;
00806 typedef TRAITS traits_type;
00807 typedef typename traits_type::int_type int_type;
00808 typedef typename traits_type::pos_type pos_type;
00809 typedef typename traits_type::off_type off_type;
00810
00811 basic_fieldstream(const result::field &F) : super(&m_Buf), m_Buf(F) { }
00812
00813 private:
00814 field_streambuf<CHAR, TRAITS> m_Buf;
00815 };
00816
00817 typedef basic_fieldstream<char> fieldstream;
00818
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841