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-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>(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        //[t12]
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); }   //[t12]
00160 
00161     int size() const { return m_Home->GetLength(m_Index,m_Col); }       //[t11]
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; }                        //[t12]
00189     reference operator*() const { return *operator->(); }               //[t12]
00190 
00191     const_iterator operator++(int);                                     //[t12]
00192     const_iterator &operator++() { ++m_Index; return *this; }           //[t1]
00193     const_iterator operator--(int);                                     //[t12]
00194     const_iterator &operator--() { --m_Index; return *this; }           //[t12]
00195 
00196     const_iterator &operator+=(difference_type i)                       //[t12]
00197         { m_Index+=i; return *this; }
00198     const_iterator &operator-=(difference_type i)                       //[t12]
00199         { m_Index-=i; return *this; }
00200 
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     bool operator>=(const const_iterator &i) const                      //[t12]
00212         {return m_Index>=i.m_Index;}
00213 
00214     inline const_iterator operator+(difference_type o) const;           //[t12]
00215 
00216     friend const_iterator operator+(difference_type o, 
00217                                     const_iterator i);                  //[t12]
00218 
00219     inline const_iterator operator-(difference_type o) const;           //[t12]
00220 
00221     inline difference_type operator-(const_iterator i) const;           //[t12]
00222 
00223     Result::size_type num() const { return Row(); }                     //[t1]
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); }      //[t1]
00231   inline const_iterator end() const;                                    //[t1]
00232   // TODO: Reverse iterators
00233 
00234   size_type size() const { return m_Result ? PQntuples(m_Result) : 0; } //[t2]
00235   bool empty() const { return !m_Result || !PQntuples(m_Result); }      //[t11]
00236   size_type capacity() const { return size(); }                         //[t20]
00237 
00238   const Tuple operator[](size_type i) const { return Tuple(this, i); }  //[t2]
00239   const Tuple at(size_type) const;                                      //[t10]
00240 
00241   void clear() { LoseRef(); }                                           //[t20]
00242 
00243   Tuple::size_type Columns() const { return PQnfields(m_Result); }      //[t11]
00244 
00246   Tuple::size_type ColumnNumber(const char Name[]) const                //[t11]
00247         {return PQfnumber(m_Result,Name);}
00249   Tuple::size_type ColumnNumber(const std::string &Name) const          //[t11]
00250         {return ColumnNumber(Name.c_str());}
00251   const char *ColumnName(Tuple::size_type Number) const                 //[t11]
00252         {return PQfname(m_Result,Number);}
00253 
00255 
00256   Oid InsertedOid() const { return PQoidValue(m_Result); }              //[t13]
00257 
00259   /*** Returns zero for all other commands. */
00260   size_type AffectedRows() const;                                       //[t7]
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 } // namespace pqxx
00357 
00358 
00360 
00377 template<typename STREAM>
00378 inline STREAM &operator<<(STREAM &S, const pqxx::Result::Field &F)      //[t46]
00379 {
00380   S << F.c_str();
00381   return S;
00382 }
00383 
00384 
00385 
00386 /* 
00387 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More 
00388 Effective C++", points out that it is good style to have any class containing 
00389 a member of pointer type define its own destructor--just to show that it knows
00390 what it is doing.  This helps prevent nasty memory leak / double deletion bugs
00391 typically resulting from programmers' omission to deal with such issues in
00392 their destructors.
00393 
00394 The -Weffc++ option in gcc generates warnings for noncompliance with Scott's
00395 style guidelines, and hence necessitates the definition of this destructor,\
00396 trivial as it may be.
00397 
00398 [2] IIRC Alex Stepanov, the inventor of the STL, once remarked that having
00399 this as standard behaviour for pointers would be useful in some algorithms.
00400 So even if this makes me look foolish, I would seem to be in distinguished 
00401 company.
00402 */
00403 
00404 #endif
00405 

Generated on Mon Mar 17 22:59:04 2003 for libpqxx by doxygen1.3-rc3