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[](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(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   protected:
00082     const Result *m_Home;
00083     Result::size_type m_Index;
00084 
00085     
00086     Tuple();
00087   };
00088 
00089 
00091 
00094   class PQXX_LIBEXPORT Field : private Tuple
00095   {
00096   public:
00097     typedef size_t size_type;
00098 
00099     Field(const Tuple &R, Tuple::size_type C) : Tuple(R), m_Col(C) {}   
00100 
00102     const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);} 
00103 
00105     inline const char *Name() const;                                    
00106 
00108     template<typename T> bool to(T &Obj) const                          
00109     {
00110       if (is_null())
00111         return false;
00112 
00113       try
00114       {
00115         FromString(c_str(), Obj);
00116       }
00117       catch (const PGSTD::exception &e)
00118       {
00119         throw PGSTD::runtime_error("Error reading field " + 
00120                                    PGSTD::string(Name()) +
00121                                    ": " +
00122                                    e.what());
00123       }
00124       return true;
00125     }
00126 
00127 #ifdef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00128 
00129     template<> bool to(PGSTD::string &Obj) const
00130     {
00131       if (is_null())
00132         return false;
00133       Obj = c_str();
00134       return true;
00135     }
00136 
00138 
00141     template<> bool to(const char *&Obj) const
00142     {
00143       if (is_null()) 
00144         return false;
00145       Obj = c_str();
00146       return true;
00147     }
00148 #endif
00149 
00150 
00152     template<typename T> bool to(T &Obj, const T &Default) const        
00153     {
00154       const bool NotNull = to(Obj);
00155       if (!NotNull)
00156         Obj = Default;
00157       return NotNull;
00158     }
00159 
00160     bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }   
00161 
00162     int size() const { return m_Home->GetLength(m_Index,m_Col); }       
00163 
00164   private:
00165 
00166     Tuple::size_type m_Col;
00167   };
00168 
00169 
00171 
00175   class PQXX_LIBEXPORT const_iterator : 
00176     public PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00177                          const Tuple,
00178                          Result::size_type>, 
00179     public Tuple
00180   {
00181   public:
00182 
00189     pointer operator->()  const { return this; }                        
00190     reference operator*() const { return *operator->(); }               
00191 
00192     const_iterator operator++(int);                                     
00193     const_iterator &operator++() { ++m_Index; return *this; }           
00194     const_iterator operator--(int);                                     
00195     const_iterator &operator--() { --m_Index; return *this; }           
00196 
00197     const_iterator &operator+=(difference_type i)                       
00198         { m_Index+=i; return *this; }
00199     const_iterator &operator-=(difference_type i)                       
00200         { m_Index-=i; return *this; }
00201 
00202     bool operator==(const const_iterator &i) const                      
00203         {return m_Index==i.m_Index;}
00204     bool operator!=(const const_iterator &i) const                      
00205         {return m_Index!=i.m_Index;}
00206     bool operator<(const const_iterator &i) const                       
00207          {return m_Index<i.m_Index;}
00208     bool operator<=(const const_iterator &i) const                      
00209         {return m_Index<=i.m_Index;}
00210     bool operator>(const const_iterator &i) const                       
00211         {return m_Index>i.m_Index;}
00212     bool operator>=(const const_iterator &i) const                      
00213         {return m_Index>=i.m_Index;}
00214 
00215     inline const_iterator operator+(difference_type o) const;           
00216 
00217     friend const_iterator operator+(difference_type o, 
00218                                     const_iterator i);                  
00219 
00220     inline const_iterator operator-(difference_type o) const;           
00221 
00222     inline difference_type operator-(const_iterator i) const;           
00223 
00224     Result::size_type num() const { return Row(); }                     
00225 
00226   private:
00227     friend class Result;
00228     const_iterator(const Result *r, Result::size_type i) : Tuple(r, i) {}
00229   };
00230 
00231   const_iterator begin() const { return const_iterator(this, 0); }      
00232   inline const_iterator end() const;                                    
00233   
00234 
00235   size_type size() const { return m_Result ? PQntuples(m_Result) : 0; } 
00236   bool empty() const { return !m_Result || !PQntuples(m_Result); }      
00237   size_type capacity() const { return size(); }                         
00238 
00239   const Tuple operator[](size_type i) const { return Tuple(this, i); }  
00240   const Tuple at(size_type) const;                                      
00241 
00242   void clear() { LoseRef(); }                                           
00243 
00244   Tuple::size_type Columns() const { return PQnfields(m_Result); }      
00245 
00247   Tuple::size_type ColumnNumber(const char Name[]) const                
00248         {return PQfnumber(m_Result,Name);}
00250   Tuple::size_type ColumnNumber(std::string Name) const                 
00251         {return ColumnNumber(Name.c_str());}
00252   const char *ColumnName(Tuple::size_type Number) const                 
00253         {return PQfname(m_Result,Number);}
00254 
00256 
00257   Oid InsertedOid() const { return PQoidValue(m_Result); }              
00258 
00260   
00261   size_type AffectedRows() const;                                       
00262 
00263 private:
00264   PGresult *m_Result;
00265   mutable int *m_Refcount;
00266 
00267   friend class Result::Field;
00268   const char *GetValue(size_type Row, Tuple::size_type Col) const;
00269   bool GetIsNull(size_type Row, Tuple::size_type Col) const;
00270   Field::size_type GetLength(size_type Row, Tuple::size_type Col) const;
00271 
00272   friend class Connection;
00273   explicit Result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00274   Result &operator=(PGresult *);
00275   bool operator!() const { return !m_Result; }
00276   operator bool() const { return m_Result != 0; }
00277   void CheckStatus() const;
00278 
00279 
00280   void MakeRef(PGresult *);
00281   void MakeRef(const Result &);
00282   void LoseRef() throw ();
00283 };
00284 
00285 
00286 inline Result::Field 
00287 Result::Tuple::operator[](Result::Tuple::size_type i) const 
00288 { 
00289   return Field(*this, i); 
00290 }
00291 
00292 inline Result::Tuple::size_type Result::Tuple::size() const 
00293 { 
00294   return m_Home->Columns(); 
00295 }
00296 
00297 inline const char *Result::Field::Name() const 
00298 { 
00299   return m_Home->ColumnName(m_Col); 
00300 }
00301 
00302 
00303 #ifndef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00304 
00305 template<> inline bool Result::Field::to(PGSTD::string &Obj) const
00306 {
00307   if (is_null())
00308     return false;
00309   Obj = c_str();
00310   return true;
00311 }
00312 
00314 
00317 template<> inline bool Result::Field::to(const char *&Obj) const
00318 {
00319   if (is_null()) 
00320     return false;
00321   Obj = c_str();
00322   return true;
00323 }
00324 #endif
00325 
00326 
00327 
00328 inline Result::const_iterator 
00329 Result::const_iterator::operator+(difference_type o) const
00330 {
00331   return const_iterator(m_Home, m_Index + o);
00332 }
00333 
00334 inline Result::const_iterator 
00335 operator+(Result::const_iterator::difference_type o, 
00336           Result::const_iterator i)
00337 {
00338   return i + o;
00339 }
00340 
00341 inline Result::const_iterator 
00342 Result::const_iterator::operator-(difference_type o) const
00343 {
00344   return const_iterator(m_Home, m_Index - o);
00345 }
00346 
00347 inline Result::const_iterator::difference_type 
00348 Result::const_iterator::operator-(const_iterator i) const
00349 { 
00350   return num()-i.num(); 
00351 }
00352 
00353 inline Result::const_iterator Result::end() const 
00354 { 
00355   return const_iterator(this, size()); 
00356 }
00357 
00358 } 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 #endif
00380