Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

result.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/result.h
00005  *
00006  *   DESCRIPTION
00007  *      definitions for the pqxx::Result class and support classes.
00008  *   pqxx::Result represents the set of result tuples from a database query
00009  *
00010  * Copyright (c) 2001-2003, Jeroen T. Vermeulen <jtv@xs4all.nl>
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 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
00022  */
00023 
00024 
00025 // TODO: Support postgres arrays
00026 
00027 namespace pqxx
00028 {
00029 
00031 
00038 class PQXX_LIBEXPORT Result
00039 {
00040 public:
00041   Result() : m_Result(0), m_Refcount(0) {}                              //[t3]
00042   Result(const Result &rhs) :                                           //[t1]
00043           m_Result(0), m_Refcount(0) { MakeRef(rhs); }
00044   ~Result() { LoseRef(); }                                              //[t1]
00045   
00046   Result &operator=(const Result &);                                    //[t10]
00047 
00048   typedef Result_size_type size_type;
00049   class Field;
00050 
00051   // TODO: Field iterators
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() {} // Yes Scott Meyers, you're absolutely right[1]
00068 
00069     inline Field operator[](size_type) const;                           //[t1]
00070     Field operator[](const char[]) const;                               //[t11]
00071     Field operator[](const PGSTD::string &s) const                      //[t11]
00072         { return operator[](s.c_str()); }
00073     Field at(size_type) const;                                          //[t10]
00074     Field at(const char[]) const;                                       //[t11]
00075     Field at(const PGSTD::string &s) const { return at(s.c_str()); }    //[t11]
00076 
00077     inline size_type size() const;                                      //[t11]
00078 
00079     Result::size_type Row() const { return m_Index; }                   //[t11]
00080 
00081   protected:
00082     const Result *m_Home;
00083     Result::size_type m_Index;
00084 
00085     // Not allowed:
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) {}   //[t1]
00105 
00107 
00112     const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);} //[t2]
00113 
00115     inline const char *Name() const;                                    //[t11]
00116 
00118     template<typename T> bool to(T &Obj) const                          //[t1]
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 &Obj) const
00141     {
00142       if (is_null())
00143         return false;
00144       Obj = c_str();
00145       return true;
00146     }
00147 
00149 
00152     template<> bool to(const char *&Obj) const
00153     {
00154       if (is_null()) 
00155         return false;
00156       Obj = c_str();
00157       return true;
00158     }
00159 #endif
00160 
00161 
00163     template<typename T> bool to(T &Obj, const T &Default) const        //[t12]
00164     {
00165       const bool NotNull = to(Obj);
00166       if (!NotNull)
00167         Obj = Default;
00168       return NotNull;
00169     }
00170 
00171     bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }   //[t12]
00172 
00173     int size() const { return m_Home->GetLength(m_Index,m_Col); }       //[t11]
00174 
00175   private:
00176 
00177     Tuple::size_type m_Col;
00178   };
00179 
00180 
00182 
00186   class PQXX_LIBEXPORT const_iterator : 
00187     public PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00188                          const Tuple,
00189                          Result::size_type>, 
00190     public Tuple
00191   {
00192   public:
00193 
00200     pointer operator->()  const { return this; }                        //[t12]
00201     reference operator*() const { return *operator->(); }               //[t12]
00202 
00203     const_iterator operator++(int);                                     //[t12]
00204     const_iterator &operator++() { ++m_Index; return *this; }           //[t1]
00205     const_iterator operator--(int);                                     //[t12]
00206     const_iterator &operator--() { --m_Index; return *this; }           //[t12]
00207 
00208     const_iterator &operator+=(difference_type i)                       //[t12]
00209         { m_Index+=i; return *this; }
00210     const_iterator &operator-=(difference_type i)                       //[t12]
00211         { m_Index-=i; return *this; }
00212 
00213     bool operator==(const const_iterator &i) const                      //[t12]
00214         {return m_Index==i.m_Index;}
00215     bool operator!=(const const_iterator &i) const                      //[t12]
00216         {return m_Index!=i.m_Index;}
00217     bool operator<(const const_iterator &i) const                       //[t12]
00218          {return m_Index<i.m_Index;}
00219     bool operator<=(const const_iterator &i) const                      //[t12]
00220         {return m_Index<=i.m_Index;}
00221     bool operator>(const const_iterator &i) const                       //[t12]
00222         {return m_Index>i.m_Index;}
00223     bool operator>=(const const_iterator &i) const                      //[t12]
00224         {return m_Index>=i.m_Index;}
00225 
00226     inline const_iterator operator+(difference_type o) const;           //[t12]
00227 
00228     friend const_iterator operator+(difference_type o, 
00229                                     const_iterator i);                  //[t12]
00230 
00231     inline const_iterator operator-(difference_type o) const;           //[t12]
00232 
00233     inline difference_type operator-(const_iterator i) const;           //[t12]
00234 
00235     Result::size_type num() const { return Row(); }                     //[t1]
00236 
00237   private:
00238     friend class Result;
00239     const_iterator(const Result *r, Result::size_type i) : Tuple(r, i) {}
00240   };
00241 
00242   const_iterator begin() const { return const_iterator(this, 0); }      //[t1]
00243   inline const_iterator end() const;                                    //[t1]
00244   // TODO: Reverse iterators
00245 
00246   size_type size() const { return m_Result ? PQntuples(m_Result) : 0; } //[t2]
00247   bool empty() const { return !m_Result || !PQntuples(m_Result); }      //[t11]
00248   size_type capacity() const { return size(); }                         //[t20]
00249 
00250   const Tuple operator[](size_type i) const { return Tuple(this, i); }  //[t2]
00251   const Tuple at(size_type) const;                                      //[t10]
00252 
00253   void clear() { LoseRef(); }                                           //[t20]
00254 
00255   Tuple::size_type Columns() const { return PQnfields(m_Result); }      //[t11]
00256 
00258   Tuple::size_type ColumnNumber(const char Name[]) const                //[t11]
00259         {return PQfnumber(m_Result,Name);}
00261   Tuple::size_type ColumnNumber(const std::string &Name) const          //[t11]
00262         {return ColumnNumber(Name.c_str());}
00263   const char *ColumnName(Tuple::size_type Number) const                 //[t11]
00264         {return PQfname(m_Result,Number);}
00265 
00267 
00268   Oid InsertedOid() const { return PQoidValue(m_Result); }              //[t13]
00269 
00271   /*** Returns zero for all other commands. */
00272   size_type AffectedRows() const;                                       //[t7]
00273 
00274 private:
00275   PGresult *m_Result;
00276   mutable int *m_Refcount;
00277 
00278   friend class Result::Field;
00279   const char *GetValue(size_type Row, Tuple::size_type Col) const;
00280   bool GetIsNull(size_type Row, Tuple::size_type Col) const;
00281   Field::size_type GetLength(size_type Row, Tuple::size_type Col) const;
00282 
00283   friend class Connection;
00284   explicit Result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00285   Result &operator=(PGresult *);
00286   bool operator!() const throw () { return !m_Result; }
00287   operator bool() const throw () { return m_Result != 0; }
00288   void CheckStatus() const;
00289 
00290   friend class Cursor;
00291   const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00292 
00293 
00294   void MakeRef(PGresult *);
00295   void MakeRef(const Result &);
00296   void LoseRef() throw ();
00297 };
00298 
00299 
00300 inline Result::Field 
00301 Result::Tuple::operator[](Result::Tuple::size_type i) const 
00302 { 
00303   return Field(*this, i); 
00304 }
00305 
00306 inline Result::Tuple::size_type Result::Tuple::size() const 
00307 { 
00308   return m_Home->Columns(); 
00309 }
00310 
00311 inline const char *Result::Field::Name() const 
00312 { 
00313   return m_Home->ColumnName(m_Col); 
00314 }
00315 
00316 
00317 #ifndef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00318 
00319 template<> inline bool Result::Field::to(PGSTD::string &Obj) const
00320 {
00321   if (is_null())
00322     return false;
00323   Obj = c_str();
00324   return true;
00325 }
00326 
00328 
00331 template<> inline bool Result::Field::to(const char *&Obj) const
00332 {
00333   if (is_null()) 
00334     return false;
00335   Obj = c_str();
00336   return true;
00337 }
00338 #endif
00339 
00340 
00341 
00342 inline Result::const_iterator 
00343 Result::const_iterator::operator+(difference_type o) const
00344 {
00345   return const_iterator(m_Home, m_Index + o);
00346 }
00347 
00348 inline Result::const_iterator 
00349 operator+(Result::const_iterator::difference_type o, 
00350           Result::const_iterator i)
00351 {
00352   return i + o;
00353 }
00354 
00355 inline Result::const_iterator 
00356 Result::const_iterator::operator-(difference_type o) const
00357 {
00358   return const_iterator(m_Home, m_Index - o);
00359 }
00360 
00361 inline Result::const_iterator::difference_type 
00362 Result::const_iterator::operator-(const_iterator i) const
00363 { 
00364   return num()-i.num(); 
00365 }
00366 
00367 inline Result::const_iterator Result::end() const 
00368 { 
00369   return const_iterator(this, size()); 
00370 }
00371 
00372 } // namespace pqxx
00373 
00374 
00376 
00393 template<typename STREAM>
00394 inline STREAM &operator<<(STREAM &S, const pqxx::Result::Field &F)      //[t46]
00395 {
00396   S << F.c_str();
00397   return S;
00398 }
00399 
00400 
00401 
00402 /* 
00403 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More 
00404 Effective C++", points out that it is good style to have any class containing 
00405 a member of pointer type define its own destructor--just to show that it knows
00406 what it is doing.  This helps prevent nasty memory leak / double deletion bugs
00407 typically resulting from programmers' omission to deal with such issues in
00408 their destructors.
00409 
00410 The -Weffc++ option in gcc generates warnings for noncompliance with Scott's
00411 style guidelines, and hence necessitates the definition of this destructor,\
00412 trivial as it may be.
00413 
00414 [2] IIRC Alex Stepanov, the inventor of the STL, once remarked that having
00415 this as standard behaviour for pointers would be useful in some algorithms.
00416 So even if this makes me look foolish, I would seem to be in distinguished 
00417 company.
00418 */
00419 
00420 #endif
00421 

Generated on Fri Feb 28 19:23:32 2003 for libpqxx by doxygen1.3-rc3