Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

result.hxx

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/result.hxx
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  *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.
00010  *
00011  * Copyright (c) 2001-2004, Jeroen T. Vermeulen <jtv@xs4all.nl>
00012  *
00013  * See COPYING for copyright license.  If you did not receive a file called
00014  * COPYING with this source code, please notify the distributor of this mistake,
00015  * or contact the author.
00016  *
00017  *-------------------------------------------------------------------------
00018  */
00019 #ifdef PQXX_HAVE_IOS
00020 #include <ios>
00021 #endif
00022 
00023 #include <stdexcept>
00024 
00025 #include "pqxx/util"
00026 
00027 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
00028  */
00029 
00030 // TODO: Support SQL arrays
00031 // TODO: value_type
00032 
00033 namespace pqxx
00034 {
00036 
00043 class PQXX_LIBEXPORT result : private internal::PQAlloc<internal::pq::PGresult>
00044 {
00045   typedef internal::PQAlloc<internal::pq::PGresult> super;
00046 public:
00047   class const_iterator;
00048   class const_fielditerator;
00049   class const_reverse_fielditerator;
00050   class tuple;
00051   class field;
00052   typedef unsigned long size_type;
00053   typedef signed long difference_type;
00054   typedef tuple reference;
00055   typedef const_iterator pointer;
00056 
00058 
00067   class PQXX_LIBEXPORT tuple
00068   {
00069   public:
00070     typedef unsigned int size_type;
00071     typedef signed int difference_type;
00072     typedef const_fielditerator const_iterator;
00073     typedef field reference;
00074     typedef const_fielditerator pointer;
00075     typedef const_reverse_fielditerator const_reverse_iterator;
00076 
00077     tuple(const result *r, result::size_type i) throw () : 
00078       m_Home(r), m_Index(i) {}
00079     ~tuple() throw () {} // Yes Scott Meyers, you're absolutely right[1]
00080 
00081     bool operator==(const tuple &) const throw ();                      //[t75]
00082     bool operator!=(const tuple &rhs) const throw ()                    //[t75]
00083         { return !operator==(rhs); }
00084 
00085     const_iterator begin() const throw ()                               //[t82]
00086         { return const_iterator(*this, 0); }
00087     const_iterator end() const throw ()                                 //[t82]
00088         { return const_iterator(*this, size()); }
00089 
00090     reference front() const throw () { return field(*this, 0); }        //[t74]
00091     reference back() const throw () { return field(*this, size()-1); }  //[t75]
00092 
00093     const_reverse_fielditerator rbegin() const;                         //[t82]
00094     const_reverse_fielditerator rend() const;                           //[t82]
00095 
00096     reference operator[](size_type i) const throw ()                    //[t11]
00097         { return field(*this, i); }
00098     reference operator[](int i) const throw ()                          //[t2]
00099         { return operator[](size_type(i)); }
00100     reference operator[](const char[]) const;                           //[t11]
00101     reference operator[](const PGSTD::string &s) const                  //[t11]
00102         { return operator[](s.c_str()); }
00103     reference at(size_type) const throw (PGSTD::out_of_range);          //[t11]
00104     reference at(int i) const throw (PGSTD::out_of_range)               //[t11]
00105         { return at(size_type(i)); }
00106     reference at(const char[]) const;                                   //[t11]
00107     reference at(const PGSTD::string &s) const                          //[t11]
00108         { return at(s.c_str()); }
00109 
00110     size_type size() const throw () { return m_Home->columns(); }       //[t11]
00111 
00112     void swap(tuple &rhs) throw ()                                      //[t11]
00113     {
00114       const result *const h(m_Home);
00115       const result::size_type i(m_Index);
00116       m_Home = rhs.m_Home;
00117       m_Index = rhs.m_Index;
00118       rhs.m_Home = h;
00119       rhs.m_Index = i;
00120     }
00121 
00122     result::size_type rownumber() const throw () { return m_Index; }    //[t11]
00123 
00125     size_type column_number(const PGSTD::string &ColName) const         //[t30]
00126         { return m_Home->column_number(ColName); }
00127 
00129     size_type column_number(const char ColName[]) const                 //[t30]
00130         { return m_Home->column_number(ColName); }
00131 
00133     oid column_type(size_type ColNum) const                             //[t7]
00134         { return m_Home->column_type(ColNum); }
00135 
00137     oid column_type(int ColNum) const                                   //[t7]
00138         { return column_type(size_type(ColNum)); }
00139 
00141     oid column_type(const PGSTD::string &ColName) const                 //[t7]
00142         { return column_type(column_number(ColName)); }
00143 
00145     oid column_type(const char ColName[]) const                         //[t7]
00146         { return column_type(column_number(ColName)); }
00147 
00148     result::size_type num() const { return rownumber(); }               //[t1]
00149 
00150 #ifdef PQXX_HAVE_PQFTABLE
00151     oid column_table(size_type ColNum) const                            //[t2]
00152         { return m_Home->column_table(ColNum); }
00153     oid column_table(int ColNum) const                                  //[t2]
00154         { return column_table(size_type(ColNum)); }
00155     oid column_table(const PGSTD::string &ColName) const                //[t2]
00156         { return column_table(column_number(ColName)); }
00157 #endif
00158 
00159 
00160 #ifdef PQXX_DEPRECATED_HEADERS
00161 
00162     result::size_type Row() const { return rownumber(); }
00163 
00165     size_type ColumnNumber(const PGSTD::string &ColName) const 
00166         { return column_number(ColName); }
00167 
00169     size_type ColumnNumber(const char ColName[]) const 
00170         { return column_number(ColName); }
00171 #endif
00172 
00173   protected:
00174     friend class field;
00175     const result *m_Home;
00176     result::size_type m_Index;
00177 
00178     // Not allowed:
00179     tuple();
00180   };
00181 
00183 
00186   class PQXX_LIBEXPORT field
00187   {
00188   public:
00189     typedef size_t size_type;
00190 
00192 
00196     field(const tuple &T, tuple::size_type C) throw () :                //[t1]
00197         m_tup(T), m_col(C) {}
00198 
00200 
00215     bool operator==(const field &) const;                               //[t75]
00216 
00218 
00220     bool operator!=(const field &rhs) const {return !operator==(rhs);}  //[t82]
00221 
00223 
00228     const char *c_str() const { return home()->GetValue(idx(),col()); } //[t2]
00229 
00231     const char *name() const { return home()->column_name(col()); }     //[t11]
00232 
00234     oid type() const { return home()->column_type(col()); }             //[t7]
00235 
00236 #ifdef PQXX_HAVE_PQFTABLE
00237 
00238 
00240     oid table() const { return home()->column_table(col()); }           //[t2]
00241 #endif
00242 
00244 
00253     template<typename T> bool to(T &Obj) const                          //[t3]
00254     {
00255       if (is_null())
00256         return false;
00257 
00258       try
00259       {
00260         from_string(c_str(), Obj);
00261       }
00262       catch (const PGSTD::exception &e)
00263       {
00264         throw PGSTD::domain_error("Error reading field " + 
00265                                   PGSTD::string(name()) + ": " +
00266                                   e.what());
00267       }
00268       return true;
00269     }
00270 
00272     template<typename T> bool operator>>(T &Obj) const                  //[t7]
00273         { return to(Obj); }
00274 
00275 #ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00276 
00277     template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00278 
00280 
00283     template<> bool to<const char *>(const char *&Obj) const;
00284 #endif
00285 
00287     template<typename T> bool to(T &Obj, const T &Default) const                //[t12]
00288     {
00289       const bool NotNull = to(Obj);
00290       if (!NotNull) Obj = Default;
00291       return NotNull;
00292     }
00293 
00295 
00298     template<typename T> T as(const T &Default) const                   //[t1]
00299     {
00300       T Obj;
00301       to(Obj, Default);
00302       return Obj;
00303     }
00304 
00306     template<typename T> T as() const                                   //[t45]
00307     {
00308       T Obj;
00309       const bool NotNull = to(Obj);
00310       if (!NotNull) throw PGSTD::domain_error("Attempt to read null field");
00311       return Obj;
00312     }
00313 
00314     bool is_null() const { return home()->GetIsNull(idx(), col()); }    //[t12]
00315     size_type size() const throw ()                                     //[t11]
00316         { return home()->GetLength(idx(),col()); }
00317     tuple::size_type num() const { return col(); }                      //[t82]
00318 
00319 #ifdef PQXX_DEPRECATED_HEADERS
00320 
00321     const char *Name() const {return name();}
00322 #endif
00323 
00324   private:
00325     const result *home() const throw () { return m_tup.m_Home; }
00326     result::size_type idx() const throw () { return m_tup.m_Index; }
00327 
00328   protected:
00329     const tuple::size_type col() const throw () { return m_col; }
00330     tuple m_tup;
00331     tuple::size_type m_col;
00332   };
00333 
00334   typedef PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00335                            const tuple,
00336                            result::difference_type,
00337                            const_iterator,
00338                            tuple> const_iterator_base;
00339 
00341 
00345   class PQXX_LIBEXPORT const_iterator : 
00346     public const_iterator_base,
00347     public tuple
00348   {
00349   public:
00350     typedef const tuple *pointer;
00351     typedef tuple reference;
00352     typedef result::size_type size_type;
00353     typedef result::difference_type difference_type;
00354 
00355     const_iterator() throw () : tuple(0,0) {}
00356     const_iterator(const tuple &t) throw () : tuple(t) {}
00357 
00364     pointer operator->() const { return this; }                         //[t12]
00365     reference operator*() const { return tuple(*this); }                //[t12]
00366 
00367     const_iterator operator++(int);                                     //[t12]
00368     const_iterator &operator++() { ++m_Index; return *this; }   //[t1]
00369     const_iterator operator--(int);                                     //[t12]
00370     const_iterator &operator--() { --m_Index; return *this; }   //[t12]
00371 
00372     const_iterator &operator+=(difference_type i)                       //[t12]
00373         { m_Index+=i; return *this; }
00374     const_iterator &operator-=(difference_type i)                       //[t12]
00375         { m_Index-=i; return *this; }
00376 
00377     bool operator==(const const_iterator &i) const                      //[t12]
00378         {return m_Index==i.m_Index;}
00379     bool operator!=(const const_iterator &i) const                      //[t12]
00380         {return m_Index!=i.m_Index;}
00381     bool operator<(const const_iterator &i) const                       //[t12]
00382         {return m_Index<i.m_Index;}
00383     bool operator<=(const const_iterator &i) const                      //[t12]
00384         {return m_Index<=i.m_Index;}
00385     bool operator>(const const_iterator &i) const                       //[t12]
00386         {return m_Index>i.m_Index;}
00387     bool operator>=(const const_iterator &i) const                      //[t12]
00388         {return m_Index>=i.m_Index;}
00389 
00390     inline const_iterator operator+(difference_type) const;             //[t12]
00391     friend const_iterator
00392     operator+(difference_type, const_iterator);                 //[t12]
00393     inline const_iterator operator-(difference_type) const;             //[t12]
00394     inline difference_type operator-(const_iterator) const;             //[t12]
00395 
00396   private:
00397     friend class pqxx::result;
00398     const_iterator(const pqxx::result *r, result::size_type i) throw () :
00399         tuple(r, i) {}
00400   };
00401 
00402   class PQXX_LIBEXPORT const_reverse_iterator : private const_iterator
00403   {
00404   public:
00405     typedef const_iterator iterator_type;
00406     using iterator_type::iterator_category;
00407     using iterator_type::value_type;
00408     using iterator_type::difference_type;
00409     using iterator_type::pointer;
00410     using iterator_type::reference;
00411     using iterator_type::operator=;
00412 
00413     const_reverse_iterator(const const_reverse_iterator &rhs) :         //[t75]
00414       const_iterator(rhs), m_tmp(rhs) {}
00415     explicit const_reverse_iterator(const const_iterator &rhs) :        //[t75]
00416       const_iterator(rhs), m_tmp() {}
00417 
00418     iterator_type base() const throw () { return *this; }               //[t75]
00419 
00420     pointer operator->() const throw ()                                 //[t75]
00421         { m_tmp=*this; --m_tmp; return &m_tmp; }
00422     reference operator*() const throw () { return *operator->(); }      //[t75]
00423     const_reverse_iterator operator++()                                 //[t75]
00424         { iterator_type::operator--(); return *this; }
00425     const_reverse_iterator operator++(int)                              //[t75]
00426     {
00427       const const_reverse_iterator tmp(*this);
00428       iterator_type::operator--();
00429       return tmp;
00430     }
00431     const_reverse_iterator &operator--()                                //[t75]
00432         { iterator_type::operator++(); return *this; }
00433     const_reverse_iterator operator--(int)                              //[t75]
00434     {
00435       const_reverse_iterator tmp(*this);
00436       iterator_type::operator++();
00437       return tmp;
00438     }
00439     const_reverse_iterator operator+(difference_type i) const           //[t75]
00440         { return const_reverse_iterator(iterator_type(*this)-i); }
00441     const_reverse_iterator &operator+=(difference_type i)               //[t75]
00442         { iterator_type::operator-=(i); return *this; }
00443     const_reverse_iterator operator-(difference_type i)                 //[t75]
00444         { return const_reverse_iterator(iterator_type(*this)+i); }
00445     const_reverse_iterator &operator-=(difference_type i)               //[t75]
00446         { iterator_type::operator+=(i); return *this; }
00447 
00448     using iterator_type::operator==;
00449     using iterator_type::operator!=;
00450     bool operator==(const const_reverse_iterator &rhs) const throw ()   //[t75]
00451         { return iterator_type::operator==(rhs); }
00452     bool operator!=(const const_reverse_iterator &rhs) const throw ()   //[t75]
00453         { return !operator==(rhs); }
00454 
00455     bool operator<(const const_reverse_iterator &rhs) const             //[t75]
00456         { return iterator_type::operator>(rhs); }
00457     bool operator<=(const const_reverse_iterator &rhs) const            //[t75]
00458         { return iterator_type::operator>=(rhs); }
00459     bool operator>(const const_reverse_iterator &rhs) const             //[t75]
00460         { return iterator_type::operator<(rhs); }
00461     bool operator>=(const const_reverse_iterator &rhs) const            //[t75]
00462         { return iterator_type::operator<=(rhs); }
00463     difference_type operator-(const const_reverse_iterator &rhs) const  //[t75]
00464         { return rhs.base() - base(); }
00465 
00466   private:
00468 
00473     mutable iterator_type m_tmp;
00474   };
00475 
00476   class PQXX_LIBEXPORT const_fielditerator : 
00477     public PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00478                            const field,
00479                            tuple::size_type>, 
00480     public field
00481   {
00482     typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
00483                                   const field,
00484                                   tuple::size_type> it;
00485   public:
00486     using it::pointer;
00487     typedef tuple::size_type size_type;
00488     typedef tuple::difference_type difference_type;
00489     typedef field reference;
00490 
00491     const_fielditerator(const tuple &T, tuple::size_type C) throw () :  //[t82]
00492       field(T, C) {}
00493     const_fielditerator(const field &F) throw () : field(F) {}          //[t82]
00494 
00495     pointer operator->() const { return this; }                         //[t82]
00496     reference operator*() const { return field(*this); }                //[t82]
00497 
00498     const_fielditerator operator++(int);                                //[t82]
00499     const_fielditerator &operator++() { ++m_col; return *this; }        //[t82]
00500     const_fielditerator operator--(int);                                //[t82]
00501     const_fielditerator &operator--() { --m_col; return *this; }        //[t82]
00502 
00503     const_fielditerator &operator+=(difference_type i)                  //[t82]
00504         { m_col+=i; return *this; }
00505     const_fielditerator &operator-=(difference_type i)                  //[t82]
00506         { m_col-=i; return *this; }
00507 
00508     bool operator==(const const_fielditerator &i) const                 //[t82]
00509         {return col()==i.col();}
00510     bool operator!=(const const_fielditerator &i) const                 //[t82]
00511         {return col()!=i.col();}
00512     bool operator<(const const_fielditerator &i) const                  //[t82]
00513         {return col()<i.col();}
00514     bool operator<=(const const_fielditerator &i) const                 //[t82]
00515         {return col()<=i.col();}
00516     bool operator>(const const_fielditerator &i) const                  //[t82]
00517         {return col()>i.col();}
00518     bool operator>=(const const_fielditerator &i) const                 //[t82]
00519         {return col()>=i.col();}
00520 
00521     inline const_fielditerator operator+(difference_type) const;        //[t82]
00522 
00523     friend const_fielditerator operator+(difference_type, 
00524                                           const_fielditerator);         //[t82]
00525 
00526     inline const_fielditerator operator-(difference_type) const;        //[t82]
00527     inline difference_type operator-(const_fielditerator) const;        //[t82]
00528   };
00529 
00530   class PQXX_LIBEXPORT const_reverse_fielditerator : private const_fielditerator
00531   {
00532   public:
00533     typedef const_fielditerator iterator_type;
00534     using iterator_type::iterator_category;
00535     using iterator_type::value_type;
00536     using iterator_type::difference_type;
00537     using iterator_type::pointer;
00538     using iterator_type::reference;
00539     using iterator_type::operator=;
00540 
00541     iterator_type base() const throw () { return *this; }               //[t82]
00542     const_reverse_fielditerator(const const_reverse_fielditerator &rhs) //[t82]
00543       : const_fielditerator(rhs), m_tmp(rhs.m_tmp) {}
00544     explicit
00545       const_reverse_fielditerator(const const_fielditerator &rhs) :     //[t82]
00546       const_fielditerator(rhs), m_tmp(rhs) {}
00547 
00548     pointer operator->() const throw ()                                 //[t82]
00549         { m_tmp = *this; --m_tmp; return &m_tmp; }
00550     reference operator*() const throw () { return *operator->(); }      //[t82]
00551     const_reverse_fielditerator operator++()                            //[t82]
00552         { iterator_type::operator--(); return *this; }
00553     const_reverse_fielditerator operator++(int)                         //[t82]
00554     {
00555       const const_reverse_fielditerator tmp(*this);
00556       iterator_type::operator--();
00557       return tmp;
00558     }
00559     const_reverse_fielditerator &operator--()                           //[t82]
00560         { iterator_type::operator++(); return *this; }
00561     const_reverse_fielditerator operator--(int)                         //[t82]
00562     {
00563       const_reverse_fielditerator tmp(*this);
00564       iterator_type::operator++();
00565       return tmp;
00566     }
00567     const_reverse_fielditerator operator+(difference_type i) const      //[t82]
00568         { return const_reverse_fielditerator(iterator_type(*this)-i); }
00569     const_reverse_fielditerator &operator+=(difference_type i)          //[t82]
00570         { iterator_type::operator-=(i); return *this; }
00571     const_reverse_fielditerator operator-(difference_type i)            //[t82]
00572         { return const_reverse_fielditerator(iterator_type(*this)+i); }
00573     const_reverse_fielditerator &operator-=(difference_type i)          //[t82]
00574         { iterator_type::operator+=(i); return *this; }
00575 
00576     using iterator_type::operator==;
00577     using iterator_type::operator!=;
00578     bool
00579       operator==(const const_reverse_fielditerator &rhs) const throw () //[t82]
00580         { return iterator_type::operator==(rhs); }
00581     bool
00582       operator!=(const const_reverse_fielditerator &rhs) const throw () //[t82]
00583         { return !operator==(rhs); }
00584 
00585 
00586     bool operator<(const const_reverse_fielditerator &rhs) const        //[t82]
00587         { return iterator_type::operator>(rhs); }
00588     bool operator<=(const const_reverse_fielditerator &rhs) const       //[t82]
00589         { return iterator_type::operator>=(rhs); }
00590     bool operator>(const const_reverse_fielditerator &rhs) const        //[t82]
00591         { return iterator_type::operator<(rhs); }
00592     bool operator>=(const const_reverse_fielditerator &rhs) const       //[t82]
00593         { return iterator_type::operator<=(rhs); }
00594     difference_type
00595       operator-(const const_reverse_fielditerator &rhs) const           //[t82]
00596         { return rhs.base() - base(); }
00597 
00598   private:
00600 
00605     mutable iterator_type m_tmp;
00606   };
00607 
00608 
00609   result() throw () : super() {}                                        //[t3]
00610   result(const result &rhs) throw () : super(rhs) {}                    //[t1]
00611   
00612   result &operator=(const result &rhs) throw ()                         //[t10]
00613         { super::operator=(rhs); return *this; }
00614 
00615   bool operator==(const result &) const throw ();                       //[t70]
00616   bool operator!=(const result &rhs) const throw ()                     //[t70]
00617         { return !operator==(rhs); }
00618 
00619   const_reverse_iterator rbegin() const                                 //[t75]
00620         { return const_reverse_iterator(end()); }
00621   const_reverse_iterator rend() const                                   //[t75]
00622         { return const_reverse_iterator(begin()); }
00623 
00624   const_iterator begin() const throw ()                                 //[t1]
00625         { return const_iterator(this, 0); }
00626   inline const_iterator end() const throw ();                           //[t1]
00627 
00628   reference front() const throw () { return tuple(this,0); }            //[t74]
00629   reference back() const throw () {return tuple(this,size()-1);}        //[t75]
00630 
00631   size_type size() const throw ()                                       //[t2]
00632         { return c_ptr() ? PQXXPQ::PQntuples(c_ptr()) : 0; }
00633   bool empty() const                                                    //[t11]
00634         { return !c_ptr() || !PQXXPQ::PQntuples(c_ptr()); }
00635   size_type capacity() const throw () { return size(); }                //[t20]
00636 
00637   void swap(result &) throw ();                                         //[t77]
00638 
00639   const tuple operator[](size_type i) const throw ()                    //[t2]
00640         { return tuple(this, i); }
00641   const tuple at(size_type) const throw (PGSTD::out_of_range);          //[t10]
00642 
00643   using super::clear;                                                   //[t20]
00644 
00646   tuple::size_type columns() const throw ()                             //[t11]
00647         { return PQnfields(c_ptr()); }
00648 
00650   tuple::size_type column_number(const char ColName[]) const;           //[t11]
00651 
00653   tuple::size_type column_number(const PGSTD::string &Name) const       //[t11]
00654         {return column_number(Name.c_str());}
00655 
00657   const char *column_name(tuple::size_type Number) const;               //[t11]
00658 
00660   inline oid column_type(tuple::size_type ColNum) const;                //[t7]
00662   inline oid column_type(int ColNum) const                              //[t7]
00663         { return column_type(tuple::size_type(ColNum)); }
00664 
00666   oid column_type(const PGSTD::string &ColName) const                   //[t7]
00667         { return column_type(column_number(ColName)); }
00668 
00670   oid column_type(const char ColName[]) const                           //[t7]
00671         { return column_type(column_number(ColName)); }
00672 
00673 #ifdef PQXX_HAVE_PQFTABLE
00674 
00675   oid column_table(tuple::size_type ColNum) const;                      //[t2]
00677   oid column_table(int ColNum) const                                    //[t2]
00678         { return column_table(tuple::size_type(ColNum)); } 
00679 
00681   oid column_table(const PGSTD::string &ColName) const                  //[t2]
00682         { return column_table(column_number(ColName)); }
00683 #endif
00684 
00686 
00688   oid inserted_oid() const { return PQoidValue(c_ptr()); }              //[t13]
00689 
00690 
00692   /*** Returns zero for all other commands. */
00693   size_type affected_rows() const;                                      //[t7]
00694 
00695 
00696 #ifdef PQXX_DEPRECATED_HEADERS
00697 
00698   typedef tuple Tuple;
00700   typedef field Field;
00702   oid InsertedOid() const { return inserted_oid(); }
00704   size_type AffectedRows() const { return affected_rows(); }
00706   tuple::size_type Columns() const { return columns(); }
00708   tuple::size_type ColumnNumber(const char Name[]) const
00709         {return PQfnumber(c_ptr(),Name);}
00711   tuple::size_type ColumnNumber(const PGSTD::string &Name) const
00712         {return ColumnNumber(Name.c_str());}
00714   const char *ColumnName(tuple::size_type Number) const
00715         {return PQfname(c_ptr(),Number);}
00716 #endif
00717 
00718 
00719 private:
00720   friend class pqxx::result::field;
00721   const char *GetValue(size_type Row, tuple::size_type Col) const;
00722   bool GetIsNull(size_type Row, tuple::size_type Col) const;
00723   field::size_type GetLength(size_type Row, tuple::size_type Col) const;
00724 
00725   friend class connection_base;
00726   friend class pipeline;
00727   explicit result(PQXXPQ::PGresult *rhs) throw () : super(rhs) {}
00728   result &operator=(PQXXPQ::PGresult *rhs) throw ()
00729         { super::operator=(rhs); return *this; }
00730   bool operator!() const throw () { return !c_ptr(); }
00731   operator bool() const throw () { return c_ptr() != 0; }
00732   void CheckStatus(const PGSTD::string &Query) const;
00733   void CheckStatus(const char Query[]) const;
00734   int errorposition() const throw ();
00735   PGSTD::string StatusError() const;
00736 
00737   friend class Cursor;
00738   const char *CmdStatus() const throw () { return PQcmdStatus(c_ptr()); }
00739 };
00740 
00741 
00743 
00760 template<typename STREAM>
00761 inline STREAM &operator<<(STREAM &S, const pqxx::result::field &F)      //[t46]
00762 {
00763   S.write(F.c_str(), F.size());
00764   return S;
00765 }
00766 
00767 
00769 template<typename T>
00770 inline void from_string(const result::field &F, T &Obj)                 //[t46]
00771         { from_string(F.c_str(), Obj); }
00772 
00774 template<>
00775 inline PGSTD::string to_string(const result::field &Obj)                //[t74]
00776         { return to_string(Obj.c_str()); }
00777 
00778 
00780 template<> 
00781 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
00782 {
00783   if (is_null()) return false;
00784   Obj = c_str();
00785   return true;
00786 }
00787 
00789 
00792 template<> 
00793 inline bool result::field::to<const char *>(const char *&Obj) const
00794 {
00795   if (is_null()) return false;
00796   Obj = c_str();
00797   return true;
00798 }
00799 
00800 
00801 inline result::tuple::const_reverse_iterator result::tuple::rbegin() const
00802         { return const_reverse_fielditerator(end()); }
00803 inline result::tuple::const_reverse_iterator result::tuple::rend() const
00804         { return const_reverse_fielditerator(begin()); }
00805 
00806 inline result::const_iterator 
00807 result::const_iterator::operator+(difference_type o) const
00808 {
00809   return const_iterator(m_Home, m_Index + o);
00810 }
00811 
00812 inline result::const_iterator 
00813 operator+(result::const_iterator::difference_type o, result::const_iterator i)
00814 {
00815   return i + o;
00816 }
00817 
00818 inline result::const_iterator 
00819 result::const_iterator::operator-(difference_type o) const
00820 {
00821   return const_iterator(m_Home, m_Index - o);
00822 }
00823 
00824 inline result::const_iterator::difference_type 
00825 result::const_iterator::operator-(const_iterator i) const
00826 { 
00827   return num()-i.num(); 
00828 }
00829 
00830 inline result::const_iterator result::end() const throw ()
00831 { 
00832   return const_iterator(this, size()); 
00833 }
00834 
00835 
00836 inline result::const_reverse_iterator
00837 operator+(result::const_reverse_iterator::difference_type n,
00838           const result::const_reverse_iterator &i)
00839 {
00840   return result::const_reverse_iterator(i.base() - n);
00841 }
00842 
00843 inline result::const_fielditerator 
00844 result::const_fielditerator::operator+(difference_type o) const
00845 {
00846   return const_fielditerator(m_tup, col() + o);
00847 }
00848 
00849 inline result::const_fielditerator 
00850 operator+(result::const_fielditerator::difference_type o,
00851           result::const_fielditerator i)
00852 {
00853   return i + o;
00854 }
00855 
00856 inline result::const_fielditerator 
00857 result::const_fielditerator::operator-(difference_type o) const
00858 {
00859   return const_fielditerator(m_tup, col() - o);
00860 }
00861 
00862 inline result::const_fielditerator::difference_type 
00863 result::const_fielditerator::operator-(const_fielditerator i) const
00864 { 
00865   return num()-i.num(); 
00866 }
00867 
00868 
00869 inline oid result::column_type(tuple::size_type ColNum) const
00870 {
00871   const oid T = PQftype(c_ptr(), ColNum);
00872   if (T == oid_none)
00873     throw PGSTD::invalid_argument(
00874                 "Attempt to retrieve type of nonexistant column " +
00875                 to_string(ColNum) + " "
00876                 "of query result");
00877   return T;
00878 }
00879 
00880 
00881 
00882 #ifdef PQXX_HAVE_PQFTABLE
00883 inline oid result::column_table(tuple::size_type ColNum) const
00884 {
00885   const oid T = PQftable(c_ptr(), ColNum);
00886 
00887   /* If we get oid_none, it may be because the column is computed, or because
00888    * we got an invalid row number.
00889    */
00890   // TODO: Skip this if we first computed the column name ourselves
00891   if ((T == oid_none) &&
00892       (ColNum >= columns()))
00893     throw PGSTD::invalid_argument("Attempt to retrieve table ID for column " +
00894                                   to_string(ColNum) + " "
00895                                   "out of " + to_string(columns()));
00896   return T;
00897 }
00898 #endif
00899 
00900 
00901 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00902   class field_streambuf :
00903 #ifdef PQXX_HAVE_STREAMBUF
00904   public PGSTD::basic_streambuf<CHAR, TRAITS>
00905 #else
00906   public PGSTD::streambuf
00907 #endif
00908 {
00909 public:
00910   typedef CHAR char_type;
00911   typedef TRAITS traits_type;
00912   typedef typename traits_type::int_type int_type;
00913 #ifdef PQXX_HAVE_STREAMBUF
00914   typedef typename traits_type::pos_type pos_type;
00915   typedef typename traits_type::off_type off_type;
00916 #else
00917   typedef streamoff off_type;
00918   typedef streampos pos_type;
00919 #endif
00920   typedef PGSTD::ios::openmode openmode;
00921   typedef PGSTD::ios::seekdir seekdir;
00922 
00923   explicit field_streambuf(const result::field &F) :                    //[t74]
00924     m_Field(F)
00925   {
00926     initialize();
00927   }
00928 
00929 #ifdef PQXX_HAVE_STREAMBUF
00930 protected:
00931 #endif
00932   virtual int sync() { return traits_type::eof(); }
00933 
00934 protected:
00935   virtual pos_type seekoff(off_type, seekdir, openmode)
00936   {
00937     return traits_type::eof();
00938   }
00939 
00940   virtual pos_type seekpos(pos_type, openmode) {return traits_type::eof();}
00941 
00942   virtual int_type overflow(int_type) { return traits_type::eof(); }
00943 
00944   virtual int_type underflow() { return traits_type::eof(); }
00945 
00946 private:
00947   const result::field &m_Field;
00948 
00949   int_type initialize()
00950   {
00951     char_type *G = 
00952       reinterpret_cast<char_type *>(const_cast<char *>(m_Field.c_str()));
00953     setg(G, G, G + m_Field.size());
00954     return m_Field.size();
00955   }
00956 };
00957 
00958 
00960 
00974 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00975   class basic_fieldstream :
00976 #ifdef PQXX_HAVE_STREAMBUF
00977     public PGSTD::basic_istream<CHAR, TRAITS>
00978 #else
00979     public PGSTD::istream
00980 #endif
00981 {
00982 #ifdef PQXX_HAVE_STREAMBUF
00983   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00984 #else
00985   typedef PGSTD::istream super;
00986 #endif
00987 
00988 public:
00989   typedef CHAR char_type;
00990   typedef TRAITS traits_type;
00991   typedef typename traits_type::int_type int_type;
00992   typedef typename traits_type::pos_type pos_type;
00993   typedef typename traits_type::off_type off_type;
00994 
00995   basic_fieldstream(const result::field &F) : super(&m_Buf), m_Buf(F) { }
00996 
00997 private:
00998   field_streambuf<CHAR, TRAITS> m_Buf;
00999 };
01000 
01001 typedef basic_fieldstream<char> fieldstream;
01002 
01003 } // namespace pqxx
01004 
01005 
01006 
01007 /* 
01008 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More 
01009 Effective C++", points out that it is good style to have any class containing 
01010 a member of pointer type define its own destructor--just to show that it knows
01011 what it is doing.  This helps prevent nasty memory leak / double deletion bugs
01012 typically resulting from programmers' omission to deal with such issues in
01013 their destructors.
01014 
01015 The -Weffc++ option in gcc generates warnings for noncompliance with Scott's
01016 style guidelines, and hence necessitates the definition of this destructor,\
01017 trivial as it may be.
01018 
01019 [2] IIRC Alex Stepanov, the inventor of the STL, once remarked that having
01020 this as standard behaviour for pointers would be useful in some algorithms.
01021 So even if this makes me look foolish, I would seem to be in distinguished 
01022 company.
01023 */
01024 
01025 

Generated on Mon Nov 1 19:13:36 2004 for libpqxx by  doxygen 1.3.9.1