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 namespace pqxx
00030 {
00031
00033
00040 class PQXX_LIBEXPORT result
00041 {
00042 public:
00043 result() : m_Result(0), m_Refcount(0) {}
00044 result(const result &rhs) :
00045 m_Result(0), m_Refcount(0) { MakeRef(rhs); }
00046 ~result() { LoseRef(); }
00047
00048 result &operator=(const result &);
00049
00050 typedef result_size_type size_type;
00051 class field;
00052
00053
00054
00056
00064 class PQXX_LIBEXPORT tuple
00065 {
00066 public:
00067 typedef tuple_size_type size_type;
00068 tuple(const result *r, result::size_type i) throw() :
00069 m_Home(r), m_Index(i) {}
00070 ~tuple() {}
00071
00072 inline field operator[](size_type) const throw ();
00073 field operator[](const char[]) const;
00074 field operator[](const PGSTD::string &s) const
00075 { return operator[](s.c_str()); }
00076 field at(size_type) const throw (PGSTD::out_of_range);
00077 field at(const char[]) const;
00078 field at(const PGSTD::string &s) const { return at(s.c_str()); }
00079
00080 inline size_type size() const;
00081
00082 #ifdef PQXX_DEPRECATED_HEADERS
00083
00084 result::size_type Row() const { return rownumber(); }
00085
00087 size_type ColumnNumber(const PGSTD::string &ColName) const
00088 { return m_Home->ColumnNumber(ColName); }
00089
00091 size_type ColumnNumber(const char ColName[]) const
00092 { return m_Home->ColumnNumber(ColName); }
00093 #endif
00094
00095 result::size_type rownumber() const { return m_Index; }
00096
00098 size_type column_number(const PGSTD::string &ColName) const
00099 { return m_Home->column_number(ColName); }
00100
00102 size_type column_number(const char ColName[]) const
00103 { return m_Home->column_number(ColName); }
00104
00106 oid column_type(size_type ColNum) const
00107 { return m_Home->column_type(ColNum); }
00108
00110 oid column_type(const PGSTD::string &ColName) const
00111 { return column_type(column_number(ColName)); }
00112
00114 oid column_type(const char ColName[]) const
00115 { return column_type(column_number(ColName)); }
00116
00117 #ifdef PQXX_HAVE_PQFTABLE
00118 oid column_table(size_type ColNum) const
00119 { return m_Home->column_table(ColNum); }
00120 oid column_table(const PGSTD::string &ColName) const
00121 { return column_table(column_number(ColName)); }
00122 #endif
00123
00124 protected:
00125 const result *m_Home;
00126 result::size_type m_Index;
00127
00128
00129 tuple();
00130 };
00131
00132 #ifdef PQXX_DEPRECATED_HEADERS
00133
00134 typedef tuple Tuple;
00135 #endif
00136
00137
00139
00142 class PQXX_LIBEXPORT field : private tuple
00143 {
00144 public:
00145 typedef size_t size_type;
00146
00148
00152 field(const tuple &R, tuple::size_type C) throw () :
00153 tuple(R), m_Col(C) {}
00154
00156
00161 const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);}
00162
00163 #ifdef PQXX_DEPRECATED_HEADERS
00164
00165 const char *Name() const {return name();}
00166 #endif
00167
00169 inline const char *name() const;
00170
00172 oid type() const
00173 { return m_Home->column_type(m_Col); }
00174
00175 #ifdef PQXX_HAVE_PQFTABLE
00176
00177
00179 oid table() const { return m_Home->column_table(m_Col); }
00180 #endif
00181
00183
00192 template<typename T> bool to(T &Obj) const
00193 {
00194 if (is_null())
00195 return false;
00196
00197 try
00198 {
00199 FromString(c_str(), Obj);
00200 }
00201 catch (const PGSTD::exception &e)
00202 {
00203 throw PGSTD::domain_error("Error reading field " +
00204 PGSTD::string(name()) +
00205 ": " +
00206 e.what());
00207 }
00208 return true;
00209 }
00210
00211
00212 #ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00213
00214 template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00215
00217
00220 template<> bool to<const char *>(const char *&Obj) const;
00221 #endif
00222
00223
00225 template<typename T> bool to(T &Obj, const T &Default) const
00226 {
00227 const bool NotNull = to(Obj);
00228 if (!NotNull)
00229 Obj = Default;
00230 return NotNull;
00231 }
00232
00234
00237 template<typename T> T as(const T &Default) const
00238 {
00239 T Obj;
00240 to(Obj, Default);
00241 return Obj;
00242 }
00243
00245 template<typename T> T as() const
00246 {
00247 T Obj;
00248 const bool NotNull = to(Obj);
00249 if (!NotNull) throw PGSTD::domain_error("Attempt to read null field");
00250 return Obj;
00251 }
00252
00253 bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }
00254
00255 size_type size() const { return m_Home->GetLength(m_Index,m_Col); }
00256
00257 private:
00258
00259 tuple::size_type m_Col;
00260 };
00261
00262 #ifdef PQXX_DEPRECATED_HEADERS
00263
00264 typedef field Field;
00265 #endif
00266
00268
00272 class PQXX_LIBEXPORT const_iterator :
00273 public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00274 const tuple,
00275 result::size_type>,
00276 public tuple
00277 {
00278 public:
00279 const_iterator() : tuple(0,0) {}
00280
00287 pointer operator->() const { return this; }
00288 reference operator*() const { return *operator->(); }
00289
00290 const_iterator operator++(int);
00291 const_iterator &operator++() { ++m_Index; return *this; }
00292 const_iterator operator--(int);
00293 const_iterator &operator--() { --m_Index; return *this; }
00294
00295 const_iterator &operator+=(difference_type i)
00296 { m_Index+=i; return *this; }
00297 const_iterator &operator-=(difference_type i)
00298 { m_Index-=i; return *this; }
00299
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 bool operator<(const const_iterator &i) const
00305 {return m_Index<i.m_Index;}
00306 bool operator<=(const const_iterator &i) const
00307 {return m_Index<=i.m_Index;}
00308 bool operator>(const const_iterator &i) const
00309 {return m_Index>i.m_Index;}
00310 bool operator>=(const const_iterator &i) const
00311 {return m_Index>=i.m_Index;}
00312
00313 inline const_iterator operator+(difference_type o) const;
00314
00315 friend const_iterator operator+(difference_type o,
00316 const_iterator i);
00317
00318 inline const_iterator operator-(difference_type o) const;
00319
00320 inline difference_type operator-(const_iterator i) const;
00321
00322 result::size_type num() const { return rownumber(); }
00323
00324 private:
00325 friend class result;
00326 const_iterator(const result *r, result::size_type i) : tuple(r, i) {}
00327 };
00328
00329 const_iterator begin() const { return const_iterator(this, 0); }
00330 inline const_iterator end() const;
00331
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 const tuple operator[](size_type i) const throw ()
00338 { return tuple(this, i); }
00339 const tuple at(size_type) const throw (PGSTD::out_of_range);
00340
00341 void clear() { LoseRef(); }
00342
00343 #ifdef PQXX_DEPRECATED_HEADERS
00344
00345 tuple::size_type Columns() const { return columns(); }
00346
00348 tuple::size_type ColumnNumber(const char Name[]) const
00349 {return PQfnumber(m_Result,Name);}
00351 tuple::size_type ColumnNumber(const PGSTD::string &Name) const
00352 {return ColumnNumber(Name.c_str());}
00354 const char *ColumnName(tuple::size_type Number) const
00355 {return PQfname(m_Result,Number);}
00356 #endif
00357
00359 tuple::size_type columns() const { return PQnfields(m_Result); }
00360
00362 tuple::size_type column_number(const char ColName[]) const;
00363
00365 tuple::size_type column_number(const PGSTD::string &Name) const
00366 {return column_number(Name.c_str());}
00367
00369 const char *column_name(tuple::size_type Number) const;
00370
00372 inline oid column_type(tuple::size_type ColNum) const;
00373
00375 oid column_type(const PGSTD::string &ColName) const
00376 { return column_type(column_number(ColName)); }
00377
00379 oid column_type(const char ColName[]) const
00380 { return column_type(column_number(ColName)); }
00381
00382 #ifdef PQXX_HAVE_PQFTABLE
00383
00384 oid column_table(tuple::size_type ColNum) const;
00385
00387 oid column_table(const PGSTD::string &ColName) const
00388 { return column_table(column_number(ColName)); }
00389 #endif
00390
00391 #ifdef PQXX_DEPRECATED_HEADERS
00392
00393 oid InsertedOid() const { return inserted_oid(); }
00395 size_type AffectedRows() const { return affected_rows(); }
00396 #endif
00397
00399
00401 oid inserted_oid() const { return PQoidValue(m_Result); }
00402
00403
00405
00406 size_type affected_rows() const;
00407
00408 private:
00409 PGresult *m_Result;
00410 mutable int *m_Refcount;
00411
00412 friend class result::field;
00413 const char *GetValue(size_type Row, tuple::size_type Col) const;
00414 bool GetIsNull(size_type Row, tuple::size_type Col) const;
00415 field::size_type GetLength(size_type Row, tuple::size_type Col) const;
00416
00417 friend class connection_base;
00418 explicit result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00419 result &operator=(PGresult *);
00420 bool operator!() const throw () { return !m_Result; }
00421 operator bool() const throw () { return m_Result != 0; }
00422 void CheckStatus(const PGSTD::string &Query) const;
00423
00424 friend class Cursor;
00425 const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00426
00427
00428 void MakeRef(PGresult *);
00429 void MakeRef(const result &);
00430 void LoseRef() throw ();
00431 };
00432
00433
00435
00452 template<typename STREAM>
00453 inline STREAM &operator<<(STREAM &S, const pqxx::result::field &F)
00454 {
00455 S << F.c_str();
00456 return S;
00457 }
00458
00459
00460
00461 inline result::field
00462 result::tuple::operator[](result::tuple::size_type i) const throw ()
00463 {
00464 return field(*this, i);
00465 }
00466
00467 inline result::tuple::size_type result::tuple::size() const
00468 {
00469 return m_Home->columns();
00470 }
00471
00472 inline const char *result::field::name() const
00473 {
00474 return m_Home->column_name(m_Col);
00475 }
00476
00478 template<>
00479 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
00480 {
00481 if (is_null()) return false;
00482 Obj = c_str();
00483 return true;
00484 }
00485
00487
00490 template<>
00491 inline bool result::field::to<const char *>(const char *&Obj) const
00492 {
00493 if (is_null()) return false;
00494 Obj = c_str();
00495 return true;
00496 }
00497
00498
00499 inline result::const_iterator
00500 result::const_iterator::operator+(difference_type o) const
00501 {
00502 return const_iterator(m_Home, m_Index + o);
00503 }
00504
00505 inline result::const_iterator
00506 operator+(result::const_iterator::difference_type o,
00507 result::const_iterator i)
00508 {
00509 return i + o;
00510 }
00511
00512 inline result::const_iterator
00513 result::const_iterator::operator-(difference_type o) const
00514 {
00515 return const_iterator(m_Home, m_Index - o);
00516 }
00517
00518 inline result::const_iterator::difference_type
00519 result::const_iterator::operator-(const_iterator i) const
00520 {
00521 return num()-i.num();
00522 }
00523
00524 inline result::const_iterator result::end() const
00525 {
00526 return const_iterator(this, size());
00527 }
00528
00529 inline oid result::column_type(tuple::size_type ColNum) const
00530 {
00531 const oid T = PQftype(m_Result, ColNum);
00532 if (T == oid_none)
00533 throw PGSTD::invalid_argument(
00534 "Attempt to retrieve type of nonexistant column " +
00535 ToString(ColNum) + " "
00536 "of query result");
00537 return T;
00538 }
00539
00540
00541 #ifdef PQXX_HAVE_PQFTABLE
00542 inline oid result::column_table(tuple::size_type ColNum) const
00543 {
00544 const oid T = PQftable(m_Result, ColNum);
00545
00546
00547
00548
00549
00550 if ((T == InvalidOid) &&
00551 ((ColNum < 0) || (ColNum >= columns())))
00552 throw PGSTD::invalid_argument("Attempt to retrieve table ID for column " +
00553 ToString(ColNum) + " "
00554 "out of " + ToString(columns()));
00555 return T;
00556 }
00557 #endif
00558
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581