Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

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

Generated on Tue Feb 25 20:09:35 2003 for libpqxx by doxygen1.3-rc3