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     size_type ColumnNumber(const char ColName[]) const                  //[]
00082         { return m_Home->ColumnNumber(ColName); }
00083 
00084   protected:
00085     const Result *m_Home;
00086     Result::size_type m_Index;
00087 
00088     // Not allowed:
00089     Tuple();
00090   };
00091 
00092 
00094 
00097   class PQXX_LIBEXPORT Field : private Tuple
00098   {
00099   public:
00100     typedef size_t size_type;
00101 
00103 
00107     Field(const Tuple &R, Tuple::size_type C) : Tuple(R), m_Col(C) {}   //[t1]
00108 
00110 
00115     const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);} //[t2]
00116 
00118     inline const char *Name() const;                                    //[t11]
00119 
00121     template<typename T> bool to(T &Obj) const                          //[t1]
00122     {
00123       if (is_null())
00124         return false;
00125 
00126       try
00127       {
00128         FromString(c_str(), Obj);
00129       }
00130       catch (const PGSTD::exception &e)
00131       {
00132         throw PGSTD::runtime_error("Error reading field " + 
00133                                    PGSTD::string(Name()) +
00134                                    ": " +
00135                                    e.what());
00136       }
00137       return true;
00138     }
00139 
00140 
00141 #ifdef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00142 
00143     template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00144 
00146 
00149     template<> bool to<const char *>(const char *&Obj) const;
00150 #endif
00151 
00152 
00154     template<typename T> bool to(T &Obj, const T &Default) const        //[t12]
00155     {
00156       const bool NotNull = to(Obj);
00157       if (!NotNull)
00158         Obj = Default;
00159       return NotNull;
00160     }
00161 
00162     bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }   //[t12]
00163 
00164     int size() const { return m_Home->GetLength(m_Index,m_Col); }       //[t11]
00165 
00166   private:
00167 
00168     Tuple::size_type m_Col;
00169   };
00170 
00171 
00173 
00177   class PQXX_LIBEXPORT const_iterator : 
00178     public PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00179                          const Tuple,
00180                          Result::size_type>, 
00181     public Tuple
00182   {
00183   public:
00184     const_iterator() : Tuple(0,0) {}
00185 
00192     pointer operator->()  const { return this; }                        //[t12]
00193     reference operator*() const { return *operator->(); }               //[t12]
00194 
00195     const_iterator operator++(int);                                     //[t12]
00196     const_iterator &operator++() { ++m_Index; return *this; }           //[t1]
00197     const_iterator operator--(int);                                     //[t12]
00198     const_iterator &operator--() { --m_Index; return *this; }           //[t12]
00199 
00200     const_iterator &operator+=(difference_type i)                       //[t12]
00201         { m_Index+=i; return *this; }
00202     const_iterator &operator-=(difference_type i)                       //[t12]
00203         { m_Index-=i; return *this; }
00204 
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     bool operator>(const const_iterator &i) const                       //[t12]
00214         {return m_Index>i.m_Index;}
00215     bool operator>=(const const_iterator &i) const                      //[t12]
00216         {return m_Index>=i.m_Index;}
00217 
00218     inline const_iterator operator+(difference_type o) const;           //[t12]
00219 
00220     friend const_iterator operator+(difference_type o, 
00221                                     const_iterator i);                  //[t12]
00222 
00223     inline const_iterator operator-(difference_type o) const;           //[t12]
00224 
00225     inline difference_type operator-(const_iterator i) const;           //[t12]
00226 
00227     Result::size_type num() const { return Row(); }                     //[t1]
00228 
00229   private:
00230     friend class Result;
00231     const_iterator(const Result *r, Result::size_type i) : Tuple(r, i) {}
00232   };
00233 
00234   const_iterator begin() const { return const_iterator(this, 0); }      //[t1]
00235   inline const_iterator end() const;                                    //[t1]
00236   // TODO: Reverse iterators
00237 
00238   size_type size() const { return m_Result ? PQntuples(m_Result) : 0; } //[t2]
00239   bool empty() const { return !m_Result || !PQntuples(m_Result); }      //[t11]
00240   size_type capacity() const { return size(); }                         //[t20]
00241 
00242   const Tuple operator[](size_type i) const { return Tuple(this, i); }  //[t2]
00243   const Tuple at(size_type) const;                                      //[t10]
00244 
00245   void clear() { LoseRef(); }                                           //[t20]
00246 
00247   Tuple::size_type Columns() const { return PQnfields(m_Result); }      //[t11]
00248 
00250   Tuple::size_type ColumnNumber(const char Name[]) const                //[t11]
00251         {return PQfnumber(m_Result,Name);}
00253   Tuple::size_type ColumnNumber(const std::string &Name) const          //[t11]
00254         {return ColumnNumber(Name.c_str());}
00255   const char *ColumnName(Tuple::size_type Number) const                 //[t11]
00256         {return PQfname(m_Result,Number);}
00257 
00259 
00260   Oid InsertedOid() const { return PQoidValue(m_Result); }              //[t13]
00261 
00263   /*** Returns zero for all other commands. */
00264   size_type AffectedRows() const;                                       //[t7]
00265 
00266 private:
00267   PGresult *m_Result;
00268   mutable int *m_Refcount;
00269 
00270   friend class Result::Field;
00271   const char *GetValue(size_type Row, Tuple::size_type Col) const;
00272   bool GetIsNull(size_type Row, Tuple::size_type Col) const;
00273   Field::size_type GetLength(size_type Row, Tuple::size_type Col) const;
00274 
00275   friend class ConnectionItf;
00276   explicit Result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00277   Result &operator=(PGresult *);
00278   bool operator!() const throw () { return !m_Result; }
00279   operator bool() const throw () { return m_Result != 0; }
00280   void CheckStatus(const PGSTD::string &Query) const;
00281 
00282   friend class Cursor;
00283   const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00284 
00285 
00286   void MakeRef(PGresult *);
00287   void MakeRef(const Result &);
00288   void LoseRef() throw ();
00289 };
00290 
00291 
00292 inline Result::Field 
00293 Result::Tuple::operator[](Result::Tuple::size_type i) const 
00294 { 
00295   return Field(*this, i); 
00296 }
00297 
00298 inline Result::Tuple::size_type Result::Tuple::size() const 
00299 { 
00300   return m_Home->Columns(); 
00301 }
00302 
00303 inline const char *Result::Field::Name() const 
00304 { 
00305   return m_Home->ColumnName(m_Col); 
00306 }
00307 
00309 template<> 
00310 inline bool Result::Field::to<PGSTD::string>(PGSTD::string &Obj) const
00311 {
00312   if (is_null()) return false;
00313   Obj = c_str();
00314   return true;
00315 }
00316 
00318 
00321 template<> 
00322 inline bool Result::Field::to<const char *>(const char *&Obj) const
00323 {
00324   if (is_null()) return false;
00325   Obj = c_str();
00326   return true;
00327 }
00328 
00329 
00330 inline Result::const_iterator 
00331 Result::const_iterator::operator+(difference_type o) const
00332 {
00333   return const_iterator(m_Home, m_Index + o);
00334 }
00335 
00336 inline Result::const_iterator 
00337 operator+(Result::const_iterator::difference_type o, 
00338           Result::const_iterator i)
00339 {
00340   return i + o;
00341 }
00342 
00343 inline Result::const_iterator 
00344 Result::const_iterator::operator-(difference_type o) const
00345 {
00346   return const_iterator(m_Home, m_Index - o);
00347 }
00348 
00349 inline Result::const_iterator::difference_type 
00350 Result::const_iterator::operator-(const_iterator i) const
00351 { 
00352   return num()-i.num(); 
00353 }
00354 
00355 inline Result::const_iterator Result::end() const 
00356 { 
00357   return const_iterator(this, size()); 
00358 }
00359 
00360 } // namespace pqxx
00361 
00362 
00364 
00381 template<typename STREAM>
00382 inline STREAM &operator<<(STREAM &S, const pqxx::Result::Field &F)      //[t46]
00383 {
00384   S << F.c_str();
00385   return S;
00386 }
00387 
00388 
00389 
00390 /* 
00391 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More 
00392 Effective C++", points out that it is good style to have any class containing 
00393 a member of pointer type define its own destructor--just to show that it knows
00394 what it is doing.  This helps prevent nasty memory leak / double deletion bugs
00395 typically resulting from programmers' omission to deal with such issues in
00396 their destructors.
00397 
00398 The -Weffc++ option in gcc generates warnings for noncompliance with Scott's
00399 style guidelines, and hence necessitates the definition of this destructor,\
00400 trivial as it may be.
00401 
00402 [2] IIRC Alex Stepanov, the inventor of the STL, once remarked that having
00403 this as standard behaviour for pointers would be useful in some algorithms.
00404 So even if this makes me look foolish, I would seem to be in distinguished 
00405 company.
00406 */
00407 
00408 #endif
00409 

Generated on Mon Mar 31 11:29:45 2003 for libpqxx by doxygen1.3-rc3