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 
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[](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(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 
00086 
00088 
00091   class PQXX_LIBEXPORT Field : private Tuple
00092   {
00093   public:
00094     typedef size_t size_type;
00095 
00096     Field(const Tuple &R, Tuple::size_type C) : Tuple(R), m_Col(C) {}   //[t1]
00097 
00099     const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);} //[t2]
00100 
00102     inline const char *Name() const;                                    //[t11]
00103 
00105     template<typename T> bool to(T &Obj) const                          //[t1]
00106     {
00107       if (is_null())
00108         return false;
00109 
00110       try
00111       {
00112         FromString(c_str(), Obj);
00113       }
00114       catch (const PGSTD::exception &e)
00115       {
00116         throw PGSTD::runtime_error("Error reading field " + 
00117                                    PGSTD::string(Name()) +
00118                                    ": " +
00119                                    e.what());
00120       }
00121       return true;
00122     }
00123 
00124 #ifdef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00125 
00126     template<> bool to(PGSTD::string &Obj) const
00127     {
00128       if (is_null())
00129         return false;
00130       Obj = c_str();
00131       return true;
00132     }
00133 
00135 
00138     template<> bool to(const char *&Obj) const
00139     {
00140       if (is_null()) 
00141         return false;
00142       Obj = c_str();
00143       return true;
00144     }
00145 #endif
00146 
00147 
00149     template<typename T> bool to(T &Obj, const T &Default) const        //[t12]
00150     {
00151       const bool NotNull = to(Obj);
00152       if (!NotNull)
00153         Obj = Default;
00154       return NotNull;
00155     }
00156 
00157     bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }   //[t12]
00158 
00159     int size() const { return m_Home->GetLength(m_Index,m_Col); }       //[t11]
00160 
00161   private:
00162 
00163     Tuple::size_type m_Col;
00164   };
00165 
00166 
00168 
00172   class PQXX_LIBEXPORT const_iterator : 
00173     public PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00174                          const Tuple,
00175                          Result::size_type>, 
00176     public Tuple
00177   {
00178   public:
00179 
00186     pointer operator->()  const { return this; }                        //[t12]
00187     reference operator*() const { return *operator->(); }               //[t12]
00188 
00189     const_iterator operator++(int);                                     //[t12]
00190     const_iterator &operator++() { ++m_Index; return *this; }           //[t1]
00191     const_iterator operator--(int);                                     //[t12]
00192     const_iterator &operator--() { --m_Index; return *this; }           //[t12]
00193 
00194     const_iterator &operator+=(difference_type i)                       //[t12]
00195         { m_Index+=i; return *this; }
00196     const_iterator &operator-=(difference_type i)                       //[t12]
00197         { m_Index-=i; return *this; }
00198 
00199     bool operator==(const const_iterator &i) const                      //[t12]
00200         {return m_Index==i.m_Index;}
00201     bool operator!=(const const_iterator &i) const                      //[t12]
00202         {return m_Index!=i.m_Index;}
00203     bool operator<(const const_iterator &i) const                       //[t12]
00204          {return m_Index<i.m_Index;}
00205     bool operator<=(const const_iterator &i) const                      //[t12]
00206         {return m_Index<=i.m_Index;}
00207     bool operator>(const const_iterator &i) const                       //[t12]
00208         {return m_Index>i.m_Index;}
00209     bool operator>=(const const_iterator &i) const                      //[t12]
00210         {return m_Index>=i.m_Index;}
00211 
00212     inline const_iterator operator+(difference_type o) const;           //[t12]
00213 
00214     friend const_iterator operator+(difference_type o, 
00215                                     const_iterator i);                  //[t12]
00216 
00217     inline const_iterator operator-(difference_type o) const;           //[t12]
00218 
00219     inline difference_type operator-(const_iterator i) const;           //[t12]
00220 
00221     Result::size_type num() const { return Row(); }                     //[t1]
00222 
00223   private:
00224     friend class Result;
00225     const_iterator(const Result *r, Result::size_type i) : Tuple(r, i) {}
00226   };
00227 
00228   const_iterator begin() const { return const_iterator(this, 0); }      //[t1]
00229   inline const_iterator end() const;                                    //[t1]
00230   // TODO: Reverse iterators
00231 
00232   size_type size() const { return m_Result ? PQntuples(m_Result) : 0; } //[t2]
00233   bool empty() const { return !m_Result || !PQntuples(m_Result); }      //[t11]
00234   size_type capacity() const { return size(); }                         //[t20]
00235 
00236   const Tuple operator[](size_type i) const { return Tuple(this, i); }  //[t2]
00237   const Tuple at(size_type) const;                                      //[t10]
00238 
00239   void clear() { LoseRef(); }                                           //[t20]
00240 
00241   Tuple::size_type Columns() const { return PQnfields(m_Result); }      //[t11]
00242 
00244   Tuple::size_type ColumnNumber(const char Name[]) const                //[t11]
00245         {return PQfnumber(m_Result,Name);}
00247   Tuple::size_type ColumnNumber(std::string Name) const                 //[t11]
00248         {return ColumnNumber(Name.c_str());}
00249   const char *ColumnName(Tuple::size_type Number) const                 //[t11]
00250         {return PQfname(m_Result,Number);}
00251 
00253 
00254   Oid InsertedOid() const { return PQoidValue(m_Result); }              //[13]
00255 
00257   /*** Returns zero for all other commands. */
00258   size_type AffectedRows() const;                                       //[t7]
00259 
00260 private:
00261   PGresult *m_Result;
00262   mutable int *m_Refcount;
00263 
00264   friend class Result::Field;
00265   const char *GetValue(size_type Row, Tuple::size_type Col) const;
00266   bool GetIsNull(size_type Row, Tuple::size_type Col) const;
00267   Field::size_type GetLength(size_type Row, Tuple::size_type Col) const;
00268 
00269   friend class Connection;
00270   explicit Result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00271   Result &operator=(PGresult *);
00272   bool operator!() const { return !m_Result; }
00273   operator bool() const { return m_Result != 0; }
00274   void CheckStatus() const;
00275 
00276 
00277   void MakeRef(PGresult *);
00278   void MakeRef(const Result &);
00279   void LoseRef() throw ();
00280 };
00281 
00282 
00283 inline Result::Field 
00284 Result::Tuple::operator[](Result::Tuple::size_type i) const 
00285 { 
00286   return Field(*this, i); 
00287 }
00288 
00289 inline Result::Tuple::size_type Result::Tuple::size() const 
00290 { 
00291   return m_Home->Columns(); 
00292 }
00293 
00294 inline const char *Result::Field::Name() const 
00295 { 
00296   return m_Home->ColumnName(m_Col); 
00297 }
00298 
00299 
00300 #ifndef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00301 
00302 template<> inline bool Result::Field::to(PGSTD::string &Obj) const
00303 {
00304   if (is_null())
00305     return false;
00306   Obj = c_str();
00307   return true;
00308 }
00309 
00311 
00314 template<> inline bool Result::Field::to(const char *&Obj) const
00315 {
00316   if (is_null()) 
00317     return false;
00318   Obj = c_str();
00319   return true;
00320 }
00321 #endif
00322 
00323 
00324 
00325 inline Result::const_iterator 
00326 Result::const_iterator::operator+(difference_type o) const
00327 {
00328   return const_iterator(m_Home, m_Index + o);
00329 }
00330 
00331 inline Result::const_iterator 
00332 operator+(Result::const_iterator::difference_type o, 
00333           Result::const_iterator i)
00334 {
00335   return i + o;
00336 }
00337 
00338 inline Result::const_iterator 
00339 Result::const_iterator::operator-(difference_type o) const
00340 {
00341   return const_iterator(m_Home, m_Index - o);
00342 }
00343 
00344 inline Result::const_iterator::difference_type 
00345 Result::const_iterator::operator-(const_iterator i) const
00346 { 
00347   return num()-i.num(); 
00348 }
00349 
00350 inline Result::const_iterator Result::end() const 
00351 { 
00352   return const_iterator(this, size()); 
00353 }
00354 
00355 } // namespace pqxx
00356 
00357 
00358 /* 
00359 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More 
00360 Effective C++", points out that it is good style to have any class containing 
00361 a member of pointer type define its own destructor--just to show that it knows
00362 what it is doing.  This helps prevent nasty memory leak / double deletion bugs
00363 typically resulting from programmers' omission to deal with such issues in
00364 their destructors.
00365 
00366 The -Weffc++ option in gcc generates warnings for noncompliance with Scott's
00367 style guidelines, and hence necessitates the definition of this destructor,\
00368 trivial as it may be.
00369 
00370 [2] IIRC Alex Stepanov, the inventor of the STL, once remarked that having
00371 this as standard behaviour for pointers would be useful in some algorithms.
00372 So even if this makes me look foolish, I would seem to be in distinguished 
00373 company.
00374 */
00375 
00376 #endif
00377 

Generated on Wed Oct 23 15:57:05 2002 for libpqxx by doxygen1.2.18