00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef PQXX_RESULT_H
00019 #define PQXX_RESULT_H
00020
00021 #include <stdexcept>
00022
00023 #include "pqxx/util.h"
00024
00025
00026
00027
00028
00029
00030
00031 namespace pqxx
00032 {
00033
00035
00042 class PQXX_LIBEXPORT result
00043 {
00044 public:
00045 result() : m_Result(0), m_Refcount(0) {}
00046 result(const result &rhs) :
00047 m_Result(0), m_Refcount(0) { MakeRef(rhs); }
00048 ~result() { LoseRef(); }
00049
00050 result &operator=(const result &);
00051
00052 typedef result_size_type size_type;
00053 class field;
00054
00055
00056
00058
00066 class PQXX_LIBEXPORT tuple
00067 {
00068 public:
00069 typedef tuple_size_type size_type;
00070 tuple(const result *r, result::size_type i) : m_Home(r), m_Index(i) {}
00071 ~tuple() {}
00072
00073 inline field operator[](size_type) const;
00074 field operator[](const char[]) const;
00075 field operator[](const PGSTD::string &s) const
00076 { return operator[](s.c_str()); }
00077 field at(size_type) const;
00078 field at(const char[]) const;
00079 field at(const PGSTD::string &s) const { return at(s.c_str()); }
00080
00081 inline size_type size() const;
00082
00083 result::size_type Row() const { return m_Index; }
00084
00085 size_type ColumnNumber(const PGSTD::string &ColName) const
00086 { return m_Home->ColumnNumber(ColName); }
00087
00088 size_type ColumnNumber(const char ColName[]) const
00089 { return m_Home->ColumnNumber(ColName); }
00090
00091 protected:
00092 const result *m_Home;
00093 result::size_type m_Index;
00094
00095
00096 tuple();
00097 };
00098
00100 typedef tuple Tuple;
00101
00102
00104
00107 class PQXX_LIBEXPORT field : private tuple
00108 {
00109 public:
00110 typedef size_t size_type;
00111
00113
00117 field(const tuple &R, tuple::size_type C) : tuple(R), m_Col(C) {}
00118
00120
00125 const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);}
00126
00128 inline const char *Name() const;
00129
00131
00140 template<typename T> bool to(T &Obj) const
00141 {
00142 if (is_null())
00143 return false;
00144
00145 try
00146 {
00147 FromString(c_str(), Obj);
00148 }
00149 catch (const PGSTD::exception &e)
00150 {
00151 throw PGSTD::runtime_error("Error reading field " +
00152 PGSTD::string(Name()) +
00153 ": " +
00154 e.what());
00155 }
00156 return true;
00157 }
00158
00159
00160 #ifdef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00161
00162 template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00163
00165
00168 template<> bool to<const char *>(const char *&Obj) const;
00169 #endif
00170
00171
00173 template<typename T> bool to(T &Obj, const T &Default) const
00174 {
00175 const bool NotNull = to(Obj);
00176 if (!NotNull)
00177 Obj = Default;
00178 return NotNull;
00179 }
00180
00182
00185 template<typename T> T as(const T &Default) const
00186 {
00187 T Obj;
00188 return to(Obj) ? Obj : Default;
00189 }
00190
00191 bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }
00192
00193 size_type size() const { return m_Home->GetLength(m_Index,m_Col); }
00194
00195 private:
00196
00197 tuple::size_type m_Col;
00198 };
00199
00201 typedef field Field;
00202
00204
00208 class PQXX_LIBEXPORT const_iterator :
00209 public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00210 const tuple,
00211 result::size_type>,
00212 public tuple
00213 {
00214 public:
00215 const_iterator() : tuple(0,0) {}
00216
00223 pointer operator->() const { return this; }
00224 reference operator*() const { return *operator->(); }
00225
00226 const_iterator operator++(int);
00227 const_iterator &operator++() { ++m_Index; return *this; }
00228 const_iterator operator--(int);
00229 const_iterator &operator--() { --m_Index; return *this; }
00230
00231 const_iterator &operator+=(difference_type i)
00232 { m_Index+=i; return *this; }
00233 const_iterator &operator-=(difference_type i)
00234 { m_Index-=i; return *this; }
00235
00236 bool operator==(const const_iterator &i) const
00237 {return m_Index==i.m_Index;}
00238 bool operator!=(const const_iterator &i) const
00239 {return m_Index!=i.m_Index;}
00240 bool operator<(const const_iterator &i) const
00241 {return m_Index<i.m_Index;}
00242 bool operator<=(const const_iterator &i) const
00243 {return m_Index<=i.m_Index;}
00244 bool operator>(const const_iterator &i) const
00245 {return m_Index>i.m_Index;}
00246 bool operator>=(const const_iterator &i) const
00247 {return m_Index>=i.m_Index;}
00248
00249 inline const_iterator operator+(difference_type o) const;
00250
00251 friend const_iterator operator+(difference_type o,
00252 const_iterator i);
00253
00254 inline const_iterator operator-(difference_type o) const;
00255
00256 inline difference_type operator-(const_iterator i) const;
00257
00258 result::size_type num() const { return Row(); }
00259
00260 private:
00261 friend class result;
00262 const_iterator(const result *r, result::size_type i) : tuple(r, i) {}
00263 };
00264
00265 const_iterator begin() const { return const_iterator(this, 0); }
00266 inline const_iterator end() const;
00267
00268
00269 size_type size() const { return m_Result ? PQntuples(m_Result) : 0; }
00270 bool empty() const { return !m_Result || !PQntuples(m_Result); }
00271 size_type capacity() const { return size(); }
00272
00273 const tuple operator[](size_type i) const { return tuple(this, i); }
00274 const tuple at(size_type) const;
00275
00276 void clear() { LoseRef(); }
00277
00278 tuple::size_type Columns() const { return PQnfields(m_Result); }
00279
00281 tuple::size_type ColumnNumber(const char Name[]) const
00282 {return PQfnumber(m_Result,Name);}
00284 tuple::size_type ColumnNumber(const std::string &Name) const
00285 {return ColumnNumber(Name.c_str());}
00286 const char *ColumnName(tuple::size_type Number) const
00287 {return PQfname(m_Result,Number);}
00288
00290
00292 oid InsertedOid() const { return PQoidValue(m_Result); }
00293
00295
00296 size_type AffectedRows() const;
00297
00298 private:
00299 PGresult *m_Result;
00300 mutable int *m_Refcount;
00301
00302 friend class result::field;
00303 const char *GetValue(size_type Row, tuple::size_type Col) const;
00304 bool GetIsNull(size_type Row, tuple::size_type Col) const;
00305 field::size_type GetLength(size_type Row, tuple::size_type Col) const;
00306
00307 friend class connection_base;
00308 explicit result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00309 result &operator=(PGresult *);
00310 bool operator!() const throw () { return !m_Result; }
00311 operator bool() const throw () { return m_Result != 0; }
00312 void CheckStatus(const PGSTD::string &Query) const;
00313
00314 friend class Cursor;
00315 const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00316
00317
00318 void MakeRef(PGresult *);
00319 void MakeRef(const result &);
00320 void LoseRef() throw ();
00321 };
00322
00323
00325
00332 class PQXX_LIBEXPORT binarystring : private PQAlloc<unsigned char>
00333 {
00334 typedef PQAlloc<unsigned char> super;
00335 public:
00336 typedef size_t size_type;
00337
00339
00342 explicit binarystring(const result::field &F) :
00343 super(),
00344 m_size(0)
00345 {
00346 super::operator=(PQunescapeBytea(reinterpret_cast<unsigned char *>(
00347 const_cast<char *>(F.c_str())), &m_size));
00348
00349
00350 if (!c_ptr())
00351 throw std::runtime_error("Unable to read bytea field");
00352 }
00353
00355 size_type size() const throw () { return m_size; }
00356
00358 const unsigned char *bytes() const throw () { return c_ptr(); }
00359
00360 private:
00361 size_type m_size;
00362 };
00363
00364
00366 typedef binarystring BinaryString;
00367
00369 typedef result Result;
00370
00371
00373
00390 template<typename STREAM>
00391 inline STREAM &operator<<(STREAM &S, const pqxx::result::field &F)
00392 {
00393 S << F.c_str();
00394 return S;
00395 }
00396
00397
00398
00399 inline result::field
00400 result::tuple::operator[](result::tuple::size_type i) const
00401 {
00402 return field(*this, i);
00403 }
00404
00405 inline result::tuple::size_type result::tuple::size() const
00406 {
00407 return m_Home->Columns();
00408 }
00409
00410 inline const char *result::field::Name() const
00411 {
00412 return m_Home->ColumnName(m_Col);
00413 }
00414
00416 template<>
00417 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
00418 {
00419 if (is_null()) return false;
00420 Obj = c_str();
00421 return true;
00422 }
00423
00425
00428 template<>
00429 inline bool result::field::to<const char *>(const char *&Obj) const
00430 {
00431 if (is_null()) return false;
00432 Obj = c_str();
00433 return true;
00434 }
00435
00436
00437 inline result::const_iterator
00438 result::const_iterator::operator+(difference_type o) const
00439 {
00440 return const_iterator(m_Home, m_Index + o);
00441 }
00442
00443 inline result::const_iterator
00444 operator+(result::const_iterator::difference_type o,
00445 result::const_iterator i)
00446 {
00447 return i + o;
00448 }
00449
00450 inline result::const_iterator
00451 result::const_iterator::operator-(difference_type o) const
00452 {
00453 return const_iterator(m_Home, m_Index - o);
00454 }
00455
00456 inline result::const_iterator::difference_type
00457 result::const_iterator::operator-(const_iterator i) const
00458 {
00459 return num()-i.num();
00460 }
00461
00462 inline result::const_iterator result::end() const
00463 {
00464 return const_iterator(this, size());
00465 }
00466
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 #endif
00490