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

Generated on Sat Feb 15 18:04:50 2003 for libpqxx by doxygen1.3-rc2