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     {
00142       if (is_null()) return false;
00143       Obj = c_str();
00144       return true;
00145     }
00146 
00148 
00151     template<> bool to<const char *>(const char *&Obj) const
00152     {
00153       if (is_null()) return false;
00154       Obj = c_str();
00155       return true;
00156     }
00157 #endif
00158 
00159 
00161     template<typename T> bool to(T &Obj, const T &Default) const        //[t12]
00162     {
00163       const bool NotNull = to(Obj);
00164       if (!NotNull)
00165         Obj = Default;
00166       return NotNull;
00167     }
00168 
00169     bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }   //[t12]
00170 
00171     int size() const { return m_Home->GetLength(m_Index,m_Col); }       //[t11]
00172 
00173   private:
00174 
00175     Tuple::size_type m_Col;
00176   };
00177 
00178 
00180 
00184   class PQXX_LIBEXPORT const_iterator : 
00185     public PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00186                          const Tuple,
00187                          Result::size_type>, 
00188     public Tuple
00189   {
00190   public:
00191 
00198     pointer operator->()  const { return this; }                        //[t12]
00199     reference operator*() const { return *operator->(); }               //[t12]
00200 
00201     const_iterator operator++(int);                                     //[t12]
00202     const_iterator &operator++() { ++m_Index; return *this; }           //[t1]
00203     const_iterator operator--(int);                                     //[t12]
00204     const_iterator &operator--() { --m_Index; return *this; }           //[t12]
00205 
00206     const_iterator &operator+=(difference_type i)                       //[t12]
00207         { m_Index+=i; return *this; }
00208     const_iterator &operator-=(difference_type i)                       //[t12]
00209         { m_Index-=i; return *this; }
00210 
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     bool operator<=(const const_iterator &i) const                      //[t12]
00218         {return m_Index<=i.m_Index;}
00219     bool operator>(const const_iterator &i) const                       //[t12]
00220         {return m_Index>i.m_Index;}
00221     bool operator>=(const const_iterator &i) const                      //[t12]
00222         {return m_Index>=i.m_Index;}
00223 
00224     inline const_iterator operator+(difference_type o) const;           //[t12]
00225 
00226     friend const_iterator operator+(difference_type o, 
00227                                     const_iterator i);                  //[t12]
00228 
00229     inline const_iterator operator-(difference_type o) const;           //[t12]
00230 
00231     inline difference_type operator-(const_iterator i) const;           //[t12]
00232 
00233     Result::size_type num() const { return Row(); }                     //[t1]
00234 
00235   private:
00236     friend class Result;
00237     const_iterator(const Result *r, Result::size_type i) : Tuple(r, i) {}
00238   };
00239 
00240   const_iterator begin() const { return const_iterator(this, 0); }      //[t1]
00241   inline const_iterator end() const;                                    //[t1]
00242   // TODO: Reverse iterators
00243 
00244   size_type size() const { return m_Result ? PQntuples(m_Result) : 0; } //[t2]
00245   bool empty() const { return !m_Result || !PQntuples(m_Result); }      //[t11]
00246   size_type capacity() const { return size(); }                         //[t20]
00247 
00248   const Tuple operator[](size_type i) const { return Tuple(this, i); }  //[t2]
00249   const Tuple at(size_type) const;                                      //[t10]
00250 
00251   void clear() { LoseRef(); }                                           //[t20]
00252 
00253   Tuple::size_type Columns() const { return PQnfields(m_Result); }      //[t11]
00254 
00256   Tuple::size_type ColumnNumber(const char Name[]) const                //[t11]
00257         {return PQfnumber(m_Result,Name);}
00259   Tuple::size_type ColumnNumber(const std::string &Name) const          //[t11]
00260         {return ColumnNumber(Name.c_str());}
00261   const char *ColumnName(Tuple::size_type Number) const                 //[t11]
00262         {return PQfname(m_Result,Number);}
00263 
00265 
00266   Oid InsertedOid() const { return PQoidValue(m_Result); }              //[t13]
00267 
00269   /*** Returns zero for all other commands. */
00270   size_type AffectedRows() const;                                       //[t7]
00271 
00272 private:
00273   PGresult *m_Result;
00274   mutable int *m_Refcount;
00275 
00276   friend class Result::Field;
00277   const char *GetValue(size_type Row, Tuple::size_type Col) const;
00278   bool GetIsNull(size_type Row, Tuple::size_type Col) const;
00279   Field::size_type GetLength(size_type Row, Tuple::size_type Col) const;
00280 
00281   friend class ConnectionItf;
00282   explicit Result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00283   Result &operator=(PGresult *);
00284   bool operator!() const throw () { return !m_Result; }
00285   operator bool() const throw () { return m_Result != 0; }
00286   void CheckStatus() const;
00287 
00288   friend class Cursor;
00289   const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00290 
00291 
00292   void MakeRef(PGresult *);
00293   void MakeRef(const Result &);
00294   void LoseRef() throw ();
00295 };
00296 
00297 
00298 inline Result::Field 
00299 Result::Tuple::operator[](Result::Tuple::size_type i) const 
00300 { 
00301   return Field(*this, i); 
00302 }
00303 
00304 inline Result::Tuple::size_type Result::Tuple::size() const 
00305 { 
00306   return m_Home->Columns(); 
00307 }
00308 
00309 inline const char *Result::Field::Name() const 
00310 { 
00311   return m_Home->ColumnName(m_Col); 
00312 }
00313 
00314 
00315 #ifndef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00316 
00317 template<> 
00318 inline bool Result::Field::to<PGSTD::string>(PGSTD::string &Obj) const
00319 {
00320   if (is_null()) return false;
00321   Obj = c_str();
00322   return true;
00323 }
00324 
00326 
00329 template<> 
00330 inline bool Result::Field::to<const char *>(const char *&Obj) const
00331 {
00332   if (is_null()) return false;
00333   Obj = c_str();
00334   return true;
00335 }
00336 #endif
00337 
00338 
00339 
00340 inline Result::const_iterator 
00341 Result::const_iterator::operator+(difference_type o) const
00342 {
00343   return const_iterator(m_Home, m_Index + o);
00344 }
00345 
00346 inline Result::const_iterator 
00347 operator+(Result::const_iterator::difference_type o, 
00348           Result::const_iterator i)
00349 {
00350   return i + o;
00351 }
00352 
00353 inline Result::const_iterator 
00354 Result::const_iterator::operator-(difference_type o) const
00355 {
00356   return const_iterator(m_Home, m_Index - o);
00357 }
00358 
00359 inline Result::const_iterator::difference_type 
00360 Result::const_iterator::operator-(const_iterator i) const
00361 { 
00362   return num()-i.num(); 
00363 }
00364 
00365 inline Result::const_iterator Result::end() const 
00366 { 
00367   return const_iterator(this, size()); 
00368 }
00369 
00370 } // namespace pqxx
00371 
00372 
00374 
00391 template<typename STREAM>
00392 inline STREAM &operator<<(STREAM &S, const pqxx::Result::Field &F)      //[t46]
00393 {
00394   S << F.c_str();
00395   return S;
00396 }
00397 
00398 
00399 
00400 /* 
00401 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More 
00402 Effective C++", points out that it is good style to have any class containing 
00403 a member of pointer type define its own destructor--just to show that it knows
00404 what it is doing.  This helps prevent nasty memory leak / double deletion bugs
00405 typically resulting from programmers' omission to deal with such issues in
00406 their destructors.
00407 
00408 The -Weffc++ option in gcc generates warnings for noncompliance with Scott's
00409 style guidelines, and hence necessitates the definition of this destructor,\
00410 trivial as it may be.
00411 
00412 [2] IIRC Alex Stepanov, the inventor of the STL, once remarked that having
00413 this as standard behaviour for pointers would be useful in some algorithms.
00414 So even if this makes me look foolish, I would seem to be in distinguished 
00415 company.
00416 */
00417 
00418 #endif
00419 

Generated on Sat Mar 15 20:47:39 2003 for libpqxx by doxygen1.3-rc3