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

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-2002, 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 // TODO: Cursor-based bidirectional iterators for hidden incremental retrieval
00027 
00028 namespace pqxx
00029 {
00030 
00032 
00039 class PQXX_LIBEXPORT Result
00040 {
00041 public:
00042   Result() : m_Result(0), m_Refcount(0) {}                              //[t3]
00043   Result(const Result &rhs) :                                           //[t1]
00044           m_Result(0), m_Refcount(0) { MakeRef(rhs); }
00045   ~Result() { LoseRef(); }                                              //[t1]
00046   
00047   Result &operator=(const Result &);                                    //[t10]
00048 
00049   typedef Result_size_type size_type;
00050   class Field;
00051 
00052   // TODO: Field iterators
00053  
00055 
00063   class Tuple
00064   {
00065   public:
00066     typedef Tuple_size_type size_type;
00067     Tuple(const Result *r, size_type i) : m_Home(r), m_Index(i) {}
00068     ~Tuple() {} // Yes Scott Meyers, you're absolutely right[1]
00069 
00070     inline Field operator[](size_type) const;                           //[t1]
00071     Field operator[](const char[]) const;                               //[t11]
00072     Field operator[](PGSTD::string s) const                             //[t11]
00073         { return operator[](s.c_str()); }
00074     Field at(size_type) const;                                          //[t10]
00075     Field at(const char[]) const;                                       //[t11]
00076     Field at(PGSTD::string s) const { return at(s.c_str()); }           //[t11]
00077 
00078     inline size_type size() const;                                      //[t11]
00079 
00080     Result::size_type Row() const { return m_Index; }                   //[t11]
00081 
00082   protected:
00083     const Result *m_Home;
00084     Result::size_type m_Index;
00085   };
00086 
00087 
00089 
00092   class Field : private Tuple
00093   {
00094   public:
00095     using Tuple::size_type;
00096 
00097     Field(const Tuple &R, Tuple::size_type C) : Tuple(R), m_Col(C) {}   //[t1]
00098 
00100     const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);} //[t2]
00101 
00103     inline const char *Name() const;                                    //[t11]
00104 
00106     template<typename T> bool to(T &Obj) const                          //[t1]
00107     {
00108       if (is_null())
00109         return false;
00110 
00111       try
00112       {
00113         FromString(c_str(), Obj);
00114       }
00115       catch (const PGSTD::exception &e)
00116       {
00117         throw PGSTD::runtime_error("Error reading field " + 
00118                                  PGSTD::string(Name()) +
00119                                  ": " +
00120                                  e.what());
00121       }
00122       return true;
00123     }
00124 
00126     template<typename T> bool to(T &Obj, const T &Default) const        //[t12]
00127     {
00128       const bool NotNull = to(Obj);
00129       if (!NotNull)
00130         Obj = Default;
00131       return NotNull;
00132     }
00133 
00134     bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }   //[t12]
00135 
00136     int size() const { return m_Home->GetLength(m_Index,m_Col); }       //[t11]
00137 
00138   private:
00139 
00140     Tuple::size_type m_Col;
00141   };
00142 
00143 
00145 
00149   class const_iterator : 
00150     public PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00151                          const Tuple,
00152                          Result::size_type>, 
00153     public Tuple
00154   {
00155   public:
00156 
00163     pointer operator->()  const { return this; }                        //[t12]
00164     reference operator*() const { return *operator->(); }               //[t12]
00165 
00166     const_iterator operator++(int);                                     //[t12]
00167     const_iterator &operator++() { ++m_Index; return *this; }           //[t1]
00168     const_iterator operator--(int);                                     //[t12]
00169     const_iterator &operator--() { --m_Index; return *this; }           //[t12]
00170 
00171     const_iterator &operator+=(difference_type i)                       //[t12]
00172         { m_Index+=i; return *this; }
00173     const_iterator &operator-=(difference_type i)                       //[t12]
00174         { m_Index-=i; return *this; }
00175 
00176     bool operator==(const const_iterator &i) const                      //[t12]
00177         {return m_Index==i.m_Index;}
00178     bool operator!=(const const_iterator &i) const                      //[t12]
00179         {return m_Index!=i.m_Index;}
00180     bool operator<(const const_iterator &i) const                       //[t12]
00181          {return m_Index<i.m_Index;}
00182     bool operator<=(const const_iterator &i) const                      //[t12]
00183         {return m_Index<=i.m_Index;}
00184     bool operator>(const const_iterator &i) const                       //[t12]
00185         {return m_Index>i.m_Index;}
00186     bool operator>=(const const_iterator &i) const                      //[t12]
00187         {return m_Index>=i.m_Index;}
00188 
00189     inline const_iterator operator+(difference_type o) const;           //[t12]
00190 
00191     friend const_iterator operator+(difference_type o, 
00192                                     const_iterator i);                  //[t12]
00193 
00194     inline const_iterator operator-(difference_type o) const;           //[t12]
00195 
00196     inline difference_type operator-(const_iterator i) const;           //[t12]
00197 
00198     Result::size_type num() const { return Row(); }                     //[t1]
00199 
00200   private:
00201     friend class Result;
00202     const_iterator(const Result *r, Result::size_type i) : Tuple(r, i) {}
00203   };
00204 
00205   const_iterator begin() const { return const_iterator(this, 0); }      //[t1]
00206   inline const_iterator end() const;                                    //[t1]
00207   // TODO: Reverse iterators
00208 
00209   size_type size() const { return m_Result ? PQntuples(m_Result) : 0; } //[t2]
00210   bool empty() const { return !m_Result || !PQntuples(m_Result); }      //[t11]
00211   size_type capacity() const { return size(); }                         //[]
00212 
00213   const Tuple operator[](size_type i) const { return Tuple(this, i); }  //[t2]
00214   const Tuple at(size_type i) const;                                    //[t10]
00215 
00216   void clear() { LoseRef(); }                                           //[]
00217 
00218   Tuple::size_type Columns() const { return PQnfields(m_Result); }      //[t11]
00219 
00221   Tuple::size_type ColumnNumber(const char Name[]) const                //[t11]
00222         {return PQfnumber(m_Result,Name);}
00224   Tuple::size_type ColumnNumber(std::string Name) const                 //[t11]
00225         {return ColumnNumber(Name.c_str());}
00226   const char *ColumnName(Tuple::size_type Number) const                 //[t11]
00227         {return PQfname(m_Result,Number);}
00228 
00229 private:
00230   PGresult *m_Result;
00231   mutable int *m_Refcount;
00232 
00233   friend class Result::Field;
00234   const char *GetValue(size_type Row, Tuple::size_type Col) const;
00235   bool GetIsNull(size_type Row, Tuple::size_type Col) const;
00236   Field::size_type GetLength(size_type Row, Tuple::size_type Col) const;
00237 
00238   friend class Connection;
00239   explicit Result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00240   Result &operator=(PGresult *);
00241   bool operator!() const { return !m_Result; }
00242   operator bool() const { return m_Result != 0; }
00243   void CheckStatus() const;
00244 
00245 
00246   void MakeRef(PGresult *);
00247   void MakeRef(const Result &);
00248   void LoseRef() throw ();
00249 };
00250 
00251 
00252 
00253 
00254 template<> inline bool Result::Field::to(PGSTD::string &Obj) const
00255 {
00256   if (is_null())
00257     return false;
00258   Obj = c_str();
00259   return true;
00260 }
00261 
00262 template<> inline bool Result::Field::to(const char *&Obj) const
00263 {
00264   if (is_null()) 
00265     return false;
00266   Obj = c_str();
00267   return true;
00268 }
00269 
00270 
00271 inline Result::Field 
00272 Result::Tuple::operator[](Result::Tuple::size_type i) const 
00273 { 
00274   return Field(*this, i); 
00275 }
00276 
00277 inline Result::Tuple::size_type Result::Tuple::size() const 
00278 { 
00279   return m_Home->Columns(); 
00280 }
00281 
00282 inline const char *Result::Field::Name() const 
00283 { 
00284   return m_Home->ColumnName(m_Col); 
00285 }
00286 
00287 inline Result::const_iterator 
00288 Result::const_iterator::operator+(difference_type o) const
00289 {
00290   return const_iterator(m_Home, m_Index + o);
00291 }
00292 
00293 inline Result::const_iterator 
00294 operator+(Result::const_iterator::difference_type o, 
00295           Result::const_iterator i)
00296 {
00297   return i + o;
00298 }
00299 
00300 inline Result::const_iterator 
00301 Result::const_iterator::operator-(difference_type o) const
00302 {
00303   return const_iterator(m_Home, m_Index - o);
00304 }
00305 
00306 inline Result::const_iterator::difference_type 
00307 Result::const_iterator::operator-(const_iterator i) const
00308 { 
00309   return num()-i.num(); 
00310 }
00311 
00312 inline Result::const_iterator Result::end() const 
00313 { 
00314   return const_iterator(this, size()); 
00315 }
00316 
00317 } // namespace
00318 
00319 
00320 /* 
00321 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More 
00322 Effective C++", points out that it is good style to have any class containing 
00323 a member of pointer type define its own destructor--just to show that it knows
00324 what it is doing.  This helps prevent nasty memory leak / double deletion bugs
00325 typically resulting from programmers' omission to deal with such issues in
00326 their destructors.
00327 
00328 The -Weffc++ option in gcc generates warnings for noncompliance with Scott's
00329 style guidelines, and hence necessitates the definition of this destructor,\
00330 trivial as it may be.
00331 
00332 [2] IIRC Alex Stepanov, the inventor of the STL, once remarked that having
00333 this as standard behaviour for pointers would be useful in some algorithms.
00334 So even if this makes me look foolish, I would seem to be in distinguished 
00335 company.
00336 */
00337 
00338 #endif
00339 

Generated on Sat Aug 10 21:52:38 2002 for libpqxx by doxygen1.2.16