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 size_type ColumnNumber(const char ColName[]) const
00082 { return m_Home->ColumnNumber(ColName); }
00083
00084 protected:
00085 const Result *m_Home;
00086 Result::size_type m_Index;
00087
00088
00089 Tuple();
00090 };
00091
00092
00094
00097 class PQXX_LIBEXPORT Field : private Tuple
00098 {
00099 public:
00100 typedef size_t size_type;
00101
00103
00107 Field(const Tuple &R, Tuple::size_type C) : Tuple(R), m_Col(C) {}
00108
00110
00115 const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);}
00116
00118 inline const char *Name() const;
00119
00121 template<typename T> bool to(T &Obj) const
00122 {
00123 if (is_null())
00124 return false;
00125
00126 try
00127 {
00128 FromString(c_str(), Obj);
00129 }
00130 catch (const PGSTD::exception &e)
00131 {
00132 throw PGSTD::runtime_error("Error reading field " +
00133 PGSTD::string(Name()) +
00134 ": " +
00135 e.what());
00136 }
00137 return true;
00138 }
00139
00140
00141 #ifdef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00142
00143 template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00144
00146
00149 template<> bool to<const char *>(const char *&Obj) const;
00150 #endif
00151
00152
00154 template<typename T> bool to(T &Obj, const T &Default) const
00155 {
00156 const bool NotNull = to(Obj);
00157 if (!NotNull)
00158 Obj = Default;
00159 return NotNull;
00160 }
00161
00162 bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }
00163
00164 int size() const { return m_Home->GetLength(m_Index,m_Col); }
00165
00166 private:
00167
00168 Tuple::size_type m_Col;
00169 };
00170
00171
00173
00177 class PQXX_LIBEXPORT const_iterator :
00178 public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00179 const Tuple,
00180 Result::size_type>,
00181 public Tuple
00182 {
00183 public:
00184 const_iterator() : Tuple(0,0) {}
00185
00192 pointer operator->() const { return this; }
00193 reference operator*() const { return *operator->(); }
00194
00195 const_iterator operator++(int);
00196 const_iterator &operator++() { ++m_Index; return *this; }
00197 const_iterator operator--(int);
00198 const_iterator &operator--() { --m_Index; return *this; }
00199
00200 const_iterator &operator+=(difference_type i)
00201 { m_Index+=i; return *this; }
00202 const_iterator &operator-=(difference_type i)
00203 { m_Index-=i; return *this; }
00204
00205 bool operator==(const const_iterator &i) const
00206 {return m_Index==i.m_Index;}
00207 bool operator!=(const const_iterator &i) const
00208 {return m_Index!=i.m_Index;}
00209 bool operator<(const const_iterator &i) const
00210 {return m_Index<i.m_Index;}
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
00218 inline const_iterator operator+(difference_type o) const;
00219
00220 friend const_iterator operator+(difference_type o,
00221 const_iterator i);
00222
00223 inline const_iterator operator-(difference_type o) const;
00224
00225 inline difference_type operator-(const_iterator i) const;
00226
00227 Result::size_type num() const { return Row(); }
00228
00229 private:
00230 friend class Result;
00231 const_iterator(const Result *r, Result::size_type i) : Tuple(r, i) {}
00232 };
00233
00234 const_iterator begin() const { return const_iterator(this, 0); }
00235 inline const_iterator end() const;
00236
00237
00238 size_type size() const { return m_Result ? PQntuples(m_Result) : 0; }
00239 bool empty() const { return !m_Result || !PQntuples(m_Result); }
00240 size_type capacity() const { return size(); }
00241
00242 const Tuple operator[](size_type i) const { return Tuple(this, i); }
00243 const Tuple at(size_type) const;
00244
00245 void clear() { LoseRef(); }
00246
00247 Tuple::size_type Columns() const { return PQnfields(m_Result); }
00248
00250 Tuple::size_type ColumnNumber(const char Name[]) const
00251 {return PQfnumber(m_Result,Name);}
00253 Tuple::size_type ColumnNumber(const std::string &Name) const
00254 {return ColumnNumber(Name.c_str());}
00255 const char *ColumnName(Tuple::size_type Number) const
00256 {return PQfname(m_Result,Number);}
00257
00259
00260 Oid InsertedOid() const { return PQoidValue(m_Result); }
00261
00263
00264 size_type AffectedRows() const;
00265
00266 private:
00267 PGresult *m_Result;
00268 mutable int *m_Refcount;
00269
00270 friend class Result::Field;
00271 const char *GetValue(size_type Row, Tuple::size_type Col) const;
00272 bool GetIsNull(size_type Row, Tuple::size_type Col) const;
00273 Field::size_type GetLength(size_type Row, Tuple::size_type Col) const;
00274
00275 friend class ConnectionItf;
00276 explicit Result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00277 Result &operator=(PGresult *);
00278 bool operator!() const throw () { return !m_Result; }
00279 operator bool() const throw () { return m_Result != 0; }
00280 void CheckStatus(const PGSTD::string &Query) const;
00281
00282 friend class Cursor;
00283 const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00284
00285
00286 void MakeRef(PGresult *);
00287 void MakeRef(const Result &);
00288 void LoseRef() throw ();
00289 };
00290
00291
00292 inline Result::Field
00293 Result::Tuple::operator[](Result::Tuple::size_type i) const
00294 {
00295 return Field(*this, i);
00296 }
00297
00298 inline Result::Tuple::size_type Result::Tuple::size() const
00299 {
00300 return m_Home->Columns();
00301 }
00302
00303 inline const char *Result::Field::Name() const
00304 {
00305 return m_Home->ColumnName(m_Col);
00306 }
00307
00309 template<>
00310 inline bool Result::Field::to<PGSTD::string>(PGSTD::string &Obj) const
00311 {
00312 if (is_null()) return false;
00313 Obj = c_str();
00314 return true;
00315 }
00316
00318
00321 template<>
00322 inline bool Result::Field::to<const char *>(const char *&Obj) const
00323 {
00324 if (is_null()) return false;
00325 Obj = c_str();
00326 return true;
00327 }
00328
00329
00330 inline Result::const_iterator
00331 Result::const_iterator::operator+(difference_type o) const
00332 {
00333 return const_iterator(m_Home, m_Index + o);
00334 }
00335
00336 inline Result::const_iterator
00337 operator+(Result::const_iterator::difference_type o,
00338 Result::const_iterator i)
00339 {
00340 return i + o;
00341 }
00342
00343 inline Result::const_iterator
00344 Result::const_iterator::operator-(difference_type o) const
00345 {
00346 return const_iterator(m_Home, m_Index - o);
00347 }
00348
00349 inline Result::const_iterator::difference_type
00350 Result::const_iterator::operator-(const_iterator i) const
00351 {
00352 return num()-i.num();
00353 }
00354
00355 inline Result::const_iterator Result::end() const
00356 {
00357 return const_iterator(this, size());
00358 }
00359
00360 }
00361
00362
00364
00381 template<typename STREAM>
00382 inline STREAM &operator<<(STREAM &S, const pqxx::Result::Field &F)
00383 {
00384 S << F.c_str();
00385 return S;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 #endif
00409