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 PGSTD::string &ColName) const
00082 { return m_Home->ColumnNumber(ColName); }
00083
00084 size_type ColumnNumber(const char ColName[]) const
00085 { return m_Home->ColumnNumber(ColName); }
00086
00087 protected:
00088 const Result *m_Home;
00089 Result::size_type m_Index;
00090
00091
00092 Tuple();
00093 };
00094
00095
00097
00100 class PQXX_LIBEXPORT Field : private Tuple
00101 {
00102 public:
00103 typedef size_t size_type;
00104
00106
00110 Field(const Tuple &R, Tuple::size_type C) : Tuple(R), m_Col(C) {}
00111
00113
00118 const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);}
00119
00121 inline const char *Name() const;
00122
00124
00132 template<typename T> bool to(T &Obj) const
00133 {
00134 if (is_null())
00135 return false;
00136
00137 try
00138 {
00139 FromString(c_str(), Obj);
00140 }
00141 catch (const PGSTD::exception &e)
00142 {
00143 throw PGSTD::runtime_error("Error reading field " +
00144 PGSTD::string(Name()) +
00145 ": " +
00146 e.what());
00147 }
00148 return true;
00149 }
00150
00151
00152 #ifdef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00153
00154 template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00155
00157
00160 template<> bool to<const char *>(const char *&Obj) const;
00161 #endif
00162
00163
00165 template<typename T> bool to(T &Obj, const T &Default) const
00166 {
00167 const bool NotNull = to(Obj);
00168 if (!NotNull)
00169 Obj = Default;
00170 return NotNull;
00171 }
00172
00174
00177 template<typename T> T as(const T &Default) const
00178 {
00179 T Obj;
00180 return to(Obj) ? Obj : Default;
00181 }
00182
00183 bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }
00184
00185 size_type size() const { return m_Home->GetLength(m_Index,m_Col); }
00186
00187 private:
00188
00189 Tuple::size_type m_Col;
00190 };
00191
00192
00194
00198 class PQXX_LIBEXPORT const_iterator :
00199 public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00200 const Tuple,
00201 Result::size_type>,
00202 public Tuple
00203 {
00204 public:
00205 const_iterator() : Tuple(0,0) {}
00206
00213 pointer operator->() const { return this; }
00214 reference operator*() const { return *operator->(); }
00215
00216 const_iterator operator++(int);
00217 const_iterator &operator++() { ++m_Index; return *this; }
00218 const_iterator operator--(int);
00219 const_iterator &operator--() { --m_Index; return *this; }
00220
00221 const_iterator &operator+=(difference_type i)
00222 { m_Index+=i; return *this; }
00223 const_iterator &operator-=(difference_type i)
00224 { m_Index-=i; return *this; }
00225
00226 bool operator==(const const_iterator &i) const
00227 {return m_Index==i.m_Index;}
00228 bool operator!=(const const_iterator &i) const
00229 {return m_Index!=i.m_Index;}
00230 bool operator<(const const_iterator &i) const
00231 {return m_Index<i.m_Index;}
00232 bool operator<=(const const_iterator &i) const
00233 {return m_Index<=i.m_Index;}
00234 bool operator>(const const_iterator &i) const
00235 {return m_Index>i.m_Index;}
00236 bool operator>=(const const_iterator &i) const
00237 {return m_Index>=i.m_Index;}
00238
00239 inline const_iterator operator+(difference_type o) const;
00240
00241 friend const_iterator operator+(difference_type o,
00242 const_iterator i);
00243
00244 inline const_iterator operator-(difference_type o) const;
00245
00246 inline difference_type operator-(const_iterator i) const;
00247
00248 Result::size_type num() const { return Row(); }
00249
00250 private:
00251 friend class Result;
00252 const_iterator(const Result *r, Result::size_type i) : Tuple(r, i) {}
00253 };
00254
00255 const_iterator begin() const { return const_iterator(this, 0); }
00256 inline const_iterator end() const;
00257
00258
00259 size_type size() const { return m_Result ? PQntuples(m_Result) : 0; }
00260 bool empty() const { return !m_Result || !PQntuples(m_Result); }
00261 size_type capacity() const { return size(); }
00262
00263 const Tuple operator[](size_type i) const { return Tuple(this, i); }
00264 const Tuple at(size_type) const;
00265
00266 void clear() { LoseRef(); }
00267
00268 Tuple::size_type Columns() const { return PQnfields(m_Result); }
00269
00271 Tuple::size_type ColumnNumber(const char Name[]) const
00272 {return PQfnumber(m_Result,Name);}
00274 Tuple::size_type ColumnNumber(const std::string &Name) const
00275 {return ColumnNumber(Name.c_str());}
00276 const char *ColumnName(Tuple::size_type Number) const
00277 {return PQfname(m_Result,Number);}
00278
00280
00281 Oid InsertedOid() const { return PQoidValue(m_Result); }
00282
00284
00285 size_type AffectedRows() const;
00286
00287 private:
00288 PGresult *m_Result;
00289 mutable int *m_Refcount;
00290
00291 friend class Result::Field;
00292 const char *GetValue(size_type Row, Tuple::size_type Col) const;
00293 bool GetIsNull(size_type Row, Tuple::size_type Col) const;
00294 Field::size_type GetLength(size_type Row, Tuple::size_type Col) const;
00295
00296 friend class Connection_base;
00297 explicit Result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00298 Result &operator=(PGresult *);
00299 bool operator!() const throw () { return !m_Result; }
00300 operator bool() const throw () { return m_Result != 0; }
00301 void CheckStatus(const PGSTD::string &Query) const;
00302
00303 friend class Cursor;
00304 const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00305
00306
00307 void MakeRef(PGresult *);
00308 void MakeRef(const Result &);
00309 void LoseRef() throw ();
00310 };
00311
00312
00314
00321 class BinaryString : private PQAlloc<unsigned char>
00322 {
00323 typedef PQAlloc<unsigned char> super;
00324 public:
00325 typedef size_t size_type;
00326
00328
00331 explicit BinaryString(const Result::Field &F) :
00332 super(),
00333 m_size(0)
00334 {
00335 super::operator=(PQunescapeBytea(reinterpret_cast<unsigned char *>(
00336 const_cast<char *>(F.c_str())), &m_size));
00337
00338
00339 if (!c_ptr())
00340 throw std::runtime_error("Unable to read bytea field");
00341 }
00342
00344 size_type size() const throw () { return m_size; }
00345
00347 const unsigned char *bytes() const throw () { return c_ptr(); }
00348
00349 private:
00350 size_type m_size;
00351 };
00352
00353
00355
00372 template<typename STREAM>
00373 inline STREAM &operator<<(STREAM &S, const pqxx::Result::Field &F)
00374 {
00375 S << F.c_str();
00376 return S;
00377 }
00378
00379
00380
00381 inline Result::Field
00382 Result::Tuple::operator[](Result::Tuple::size_type i) const
00383 {
00384 return Field(*this, i);
00385 }
00386
00387 inline Result::Tuple::size_type Result::Tuple::size() const
00388 {
00389 return m_Home->Columns();
00390 }
00391
00392 inline const char *Result::Field::Name() const
00393 {
00394 return m_Home->ColumnName(m_Col);
00395 }
00396
00398 template<>
00399 inline bool Result::Field::to<PGSTD::string>(PGSTD::string &Obj) const
00400 {
00401 if (is_null()) return false;
00402 Obj = c_str();
00403 return true;
00404 }
00405
00407
00410 template<>
00411 inline bool Result::Field::to<const char *>(const char *&Obj) const
00412 {
00413 if (is_null()) return false;
00414 Obj = c_str();
00415 return true;
00416 }
00417
00418
00419 inline Result::const_iterator
00420 Result::const_iterator::operator+(difference_type o) const
00421 {
00422 return const_iterator(m_Home, m_Index + o);
00423 }
00424
00425 inline Result::const_iterator
00426 operator+(Result::const_iterator::difference_type o,
00427 Result::const_iterator i)
00428 {
00429 return i + o;
00430 }
00431
00432 inline Result::const_iterator
00433 Result::const_iterator::operator-(difference_type o) const
00434 {
00435 return const_iterator(m_Home, m_Index - o);
00436 }
00437
00438 inline Result::const_iterator::difference_type
00439 Result::const_iterator::operator-(const_iterator i) const
00440 {
00441 return num()-i.num();
00442 }
00443
00444 inline Result::const_iterator Result::end() const
00445 {
00446 return const_iterator(this, size());
00447 }
00448
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471 #endif
00472