00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdexcept>
00020
00021 #include "pqxx/util"
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 namespace pqxx
00032 {
00033
00035
00042 class PQXX_LIBEXPORT result
00043 {
00044 public:
00045 result() throw () : m_Result(0), m_Refcount(0) {}
00046 result(const result &rhs) throw () :
00047 m_Result(0), m_Refcount(0) { MakeRef(rhs); }
00048 ~result() { LoseRef(); }
00049
00050 result &operator=(const result &) throw ();
00051
00052 typedef result_size_type size_type;
00053 class field;
00054
00055
00056
00058
00066 class PQXX_LIBEXPORT tuple
00067 {
00068 public:
00069 typedef tuple_size_type size_type;
00070 tuple(const result *r, result::size_type i) throw () :
00071 m_Home(r), m_Index(i) {}
00072 ~tuple() throw () {}
00073
00074 inline field operator[](size_type) const throw ();
00075 field operator[](const char[]) const;
00076 field operator[](const PGSTD::string &s) const
00077 { return operator[](s.c_str()); }
00078 field at(size_type) const throw (PGSTD::out_of_range);
00079 field at(const char[]) const;
00080 field at(const PGSTD::string &s) const { return at(s.c_str()); }
00081
00082 inline size_type size() const throw ();
00083
00084 result::size_type rownumber() const throw () { return m_Index; }
00085
00087 size_type column_number(const PGSTD::string &ColName) const
00088 { return m_Home->column_number(ColName); }
00089
00091 size_type column_number(const char ColName[]) const
00092 { return m_Home->column_number(ColName); }
00093
00095 oid column_type(size_type ColNum) const
00096 { return m_Home->column_type(ColNum); }
00097
00099 oid column_type(const PGSTD::string &ColName) const
00100 { return column_type(column_number(ColName)); }
00101
00103 oid column_type(const char ColName[]) const
00104 { return column_type(column_number(ColName)); }
00105
00106 #ifdef PQXX_HAVE_PQFTABLE
00107 oid column_table(size_type ColNum) const
00108 { return m_Home->column_table(ColNum); }
00109 oid column_table(const PGSTD::string &ColName) const
00110 { return column_table(column_number(ColName)); }
00111 #endif
00112
00113
00114 #ifdef PQXX_DEPRECATED_HEADERS
00115
00116 result::size_type Row() const { return rownumber(); }
00117
00119 size_type ColumnNumber(const PGSTD::string &ColName) const
00120 { return m_Home->ColumnNumber(ColName); }
00121
00123 size_type ColumnNumber(const char ColName[]) const
00124 { return m_Home->ColumnNumber(ColName); }
00125 #endif
00126
00127
00128 protected:
00129 const result *m_Home;
00130 result::size_type m_Index;
00131
00132
00133 tuple();
00134 };
00135
00137
00140 class PQXX_LIBEXPORT field : private tuple
00141 {
00142 public:
00143 typedef size_t size_type;
00144
00146
00150 field(const tuple &R, tuple::size_type C) throw () :
00151 tuple(R), m_Col(C) {}
00152
00154
00159 const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);}
00160
00162 inline const char *name() const;
00163
00165 oid type() const
00166 { return m_Home->column_type(m_Col); }
00167
00168 #ifdef PQXX_HAVE_PQFTABLE
00169
00170
00172 oid table() const { return m_Home->column_table(m_Col); }
00173 #endif
00174
00176
00185 template<typename T> bool to(T &Obj) const
00186 {
00187 if (is_null())
00188 return false;
00189
00190 try
00191 {
00192 from_string(c_str(), Obj);
00193 }
00194 catch (const PGSTD::exception &e)
00195 {
00196 throw PGSTD::domain_error("Error reading field " +
00197 PGSTD::string(name()) +
00198 ": " +
00199 e.what());
00200 }
00201 return true;
00202 }
00203
00204
00205 #ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00206
00207 template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00208
00210
00213 template<> bool to<const char *>(const char *&Obj) const;
00214 #endif
00215
00216
00218 template<typename T> bool to(T &Obj, const T &Default) const
00219 {
00220 const bool NotNull = to(Obj);
00221 if (!NotNull)
00222 Obj = Default;
00223 return NotNull;
00224 }
00225
00227
00230 template<typename T> T as(const T &Default) const
00231 {
00232 T Obj;
00233 to(Obj, Default);
00234 return Obj;
00235 }
00236
00238 template<typename T> T as() const
00239 {
00240 T Obj;
00241 const bool NotNull = to(Obj);
00242 if (!NotNull) throw PGSTD::domain_error("Attempt to read null field");
00243 return Obj;
00244 }
00245
00246 bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }
00247
00248 size_type size() const { return m_Home->GetLength(m_Index,m_Col); }
00249
00250 #ifdef PQXX_DEPRECATED_HEADERS
00251
00252 const char *Name() const {return name();}
00253 #endif
00254
00255 private:
00256 tuple::size_type m_Col;
00257 };
00258
00260
00264 class PQXX_LIBEXPORT const_iterator :
00265 public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00266 const tuple,
00267 result::size_type>,
00268 public tuple
00269 {
00270 public:
00271 const_iterator() : tuple(0,0) {}
00272
00279 pointer operator->() const { return this; }
00280 reference operator*() const { return *operator->(); }
00281
00282 const_iterator operator++(int);
00283 const_iterator &operator++() { ++m_Index; return *this; }
00284 const_iterator operator--(int);
00285 const_iterator &operator--() { --m_Index; return *this; }
00286
00287 const_iterator &operator+=(difference_type i)
00288 { m_Index+=i; return *this; }
00289 const_iterator &operator-=(difference_type i)
00290 { m_Index-=i; return *this; }
00291
00292 bool operator==(const const_iterator &i) const
00293 {return m_Index==i.m_Index;}
00294 bool operator!=(const const_iterator &i) const
00295 {return m_Index!=i.m_Index;}
00296 bool operator<(const const_iterator &i) const
00297 {return m_Index<i.m_Index;}
00298 bool operator<=(const const_iterator &i) const
00299 {return m_Index<=i.m_Index;}
00300 bool operator>(const const_iterator &i) const
00301 {return m_Index>i.m_Index;}
00302 bool operator>=(const const_iterator &i) const
00303 {return m_Index>=i.m_Index;}
00304
00305 inline const_iterator operator+(difference_type o) const;
00306
00307 friend const_iterator operator+(difference_type o,
00308 const_iterator i);
00309
00310 inline const_iterator operator-(difference_type o) const;
00311
00312 inline difference_type operator-(const_iterator i) const;
00313
00314 result::size_type num() const { return rownumber(); }
00315
00316 private:
00317 friend class result;
00318 const_iterator(const result *r, result::size_type i) : tuple(r, i) {}
00319 };
00320
00321 #ifdef PQXX_HAVE_REVERSE_ITERATOR
00322 typedef PGSTD::reverse_iterator<const_iterator> const_reverse_iterator;
00323 const_reverse_iterator rbegin() const
00324 { return const_reverse_iterator(end()); }
00325 const_reverse_iterator rend() const
00326 { return const_reverse_iterator(begin()); }
00327 #endif
00328
00329 const_iterator begin() const { return const_iterator(this, 0); }
00330 inline const_iterator end() const;
00331
00332 size_type size() const { return m_Result ? PQntuples(m_Result) : 0; }
00333 bool empty() const { return !m_Result || !PQntuples(m_Result); }
00334 size_type capacity() const { return size(); }
00335
00336 void swap(result &other) throw ();
00337
00338 const tuple operator[](size_type i) const throw ()
00339 { return tuple(this, i); }
00340 const tuple at(size_type) const throw (PGSTD::out_of_range);
00341
00342 void clear() throw () { LoseRef(); }
00343
00345 tuple::size_type columns() const throw ()
00346 { return PQnfields(m_Result); }
00347
00349 tuple::size_type column_number(const char ColName[]) const;
00350
00352 tuple::size_type column_number(const PGSTD::string &Name) const
00353 {return column_number(Name.c_str());}
00354
00356 const char *column_name(tuple::size_type Number) const;
00357
00359 inline oid column_type(tuple::size_type ColNum) const;
00360
00362 oid column_type(const PGSTD::string &ColName) const
00363 { return column_type(column_number(ColName)); }
00364
00366 oid column_type(const char ColName[]) const
00367 { return column_type(column_number(ColName)); }
00368
00369 #ifdef PQXX_HAVE_PQFTABLE
00370
00371 oid column_table(tuple::size_type ColNum) const;
00372
00374 oid column_table(const PGSTD::string &ColName) const
00375 { return column_table(column_number(ColName)); }
00376 #endif
00377
00378
00380
00382 oid inserted_oid() const { return PQoidValue(m_Result); }
00383
00384
00386
00387 size_type affected_rows() const;
00388
00389
00390 #ifdef PQXX_DEPRECATED_HEADERS
00391
00392 typedef tuple Tuple;
00394 typedef field Field;
00396 oid InsertedOid() const { return inserted_oid(); }
00398 size_type AffectedRows() const { return affected_rows(); }
00400 tuple::size_type Columns() const { return columns(); }
00402 tuple::size_type ColumnNumber(const char Name[]) const
00403 {return PQfnumber(m_Result,Name);}
00405 tuple::size_type ColumnNumber(const PGSTD::string &Name) const
00406 {return ColumnNumber(Name.c_str());}
00408 const char *ColumnName(tuple::size_type Number) const
00409 {return PQfname(m_Result,Number);}
00410 #endif
00411
00412
00413 private:
00414 PGresult *m_Result;
00415 mutable int *m_Refcount;
00416
00417 friend class result::field;
00418 const char *GetValue(size_type Row, tuple::size_type Col) const;
00419 bool GetIsNull(size_type Row, tuple::size_type Col) const;
00420 field::size_type GetLength(size_type Row, tuple::size_type Col) const;
00421
00422 friend class connection_base;
00423 explicit result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00424 result &operator=(PGresult *);
00425 bool operator!() const throw () { return !m_Result; }
00426 operator bool() const throw () { return m_Result != 0; }
00427 friend class pipeline;
00428 void CheckStatus(const PGSTD::string &Query) const;
00429 void CheckStatus(const char Query[]) const;
00430 PGSTD::string StatusError() const;
00431
00432 friend class Cursor;
00433 const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00434
00435
00436 void MakeRef(PGresult *);
00437 void MakeRef(const result &) throw ();
00438 void LoseRef() throw ();
00439 };
00440
00441
00443
00460 template<typename STREAM>
00461 inline STREAM &operator<<(STREAM &S, const pqxx::result::field &F)
00462 {
00463 S.write(F.c_str(), F.size());
00464 return S;
00465 }
00466
00467
00469 template<typename T>
00470 inline void from_string(const result::field &F, T &Obj)
00471 { from_string(F.c_str(), Obj); }
00472
00474 template<>
00475 inline PGSTD::string to_string(const result::field &Obj)
00476 { return to_string(Obj.c_str()); }
00477
00478 inline result::field
00479 result::tuple::operator[](result::tuple::size_type i) const throw ()
00480 {
00481 return field(*this, i);
00482 }
00483
00484 inline result::tuple::size_type result::tuple::size() const throw ()
00485 {
00486 return m_Home->columns();
00487 }
00488
00489 inline const char *result::field::name() const
00490 {
00491 return m_Home->column_name(m_Col);
00492 }
00493
00495 template<>
00496 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
00497 {
00498 if (is_null()) return false;
00499 Obj = c_str();
00500 return true;
00501 }
00502
00504
00507 template<>
00508 inline bool result::field::to<const char *>(const char *&Obj) const
00509 {
00510 if (is_null()) return false;
00511 Obj = c_str();
00512 return true;
00513 }
00514
00515
00516 inline result::const_iterator
00517 result::const_iterator::operator+(difference_type o) const
00518 {
00519 return const_iterator(m_Home, m_Index + o);
00520 }
00521
00522 inline result::const_iterator
00523 operator+(result::const_iterator::difference_type o,
00524 result::const_iterator i)
00525 {
00526 return i + o;
00527 }
00528
00529 inline result::const_iterator
00530 result::const_iterator::operator-(difference_type o) const
00531 {
00532 return const_iterator(m_Home, m_Index - o);
00533 }
00534
00535 inline result::const_iterator::difference_type
00536 result::const_iterator::operator-(const_iterator i) const
00537 {
00538 return num()-i.num();
00539 }
00540
00541 inline result::const_iterator result::end() const
00542 {
00543 return const_iterator(this, size());
00544 }
00545
00546 inline oid result::column_type(tuple::size_type ColNum) const
00547 {
00548 const oid T = PQftype(m_Result, ColNum);
00549 if (T == oid_none)
00550 throw PGSTD::invalid_argument(
00551 "Attempt to retrieve type of nonexistant column " +
00552 to_string(ColNum) + " "
00553 "of query result");
00554 return T;
00555 }
00556
00557
00558 #ifdef PQXX_HAVE_PQFTABLE
00559 inline oid result::column_table(tuple::size_type ColNum) const
00560 {
00561 const oid T = PQftable(m_Result, ColNum);
00562
00563
00564
00565
00566
00567 if ((T == InvalidOid) &&
00568 ((ColNum < 0) || (ColNum >= columns())))
00569 throw PGSTD::invalid_argument("Attempt to retrieve table ID for column " +
00570 to_string(ColNum) + " "
00571 "out of " + to_string(columns()));
00572 return T;
00573 }
00574 #endif
00575
00576
00577 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00578 class field_streambuf :
00579 #ifdef PQXX_HAVE_STREAMBUF
00580 public PGSTD::basic_streambuf<CHAR, TRAITS>
00581 #else
00582 public PGSTD::streambuf
00583 #endif
00584 {
00585 typedef long size_type;
00586 public:
00587 typedef CHAR char_type;
00588 typedef TRAITS traits_type;
00589 typedef typename traits_type::int_type int_type;
00590 #ifdef PQXX_HAVE_STREAMBUF
00591 typedef typename traits_type::pos_type pos_type;
00592 typedef typename traits_type::off_type off_type;
00593 #else
00594 typedef streamoff off_type;
00595 typedef streampos pos_type;
00596 #endif
00597 typedef PGSTD::ios::openmode openmode;
00598 typedef PGSTD::ios::seekdir seekdir;
00599
00600 explicit field_streambuf(const result::field &F) :
00601 m_Field(F)
00602 {
00603 initialize();
00604 }
00605
00606 #ifdef PQXX_HAVE_STREAMBUF
00607 protected:
00608 #endif
00609 virtual int sync() { return traits_type::eof(); }
00610
00611 protected:
00612 virtual pos_type seekoff(off_type, seekdir, openmode)
00613 {
00614 return traits_type::eof();
00615 }
00616
00617 virtual pos_type seekpos(pos_type, openmode) {return traits_type::eof();}
00618
00619 virtual int_type overflow(int_type) { return traits_type::eof(); }
00620
00621
00622 virtual int_type underflow() { return initialize(); }
00623
00624 private:
00625 const result::field &m_Field;
00626
00627 int_type initialize() throw ()
00628 {
00629 char_type *G =
00630 reinterpret_cast<char_type *>(const_cast<char *>(m_Field.c_str()));
00631 setg(G, G, G + m_Field.size());
00632 return m_Field.size();
00633 }
00634 };
00635
00636
00638
00652 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00653 class basic_fieldstream :
00654 #ifdef PQXX_HAVE_STREAMBUF
00655 public PGSTD::basic_istream<CHAR, TRAITS>
00656 #else
00657 public PGSTD::istream
00658 #endif
00659 {
00660 #ifdef PQXX_HAVE_STREAMBUF
00661 typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00662 #else
00663 typedef PGSTD::istream super;
00664 #endif
00665
00666 public:
00667 typedef CHAR char_type;
00668 typedef TRAITS traits_type;
00669 typedef typename traits_type::int_type int_type;
00670 typedef typename traits_type::pos_type pos_type;
00671 typedef typename traits_type::off_type off_type;
00672
00673 basic_fieldstream(const result::field &F) : super(&m_Buf), m_Buf(F) { }
00674
00675 private:
00676 field_streambuf<CHAR, TRAITS> m_Buf;
00677 };
00678
00679 typedef basic_fieldstream<char> fieldstream;
00680
00681 }
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703