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-2006, 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 #include "pqxx/compiler-public.hxx"
00020 #include "pqxx/compiler-internal-pre.hxx"
00021 
00022 #ifdef PQXX_HAVE_IOS
00023 #include <ios>
00024 #endif
00025 
00026 #include <stdexcept>
00027 
00028 #include "pqxx/util"
00029 
00030 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
00031  */
00032 
00033 // TODO: Support SQL arrays
00034 
00035 namespace pqxx
00036 {
00037 class result;
00038 
00039 namespace internal
00040 {
00042 struct PQXX_PRIVATE result_data
00043 {
00045 
00048   pqxx::internal::pq::PGresult *data;
00049 
00051   int protocol;
00052 
00054   PGSTD::string query;
00055 
00056   // TODO: Locking for result copy-construction etc. also goes here
00057 
00058   result_data();
00059   result_data(pqxx::internal::pq::PGresult *, int, const PGSTD::string &);
00060   ~result_data();
00061 };
00062 
00063 void freemem_result_data(result_data *) throw ();
00064 template<> inline
00065 void PQAlloc<result_data>::freemem() throw () { freemem_result_data(m_Obj); }
00066 } // namespace internal
00067 
00068 
00070 
00090 class PQXX_LIBEXPORT result : private internal::PQAlloc<internal::result_data>
00091 {
00092   typedef internal::PQAlloc<internal::result_data> super;
00093 public:
00094   class const_iterator;
00095   class const_fielditerator;
00096   class const_reverse_fielditerator;
00097   class tuple;
00098   class field;
00099   typedef unsigned long size_type;
00100   typedef signed long difference_type;
00101   typedef tuple reference;
00102   typedef const_iterator pointer;
00103 
00105 
00116   class PQXX_LIBEXPORT tuple
00117   {
00118   public:
00119     typedef unsigned int size_type;
00120     typedef signed int difference_type;
00121     typedef const_fielditerator const_iterator;
00122     typedef field reference;
00123     typedef const_fielditerator pointer;
00124     typedef const_reverse_fielditerator const_reverse_iterator;
00125 
00126     tuple(const result *r, result::size_type i) throw () :
00127       m_Home(r), m_Index(i) {}
00128     ~tuple() throw () {} // Yes Scott Meyers, you're absolutely right[1]
00129 
00134     bool operator==(const tuple &) const throw ();                      //[t75]
00135     bool operator!=(const tuple &rhs) const throw ()                    //[t75]
00136         { return !operator==(rhs); }
00138 
00139     const_iterator begin() const throw ()                               //[t82]
00140         { return const_iterator(*this, 0); }
00141     const_iterator end() const throw ()                                 //[t82]
00142         { return const_iterator(*this, size()); }
00143 
00148     reference front() const throw () { return field(*this, 0); }        //[t74]
00149     reference back() const throw () { return field(*this, size()-1); }  //[t75]
00150 
00151     const_reverse_fielditerator rbegin() const;                         //[t82]
00152     const_reverse_fielditerator rend() const;                           //[t82]
00153 
00154     reference operator[](size_type i) const throw ()                    //[t11]
00155         { return field(*this, i); }
00156     reference operator[](int i) const throw ()                          //[t2]
00157         { return operator[](size_type(i)); }
00158     reference operator[](const char[]) const;                           //[t11]
00159     reference operator[](const PGSTD::string &s) const                  //[t11]
00160         { return operator[](s.c_str()); }
00161     reference at(size_type) const throw (PGSTD::out_of_range);          //[t11]
00162     reference at(int i) const throw (PGSTD::out_of_range)               //[t11]
00163         { return at(size_type(i)); }
00164     reference at(const char[]) const;                                   //[t11]
00165     reference at(const PGSTD::string &s) const                          //[t11]
00166         { return at(s.c_str()); }
00168 
00169     size_type size() const throw () { return m_Home->columns(); }       //[t11]
00170 
00171     void swap(tuple &) throw ();                                        //[t11]
00172 
00173     result::size_type rownumber() const throw () { return m_Index; }    //[t11]
00174 
00179 
00180     size_type column_number(const PGSTD::string &ColName) const         //[t30]
00181         { return m_Home->column_number(ColName); }
00182 
00184     size_type column_number(const char ColName[]) const                 //[t30]
00185         { return m_Home->column_number(ColName); }
00186 
00188     oid column_type(size_type ColNum) const                             //[t7]
00189         { return m_Home->column_type(ColNum); }
00190 
00192     oid column_type(int ColNum) const                                   //[t7]
00193         { return column_type(size_type(ColNum)); }
00194 
00196     oid column_type(const PGSTD::string &ColName) const                 //[t7]
00197         { return column_type(column_number(ColName)); }
00198 
00200     oid column_type(const char ColName[]) const                         //[t7]
00201         { return column_type(column_number(ColName)); }
00202 
00204 
00211     oid column_table(size_type ColNum) const                            //[t2]
00212         { return m_Home->column_table(ColNum); }
00214 
00221     oid column_table(int ColNum) const                                  //[t2]
00222         { return column_table(size_type(ColNum)); }
00224 
00231     oid column_table(const PGSTD::string &ColName) const                //[t2]
00232         { return column_table(column_number(ColName)); }
00233 
00235 
00245     size_type table_column(size_type ColNum) const                      //[t93]
00246         { return m_Home->table_column(ColNum); }
00247 
00249     size_type table_column(int ColNum) const                            //[t93]
00250         { return table_column(size_type(ColNum)); }
00251 
00253     size_type table_column(const PGSTD::string &ColName) const          //[t93]
00254         { return table_column(column_number(ColName)); }
00256 
00257     result::size_type num() const { return rownumber(); }               //[t1]
00258 
00259 
00260   protected:
00261     friend class field;
00262     const result *m_Home;
00263     result::size_type m_Index;
00264 
00265     // Not allowed:
00266     tuple();
00267   };
00268 
00270 
00273   class PQXX_LIBEXPORT field
00274   {
00275   public:
00276     typedef size_t size_type;
00277 
00279 
00283     field(const tuple &T, tuple::size_type C) throw () :                //[t1]
00284         m_tup(T), m_col(C) {}
00285 
00290 
00291 
00307     bool operator==(const field &) const;                               //[t75]
00308 
00310 
00312     bool operator!=(const field &rhs) const {return !operator==(rhs);}  //[t82]
00314 
00319 
00320     const char *name() const { return home()->column_name(col()); }     //[t11]
00321 
00323     oid type() const { return home()->column_type(col()); }             //[t7]
00324 
00326 
00333     oid table() const { return home()->column_table(col()); }           //[t2]
00334 
00335     tuple::size_type num() const { return col(); }                      //[t82]
00336 
00338     tuple::size_type table_column() const                               //[t93]
00339         { return home()->table_column(col()); }
00341 
00346 
00347 
00352     const char *c_str() const { return home()->GetValue(idx(),col()); } //[t2]
00353 
00355     template<typename T> bool to(T &Obj) const                          //[t3]
00356     {
00357       const char *const bytes = c_str();
00358       if (!bytes[0] && is_null()) return false;
00359       from_string(bytes, Obj);
00360       return true;
00361     }
00362 
00364     template<typename T> bool operator>>(T &Obj) const                  //[t7]
00365         { return to(Obj); }
00366 
00367 #ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00369     template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00370 
00372 
00375     template<> bool to<const char *>(const char *&Obj) const;
00376 #endif
00377 
00379     template<typename T> bool to(T &Obj, const T &Default) const        //[t12]
00380     {
00381       const bool NotNull = to(Obj);
00382       if (!NotNull) Obj = Default;
00383       return NotNull;
00384     }
00385 
00387 
00390     template<typename T> T as(const T &Default) const                   //[t1]
00391     {
00392       T Obj;
00393       to(Obj, Default);
00394       return Obj;
00395     }
00396 
00398     template<typename T> T as() const                                   //[t45]
00399     {
00400       T Obj;
00401       const bool NotNull = to(Obj);
00402       if (!NotNull) throw PGSTD::domain_error("Attempt to read null field");
00403       return Obj;
00404     }
00405 
00406     bool is_null() const { return home()->GetIsNull(idx(), col()); }    //[t12]
00407     size_type size() const throw ()                                     //[t11]
00408         { return home()->GetLength(idx(),col()); }
00410 
00411 
00412   private:
00413     const result *home() const throw () { return m_tup.m_Home; }
00414     result::size_type idx() const throw () { return m_tup.m_Index; }
00415 
00416   protected:
00417     tuple::size_type col() const throw () { return m_col; }
00418     tuple m_tup;
00419     tuple::size_type m_col;
00420   };
00421 
00422   typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
00423                            const tuple,
00424                            result::difference_type,
00425                            const_iterator,
00426                            tuple>
00427         const_iterator_base;
00428 
00430 
00434   class PQXX_LIBEXPORT const_iterator :
00435     public const_iterator_base,
00436     public tuple
00437   {
00438   public:
00439     typedef const tuple *pointer;
00440     typedef tuple reference;
00441     typedef result::size_type size_type;
00442     typedef result::difference_type difference_type;
00443 
00444     const_iterator() throw () : tuple(0,0) {}
00445     const_iterator(const tuple &t) throw () : tuple(t) {}
00446 
00462     pointer operator->() const { return this; }                         //[t12]
00463     reference operator*() const { return tuple(*this); }                //[t12]
00465 
00470     const_iterator operator++(int);                                     //[t12]
00471     const_iterator &operator++() { ++m_Index; return *this; }           //[t1]
00472     const_iterator operator--(int);                                     //[t12]
00473     const_iterator &operator--() { --m_Index; return *this; }           //[t12]
00474 
00475     const_iterator &operator+=(difference_type i)                       //[t12]
00476         { m_Index+=i; return *this; }
00477     const_iterator &operator-=(difference_type i)                       //[t12]
00478         { m_Index-=i; return *this; }
00480 
00485     bool operator==(const const_iterator &i) const                      //[t12]
00486         {return m_Index==i.m_Index;}
00487     bool operator!=(const const_iterator &i) const                      //[t12]
00488         {return m_Index!=i.m_Index;}
00489     bool operator<(const const_iterator &i) const                       //[t12]
00490         {return m_Index<i.m_Index;}
00491     bool operator<=(const const_iterator &i) const                      //[t12]
00492         {return m_Index<=i.m_Index;}
00493     bool operator>(const const_iterator &i) const                       //[t12]
00494         {return m_Index>i.m_Index;}
00495     bool operator>=(const const_iterator &i) const                      //[t12]
00496         {return m_Index>=i.m_Index;}
00498 
00503     inline const_iterator operator+(difference_type) const;             //[t12]
00504     friend const_iterator
00505     operator+(difference_type, const_iterator);                         //[t12]
00506     inline const_iterator operator-(difference_type) const;             //[t12]
00507     inline difference_type operator-(const_iterator) const;             //[t12]
00509 
00510   private:
00511     friend class pqxx::result;
00512     const_iterator(const pqxx::result *r, result::size_type i) throw () :
00513         tuple(r, i) {}
00514   };
00515 
00516   class PQXX_LIBEXPORT const_reverse_iterator : private const_iterator
00517   {
00518   public:
00519     typedef pqxx::result::const_iterator super;
00520     typedef pqxx::result::const_iterator iterator_type;
00521     using iterator_type::iterator_category;
00522     using iterator_type::difference_type;
00523     using iterator_type::pointer;
00524 #ifndef _MSC_VER
00525     using iterator_type::value_type;
00526     using iterator_type::reference;
00527 #else
00528     // Workaround for Visual C++.NET 2003, which has access problems
00529     typedef const tuple &reference;
00530     typedef tuple value_type;
00531 #endif
00532 
00533     const_reverse_iterator(const const_reverse_iterator &rhs) :         //[t75]
00534       const_iterator(rhs) {}
00535     explicit const_reverse_iterator(const const_iterator &rhs) :        //[t75]
00536       const_iterator(rhs) { super::operator--(); }
00537 
00538     iterator_type base() const throw ();                                //[t75]
00539 
00544     using const_iterator::operator->;                                   //[t75]
00545     using const_iterator::operator*;                                    //[t75]
00547 
00552     const_reverse_iterator &operator=(const const_reverse_iterator &r)  //[t75]
00553         { iterator_type::operator=(r); return *this; }
00554     const_reverse_iterator operator++()                                 //[t75]
00555         { iterator_type::operator--(); return *this; }
00556     const_reverse_iterator operator++(int);                             //[t75]
00557     const_reverse_iterator &operator--()                                //[t75]
00558         { iterator_type::operator++(); return *this; }
00559     const_reverse_iterator operator--(int);                             //[t75]
00560     const_reverse_iterator &operator+=(difference_type i)               //[t75]
00561         { iterator_type::operator-=(i); return *this; }
00562     const_reverse_iterator &operator-=(difference_type i)               //[t75]
00563         { iterator_type::operator+=(i); return *this; }
00565 
00570     const_reverse_iterator operator+(difference_type i) const           //[t75]
00571         { return const_reverse_iterator(base()-i); }
00572     const_reverse_iterator operator-(difference_type i)                 //[t75]
00573         { return const_reverse_iterator(base()+i); }
00574     difference_type operator-(const const_reverse_iterator &rhs) const  //[t75]
00575         { return rhs.const_iterator::operator-(*this); }
00577 
00582     bool operator==(const const_reverse_iterator &rhs) const throw ()   //[t75]
00583         { return iterator_type::operator==(rhs); }
00584     bool operator!=(const const_reverse_iterator &rhs) const throw ()   //[t75]
00585         { return !operator==(rhs); }
00586 
00587     bool operator<(const const_reverse_iterator &rhs) const             //[t75]
00588         { return iterator_type::operator>(rhs); }
00589     bool operator<=(const const_reverse_iterator &rhs) const            //[t75]
00590         { return iterator_type::operator>=(rhs); }
00591     bool operator>(const const_reverse_iterator &rhs) const             //[t75]
00592         { return iterator_type::operator<(rhs); }
00593     bool operator>=(const const_reverse_iterator &rhs) const            //[t75]
00594         { return iterator_type::operator<=(rhs); }
00596   };
00597 
00598   class PQXX_LIBEXPORT const_fielditerator :
00599     public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00600                            const field,
00601                            tuple::size_type>,
00602     public field
00603   {
00604     typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
00605                                   const field,
00606                                   tuple::size_type> it;
00607   public:
00608     using it::pointer;
00609     typedef tuple::size_type size_type;
00610     typedef tuple::difference_type difference_type;
00611     typedef field reference;
00612 
00613     const_fielditerator(const tuple &T, tuple::size_type C) throw () :  //[t82]
00614       field(T, C) {}
00615     const_fielditerator(const field &F) throw () : field(F) {}          //[t82]
00616 
00621     pointer operator->() const { return this; }                         //[t82]
00622     reference operator*() const { return field(*this); }                //[t82]
00624 
00629     const_fielditerator operator++(int);                                //[t82]
00630     const_fielditerator &operator++() { ++m_col; return *this; }        //[t82]
00631     const_fielditerator operator--(int);                                //[t82]
00632     const_fielditerator &operator--() { --m_col; return *this; }        //[t82]
00633 
00634     const_fielditerator &operator+=(difference_type i)                  //[t82]
00635         { m_col+=i; return *this; }
00636     const_fielditerator &operator-=(difference_type i)                  //[t82]
00637         { m_col-=i; return *this; }
00639 
00644     bool operator==(const const_fielditerator &i) const                 //[t82]
00645         {return col()==i.col();}
00646     bool operator!=(const const_fielditerator &i) const                 //[t82]
00647         {return col()!=i.col();}
00648     bool operator<(const const_fielditerator &i) const                  //[t82]
00649         {return col()<i.col();}
00650     bool operator<=(const const_fielditerator &i) const                 //[t82]
00651         {return col()<=i.col();}
00652     bool operator>(const const_fielditerator &i) const                  //[t82]
00653         {return col()>i.col();}
00654     bool operator>=(const const_fielditerator &i) const                 //[t82]
00655         {return col()>=i.col();}
00657 
00662     inline const_fielditerator operator+(difference_type) const;        //[t82]
00663 
00664     friend const_fielditerator operator+(difference_type,
00665                                           const_fielditerator);         //[t82]
00666 
00667     inline const_fielditerator operator-(difference_type) const;        //[t82]
00668     inline difference_type operator-(const_fielditerator) const;        //[t82]
00670   };
00671 
00672   class PQXX_LIBEXPORT const_reverse_fielditerator : private const_fielditerator
00673   {
00674   public:
00675     typedef const_fielditerator super;
00676     typedef const_fielditerator iterator_type;
00677     using iterator_type::iterator_category;
00678     using iterator_type::difference_type;
00679     using iterator_type::pointer;
00680 #ifndef _MSC_VER
00681     using iterator_type::value_type;
00682     using iterator_type::reference;
00683 #else
00684     // Workaround for Visual C++.NET 2003, which has access problems
00685     typedef field value_type;
00686     typedef const field &reference;
00687 #endif
00688 
00689     const_reverse_fielditerator(const const_reverse_fielditerator &r) : //[t82]
00690       const_fielditerator(r) {}
00691     explicit
00692       const_reverse_fielditerator(const super &rhs) throw() :           //[t82]
00693         const_fielditerator(rhs) { super::operator--(); }
00694 
00695     iterator_type base() const throw ();                                //[t82]
00696 
00701     using iterator_type::operator->;                                    //[t82]
00702     using iterator_type::operator*;                                     //[t82]
00704 
00709     const_reverse_fielditerator &
00710       operator=(const const_reverse_fielditerator &r)                   //[t82]
00711         { iterator_type::operator=(r); return *this; }
00712     const_reverse_fielditerator operator++()                            //[t82]
00713         { iterator_type::operator--(); return *this; }
00714     const_reverse_fielditerator operator++(int);                        //[t82]
00715     const_reverse_fielditerator &operator--()                           //[t82]
00716         { iterator_type::operator++(); return *this; }
00717     const_reverse_fielditerator operator--(int);                        //[t82]
00718     const_reverse_fielditerator &operator+=(difference_type i)          //[t82]
00719         { iterator_type::operator-=(i); return *this; }
00720     const_reverse_fielditerator &operator-=(difference_type i)          //[t82]
00721         { iterator_type::operator+=(i); return *this; }
00723 
00728     const_reverse_fielditerator operator+(difference_type i) const      //[t82]
00729         { return const_reverse_fielditerator(base()-i); }
00730     const_reverse_fielditerator operator-(difference_type i)            //[t82]
00731         { return const_reverse_fielditerator(base()+i); }
00732     difference_type
00733       operator-(const const_reverse_fielditerator &rhs) const           //[t82]
00734         { return rhs.const_fielditerator::operator-(*this); }
00736 
00741     bool
00742       operator==(const const_reverse_fielditerator &rhs) const throw () //[t82]
00743         { return iterator_type::operator==(rhs); }
00744     bool
00745       operator!=(const const_reverse_fielditerator &rhs) const throw () //[t82]
00746         { return !operator==(rhs); }
00747 
00748     bool operator<(const const_reverse_fielditerator &rhs) const        //[t82]
00749         { return iterator_type::operator>(rhs); }
00750     bool operator<=(const const_reverse_fielditerator &rhs) const       //[t82]
00751         { return iterator_type::operator>=(rhs); }
00752     bool operator>(const const_reverse_fielditerator &rhs) const        //[t82]
00753         { return iterator_type::operator<(rhs); }
00754     bool operator>=(const const_reverse_fielditerator &rhs) const       //[t82]
00755         { return iterator_type::operator<=(rhs); }
00757   };
00758 
00759 
00760   result() throw () : super(), m_data(0) {}                             //[t3]
00761   result(const result &rhs) throw () :                                  //[t1]
00762         super(rhs), m_data(rhs.m_data) {}
00763 
00764   result &operator=(const result &rhs) throw ()                         //[t10]
00765         { super::operator=(rhs); m_data=rhs.m_data; return *this; }
00766 
00771   bool operator==(const result &) const throw ();                       //[t70]
00772   bool operator!=(const result &rhs) const throw ()                     //[t70]
00773         { return !operator==(rhs); }
00775 
00776   const_reverse_iterator rbegin() const                                 //[t75]
00777         { return const_reverse_iterator(end()); }
00778   const_reverse_iterator rend() const                                   //[t75]
00779         { return const_reverse_iterator(begin()); }
00780 
00781   const_iterator begin() const throw ()                                 //[t1]
00782         { return const_iterator(this, 0); }
00783   inline const_iterator end() const throw ();                           //[t1]
00784 
00785   reference front() const throw () { return tuple(this,0); }            //[t74]
00786   reference back() const throw () {return tuple(this,size()-1);}        //[t75]
00787 
00788   size_type size() const throw ();                                      //[t2]
00789   bool empty() const throw ();                                          //[t11]
00790   size_type capacity() const throw () { return size(); }                //[t20]
00791 
00792   void swap(result &) throw ();                                         //[t77]
00793 
00794   const tuple operator[](size_type i) const throw ()                    //[t2]
00795         { return tuple(this, i); }
00796   const tuple at(size_type) const throw (PGSTD::out_of_range);          //[t10]
00797 
00798   void clear() throw () { super::clear(); m_data = 0; }                 //[t20]
00799 
00804 
00805   tuple::size_type columns() const throw ();                            //[t11]
00806 
00808   tuple::size_type column_number(const char ColName[]) const;           //[t11]
00809 
00811   tuple::size_type column_number(const PGSTD::string &Name) const       //[t11]
00812         {return column_number(Name.c_str());}
00813 
00815   const char *column_name(tuple::size_type Number) const;               //[t11]
00816 
00818   oid column_type(tuple::size_type ColNum) const;                       //[t7]
00820   oid column_type(int ColNum) const                                     //[t7]
00821         { return column_type(tuple::size_type(ColNum)); }
00822 
00824   oid column_type(const PGSTD::string &ColName) const                   //[t7]
00825         { return column_type(column_number(ColName)); }
00826 
00828   oid column_type(const char ColName[]) const                           //[t7]
00829         { return column_type(column_number(ColName)); }
00830 
00832 
00839   oid column_table(tuple::size_type ColNum) const;                      //[t2]
00840 
00842 
00849   oid column_table(int ColNum) const                                    //[t2]
00850         { return column_table(tuple::size_type(ColNum)); }
00851 
00853 
00860   oid column_table(const PGSTD::string &ColName) const                  //[t2]
00861         { return column_table(column_number(ColName)); }
00862 
00864   tuple::size_type table_column(tuple::size_type ColNum) const;         //[t93]
00865 
00867   tuple::size_type table_column(int ColNum) const                       //[t93]
00868         { return table_column(tuple::size_type(ColNum)); }
00869 
00871   tuple::size_type table_column(const PGSTD::string &ColName) const     //[t93]
00872         { return table_column(column_number(ColName)); }
00874 
00876   const PGSTD::string &query() const throw ();                          //[t70]
00877 
00879 
00882   oid inserted_oid() const;                                             //[t13]
00883 
00884 
00886 
00889   size_type affected_rows() const;                                      //[t7]
00890 
00891 
00892 private:
00893   friend class pqxx::result::field;
00894   const char *GetValue(size_type Row, tuple::size_type Col) const;
00895   bool GetIsNull(size_type Row, tuple::size_type Col) const;
00896   field::size_type GetLength(size_type, tuple::size_type) const;
00897 
00898   friend class connection_base;
00899   friend class pipeline;
00900   result(internal::pq::PGresult *rhs,
00901         int protocol,
00902         const PGSTD::string &Query=PGSTD::string());
00903   bool operator!() const throw () { return !m_data; }
00904   operator bool() const throw () { return m_data != 0; }
00905 
00906   void PQXX_PRIVATE CheckStatus() const;
00907 
00908   void PQXX_PRIVATE ThrowSQLError(const PGSTD::string &Err,
00909         const PGSTD::string &Query) const;
00910   int PQXX_PRIVATE errorposition() const throw ();
00911   PGSTD::string PQXX_PRIVATE StatusError() const;
00912 
00913   friend class Cursor;  // deprecated
00914   friend class cursor_base;
00915   const char *CmdStatus() const throw ();
00916 
00918   pqxx::internal::pq::PGresult *m_data;
00919 
00920   static const PGSTD::string PQXX_PRIVATE s_empty_string;
00921 };
00922 
00923 
00925 
00945 template<typename STREAM>
00946 inline STREAM &operator<<(STREAM &S, const pqxx::result::field &F)      //[t46]
00947 {
00948   S.write(F.c_str(), F.size());
00949   return S;
00950 }
00951 
00952 
00954 template<typename T>
00955 inline void from_string(const result::field &F, T &Obj)                 //[t46]
00956         { from_string(F.c_str(), Obj, F.size()); }
00957 
00959 template<>
00960 inline PGSTD::string to_string(const result::field &Obj)                //[t74]
00961         { return PGSTD::string(Obj.c_str(), Obj.size()); }
00962 
00963 
00965 template<>
00966 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
00967 {
00968   const char *const bytes = c_str();
00969   if (!bytes[0] && is_null()) return false;
00970   Obj = PGSTD::string(bytes, size());
00971   return true;
00972 }
00973 
00975 
00980 template<>
00981 inline bool result::field::to<const char *>(const char *&Obj) const
00982 {
00983   if (is_null()) return false;
00984   Obj = c_str();
00985   return true;
00986 }
00987 
00988 
00989 inline result::tuple::const_reverse_iterator result::tuple::rbegin() const
00990         { return const_reverse_fielditerator(end()); }
00991 inline result::tuple::const_reverse_iterator result::tuple::rend() const
00992         { return const_reverse_fielditerator(begin()); }
00993 
00994 inline result::const_iterator
00995 result::const_iterator::operator+(difference_type o) const
00996         { return const_iterator(m_Home, m_Index + o); }
00997 
00998 inline result::const_iterator
00999 operator+(result::const_iterator::difference_type o, result::const_iterator i)
01000         { return i + o; }
01001 
01002 inline result::const_iterator
01003 result::const_iterator::operator-(difference_type o) const
01004         { return const_iterator(m_Home, m_Index - o); }
01005 
01006 inline result::const_iterator::difference_type
01007 result::const_iterator::operator-(const_iterator i) const
01008         { return num()-i.num(); }
01009 
01010 inline result::const_iterator result::end() const throw ()
01011         { return const_iterator(this, size()); }
01012 
01013 
01014 inline result::const_reverse_iterator
01015 operator+(result::const_reverse_iterator::difference_type n,
01016           const result::const_reverse_iterator &i)
01017         { return result::const_reverse_iterator(i.base() - n); }
01018 
01019 inline result::const_fielditerator
01020 result::const_fielditerator::operator+(difference_type o) const
01021         { return const_fielditerator(m_tup, col() + o); }
01022 
01023 inline result::const_fielditerator
01024 operator+(result::const_fielditerator::difference_type o,
01025           result::const_fielditerator i)
01026         { return i + o; }
01027 
01028 inline result::const_fielditerator
01029 result::const_fielditerator::operator-(difference_type o) const
01030         { return const_fielditerator(m_tup, col() - o); }
01031 
01032 inline result::const_fielditerator::difference_type
01033 result::const_fielditerator::operator-(const_fielditerator i) const
01034         { return num()-i.num(); }
01035 
01036 
01037 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
01038   class field_streambuf :
01039 #ifdef PQXX_HAVE_STREAMBUF
01040   public PGSTD::basic_streambuf<CHAR, TRAITS>
01041 #else
01042   public PGSTD::streambuf
01043 #endif
01044 {
01045 public:
01046   typedef CHAR char_type;
01047   typedef TRAITS traits_type;
01048   typedef typename traits_type::int_type int_type;
01049 #ifdef PQXX_HAVE_STREAMBUF
01050   typedef typename traits_type::pos_type pos_type;
01051   typedef typename traits_type::off_type off_type;
01052 #else
01053   typedef streamoff off_type;
01054   typedef streampos pos_type;
01055 #endif
01056   typedef PGSTD::ios::openmode openmode;
01057   typedef PGSTD::ios::seekdir seekdir;
01058 
01059   explicit field_streambuf(const result::field &F) :                    //[t74]
01060     m_Field(F)
01061   {
01062     initialize();
01063   }
01064 
01065 #ifdef PQXX_HAVE_STREAMBUF
01066 protected:
01067 #endif
01068   virtual int sync() { return traits_type::eof(); }
01069 
01070 protected:
01071   virtual pos_type seekoff(off_type, seekdir, openmode)
01072         { return traits_type::eof(); }
01073   virtual pos_type seekpos(pos_type, openmode) {return traits_type::eof();}
01074   virtual int_type overflow(int_type) { return traits_type::eof(); }
01075   virtual int_type underflow() { return traits_type::eof(); }
01076 
01077 private:
01078   const result::field &m_Field;
01079 
01080   int_type initialize()
01081   {
01082     char_type *G =
01083       reinterpret_cast<char_type *>(const_cast<char *>(m_Field.c_str()));
01084     setg(G, G, G + m_Field.size());
01085     return m_Field.size();
01086   }
01087 };
01088 
01089 
01091 
01099 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
01100   class basic_fieldstream :
01101 #ifdef PQXX_HAVE_STREAMBUF
01102     public PGSTD::basic_istream<CHAR, TRAITS>
01103 #else
01104     public PGSTD::istream
01105 #endif
01106 {
01107 #ifdef PQXX_HAVE_STREAMBUF
01108   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
01109 #else
01110   typedef PGSTD::istream super;
01111 #endif
01112 
01113 public:
01114   typedef CHAR char_type;
01115   typedef TRAITS traits_type;
01116   typedef typename traits_type::int_type int_type;
01117   typedef typename traits_type::pos_type pos_type;
01118   typedef typename traits_type::off_type off_type;
01119 
01120   basic_fieldstream(const result::field &F) : super(0), m_Buf(F)
01121         { super::init(&m_Buf); }
01122 
01123 private:
01124   field_streambuf<CHAR, TRAITS> m_Buf;
01125 };
01126 
01127 typedef basic_fieldstream<char> fieldstream;
01128 
01129 } // namespace pqxx
01130 
01131 
01132 
01133 /*
01134 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More
01135 Effective C++", points out that it is good style to have any class containing
01136 a member of pointer type define a destructor--just to show that it knows what it
01137 is doing with the pointer.  This helps prevent nasty memory leak / double
01138 deletion bugs typically resulting from programmers' omission to deal with such
01139 issues in their destructors.
01140 
01141 The @c -Weffc++ option in gcc generates warnings for noncompliance with Scott's
01142 style guidelines, and hence necessitates the definition of this destructor,
01143 trivial as it may be.
01144 */
01145 
01146 
01147 #include "pqxx/compiler-internal-post.hxx"

Generated on Thu Feb 1 17:12:08 2007 for libpqxx by  doxygen 1.5.1