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 

Generated on Sat Aug 15 00:16:49 2009 for libpqxx by  doxygen 1.5.8