00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <ios>
00020 #include <stdexcept>
00021
00022 #include "pqxx/util"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 namespace pqxx
00033 {
00034
00036
00043 class PQXX_LIBEXPORT result
00044 {
00045 public:
00046 result() throw () : m_Result(0), m_Refcount(0) {}
00047 result(const result &rhs) throw () :
00048 m_Result(0), m_Refcount(0) { MakeRef(rhs); }
00049 ~result() { LoseRef(); }
00050
00051 result &operator=(const result &) throw ();
00052
00053 typedef result_size_type size_type;
00054 class field;
00055
00056
00057
00059
00067 class PQXX_LIBEXPORT tuple
00068 {
00069 public:
00070 typedef tuple_size_type size_type;
00071 tuple(const result *r, result::size_type i) throw () :
00072 m_Home(r), m_Index(i) {}
00073 ~tuple() throw () {}
00074
00075 inline field operator[](size_type) const throw ();
00076 field operator[](const char[]) const;
00077 field operator[](const PGSTD::string &s) const
00078 { return operator[](s.c_str()); }
00079 field at(size_type) const throw (PGSTD::out_of_range);
00080 field at(const char[]) const;
00081 field at(const PGSTD::string &s) const { return at(s.c_str()); }
00082
00083 inline size_type size() const throw ();
00084
00085 result::size_type rownumber() const throw () { return m_Index; }
00086
00088 size_type column_number(const PGSTD::string &ColName) const
00089 { return m_Home->column_number(ColName); }
00090
00092 size_type column_number(const char ColName[]) const
00093 { return m_Home->column_number(ColName); }
00094
00096 oid column_type(size_type ColNum) const
00097 { return m_Home->column_type(ColNum); }
00098
00100 oid column_type(const PGSTD::string &ColName) const
00101 { return column_type(column_number(ColName)); }
00102
00104 oid column_type(const char ColName[]) const
00105 { return column_type(column_number(ColName)); }
00106
00107 #ifdef PQXX_HAVE_PQFTABLE
00108 oid column_table(size_type ColNum) const
00109 { return m_Home->column_table(ColNum); }
00110 oid column_table(const PGSTD::string &ColName) const
00111 { return column_table(column_number(ColName)); }
00112 #endif
00113
00114
00115 #ifdef PQXX_DEPRECATED_HEADERS
00116
00117 result::size_type Row() const { return rownumber(); }
00118
00120 size_type ColumnNumber(const PGSTD::string &ColName) const
00121 { return m_Home->ColumnNumber(ColName); }
00122
00124 size_type ColumnNumber(const char ColName[]) const
00125 { return m_Home->ColumnNumber(ColName); }
00126 #endif
00127
00128
00129 protected:
00130 const result *m_Home;
00131 result::size_type m_Index;
00132
00133
00134 tuple();
00135 };
00136
00138
00141 class PQXX_LIBEXPORT field : private tuple
00142 {
00143 public:
00144 typedef size_t size_type;
00145
00147
00151 field(const tuple &R, tuple::size_type C) throw () :
00152 tuple(R), m_Col(C) {}
00153
00155
00160 const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);}
00161
00163 inline const char *name() const;
00164
00166 oid type() const
00167 { return m_Home->column_type(m_Col); }
00168
00169 #ifdef PQXX_HAVE_PQFTABLE
00170
00171
00173 oid table() const { return m_Home->column_table(m_Col); }
00174 #endif
00175
00177
00186 template<typename T> bool to(T &Obj) const
00187 {
00188 if (is_null())
00189 return false;
00190
00191 try
00192 {
00193 from_string(c_str(), Obj);
00194 }
00195 catch (const PGSTD::exception &e)
00196 {
00197 throw PGSTD::domain_error("Error reading field " +
00198 PGSTD::string(name()) +
00199 ": " +
00200 e.what());
00201 }
00202 return true;
00203 }
00204
00205
00206 #ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00207
00208 template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00209
00211
00214 template<> bool to<const char *>(const char *&Obj) const;
00215 #endif
00216
00217
00219 template<typename T> bool to(T &Obj, const T &Default) const
00220 {
00221 const bool NotNull = to(Obj);
00222 if (!NotNull)
00223 Obj = Default;
00224 return NotNull;
00225 }
00226
00228
00231 template<typename T> T as(const T &Default) const
00232 {
00233 T Obj;
00234 to(Obj, Default);
00235 return Obj;
00236 }
00237
00239 template<typename T> T as() const
00240 {
00241 T Obj;
00242 const bool NotNull = to(Obj);
00243 if (!NotNull) throw PGSTD::domain_error("Attempt to read null field");
00244 return Obj;
00245 }
00246
00247 bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }
00248
00249 size_type size() const { return m_Home->GetLength(m_Index,m_Col); }
00250
00251 #ifdef PQXX_DEPRECATED_HEADERS
00252
00253 const char *Name() const {return name();}
00254 #endif
00255
00256 private:
00257 tuple::size_type m_Col;
00258 };
00259
00261
00265 class PQXX_LIBEXPORT const_iterator :
00266 public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00267 const tuple,
00268 result::size_type>,
00269 public tuple
00270 {
00271 public:
00272 const_iterator() : tuple(0,0) {}
00273
00280 pointer operator->() const { return this; }
00281 reference operator*() const { return *operator->(); }
00282
00283 const_iterator operator++(int);
00284 const_iterator &operator++() { ++m_Index; return *this; }
00285 const_iterator operator--(int);
00286 const_iterator &operator--() { --m_Index; return *this; }
00287
00288 const_iterator &operator+=(difference_type i)
00289 { m_Index+=i; return *this; }
00290 const_iterator &operator-=(difference_type i)
00291 { m_Index-=i; return *this; }
00292
00293 bool operator==(const const_iterator &i) const
00294 {return m_Index==i.m_Index;}
00295 bool operator!=(const const_iterator &i) const
00296 {return m_Index!=i.m_Index;}
00297 bool operator<(const const_iterator &i) const
00298 {return m_Index<i.m_Index;}
00299 bool operator<=(const const_iterator &i) const
00300 {return m_Index<=i.m_Index;}
00301 bool operator>(const const_iterator &i) const
00302 {return m_Index>i.m_Index;}
00303 bool operator>=(const const_iterator &i) const
00304 {return m_Index>=i.m_Index;}
00305
00306 inline const_iterator operator+(difference_type o) const;
00307
00308 friend const_iterator operator+(difference_type o,
00309 const_iterator i);
00310
00311 inline const_iterator operator-(difference_type o) const;
00312
00313 inline difference_type operator-(const_iterator i) const;
00314
00315 result::size_type num() const { return rownumber(); }
00316
00317 private:
00318 friend class result;
00319 const_iterator(const result *r, result::size_type i) : tuple(r, i) {}
00320 };
00321
00322 #ifdef PQXX_HAVE_REVERSE_ITERATOR
00323 typedef PGSTD::reverse_iterator<const_iterator> const_reverse_iterator;
00324 const_reverse_iterator rbegin() const
00325 { return const_reverse_iterator(end()); }
00326 const_reverse_iterator rend() const
00327 { return const_reverse_iterator(begin()); }
00328 #endif
00329
00330 const_iterator begin() const { return const_iterator(this, 0); }
00331 inline const_iterator end() const;
00332
00333 size_type size() const { return m_Result ? PQntuples(m_Result) : 0; }
00334 bool empty() const { return !m_Result || !PQntuples(m_Result); }
00335 size_type capacity() const { return size(); }
00336
00337 void swap(result &other) throw ();
00338
00339 const tuple operator[](size_type i) const throw ()
00340 { return tuple(this, i); }
00341 const tuple at(size_type) const throw (PGSTD::out_of_range);
00342
00343 void clear() throw () { LoseRef(); }
00344
00346 tuple::size_type columns() const throw ()
00347 { return PQnfields(m_Result); }
00348
00350 tuple::size_type column_number(const char ColName[]) const;
00351
00353 tuple::size_type column_number(const PGSTD::string &Name) const
00354 {return column_number(Name.c_str());}
00355
00357 const char *column_name(tuple::size_type Number) const;
00358
00360 inline oid column_type(tuple::size_type ColNum) const;
00361
00363 oid column_type(const PGSTD::string &ColName) const
00364 { return column_type(column_number(ColName)); }
00365
00367 oid column_type(const char ColName[]) const
00368 { return column_type(column_number(ColName)); }
00369
00370 #ifdef PQXX_HAVE_PQFTABLE
00371
00372 oid column_table(tuple::size_type ColNum) const;
00373
00375 oid column_table(const PGSTD::string &ColName) const
00376 { return column_table(column_number(ColName)); }
00377 #endif
00378
00379
00381
00383 oid inserted_oid() const { return PQoidValue(m_Result); }
00384
00385
00387
00388 size_type affected_rows() const;
00389
00390
00391 #ifdef PQXX_DEPRECATED_HEADERS
00392
00393 typedef tuple Tuple;
00395 typedef field Field;
00397 oid InsertedOid() const { return inserted_oid(); }
00399 size_type AffectedRows() const { return affected_rows(); }
00401 tuple::size_type Columns() const { return columns(); }
00403 tuple::size_type ColumnNumber(const char Name[]) const
00404 {return PQfnumber(m_Result,Name);}
00406 tuple::size_type ColumnNumber(const PGSTD::string &Name) const
00407 {return ColumnNumber(Name.c_str());}
00409 const char *ColumnName(tuple::size_type Number) const
00410 {return PQfname(m_Result,Number);}
00411 #endif
00412
00413
00414 private:
00415 PGresult *m_Result;
00416 mutable int *m_Refcount;
00417
00418 friend class result::field;
00419 const char *GetValue(size_type Row, tuple::size_type Col) const;
00420 bool GetIsNull(size_type Row, tuple::size_type Col) const;
00421 field::size_type GetLength(size_type Row, tuple::size_type Col) const;
00422
00423 friend class connection_base;
00424 explicit result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00425 result &operator=(PGresult *);
00426 bool operator!() const throw () { return !m_Result; }
00427 operator bool() const throw () { return m_Result != 0; }
00428 friend class pipeline;
00429 void CheckStatus(const PGSTD::string &Query) const;
00430 void CheckStatus(const char Query[]) const;
00431 PGSTD::string StatusError() const;
00432
00433 friend class Cursor;
00434 const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00435
00436
00437 void MakeRef(PGresult *);
00438 void MakeRef(const result &) throw ();
00439 void LoseRef() throw ();
00440 };
00441
00442
00444
00461 template<typename STREAM>
00462 inline STREAM &operator<<(STREAM &S, const pqxx::result::field &F)
00463 {
00464 S.write(F.c_str(), F.size());
00465 return S;
00466 }
00467
00468
00470 template<typename T>
00471 inline void from_string(const result::field &F, T &Obj)
00472 { from_string(F.c_str(), Obj); }
00473
00475 template<>
00476 inline PGSTD::string to_string(const result::field &Obj)
00477 { return to_string(Obj.c_str()); }
00478
00479 inline result::field
00480 result::tuple::operator[](result::tuple::size_type i) const throw ()
00481 {
00482 return field(*this, i);
00483 }
00484
00485 inline result::tuple::size_type result::tuple::size() const throw ()
00486 {
00487 return m_Home->columns();
00488 }
00489
00490 inline const char *result::field::name() const
00491 {
00492 return m_Home->column_name(m_Col);
00493 }
00494
00496 template<>
00497 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
00498 {
00499 if (is_null()) return false;
00500 Obj = c_str();
00501 return true;
00502 }
00503
00505
00508 template<>
00509 inline bool result::field::to<const char *>(const char *&Obj) const
00510 {
00511 if (is_null()) return false;
00512 Obj = c_str();
00513 return true;
00514 }
00515
00516
00517 inline result::const_iterator
00518 result::const_iterator::operator+(difference_type o) const
00519 {
00520 return const_iterator(m_Home, m_Index + o);
00521 }
00522
00523 inline result::const_iterator
00524 operator+(result::const_iterator::difference_type o,
00525 result::const_iterator i)
00526 {
00527 return i + o;
00528 }
00529
00530 inline result::const_iterator
00531 result::const_iterator::operator-(difference_type o) const
00532 {
00533 return const_iterator(m_Home, m_Index - o);
00534 }
00535
00536 inline result::const_iterator::difference_type
00537 result::const_iterator::operator-(const_iterator i) const
00538 {
00539 return num()-i.num();
00540 }
00541
00542 inline result::const_iterator result::end() const
00543 {
00544 return const_iterator(this, size());
00545 }
00546
00547 inline oid result::column_type(tuple::size_type ColNum) const
00548 {
00549 const oid T = PQftype(m_Result, ColNum);
00550 if (T == oid_none)
00551 throw PGSTD::invalid_argument(
00552 "Attempt to retrieve type of nonexistant column " +
00553 to_string(ColNum) + " "
00554 "of query result");
00555 return T;
00556 }
00557
00558
00559 #ifdef PQXX_HAVE_PQFTABLE
00560 inline oid result::column_table(tuple::size_type ColNum) const
00561 {
00562 const oid T = PQftable(m_Result, ColNum);
00563
00564
00565
00566
00567
00568 if ((T == InvalidOid) &&
00569 ((ColNum < 0) || (ColNum >= columns())))
00570 throw PGSTD::invalid_argument("Attempt to retrieve table ID for column " +
00571 to_string(ColNum) + " "
00572 "out of " + to_string(columns()));
00573 return T;
00574 }
00575 #endif
00576
00577
00578 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00579 class field_streambuf :
00580 #ifdef PQXX_HAVE_STREAMBUF
00581 public PGSTD::basic_streambuf<CHAR, TRAITS>
00582 #else
00583 public PGSTD::streambuf
00584 #endif
00585 {
00586 typedef long size_type;
00587 public:
00588 typedef CHAR char_type;
00589 typedef TRAITS traits_type;
00590 typedef typename traits_type::int_type int_type;
00591 #ifdef PQXX_HAVE_STREAMBUF
00592 typedef typename traits_type::pos_type pos_type;
00593 typedef typename traits_type::off_type off_type;
00594 #else
00595 typedef streamoff off_type;
00596 typedef streampos pos_type;
00597 #endif
00598 typedef PGSTD::ios::openmode openmode;
00599 typedef PGSTD::ios::seekdir seekdir;
00600
00601 explicit field_streambuf(const result::field &F) :
00602 m_Field(F)
00603 {
00604 initialize();
00605 }
00606
00607 #ifdef PQXX_HAVE_STREAMBUF
00608 protected:
00609 #endif
00610 virtual int sync() { return traits_type::eof(); }
00611
00612 protected:
00613 virtual pos_type seekoff(off_type, seekdir, openmode)
00614 {
00615 return traits_type::eof();
00616 }
00617
00618 virtual pos_type seekpos(pos_type, openmode) {return traits_type::eof();}
00619
00620 virtual int_type overflow(int_type) { return traits_type::eof(); }
00621
00622 virtual int_type underflow() { return traits_type::eof(); }
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