# 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"