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[](const 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(const 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 
00100 
00104     Field(const Tuple &R, Tuple::size_type C) : Tuple(R), m_Col(C) {}   
00105 
00107 
00112     const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);} 
00113 
00115     inline const char *Name() const;                                    
00116 
00118     template<typename T> bool to(T &Obj) const                          
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>(PGSTD::string &Obj) const;
00141 
00143 
00146     template<> bool to<const char *>(const char *&Obj) const;
00147 #endif
00148 
00149 
00151     template<typename T> bool to(T &Obj, const T &Default) const        
00152     {
00153       const bool NotNull = to(Obj);
00154       if (!NotNull)
00155         Obj = Default;
00156       return NotNull;
00157     }
00158 
00159     bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }   
00160 
00161     int size() const { return m_Home->GetLength(m_Index,m_Col); }       
00162 
00163   private:
00164 
00165     Tuple::size_type m_Col;
00166   };
00167 
00168 
00170 
00174   class PQXX_LIBEXPORT const_iterator : 
00175     public PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00176                          const Tuple,
00177                          Result::size_type>, 
00178     public Tuple
00179   {
00180   public:
00181 
00188     pointer operator->()  const { return this; }                        
00189     reference operator*() const { return *operator->(); }               
00190 
00191     const_iterator operator++(int);                                     
00192     const_iterator &operator++() { ++m_Index; return *this; }           
00193     const_iterator operator--(int);                                     
00194     const_iterator &operator--() { --m_Index; return *this; }           
00195 
00196     const_iterator &operator+=(difference_type i)                       
00197         { m_Index+=i; return *this; }
00198     const_iterator &operator-=(difference_type i)                       
00199         { m_Index-=i; return *this; }
00200 
00201     bool operator==(const const_iterator &i) const                      
00202         {return m_Index==i.m_Index;}
00203     bool operator!=(const const_iterator &i) const                      
00204         {return m_Index!=i.m_Index;}
00205     bool operator<(const const_iterator &i) const                       
00206          {return m_Index<i.m_Index;}
00207     bool operator<=(const const_iterator &i) const                      
00208         {return m_Index<=i.m_Index;}
00209     bool operator>(const const_iterator &i) const                       
00210         {return m_Index>i.m_Index;}
00211     bool operator>=(const const_iterator &i) const                      
00212         {return m_Index>=i.m_Index;}
00213 
00214     inline const_iterator operator+(difference_type o) const;           
00215 
00216     friend const_iterator operator+(difference_type o, 
00217                                     const_iterator i);                  
00218 
00219     inline const_iterator operator-(difference_type o) const;           
00220 
00221     inline difference_type operator-(const_iterator i) const;           
00222 
00223     Result::size_type num() const { return Row(); }                     
00224 
00225   private:
00226     friend class Result;
00227     const_iterator(const Result *r, Result::size_type i) : Tuple(r, i) {}
00228   };
00229 
00230   const_iterator begin() const { return const_iterator(this, 0); }      
00231   inline const_iterator end() const;                                    
00232   
00233 
00234   size_type size() const { return m_Result ? PQntuples(m_Result) : 0; } 
00235   bool empty() const { return !m_Result || !PQntuples(m_Result); }      
00236   size_type capacity() const { return size(); }                         
00237 
00238   const Tuple operator[](size_type i) const { return Tuple(this, i); }  
00239   const Tuple at(size_type) const;                                      
00240 
00241   void clear() { LoseRef(); }                                           
00242 
00243   Tuple::size_type Columns() const { return PQnfields(m_Result); }      
00244 
00246   Tuple::size_type ColumnNumber(const char Name[]) const                
00247         {return PQfnumber(m_Result,Name);}
00249   Tuple::size_type ColumnNumber(const std::string &Name) const          
00250         {return ColumnNumber(Name.c_str());}
00251   const char *ColumnName(Tuple::size_type Number) const                 
00252         {return PQfname(m_Result,Number);}
00253 
00255 
00256   Oid InsertedOid() const { return PQoidValue(m_Result); }              
00257 
00259   
00260   size_type AffectedRows() const;                                       
00261 
00262 private:
00263   PGresult *m_Result;
00264   mutable int *m_Refcount;
00265 
00266   friend class Result::Field;
00267   const char *GetValue(size_type Row, Tuple::size_type Col) const;
00268   bool GetIsNull(size_type Row, Tuple::size_type Col) const;
00269   Field::size_type GetLength(size_type Row, Tuple::size_type Col) const;
00270 
00271   friend class ConnectionItf;
00272   explicit Result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00273   Result &operator=(PGresult *);
00274   bool operator!() const throw () { return !m_Result; }
00275   operator bool() const throw () { return m_Result != 0; }
00276   void CheckStatus() const;
00277 
00278   friend class Cursor;
00279   const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00280 
00281 
00282   void MakeRef(PGresult *);
00283   void MakeRef(const Result &);
00284   void LoseRef() throw ();
00285 };
00286 
00287 
00288 inline Result::Field 
00289 Result::Tuple::operator[](Result::Tuple::size_type i) const 
00290 { 
00291   return Field(*this, i); 
00292 }
00293 
00294 inline Result::Tuple::size_type Result::Tuple::size() const 
00295 { 
00296   return m_Home->Columns(); 
00297 }
00298 
00299 inline const char *Result::Field::Name() const 
00300 { 
00301   return m_Home->ColumnName(m_Col); 
00302 }
00303 
00305 template<> 
00306 inline bool Result::Field::to<PGSTD::string>(PGSTD::string &Obj) const
00307 {
00308   if (is_null()) return false;
00309   Obj = c_str();
00310   return true;
00311 }
00312 
00314 
00317 template<> 
00318 inline bool Result::Field::to<const char *>(const char *&Obj) const
00319 {
00320   if (is_null()) return false;
00321   Obj = c_str();
00322   return true;
00323 }
00324 
00325 
00326 inline Result::const_iterator 
00327 Result::const_iterator::operator+(difference_type o) const
00328 {
00329   return const_iterator(m_Home, m_Index + o);
00330 }
00331 
00332 inline Result::const_iterator 
00333 operator+(Result::const_iterator::difference_type o, 
00334           Result::const_iterator i)
00335 {
00336   return i + o;
00337 }
00338 
00339 inline Result::const_iterator 
00340 Result::const_iterator::operator-(difference_type o) const
00341 {
00342   return const_iterator(m_Home, m_Index - o);
00343 }
00344 
00345 inline Result::const_iterator::difference_type 
00346 Result::const_iterator::operator-(const_iterator i) const
00347 { 
00348   return num()-i.num(); 
00349 }
00350 
00351 inline Result::const_iterator Result::end() const 
00352 { 
00353   return const_iterator(this, size()); 
00354 }
00355 
00356 } 
00357 
00358 
00360 
00377 template<typename STREAM>
00378 inline STREAM &operator<<(STREAM &S, const pqxx::Result::Field &F)      
00379 {
00380   S << F.c_str();
00381   return S;
00382 }
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 #endif
00405