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

result.hxx

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/result.hxx
00005  *
00006  *   DESCRIPTION
00007  *      definitions for the pqxx::result class and support classes.
00008  *   pqxx::result represents the set of result tuples from a database query
00009  *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.
00010  *
00011  * Copyright (c) 2001-2004, Jeroen T. Vermeulen <jtv@xs4all.nl>
00012  *
00013  * See COPYING for copyright license.  If you did not receive a file called
00014  * COPYING with this source code, please notify the distributor of this mistake,
00015  * or contact the author.
00016  *
00017  *-------------------------------------------------------------------------
00018  */
00019 #ifdef PQXX_HAVE_IOS
00020 #include <ios>
00021 #endif
00022 
00023 #include <stdexcept>
00024 
00025 #include "pqxx/util"
00026 
00027 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
00028  */
00029 
00030 // TODO: Support SQL arrays
00031 
00032 namespace pqxx
00033 {
00035 
00042 class PQXX_LIBEXPORT result : private internal::PQAlloc<internal::pq::PGresult>
00043 {
00044   typedef internal::PQAlloc<internal::pq::PGresult> super;
00045 public:
00046   class const_iterator;
00047   class const_fielditerator;
00048   class const_reverse_fielditerator;
00049   class tuple;
00050   class field;
00051   typedef unsigned long size_type;
00052   typedef signed long difference_type;
00053   typedef tuple reference;
00054   typedef const_iterator pointer;
00055 
00057 
00068   class PQXX_LIBEXPORT tuple
00069   {
00070   public:
00071     typedef unsigned int size_type;
00072     typedef signed int difference_type;
00073     typedef const_fielditerator const_iterator;
00074     typedef field reference;
00075     typedef const_fielditerator pointer;
00076     typedef const_reverse_fielditerator const_reverse_iterator;
00077 
00078     tuple(const result *r, result::size_type i) throw () : 
00079       m_Home(r), m_Index(i) {}
00080     ~tuple() throw () {} // Yes Scott Meyers, you're absolutely right[1]
00081 
00082     bool operator==(const tuple &) const throw ();                      //[t75]
00083     bool operator!=(const tuple &rhs) const throw ()                    //[t75]
00084         { return !operator==(rhs); }
00085 
00086     const_iterator begin() const throw ()                               //[t82]
00087         { return const_iterator(*this, 0); }
00088     const_iterator end() const throw ()                                 //[t82]
00089         { return const_iterator(*this, size()); }
00090 
00091     reference front() const throw () { return field(*this, 0); }        //[t74]
00092     reference back() const throw () { return field(*this, size()-1); }  //[t75]
00093 
00094     const_reverse_fielditerator rbegin() const;                         //[t82]
00095     const_reverse_fielditerator rend() const;                           //[t82]
00096 
00097     reference operator[](size_type i) const throw ()                    //[t11]
00098         { return field(*this, i); }
00099     reference operator[](int i) const throw ()                          //[t2]
00100         { return operator[](size_type(i)); }
00101     reference operator[](const char[]) const;                           //[t11]
00102     reference operator[](const PGSTD::string &s) const                  //[t11]
00103         { return operator[](s.c_str()); }
00104     reference at(size_type) const throw (PGSTD::out_of_range);          //[t11]
00105     reference at(int i) const throw (PGSTD::out_of_range)               //[t11]
00106         { return at(size_type(i)); }
00107     reference at(const char[]) const;                                   //[t11]
00108     reference at(const PGSTD::string &s) const                          //[t11]
00109         { return at(s.c_str()); }
00110 
00111     size_type size() const throw () { return m_Home->columns(); }       //[t11]
00112 
00113     void swap(tuple &) throw ();                                        //[t11]
00114 
00115     result::size_type rownumber() const throw () { return m_Index; }    //[t11]
00116 
00118     size_type column_number(const PGSTD::string &ColName) const         //[t30]
00119         { return m_Home->column_number(ColName); }
00120 
00122     size_type column_number(const char ColName[]) const                 //[t30]
00123         { return m_Home->column_number(ColName); }
00124 
00126     oid column_type(size_type ColNum) const                             //[t7]
00127         { return m_Home->column_type(ColNum); }
00128 
00130     oid column_type(int ColNum) const                                   //[t7]
00131         { return column_type(size_type(ColNum)); }
00132 
00134     oid column_type(const PGSTD::string &ColName) const                 //[t7]
00135         { return column_type(column_number(ColName)); }
00136 
00138     oid column_type(const char ColName[]) const                         //[t7]
00139         { return column_type(column_number(ColName)); }
00140 
00141     result::size_type num() const { return rownumber(); }               //[t1]
00142 
00143 #ifdef PQXX_HAVE_PQFTABLE
00144     oid column_table(size_type ColNum) const                            //[t2]
00145         { return m_Home->column_table(ColNum); }
00146     oid column_table(int ColNum) const                                  //[t2]
00147         { return column_table(size_type(ColNum)); }
00148     oid column_table(const PGSTD::string &ColName) const                //[t2]
00149         { return column_table(column_number(ColName)); }
00150 #endif
00151 
00152 
00153 #ifdef PQXX_DEPRECATED_HEADERS
00154 
00155     result::size_type Row() const { return rownumber(); }
00156 
00158     size_type ColumnNumber(const PGSTD::string &ColName) const 
00159         { return column_number(ColName); }
00160 
00162     size_type ColumnNumber(const char ColName[]) const 
00163         { return column_number(ColName); }
00164 #endif
00165 
00166   protected:
00167     friend class field;
00168     const result *m_Home;
00169     result::size_type m_Index;
00170 
00171     // Not allowed:
00172     tuple();
00173   };
00174 
00176 
00179   class PQXX_LIBEXPORT field
00180   {
00181   public:
00182     typedef size_t size_type;
00183 
00185 
00189     field(const tuple &T, tuple::size_type C) throw () :                //[t1]
00190         m_tup(T), m_col(C) {}
00191 
00193 
00209     bool operator==(const field &) const;                               //[t75]
00210 
00212 
00214     bool operator!=(const field &rhs) const {return !operator==(rhs);}  //[t82]
00215 
00217 
00222     const char *c_str() const { return home()->GetValue(idx(),col()); } //[t2]
00223 
00225     const char *name() const { return home()->column_name(col()); }     //[t11]
00226 
00228     oid type() const { return home()->column_type(col()); }             //[t7]
00229 
00230 #ifdef PQXX_HAVE_PQFTABLE
00231 
00232 
00234     oid table() const { return home()->column_table(col()); }           //[t2]
00235 #endif
00236 
00238     template<typename T> bool to(T &Obj) const                          //[t3]
00239     {
00240       if (is_null()) return false;
00241       try
00242       {
00243         from_string(c_str(), Obj);
00244       }
00245       catch (const PGSTD::exception &e)
00246       {
00247         throw PGSTD::domain_error("Error reading field " + 
00248                                   PGSTD::string(name()) + ": " +
00249                                   e.what());
00250       }
00251       return true;
00252     }
00253 
00255     template<typename T> bool operator>>(T &Obj) const                  //[t7]
00256         { return to(Obj); }
00257 
00258 #ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00259 
00260     template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00261 
00263 
00266     template<> bool to<const char *>(const char *&Obj) const;
00267 #endif
00268 
00270     template<typename T> bool to(T &Obj, const T &Default) const                //[t12]
00271     {
00272       const bool NotNull = to(Obj);
00273       if (!NotNull) Obj = Default;
00274       return NotNull;
00275     }
00276 
00278 
00281     template<typename T> T as(const T &Default) const                   //[t1]
00282     {
00283       T Obj;
00284       to(Obj, Default);
00285       return Obj;
00286     }
00287 
00289     template<typename T> T as() const                                   //[t45]
00290     {
00291       T Obj;
00292       const bool NotNull = to(Obj);
00293       if (!NotNull) throw PGSTD::domain_error("Attempt to read null field");
00294       return Obj;
00295     }
00296 
00297     bool is_null() const { return home()->GetIsNull(idx(), col()); }    //[t12]
00298     size_type size() const throw ()                                     //[t11]
00299         { return home()->GetLength(idx(),col()); }
00300     tuple::size_type num() const { return col(); }                      //[t82]
00301 
00302 #ifdef PQXX_DEPRECATED_HEADERS
00303 
00304     const char *Name() const {return name();}
00305 #endif
00306 
00307   private:
00308     const result *home() const throw () { return m_tup.m_Home; }
00309     result::size_type idx() const throw () { return m_tup.m_Index; }
00310 
00311   protected:
00312     const tuple::size_type col() const throw () { return m_col; }
00313     tuple m_tup;
00314     tuple::size_type m_col;
00315   };
00316 
00317   typedef PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00318                            const tuple,
00319                            result::difference_type,
00320                            const_iterator,
00321                            tuple> const_iterator_base;
00322 
00324 
00328   class PQXX_LIBEXPORT const_iterator : 
00329     public const_iterator_base,
00330     public tuple
00331   {
00332   public:
00333     typedef const tuple *pointer;
00334     typedef tuple reference;
00335     typedef result::size_type size_type;
00336     typedef result::difference_type difference_type;
00337 
00338     const_iterator() throw () : tuple(0,0) {}
00339     const_iterator(const tuple &t) throw () : tuple(t) {}
00340 
00352     pointer operator->() const { return this; }                         //[t12]
00353     reference operator*() const { return tuple(*this); }                //[t12]
00354 
00355     const_iterator operator++(int);                                     //[t12]
00356     const_iterator &operator++() { ++m_Index; return *this; }           //[t1]
00357     const_iterator operator--(int);                                     //[t12]
00358     const_iterator &operator--() { --m_Index; return *this; }           //[t12]
00359 
00360     const_iterator &operator+=(difference_type i)                       //[t12]
00361         { m_Index+=i; return *this; }
00362     const_iterator &operator-=(difference_type i)                       //[t12]
00363         { m_Index-=i; return *this; }
00364 
00365     bool operator==(const const_iterator &i) const                      //[t12]
00366         {return m_Index==i.m_Index;}
00367     bool operator!=(const const_iterator &i) const                      //[t12]
00368         {return m_Index!=i.m_Index;}
00369     bool operator<(const const_iterator &i) const                       //[t12]
00370         {return m_Index<i.m_Index;}
00371     bool operator<=(const const_iterator &i) const                      //[t12]
00372         {return m_Index<=i.m_Index;}
00373     bool operator>(const const_iterator &i) const                       //[t12]
00374         {return m_Index>i.m_Index;}
00375     bool operator>=(const const_iterator &i) const                      //[t12]
00376         {return m_Index>=i.m_Index;}
00377 
00378     inline const_iterator operator+(difference_type) const;             //[t12]
00379     friend const_iterator
00380     operator+(difference_type, const_iterator);                         //[t12]
00381     inline const_iterator operator-(difference_type) const;             //[t12]
00382     inline difference_type operator-(const_iterator) const;             //[t12]
00383 
00384   private:
00385     friend class pqxx::result;
00386     const_iterator(const pqxx::result *r, result::size_type i) throw () :
00387         tuple(r, i) {}
00388   };
00389 
00390   class PQXX_LIBEXPORT const_reverse_iterator : private const_iterator
00391   {
00392   public:
00393     typedef const_iterator iterator_type;
00394     using iterator_type::iterator_category;
00395     using iterator_type::difference_type;
00396     using iterator_type::pointer;
00397 #ifndef _MSC_VER
00398     using iterator_type::value_type;
00399     using iterator_type::reference;
00400 #else
00401     // Workaround for Visual C++.NET 2003, which has access problems
00402     typedef const tuple &reference;
00403     typedef tuple value_type;
00404 #endif
00405 
00406     const_reverse_iterator(const const_reverse_iterator &rhs) :         //[t75]
00407       const_iterator(rhs), m_tmp(rhs) {}
00408     explicit const_reverse_iterator(const const_iterator &rhs) :        //[t75]
00409       const_iterator(rhs), m_tmp() {}
00410 
00411     iterator_type base() const throw () { return *this; }               //[t75]
00412 
00413     const_reverse_iterator &operator=(const const_reverse_iterator &r)  //[]
00414         { iterator_type::operator=(r); return *this; }
00415     pointer operator->() const throw ()                                 //[t75]
00416         { m_tmp=*this; --m_tmp; return &m_tmp; }
00417     reference operator*() const throw () { return *operator->(); }      //[t75]
00418     const_reverse_iterator operator++()                                 //[t75]
00419         { iterator_type::operator--(); return *this; }
00420     const_reverse_iterator operator++(int);                             //[t75]
00421     const_reverse_iterator &operator--()                                //[t75]
00422         { iterator_type::operator++(); return *this; }
00423     const_reverse_iterator operator--(int);                             //[t75]
00424     const_reverse_iterator operator+(difference_type i) const           //[t75]
00425         { return const_reverse_iterator(iterator_type(*this)-i); }
00426     const_reverse_iterator &operator+=(difference_type i)               //[t75]
00427         { iterator_type::operator-=(i); return *this; }
00428     const_reverse_iterator operator-(difference_type i)                 //[t75]
00429         { return const_reverse_iterator(iterator_type(*this)+i); }
00430     const_reverse_iterator &operator-=(difference_type i)               //[t75]
00431         { iterator_type::operator+=(i); return *this; }
00432 
00433     bool operator==(const const_reverse_iterator &rhs) const throw ()   //[t75]
00434         { return iterator_type::operator==(rhs); }
00435     bool operator!=(const const_reverse_iterator &rhs) const throw ()   //[t75]
00436         { return !operator==(rhs); }
00437 
00438     bool operator<(const const_reverse_iterator &rhs) const             //[t75]
00439         { return iterator_type::operator>(rhs); }
00440     bool operator<=(const const_reverse_iterator &rhs) const            //[t75]
00441         { return iterator_type::operator>=(rhs); }
00442     bool operator>(const const_reverse_iterator &rhs) const             //[t75]
00443         { return iterator_type::operator<(rhs); }
00444     bool operator>=(const const_reverse_iterator &rhs) const            //[t75]
00445         { return iterator_type::operator<=(rhs); }
00446     difference_type operator-(const const_reverse_iterator &rhs) const  //[t75]
00447         { return rhs.base() - base(); }
00448 
00449   private:
00451 
00456     mutable iterator_type m_tmp;
00457   };
00458 
00459   class PQXX_LIBEXPORT const_fielditerator : 
00460     public PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00461                            const field,
00462                            tuple::size_type>, 
00463     public field
00464   {
00465     typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
00466                                   const field,
00467                                   tuple::size_type> it;
00468   public:
00469     using it::pointer;
00470     typedef tuple::size_type size_type;
00471     typedef tuple::difference_type difference_type;
00472     typedef field reference;
00473 
00474     const_fielditerator(const tuple &T, tuple::size_type C) throw () :  //[t82]
00475       field(T, C) {}
00476     const_fielditerator(const field &F) throw () : field(F) {}          //[t82]
00477 
00478     pointer operator->() const { return this; }                         //[t82]
00479     reference operator*() const { return field(*this); }                //[t82]
00480 
00481     const_fielditerator operator++(int);                                //[t82]
00482     const_fielditerator &operator++() { ++m_col; return *this; }        //[t82]
00483     const_fielditerator operator--(int);                                //[t82]
00484     const_fielditerator &operator--() { --m_col; return *this; }        //[t82]
00485 
00486     const_fielditerator &operator+=(difference_type i)                  //[t82]
00487         { m_col+=i; return *this; }
00488     const_fielditerator &operator-=(difference_type i)                  //[t82]
00489         { m_col-=i; return *this; }
00490 
00491     bool operator==(const const_fielditerator &i) const                 //[t82]
00492         {return col()==i.col();}
00493     bool operator!=(const const_fielditerator &i) const                 //[t82]
00494         {return col()!=i.col();}
00495     bool operator<(const const_fielditerator &i) const                  //[t82]
00496         {return col()<i.col();}
00497     bool operator<=(const const_fielditerator &i) const                 //[t82]
00498         {return col()<=i.col();}
00499     bool operator>(const const_fielditerator &i) const                  //[t82]
00500         {return col()>i.col();}
00501     bool operator>=(const const_fielditerator &i) const                 //[t82]
00502         {return col()>=i.col();}
00503 
00504     inline const_fielditerator operator+(difference_type) const;        //[t82]
00505 
00506     friend const_fielditerator operator+(difference_type, 
00507                                           const_fielditerator);         //[t82]
00508 
00509     inline const_fielditerator operator-(difference_type) const;        //[t82]
00510     inline difference_type operator-(const_fielditerator) const;        //[t82]
00511   };
00512 
00513   class PQXX_LIBEXPORT const_reverse_fielditerator : private const_fielditerator
00514   {
00515   public:
00516     typedef const_fielditerator iterator_type;
00517     using iterator_type::iterator_category;
00518     using iterator_type::difference_type;
00519     using iterator_type::pointer;
00520 #ifndef _MSC_VER
00521     using iterator_type::value_type;
00522     using iterator_type::reference;
00523 #else
00524     // Workaround for Visual C++.NET 2003, which has access problems
00525     typedef field value_type;
00526     typedef const field &reference;
00527 #endif
00528 
00529     iterator_type base() const throw () { return *this; }               //[t82]
00530     const_reverse_fielditerator(const const_reverse_fielditerator &rhs) //[t82]
00531       : const_fielditerator(rhs), m_tmp(rhs.m_tmp) {}
00532     explicit
00533       const_reverse_fielditerator(const const_fielditerator &rhs) :     //[t82]
00534       const_fielditerator(rhs), m_tmp(rhs) {}
00535 
00536     const_reverse_fielditerator &
00537       operator=(const const_reverse_fielditerator &r)                   //[]
00538         { iterator_type::operator=(r); return *this; }
00539     pointer operator->() const throw ()                                 //[t82]
00540         { m_tmp = *this; --m_tmp; return &m_tmp; }
00541     reference operator*() const throw () { return *operator->(); }      //[t82]
00542     const_reverse_fielditerator operator++()                            //[t82]
00543         { iterator_type::operator--(); return *this; }
00544     const_reverse_fielditerator operator++(int);                        //[t82]
00545     const_reverse_fielditerator &operator--()                           //[t82]
00546         { iterator_type::operator++(); return *this; }
00547     const_reverse_fielditerator operator--(int);                        //[t82]
00548     const_reverse_fielditerator operator+(difference_type i) const      //[t82]
00549         { return const_reverse_fielditerator(iterator_type(*this)-i); }
00550     const_reverse_fielditerator &operator+=(difference_type i)          //[t82]
00551         { iterator_type::operator-=(i); return *this; }
00552     const_reverse_fielditerator operator-(difference_type i)            //[t82]
00553         { return const_reverse_fielditerator(iterator_type(*this)+i); }
00554     const_reverse_fielditerator &operator-=(difference_type i)          //[t82]
00555         { iterator_type::operator+=(i); return *this; }
00556 
00557     bool
00558       operator==(const const_reverse_fielditerator &rhs) const throw () //[t82]
00559         { return iterator_type::operator==(rhs); }
00560     bool
00561       operator!=(const const_reverse_fielditerator &rhs) const throw () //[t82]
00562         { return !operator==(rhs); }
00563 
00564 
00565     bool operator<(const const_reverse_fielditerator &rhs) const        //[t82]
00566         { return iterator_type::operator>(rhs); }
00567     bool operator<=(const const_reverse_fielditerator &rhs) const       //[t82]
00568         { return iterator_type::operator>=(rhs); }
00569     bool operator>(const const_reverse_fielditerator &rhs) const        //[t82]
00570         { return iterator_type::operator<(rhs); }
00571     bool operator>=(const const_reverse_fielditerator &rhs) const       //[t82]
00572         { return iterator_type::operator<=(rhs); }
00573     difference_type
00574       operator-(const const_reverse_fielditerator &rhs) const           //[t82]
00575         { return rhs.base() - base(); }
00576 
00577   private:
00579 
00584     mutable iterator_type m_tmp;
00585   };
00586 
00587 
00588   result() throw () : super() {}                                        //[t3]
00589   result(const result &rhs) throw () : super(rhs) {}                    //[t1]
00590   
00591   result &operator=(const result &rhs) throw ()                         //[t10]
00592         { super::operator=(rhs); return *this; }
00593 
00594   bool operator==(const result &) const throw ();                       //[t70]
00595   bool operator!=(const result &rhs) const throw ()                     //[t70]
00596         { return !operator==(rhs); }
00597 
00598   const_reverse_iterator rbegin() const                                 //[t75]
00599         { return const_reverse_iterator(end()); }
00600   const_reverse_iterator rend() const                                   //[t75]
00601         { return const_reverse_iterator(begin()); }
00602 
00603   const_iterator begin() const throw ()                                 //[t1]
00604         { return const_iterator(this, 0); }
00605   inline const_iterator end() const throw ();                           //[t1]
00606 
00607   reference front() const throw () { return tuple(this,0); }            //[t74]
00608   reference back() const throw () {return tuple(this,size()-1);}        //[t75]
00609 
00610   size_type size() const throw ()                                       //[t2]
00611         { return c_ptr() ? PQXXPQ::PQntuples(c_ptr()) : 0; }
00612   bool empty() const                                                    //[t11]
00613         { return !c_ptr() || !PQXXPQ::PQntuples(c_ptr()); }
00614   size_type capacity() const throw () { return size(); }                //[t20]
00615 
00616   void swap(result &) throw ();                                         //[t77]
00617 
00618   const tuple operator[](size_type i) const throw ()                    //[t2]
00619         { return tuple(this, i); }
00620   const tuple at(size_type) const throw (PGSTD::out_of_range);          //[t10]
00621 
00622   using super::clear;                                                   //[t20]
00623 
00625   tuple::size_type columns() const throw ()                             //[t11]
00626         { return PQnfields(c_ptr()); }
00627 
00629   tuple::size_type column_number(const char ColName[]) const;           //[t11]
00630 
00632   tuple::size_type column_number(const PGSTD::string &Name) const       //[t11]
00633         {return column_number(Name.c_str());}
00634 
00636   const char *column_name(tuple::size_type Number) const;               //[t11]
00637 
00639   oid column_type(tuple::size_type ColNum) const;                       //[t7]
00641   oid column_type(int ColNum) const                                     //[t7]
00642         { return column_type(tuple::size_type(ColNum)); }
00643 
00645   oid column_type(const PGSTD::string &ColName) const                   //[t7]
00646         { return column_type(column_number(ColName)); }
00647 
00649   oid column_type(const char ColName[]) const                           //[t7]
00650         { return column_type(column_number(ColName)); }
00651 
00652 #ifdef PQXX_HAVE_PQFTABLE
00653 
00654   oid column_table(tuple::size_type ColNum) const;                      //[t2]
00656   oid column_table(int ColNum) const                                    //[t2]
00657         { return column_table(tuple::size_type(ColNum)); } 
00658 
00660   oid column_table(const PGSTD::string &ColName) const                  //[t2]
00661         { return column_table(column_number(ColName)); }
00662 #endif
00663 
00665 
00668   oid inserted_oid() const { return PQoidValue(c_ptr()); }              //[t13]
00669 
00670 
00672 
00675   size_type affected_rows() const;                                      //[t7]
00676 
00677 
00678 #ifdef PQXX_DEPRECATED_HEADERS
00679 
00680   typedef tuple Tuple;
00682   typedef field Field;
00684   oid InsertedOid() const { return inserted_oid(); }
00686   size_type AffectedRows() const { return affected_rows(); }
00688   tuple::size_type Columns() const { return columns(); }
00690   tuple::size_type ColumnNumber(const char Name[]) const
00691         {return PQfnumber(c_ptr(),Name);}
00693   tuple::size_type ColumnNumber(const PGSTD::string &Name) const
00694         {return ColumnNumber(Name.c_str());}
00696   const char *ColumnName(tuple::size_type Number) const
00697         {return PQfname(c_ptr(),Number);}
00698 #endif
00699 
00700 
00701 private:
00702   friend class pqxx::result::field;
00703   const char *GetValue(size_type Row, tuple::size_type Col) const;
00704   bool GetIsNull(size_type Row, tuple::size_type Col) const;
00705   field::size_type GetLength(size_type Row, tuple::size_type Col) const;
00706 
00707   friend class connection_base;
00708   friend class pipeline;
00709   explicit result(PQXXPQ::PGresult *rhs) throw () : super(rhs) {}
00710   result &operator=(PQXXPQ::PGresult *rhs) throw ()
00711         { super::operator=(rhs); return *this; }
00712   bool operator!() const throw () { return !c_ptr(); }
00713   operator bool() const throw () { return c_ptr() != 0; }
00714   void CheckStatus(const PGSTD::string &Query) const;
00715   void CheckStatus(const char Query[]) const;
00716   int errorposition() const throw ();
00717   PGSTD::string StatusError() const;
00718 
00719   friend class Cursor;
00720   const char *CmdStatus() const throw () { return PQcmdStatus(c_ptr()); }
00721 };
00722 
00723 
00725 
00744 template<typename STREAM>
00745 inline STREAM &operator<<(STREAM &S, const pqxx::result::field &F)      //[t46]
00746 {
00747   S.write(F.c_str(), F.size());
00748   return S;
00749 }
00750 
00751 
00753 template<typename T>
00754 inline void from_string(const result::field &F, T &Obj)                 //[t46]
00755         { from_string(F.c_str(), Obj); }
00756 
00758 template<>
00759 inline PGSTD::string to_string(const result::field &Obj)                //[t74]
00760         { return to_string(Obj.c_str()); }
00761 
00762 
00764 template<> 
00765 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
00766 {
00767   if (is_null()) return false;
00768   Obj = c_str();
00769   return true;
00770 }
00771 
00773 
00778 template<> 
00779 inline bool result::field::to<const char *>(const char *&Obj) const
00780 {
00781   if (is_null()) return false;
00782   Obj = c_str();
00783   return true;
00784 }
00785 
00786 
00787 inline result::tuple::const_reverse_iterator result::tuple::rbegin() const
00788         { return const_reverse_fielditerator(end()); }
00789 inline result::tuple::const_reverse_iterator result::tuple::rend() const
00790         { return const_reverse_fielditerator(begin()); }
00791 
00792 inline result::const_iterator 
00793 result::const_iterator::operator+(difference_type o) const
00794         { return const_iterator(m_Home, m_Index + o); }
00795 
00796 inline result::const_iterator 
00797 operator+(result::const_iterator::difference_type o, result::const_iterator i)
00798         { return i + o; }
00799 
00800 inline result::const_iterator 
00801 result::const_iterator::operator-(difference_type o) const
00802         { return const_iterator(m_Home, m_Index - o); }
00803 
00804 inline result::const_iterator::difference_type 
00805 result::const_iterator::operator-(const_iterator i) const
00806         { return num()-i.num(); }
00807 
00808 inline result::const_iterator result::end() const throw ()
00809         { return const_iterator(this, size()); }
00810 
00811 
00812 inline result::const_reverse_iterator
00813 operator+(result::const_reverse_iterator::difference_type n,
00814           const result::const_reverse_iterator &i)
00815         { return result::const_reverse_iterator(i.base() - n); }
00816 
00817 inline result::const_fielditerator 
00818 result::const_fielditerator::operator+(difference_type o) const
00819         { return const_fielditerator(m_tup, col() + o); }
00820 
00821 inline result::const_fielditerator 
00822 operator+(result::const_fielditerator::difference_type o,
00823           result::const_fielditerator i)
00824         { return i + o; }
00825 
00826 inline result::const_fielditerator 
00827 result::const_fielditerator::operator-(difference_type o) const
00828         { return const_fielditerator(m_tup, col() - o); }
00829 
00830 inline result::const_fielditerator::difference_type 
00831 result::const_fielditerator::operator-(const_fielditerator i) const
00832         { return num()-i.num(); }
00833 
00834 
00835 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00836   class field_streambuf :
00837 #ifdef PQXX_HAVE_STREAMBUF
00838   public PGSTD::basic_streambuf<CHAR, TRAITS>
00839 #else
00840   public PGSTD::streambuf
00841 #endif
00842 {
00843 public:
00844   typedef CHAR char_type;
00845   typedef TRAITS traits_type;
00846   typedef typename traits_type::int_type int_type;
00847 #ifdef PQXX_HAVE_STREAMBUF
00848   typedef typename traits_type::pos_type pos_type;
00849   typedef typename traits_type::off_type off_type;
00850 #else
00851   typedef streamoff off_type;
00852   typedef streampos pos_type;
00853 #endif
00854   typedef PGSTD::ios::openmode openmode;
00855   typedef PGSTD::ios::seekdir seekdir;
00856 
00857   explicit field_streambuf(const result::field &F) :                    //[t74]
00858     m_Field(F)
00859   {
00860     initialize();
00861   }
00862 
00863 #ifdef PQXX_HAVE_STREAMBUF
00864 protected:
00865 #endif
00866   virtual int sync() { return traits_type::eof(); }
00867 
00868 protected:
00869   virtual pos_type seekoff(off_type, seekdir, openmode)
00870         { return traits_type::eof(); } 
00871   virtual pos_type seekpos(pos_type, openmode) {return traits_type::eof();}
00872   virtual int_type overflow(int_type) { return traits_type::eof(); }
00873   virtual int_type underflow() { return traits_type::eof(); }
00874 
00875 private:
00876   const result::field &m_Field;
00877 
00878   int_type initialize()
00879   {
00880     char_type *G = 
00881       reinterpret_cast<char_type *>(const_cast<char *>(m_Field.c_str()));
00882     setg(G, G, G + m_Field.size());
00883     return m_Field.size();
00884   }
00885 };
00886 
00887 
00889 
00897 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
00898   class basic_fieldstream :
00899 #ifdef PQXX_HAVE_STREAMBUF
00900     public PGSTD::basic_istream<CHAR, TRAITS>
00901 #else
00902     public PGSTD::istream
00903 #endif
00904 {
00905 #ifdef PQXX_HAVE_STREAMBUF
00906   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00907 #else
00908   typedef PGSTD::istream super;
00909 #endif
00910 
00911 public:
00912   typedef CHAR char_type;
00913   typedef TRAITS traits_type;
00914   typedef typename traits_type::int_type int_type;
00915   typedef typename traits_type::pos_type pos_type;
00916   typedef typename traits_type::off_type off_type;
00917 
00918   basic_fieldstream(const result::field &F) : super(&m_Buf), m_Buf(F) { }
00919 
00920 private:
00921   field_streambuf<CHAR, TRAITS> m_Buf;
00922 };
00923 
00924 typedef basic_fieldstream<char> fieldstream;
00925 
00926 } // namespace pqxx
00927 
00928 
00929 
00930 /* 
00931 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More 
00932 Effective C++", points out that it is good style to have any class containing 
00933 a member of pointer type define a destructor--just to show that it knows what it
00934 is doing with the pointer.  This helps prevent nasty memory leak / double
00935 deletion bugs typically resulting from programmers' omission to deal with such
00936 issues in their destructors.
00937 
00938 The -Weffc++ option in gcc generates warnings for noncompliance with Scott's
00939 style guidelines, and hence necessitates the definition of this destructor,
00940 trivial as it may be.
00941 */
00942 
00943 

Generated on Mon Nov 15 11:28:00 2004 for libpqxx by  doxygen 1.3.9.1