# result.hxx

    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-2008, 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 #ifndef PQXX_H_RESULT
    00020 #define PQXX_H_RESULT
    00021
    00022 #include "pqxx/compiler-public.hxx"
    00023 #include "pqxx/compiler-internal-pre.hxx"
    00024
    00025 #ifdef PQXX_HAVE_IOS
    00026 #include <ios>
    00027 #endif
    00028
    00029 #include <stdexcept>
    00030
    00031 #include "pqxx/except"
    00032 #include "pqxx/util"
    00033
    00034 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
    00035  */
    00036
    00037 // TODO: Support SQL arrays
    00038
    00039 namespace pqxx
    00040 {
    00041 class result;
    00042
    00043 namespace internal
    00044 {
    00045 class sql_cursor;
    00046
    00048 struct PQXX_PRIVATE result_data
    00049 {
    00051
    00054   pqxx::internal::pq::PGresult *data;
    00055
    00057   int protocol;
    00058
    00060   PGSTD::string query;
    00061
    00062   int encoding_code;
    00063
    00064   // TODO: Locking for result copy-construction etc. also goes here
    00065
    00066   result_data();
    00067   result_data(pqxx::internal::pq::PGresult *,
    00068                 int protocol,
    00069                 const PGSTD::string &,
    00070                 int encoding_code);
    00071   ~result_data();
    00072 };
    00073
    00074 void PQXX_LIBEXPORT freemem_result_data(result_data *) throw ();
    00075 template<> inline
    00076 void PQAlloc<result_data>::freemem() throw () { freemem_result_data(m_Obj); }
    00077 } // namespace internal
    00078
    00079
    00081
    00101 class PQXX_LIBEXPORT result : private internal::PQAlloc<internal::result_data>
    00102 {
    00103   typedef internal::PQAlloc<internal::result_data> super;
    00104 public:
    00105   class const_iterator;
    00106   class const_fielditerator;
    00107   class const_reverse_fielditerator;
    00108   class tuple;
    00109   class field;
    00110   typedef unsigned long size_type;
    00111   typedef signed long difference_type;
    00112   typedef tuple reference;
    00113   typedef const_iterator pointer;
    00114
    00116
    00127   class PQXX_LIBEXPORT tuple
    00128   {
    00129   public:
    00130     typedef unsigned int size_type;
    00131     typedef signed int difference_type;
    00132     typedef const_fielditerator const_iterator;
    00133     typedef field reference;
    00134     typedef const_fielditerator pointer;
    00135     typedef const_reverse_fielditerator const_reverse_iterator;
    00136
    00137     tuple(const result *r, result::size_type i) throw () :
    00138       m_Home(r), m_Index(i) {}
    00139     ~tuple() throw () {} // Yes Scott Meyers, you're absolutely right[1]
    00140
    00145     bool operator==(const tuple &) const throw ();                      //[t75]
    00146     bool operator!=(const tuple &rhs) const throw ()                    //[t75]
    00147         { return !operator==(rhs); }
    00149
    00150     const_iterator begin() const throw ()                               //[t82]
    00151         { return const_iterator(*this, 0); }
    00152     const_iterator end() const throw ()                                 //[t82]
    00153         { return const_iterator(*this, size()); }
    00154
    00159     reference front() const throw () { return field(*this, 0); }        //[t74]
    00160     reference back() const throw () { return field(*this, size()-1); }  //[t75]
    00161
    00162     const_reverse_fielditerator rbegin() const;                         //[t82]
    00163     const_reverse_fielditerator rend() const;                           //[t82]
    00164
    00165     reference operator[](size_type i) const throw ()                    //[t11]
    00166         { return field(*this, i); }
    00167     reference operator[](int i) const throw ()                          //[t2]
    00168         { return operator[](size_type(i)); }
    00169     reference operator[](const char[]) const;                           //[t11]
    00170     reference operator[](const PGSTD::string &s) const                  //[t11]
    00171         { return operator[](s.c_str()); }
    00172     reference at(size_type) const throw (range_error);                  //[t11]
    00173     reference at(int i) const throw (range_error)                       //[t11]
    00174         { return at(size_type(i)); }
    00175     reference at(const char[]) const;                                   //[t11]
    00176     reference at(const PGSTD::string &s) const                          //[t11]
    00177         { return at(s.c_str()); }
    00179
    00180     size_type size() const throw () { return m_Home->columns(); }       //[t11]
    00181
    00182     void swap(tuple &) throw ();                                        //[t11]
    00183
    00184     result::size_type rownumber() const throw () { return m_Index; }    //[t11]
    00185
    00190
    00191     size_type column_number(const PGSTD::string &ColName) const         //[t30]
    00192         { return m_Home->column_number(ColName); }
    00193
    00195     size_type column_number(const char ColName[]) const                 //[t30]
    00196         { return m_Home->column_number(ColName); }
    00197
    00199     oid column_type(size_type ColNum) const                             //[t7]
    00200         { return m_Home->column_type(ColNum); }
    00201
    00203     oid column_type(int ColNum) const                                   //[t7]
    00204         { return column_type(size_type(ColNum)); }
    00205
    00207     oid column_type(const PGSTD::string &ColName) const                 //[t7]
    00208         { return column_type(column_number(ColName)); }
    00209
    00211     oid column_type(const char ColName[]) const                         //[t7]
    00212         { return column_type(column_number(ColName)); }
    00213
    00215
    00222     oid column_table(size_type ColNum) const                            //[t2]
    00223         { return m_Home->column_table(ColNum); }
    00225
    00232     oid column_table(int ColNum) const                                  //[t2]
    00233         { return column_table(size_type(ColNum)); }
    00235
    00242     oid column_table(const PGSTD::string &ColName) const                //[t2]
    00243         { return column_table(column_number(ColName)); }
    00244
    00246
    00256     size_type table_column(size_type ColNum) const                      //[t93]
    00257         { return m_Home->table_column(ColNum); }
    00258
    00260     size_type table_column(int ColNum) const                            //[t93]
    00261         { return table_column(size_type(ColNum)); }
    00262
    00264     size_type table_column(const PGSTD::string &ColName) const          //[t93]
    00265         { return table_column(column_number(ColName)); }
    00267
    00268     result::size_type num() const { return rownumber(); }               //[t1]
    00269
    00270
    00271   protected:
    00272     friend class field;
    00273     const result *m_Home;
    00274     result::size_type m_Index;
    00275
    00276     // Not allowed:
    00277     tuple();
    00278   };
    00279
    00281
    00284   class PQXX_LIBEXPORT field
    00285   {
    00286   public:
    00287     typedef size_t size_type;
    00288
    00290
    00294     field(const tuple &T, tuple::size_type C) throw () :                //[t1]
    00295         m_tup(T), m_col(C) {}
    00296
    00301
    00302
    00318     bool operator==(const field &) const;                               //[t75]
    00319
    00321
    00323     bool operator!=(const field &rhs) const {return !operator==(rhs);}  //[t82]
    00325
    00330
    00331     const char *name() const { return home()->column_name(col()); }     //[t11]
    00332
    00334     oid type() const { return home()->column_type(col()); }             //[t7]
    00335
    00337
    00344     oid table() const { return home()->column_table(col()); }           //[t2]
    00345
    00346     tuple::size_type num() const { return col(); }                      //[t82]
    00347
    00349     tuple::size_type table_column() const                               //[t93]
    00350         { return home()->table_column(col()); }
    00352
    00357
    00358
    00363     const char *c_str() const { return home()->GetValue(idx(),col()); } //[t2]
    00364
    00366     template<typename T> bool to(T &Obj) const                          //[t3]
    00367     {
    00368       const char *const bytes = c_str();
    00369       if (!bytes[0] && is_null()) return false;
    00370       from_string(bytes, Obj);
    00371       return true;
    00372     }
    00373
    00375     template<typename T> bool operator>>(T &Obj) const                  //[t7]
    00376         { return to(Obj); }
    00377
    00378 #ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
    00380     template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
    00381
    00383
    00386     template<> bool to<const char *>(const char *&Obj) const;
    00387 #endif
    00388
    00390     template<typename T> bool to(T &Obj, const T &Default) const        //[t12]
    00391     {
    00392       const bool NotNull = to(Obj);
    00393       if (!NotNull) Obj = Default;
    00394       return NotNull;
    00395     }
    00396
    00398
    00401     template<typename T> T as(const T &Default) const                   //[t1]
    00402     {
    00403       T Obj;
    00404       to(Obj, Default);
    00405       return Obj;
    00406     }
    00407
    00409     template<typename T> T as() const                                   //[t45]
    00410     {
    00411       T Obj;
    00412       const bool NotNull = to(Obj);
    00413       if (!NotNull) Obj = string_traits<T>::null();
    00414       return Obj;
    00415     }
    00416
    00417     bool is_null() const { return home()->GetIsNull(idx(), col()); }    //[t12]
    00418     size_type size() const throw ()                                     //[t11]
    00419         { return home()->GetLength(idx(),col()); }
    00421
    00422
    00423   private:
    00424     const result *home() const throw () { return m_tup.m_Home; }
    00425     result::size_type idx() const throw () { return m_tup.m_Index; }
    00426
    00427   protected:
    00428     tuple::size_type col() const throw () { return m_col; }
    00429     tuple m_tup;
    00430     tuple::size_type m_col;
    00431   };
    00432
    00433   typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
    00434                            const tuple,
    00435                            result::difference_type,
    00436                            const_iterator,
    00437                            tuple>
    00438         const_iterator_base;
    00439
    00441
    00445   class PQXX_LIBEXPORT const_iterator :
    00446     public const_iterator_base,
    00447     public tuple
    00448   {
    00449   public:
    00450     typedef const tuple *pointer;
    00451     typedef tuple reference;
    00452     typedef result::size_type size_type;
    00453     typedef result::difference_type difference_type;
    00454
    00455     const_iterator() throw () : tuple(0,0) {}
    00456     const_iterator(const tuple &t) throw () : tuple(t) {}
    00457
    00473     pointer operator->() const { return this; }                         //[t12]
    00474     reference operator*() const { return tuple(*this); }                //[t12]
    00476
    00481     const_iterator operator++(int);                                     //[t12]
    00482     const_iterator &operator++() { ++m_Index; return *this; }           //[t1]
    00483     const_iterator operator--(int);                                     //[t12]
    00484     const_iterator &operator--() { --m_Index; return *this; }           //[t12]
    00485
    00486     const_iterator &operator+=(difference_type i)                       //[t12]
    00487         { m_Index+=i; return *this; }
    00488     const_iterator &operator-=(difference_type i)                       //[t12]
    00489         { m_Index-=i; return *this; }
    00491
    00496     bool operator==(const const_iterator &i) const                      //[t12]
    00497         {return m_Index==i.m_Index;}
    00498     bool operator!=(const const_iterator &i) const                      //[t12]
    00499         {return m_Index!=i.m_Index;}
    00500     bool operator<(const const_iterator &i) const                       //[t12]
    00501         {return m_Index<i.m_Index;}
    00502     bool operator<=(const const_iterator &i) const                      //[t12]
    00503         {return m_Index<=i.m_Index;}
    00504     bool operator>(const const_iterator &i) const                       //[t12]
    00505         {return m_Index>i.m_Index;}
    00506     bool operator>=(const const_iterator &i) const                      //[t12]
    00507         {return m_Index>=i.m_Index;}
    00509
    00514     inline const_iterator operator+(difference_type) const;             //[t12]
    00515     friend const_iterator
    00516     operator+(difference_type, const_iterator);                         //[t12]
    00517     inline const_iterator operator-(difference_type) const;             //[t12]
    00518     inline difference_type operator-(const_iterator) const;             //[t12]
    00520
    00521   private:
    00522     friend class pqxx::result;
    00523     const_iterator(const pqxx::result *r, result::size_type i) throw () :
    00524         tuple(r, i) {}
    00525   };
    00526
    00527   class PQXX_LIBEXPORT const_reverse_iterator : private const_iterator
    00528   {
    00529   public:
    00530     typedef pqxx::result::const_iterator super;
    00531     typedef pqxx::result::const_iterator iterator_type;
    00532     using iterator_type::iterator_category;
    00533     using iterator_type::difference_type;
    00534     using iterator_type::pointer;
    00535 #ifndef _MSC_VER
    00536     using iterator_type::value_type;
    00537     using iterator_type::reference;
    00538 #else
    00539     // Workaround for Visual C++.NET 2003, which has access problems
    00540     typedef const tuple &reference;
    00541     typedef tuple value_type;
    00542 #endif
    00543
    00544     const_reverse_iterator(const const_reverse_iterator &rhs) :         //[t75]
    00545       const_iterator(rhs) {}
    00546     explicit const_reverse_iterator(const const_iterator &rhs) :        //[t75]
    00547       const_iterator(rhs) { super::operator--(); }
    00548
    00549     iterator_type base() const throw ();                                //[t75]
    00550
    00555     using const_iterator::operator->;                                   //[t75]
    00556     using const_iterator::operator*;                                    //[t75]
    00558
    00563     const_reverse_iterator &operator=(const const_reverse_iterator &r)  //[t75]
    00564         { iterator_type::operator=(r); return *this; }
    00565     const_reverse_iterator operator++()                                 //[t75]
    00566         { iterator_type::operator--(); return *this; }
    00567     const_reverse_iterator operator++(int);                             //[t75]
    00568     const_reverse_iterator &operator--()                                //[t75]
    00569         { iterator_type::operator++(); return *this; }
    00570     const_reverse_iterator operator--(int);                             //[t75]
    00571     const_reverse_iterator &operator+=(difference_type i)               //[t75]
    00572         { iterator_type::operator-=(i); return *this; }
    00573     const_reverse_iterator &operator-=(difference_type i)               //[t75]
    00574         { iterator_type::operator+=(i); return *this; }
    00576
    00581     const_reverse_iterator operator+(difference_type i) const           //[t75]
    00582         { return const_reverse_iterator(base()-i); }
    00583     const_reverse_iterator operator-(difference_type i)                 //[t75]
    00584         { return const_reverse_iterator(base()+i); }
    00585     difference_type operator-(const const_reverse_iterator &rhs) const  //[t75]
    00586         { return rhs.const_iterator::operator-(*this); }
    00588
    00593     bool operator==(const const_reverse_iterator &rhs) const throw ()   //[t75]
    00594         { return iterator_type::operator==(rhs); }
    00595     bool operator!=(const const_reverse_iterator &rhs) const throw ()   //[t75]
    00596         { return !operator==(rhs); }
    00597
    00598     bool operator<(const const_reverse_iterator &rhs) const             //[t75]
    00599         { return iterator_type::operator>(rhs); }
    00600     bool operator<=(const const_reverse_iterator &rhs) const            //[t75]
    00601         { return iterator_type::operator>=(rhs); }
    00602     bool operator>(const const_reverse_iterator &rhs) const             //[t75]
    00603         { return iterator_type::operator<(rhs); }
    00604     bool operator>=(const const_reverse_iterator &rhs) const            //[t75]
    00605         { return iterator_type::operator<=(rhs); }
    00607   };
    00608
    00609   class PQXX_LIBEXPORT const_fielditerator :
    00610     public PGSTD::iterator<PGSTD::random_access_iterator_tag,
    00611                            const field,
    00612                            tuple::size_type>,
    00613     public field
    00614   {
    00615     typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
    00616                                   const field,
    00617                                   tuple::size_type> it;
    00618   public:
    00619     using it::pointer;
    00620     typedef tuple::size_type size_type;
    00621     typedef tuple::difference_type difference_type;
    00622     typedef field reference;
    00623
    00624     const_fielditerator(const tuple &T, tuple::size_type C) throw () :  //[t82]
    00625       field(T, C) {}
    00626     const_fielditerator(const field &F) throw () : field(F) {}          //[t82]
    00627
    00632     pointer operator->() const { return this; }                         //[t82]
    00633     reference operator*() const { return field(*this); }                //[t82]
    00635
    00640     const_fielditerator operator++(int);                                //[t82]
    00641     const_fielditerator &operator++() { ++m_col; return *this; }        //[t82]
    00642     const_fielditerator operator--(int);                                //[t82]
    00643     const_fielditerator &operator--() { --m_col; return *this; }        //[t82]
    00644
    00645     const_fielditerator &operator+=(difference_type i)                  //[t82]
    00646         { m_col+=i; return *this; }
    00647     const_fielditerator &operator-=(difference_type i)                  //[t82]
    00648         { m_col-=i; return *this; }
    00650
    00655     bool operator==(const const_fielditerator &i) const                 //[t82]
    00656         {return col()==i.col();}
    00657     bool operator!=(const const_fielditerator &i) const                 //[t82]
    00658         {return col()!=i.col();}
    00659     bool operator<(const const_fielditerator &i) const                  //[t82]
    00660         {return col()<i.col();}
    00661     bool operator<=(const const_fielditerator &i) const                 //[t82]
    00662         {return col()<=i.col();}
    00663     bool operator>(const const_fielditerator &i) const                  //[t82]
    00664         {return col()>i.col();}
    00665     bool operator>=(const const_fielditerator &i) const                 //[t82]
    00666         {return col()>=i.col();}
    00668
    00673     inline const_fielditerator operator+(difference_type) const;        //[t82]
    00674
    00675     friend const_fielditerator operator+(difference_type,
    00676                                           const_fielditerator);         //[t82]
    00677
    00678     inline const_fielditerator operator-(difference_type) const;        //[t82]
    00679     inline difference_type operator-(const_fielditerator) const;        //[t82]
    00681   };
    00682
    00683   class PQXX_LIBEXPORT const_reverse_fielditerator : private const_fielditerator
    00684   {
    00685   public:
    00686     typedef const_fielditerator super;
    00687     typedef const_fielditerator iterator_type;
    00688     using iterator_type::iterator_category;
    00689     using iterator_type::difference_type;
    00690     using iterator_type::pointer;
    00691 #ifndef _MSC_VER
    00692     using iterator_type::value_type;
    00693     using iterator_type::reference;
    00694 #else
    00695     // Workaround for Visual C++.NET 2003, which has access problems
    00696     typedef field value_type;
    00697     typedef const field &reference;
    00698 #endif
    00699
    00700     const_reverse_fielditerator(const const_reverse_fielditerator &r) : //[t82]
    00701       const_fielditerator(r) {}
    00702     explicit
    00703       const_reverse_fielditerator(const super &rhs) throw() :           //[t82]
    00704         const_fielditerator(rhs) { super::operator--(); }
    00705
    00706     iterator_type base() const throw ();                                //[t82]
    00707
    00712     using iterator_type::operator->;                                    //[t82]
    00713     using iterator_type::operator*;                                     //[t82]
    00715
    00720     const_reverse_fielditerator &
    00721       operator=(const const_reverse_fielditerator &r)                   //[t82]
    00722         { iterator_type::operator=(r); return *this; }
    00723     const_reverse_fielditerator operator++()                            //[t82]
    00724         { iterator_type::operator--(); return *this; }
    00725     const_reverse_fielditerator operator++(int);                        //[t82]
    00726     const_reverse_fielditerator &operator--()                           //[t82]
    00727         { iterator_type::operator++(); return *this; }
    00728     const_reverse_fielditerator operator--(int);                        //[t82]
    00729     const_reverse_fielditerator &operator+=(difference_type i)          //[t82]
    00730         { iterator_type::operator-=(i); return *this; }
    00731     const_reverse_fielditerator &operator-=(difference_type i)          //[t82]
    00732         { iterator_type::operator+=(i); return *this; }
    00734
    00739     const_reverse_fielditerator operator+(difference_type i) const      //[t82]
    00740         { return const_reverse_fielditerator(base()-i); }
    00741     const_reverse_fielditerator operator-(difference_type i)            //[t82]
    00742         { return const_reverse_fielditerator(base()+i); }
    00743     difference_type
    00744       operator-(const const_reverse_fielditerator &rhs) const           //[t82]
    00745         { return rhs.const_fielditerator::operator-(*this); }
    00747
    00752     bool
    00753       operator==(const const_reverse_fielditerator &rhs) const throw () //[t82]
    00754         { return iterator_type::operator==(rhs); }
    00755     bool
    00756       operator!=(const const_reverse_fielditerator &rhs) const throw () //[t82]
    00757         { return !operator==(rhs); }
    00758
    00759     bool operator<(const const_reverse_fielditerator &rhs) const        //[t82]
    00760         { return iterator_type::operator>(rhs); }
    00761     bool operator<=(const const_reverse_fielditerator &rhs) const       //[t82]
    00762         { return iterator_type::operator>=(rhs); }
    00763     bool operator>(const const_reverse_fielditerator &rhs) const        //[t82]
    00764         { return iterator_type::operator<(rhs); }
    00765     bool operator>=(const const_reverse_fielditerator &rhs) const       //[t82]
    00766         { return iterator_type::operator<=(rhs); }
    00768   };
    00769
    00770
    00771   result() throw () : super(), m_data(0) {}                             //[t3]
    00772   result(const result &rhs) throw () :                                  //[t1]
    00773         super(rhs), m_data(rhs.m_data) {}
    00774
    00775   result &operator=(const result &rhs) throw ()                         //[t10]
    00776         { super::operator=(rhs); m_data=rhs.m_data; return *this; }
    00777
    00782   bool operator==(const result &) const throw ();                       //[t70]
    00783   bool operator!=(const result &rhs) const throw ()                     //[t70]
    00784         { return !operator==(rhs); }
    00786
    00787   const_reverse_iterator rbegin() const                                 //[t75]
    00788         { return const_reverse_iterator(end()); }
    00789   const_reverse_iterator rend() const                                   //[t75]
    00790         { return const_reverse_iterator(begin()); }
    00791
    00792   const_iterator begin() const throw ()                                 //[t1]
    00793         { return const_iterator(this, 0); }
    00794   inline const_iterator end() const throw ();                           //[t1]
    00795
    00796   reference front() const throw () { return tuple(this,0); }            //[t74]
    00797   reference back() const throw () {return tuple(this,size()-1);}        //[t75]
    00798
    00799   size_type size() const throw ();                                      //[t2]
    00800   bool empty() const throw ();                                          //[t11]
    00801   size_type capacity() const throw () { return size(); }                //[t20]
    00802
    00803   void swap(result &) throw ();                                         //[t77]
    00804
    00805   const tuple operator[](size_type i) const throw ()                    //[t2]
    00806         { return tuple(this, i); }
    00807   const tuple at(size_type) const throw (range_error);                  //[t10]
    00808
    00809   void clear() throw () { super::clear(); m_data = 0; }                 //[t20]
    00810
    00815
    00816   tuple::size_type columns() const throw ();                            //[t11]
    00817
    00819   tuple::size_type column_number(const char ColName[]) const;           //[t11]
    00820
    00822   tuple::size_type column_number(const PGSTD::string &Name) const       //[t11]
    00823         {return column_number(Name.c_str());}
    00824
    00826   const char *column_name(tuple::size_type Number) const;               //[t11]
    00827
    00829   oid column_type(tuple::size_type ColNum) const;                       //[t7]
    00831   oid column_type(int ColNum) const                                     //[t7]
    00832         { return column_type(tuple::size_type(ColNum)); }
    00833
    00835   oid column_type(const PGSTD::string &ColName) const                   //[t7]
    00836         { return column_type(column_number(ColName)); }
    00837
    00839   oid column_type(const char ColName[]) const                           //[t7]
    00840         { return column_type(column_number(ColName)); }
    00841
    00843
    00850   oid column_table(tuple::size_type ColNum) const;                      //[t2]
    00851
    00853
    00860   oid column_table(int ColNum) const                                    //[t2]
    00861         { return column_table(tuple::size_type(ColNum)); }
    00862
    00864
    00871   oid column_table(const PGSTD::string &ColName) const                  //[t2]
    00872         { return column_table(column_number(ColName)); }
    00873
    00875   tuple::size_type table_column(tuple::size_type ColNum) const;         //[t93]
    00876
    00878   tuple::size_type table_column(int ColNum) const                       //[t93]
    00879         { return table_column(tuple::size_type(ColNum)); }
    00880
    00882   tuple::size_type table_column(const PGSTD::string &ColName) const     //[t93]
    00883         { return table_column(column_number(ColName)); }
    00885
    00887   const PGSTD::string &query() const throw ();                          //[t70]
    00888
    00890
    00893   oid inserted_oid() const;                                             //[t13]
    00894
    00895
    00897
    00900   size_type affected_rows() const;                                      //[t7]
    00901
    00902
    00903 private:
    00904   friend class pqxx::result::field;
    00905   const char *GetValue(size_type Row, tuple::size_type Col) const;
    00906   bool GetIsNull(size_type Row, tuple::size_type Col) const;
    00907   field::size_type GetLength(size_type, tuple::size_type) const;
    00908
    00909   friend class connection_base;
    00910   friend class pipeline;
    00911   result(internal::pq::PGresult *rhs,
    00912         int protocol,
    00913         const PGSTD::string &Query,
    00914         int encoding_code);
    00915   bool operator!() const throw () { return !m_data; }
    00916   operator bool() const throw () { return m_data != 0; }
    00917
    00918   void PQXX_PRIVATE CheckStatus() const;
    00919
    00920   void PQXX_PRIVATE ThrowSQLError(const PGSTD::string &Err,
    00921         const PGSTD::string &Query) const;
    00922   int PQXX_PRIVATE errorposition() const throw ();
    00923   PGSTD::string PQXX_PRIVATE StatusError() const;
    00924
    00925   friend class Cursor;  // deprecated
    00926   friend class internal::sql_cursor;
    00927   const char *CmdStatus() const throw ();
    00928
    00930   pqxx::internal::pq::PGresult *m_data;
    00931
    00932   static const PGSTD::string PQXX_PRIVATE s_empty_string;
    00933 };
    00934
    00935
    00937
    00957 template<typename CHAR>
    00958 inline PGSTD::basic_ostream<CHAR> &operator<<(
    00959         PGSTD::basic_ostream<CHAR> &S, const pqxx::result::field &F)    //[t46]
    00960 {
    00961   S.write(F.c_str(), F.size());
    00962   return S;
    00963 }
    00964
    00965
    00967 template<typename T>
    00968 inline void from_string(const result::field &F, T &Obj)                 //[t46]
    00969         { from_string(F.c_str(), Obj, F.size()); }
    00970
    00972 template<>
    00973 inline PGSTD::string to_string(const result::field &Obj)                //[t74]
    00974         { return PGSTD::string(Obj.c_str(), Obj.size()); }
    00975
    00976
    00978 template<>
    00979 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
    00980 {
    00981   const char *const bytes = c_str();
    00982   if (!bytes[0] && is_null()) return false;
    00983   Obj = PGSTD::string(bytes, size());
    00984   return true;
    00985 }
    00986
    00988
    00993 template<>
    00994 inline bool result::field::to<const char *>(const char *&Obj) const
    00995 {
    00996   if (is_null()) return false;
    00997   Obj = c_str();
    00998   return true;
    00999 }
    01000
    01001
    01002 inline result::tuple::const_reverse_iterator result::tuple::rbegin() const
    01003         { return const_reverse_fielditerator(end()); }
    01004 inline result::tuple::const_reverse_iterator result::tuple::rend() const
    01005         { return const_reverse_fielditerator(begin()); }
    01006
    01007 inline result::const_iterator
    01008 result::const_iterator::operator+(difference_type o) const
    01009         { return const_iterator(m_Home, m_Index + o); }
    01010
    01011 inline result::const_iterator
    01012 operator+(result::const_iterator::difference_type o, result::const_iterator i)
    01013         { return i + o; }
    01014
    01015 inline result::const_iterator
    01016 result::const_iterator::operator-(difference_type o) const
    01017         { return const_iterator(m_Home, m_Index - o); }
    01018
    01019 inline result::const_iterator::difference_type
    01020 result::const_iterator::operator-(const_iterator i) const
    01021         { return num()-i.num(); }
    01022
    01023 inline result::const_iterator result::end() const throw ()
    01024         { return const_iterator(this, size()); }
    01025
    01026
    01027 inline result::const_reverse_iterator
    01028 operator+(result::const_reverse_iterator::difference_type n,
    01029           const result::const_reverse_iterator &i)
    01030         { return result::const_reverse_iterator(i.base() - n); }
    01031
    01032 inline result::const_fielditerator
    01033 result::const_fielditerator::operator+(difference_type o) const
    01034         { return const_fielditerator(m_tup, col() + o); }
    01035
    01036 inline result::const_fielditerator
    01037 operator+(result::const_fielditerator::difference_type o,
    01038           result::const_fielditerator i)
    01039         { return i + o; }
    01040
    01041 inline result::const_fielditerator
    01042 result::const_fielditerator::operator-(difference_type o) const
    01043         { return const_fielditerator(m_tup, col() - o); }
    01044
    01045 inline result::const_fielditerator::difference_type
    01046 result::const_fielditerator::operator-(const_fielditerator i) const
    01047         { return num()-i.num(); }
    01048
    01049
    01050 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
    01051   class field_streambuf :
    01052 #ifdef PQXX_HAVE_STREAMBUF
    01053   public PGSTD::basic_streambuf<CHAR, TRAITS>
    01054 #else
    01055   public PGSTD::streambuf
    01056 #endif
    01057 {
    01058 public:
    01059   typedef CHAR char_type;
    01060   typedef TRAITS traits_type;
    01061   typedef typename traits_type::int_type int_type;
    01062 #ifdef PQXX_HAVE_STREAMBUF
    01063   typedef typename traits_type::pos_type pos_type;
    01064   typedef typename traits_type::off_type off_type;
    01065 #else
    01066   typedef streamoff off_type;
    01067   typedef streampos pos_type;
    01068 #endif
    01069   typedef PGSTD::ios::openmode openmode;
    01070   typedef PGSTD::ios::seekdir seekdir;
    01071
    01072   explicit field_streambuf(const result::field &F) :                    //[t74]
    01073     m_Field(F)
    01074   {
    01075     initialize();
    01076   }
    01077
    01078 #ifdef PQXX_HAVE_STREAMBUF
    01079 protected:
    01080 #endif
    01081   virtual int sync() { return traits_type::eof(); }
    01082
    01083 protected:
    01084   virtual pos_type seekoff(off_type, seekdir, openmode)
    01085         { return traits_type::eof(); }
    01086   virtual pos_type seekpos(pos_type, openmode) {return traits_type::eof();}
    01087   virtual int_type overflow(int_type) { return traits_type::eof(); }
    01088   virtual int_type underflow() { return traits_type::eof(); }
    01089
    01090 private:
    01091   const result::field &m_Field;
    01092
    01093   int_type initialize()
    01094   {
    01095     char_type *G =
    01096       reinterpret_cast<char_type *>(const_cast<char *>(m_Field.c_str()));
    01097     setg(G, G, G + m_Field.size());
    01098     return int_type(m_Field.size());
    01099   }
    01100 };
    01101
    01102
    01104
    01112 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
    01113   class basic_fieldstream :
    01114 #ifdef PQXX_HAVE_STREAMBUF
    01115     public PGSTD::basic_istream<CHAR, TRAITS>
    01116 #else
    01117     public PGSTD::istream
    01118 #endif
    01119 {
    01120 #ifdef PQXX_HAVE_STREAMBUF
    01121   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
    01122 #else
    01123   typedef PGSTD::istream super;
    01124 #endif
    01125
    01126 public:
    01127   typedef CHAR char_type;
    01128   typedef TRAITS traits_type;
    01129   typedef typename traits_type::int_type int_type;
    01130   typedef typename traits_type::pos_type pos_type;
    01131   typedef typename traits_type::off_type off_type;
    01132
    01133   basic_fieldstream(const result::field &F) : super(0), m_Buf(F)
    01134         { super::init(&m_Buf); }
    01135
    01136 private:
    01137   field_streambuf<CHAR, TRAITS> m_Buf;
    01138 };
    01139
    01140 typedef basic_fieldstream<char> fieldstream;
    01141
    01142 } // namespace pqxx
    01143
    01144
    01145
    01146 /*
    01147 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More
    01148 Effective C++", points out that it is good style to have any class containing
    01149 a member of pointer type define a destructor--just to show that it knows what it
    01150 is doing with the pointer.  This helps prevent nasty memory leak / double
    01151 deletion bugs typically resulting from programmers' omission to deal with such
    01152 issues in their destructors.
    01153
    01154 The @c -Weffc++ option in gcc generates warnings for noncompliance with Scott's
    01155 style guidelines, and hence necessitates the definition of this destructor,
    01156 trivial as it may be.
    01157 */
    01158
    01159
    01160 #include "pqxx/compiler-internal-post.hxx"
    01161
    01162 #endif
    01163