00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef PQXX_RESULT_H
00015 #define PQXX_RESULT_H
00016
00017 #include <stdexcept>
00018
00019 #include "pqxx/util.h"
00020
00021
00022
00023
00024
00025
00026
00027 namespace pqxx
00028 {
00029
00031
00038 class PQXX_LIBEXPORT Result
00039 {
00040 public:
00041 Result() : m_Result(0), m_Refcount(0) {}
00042 Result(const Result &rhs) :
00043 m_Result(0), m_Refcount(0) { MakeRef(rhs); }
00044 ~Result() { LoseRef(); }
00045
00046 Result &operator=(const Result &);
00047
00048 typedef Result_size_type size_type;
00049 class Field;
00050
00051
00052
00054
00062 class PQXX_LIBEXPORT Tuple
00063 {
00064 public:
00065 typedef Tuple_size_type size_type;
00066 Tuple(const Result *r, Result::size_type i) : m_Home(r), m_Index(i) {}
00067 ~Tuple() {}
00068
00069 inline Field operator[](size_type) const;
00070 Field operator[](const char[]) const;
00071 Field operator[](const PGSTD::string &s) const
00072 { return operator[](s.c_str()); }
00073 Field at(size_type) const;
00074 Field at(const char[]) const;
00075 Field at(const PGSTD::string &s) const { return at(s.c_str()); }
00076
00077 inline size_type size() const;
00078
00079 Result::size_type Row() const { return m_Index; }
00080
00081 protected:
00082 const Result *m_Home;
00083 Result::size_type m_Index;
00084
00085
00086 Tuple();
00087 };
00088
00089
00091
00094 class PQXX_LIBEXPORT Field : private Tuple
00095 {
00096 public:
00097 typedef size_t size_type;
00098
00100
00104 Field(const Tuple &R, Tuple::size_type C) : Tuple(R), m_Col(C) {}
00105
00107
00112 const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);}
00113
00115 inline const char *Name() const;
00116
00118 template<typename T> bool to(T &Obj) const
00119 {
00120 if (is_null())
00121 return false;
00122
00123 try
00124 {
00125 FromString(c_str(), Obj);
00126 }
00127 catch (const PGSTD::exception &e)
00128 {
00129 throw PGSTD::runtime_error("Error reading field " +
00130 PGSTD::string(Name()) +
00131 ": " +
00132 e.what());
00133 }
00134 return true;
00135 }
00136
00137
00138 #ifdef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00139
00140 template<> bool to<PGSTD::string>(PGSTD::string &Obj) const
00141 {
00142 if (is_null()) return false;
00143 Obj = c_str();
00144 return true;
00145 }
00146
00148
00151 template<> bool to<const char *>(const char *&Obj) const
00152 {
00153 if (is_null()) return false;
00154 Obj = c_str();
00155 return true;
00156 }
00157 #endif
00158
00159
00161 template<typename T> bool to(T &Obj, const T &Default) const
00162 {
00163 const bool NotNull = to(Obj);
00164 if (!NotNull)
00165 Obj = Default;
00166 return NotNull;
00167 }
00168
00169 bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }
00170
00171 int size() const { return m_Home->GetLength(m_Index,m_Col); }
00172
00173 private:
00174
00175 Tuple::size_type m_Col;
00176 };
00177
00178
00180
00184 class PQXX_LIBEXPORT const_iterator :
00185 public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00186 const Tuple,
00187 Result::size_type>,
00188 public Tuple
00189 {
00190 public:
00191
00198 pointer operator->() const { return this; }
00199 reference operator*() const { return *operator->(); }
00200
00201 const_iterator operator++(int);
00202 const_iterator &operator++() { ++m_Index; return *this; }
00203 const_iterator operator--(int);
00204 const_iterator &operator--() { --m_Index; return *this; }
00205
00206 const_iterator &operator+=(difference_type i)
00207 { m_Index+=i; return *this; }
00208 const_iterator &operator-=(difference_type i)
00209 { m_Index-=i; return *this; }
00210
00211 bool operator==(const const_iterator &i) const
00212 {return m_Index==i.m_Index;}
00213 bool operator!=(const const_iterator &i) const
00214 {return m_Index!=i.m_Index;}
00215 bool operator<(const const_iterator &i) const
00216 {return m_Index<i.m_Index;}
00217 bool operator<=(const const_iterator &i) const
00218 {return m_Index<=i.m_Index;}
00219 bool operator>(const const_iterator &i) const
00220 {return m_Index>i.m_Index;}
00221 bool operator>=(const const_iterator &i) const
00222 {return m_Index>=i.m_Index;}
00223
00224 inline const_iterator operator+(difference_type o) const;
00225
00226 friend const_iterator operator+(difference_type o,
00227 const_iterator i);
00228
00229 inline const_iterator operator-(difference_type o) const;
00230
00231 inline difference_type operator-(const_iterator i) const;
00232
00233 Result::size_type num() const { return Row(); }
00234
00235 private:
00236 friend class Result;
00237 const_iterator(const Result *r, Result::size_type i) : Tuple(r, i) {}
00238 };
00239
00240 const_iterator begin() const { return const_iterator(this, 0); }
00241 inline const_iterator end() const;
00242
00243
00244 size_type size() const { return m_Result ? PQntuples(m_Result) : 0; }
00245 bool empty() const { return !m_Result || !PQntuples(m_Result); }
00246 size_type capacity() const { return size(); }
00247
00248 const Tuple operator[](size_type i) const { return Tuple(this, i); }
00249 const Tuple at(size_type) const;
00250
00251 void clear() { LoseRef(); }
00252
00253 Tuple::size_type Columns() const { return PQnfields(m_Result); }
00254
00256 Tuple::size_type ColumnNumber(const char Name[]) const
00257 {return PQfnumber(m_Result,Name);}
00259 Tuple::size_type ColumnNumber(const std::string &Name) const
00260 {return ColumnNumber(Name.c_str());}
00261 const char *ColumnName(Tuple::size_type Number) const
00262 {return PQfname(m_Result,Number);}
00263
00265
00266 Oid InsertedOid() const { return PQoidValue(m_Result); }
00267
00269
00270 size_type AffectedRows() const;
00271
00272 private:
00273 PGresult *m_Result;
00274 mutable int *m_Refcount;
00275
00276 friend class Result::Field;
00277 const char *GetValue(size_type Row, Tuple::size_type Col) const;
00278 bool GetIsNull(size_type Row, Tuple::size_type Col) const;
00279 Field::size_type GetLength(size_type Row, Tuple::size_type Col) const;
00280
00281 friend class ConnectionItf;
00282 explicit Result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00283 Result &operator=(PGresult *);
00284 bool operator!() const throw () { return !m_Result; }
00285 operator bool() const throw () { return m_Result != 0; }
00286 void CheckStatus() const;
00287
00288 friend class Cursor;
00289 const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00290
00291
00292 void MakeRef(PGresult *);
00293 void MakeRef(const Result &);
00294 void LoseRef() throw ();
00295 };
00296
00297
00298 inline Result::Field
00299 Result::Tuple::operator[](Result::Tuple::size_type i) const
00300 {
00301 return Field(*this, i);
00302 }
00303
00304 inline Result::Tuple::size_type Result::Tuple::size() const
00305 {
00306 return m_Home->Columns();
00307 }
00308
00309 inline const char *Result::Field::Name() const
00310 {
00311 return m_Home->ColumnName(m_Col);
00312 }
00313
00314
00315 #ifndef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00316
00317 template<>
00318 inline bool Result::Field::to<PGSTD::string>(PGSTD::string &Obj) const
00319 {
00320 if (is_null()) return false;
00321 Obj = c_str();
00322 return true;
00323 }
00324
00326
00329 template<>
00330 inline bool Result::Field::to<const char *>(const char *&Obj) const
00331 {
00332 if (is_null()) return false;
00333 Obj = c_str();
00334 return true;
00335 }
00336 #endif
00337
00338
00339
00340 inline Result::const_iterator
00341 Result::const_iterator::operator+(difference_type o) const
00342 {
00343 return const_iterator(m_Home, m_Index + o);
00344 }
00345
00346 inline Result::const_iterator
00347 operator+(Result::const_iterator::difference_type o,
00348 Result::const_iterator i)
00349 {
00350 return i + o;
00351 }
00352
00353 inline Result::const_iterator
00354 Result::const_iterator::operator-(difference_type o) const
00355 {
00356 return const_iterator(m_Home, m_Index - o);
00357 }
00358
00359 inline Result::const_iterator::difference_type
00360 Result::const_iterator::operator-(const_iterator i) const
00361 {
00362 return num()-i.num();
00363 }
00364
00365 inline Result::const_iterator Result::end() const
00366 {
00367 return const_iterator(this, size());
00368 }
00369
00370 }
00371
00372
00374
00391 template<typename STREAM>
00392 inline STREAM &operator<<(STREAM &S, const pqxx::Result::Field &F)
00393 {
00394 S << F.c_str();
00395 return S;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 #endif
00419