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-2010, 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/strconv"
00033 #include "pqxx/util"
00034 
00035 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
00036  */
00037 
00038 // TODO: Support SQL arrays
00039 
00040 namespace pqxx
00041 {
00042 class result;
00043 
00044 namespace internal
00045 {
00046 class sql_cursor;
00047 
00049 struct PQXX_PRIVATE result_data
00050 {
00052 
00055   pqxx::internal::pq::PGresult *data;
00056 
00058   int protocol;
00059 
00061   PGSTD::string query;
00062 
00063   int encoding_code;
00064 
00065   // TODO: Locking for result copy-construction etc. also goes here
00066 
00067   result_data();
00068   result_data(pqxx::internal::pq::PGresult *,
00069                 int protocol,
00070                 const PGSTD::string &,
00071                 int encoding_code);
00072   ~result_data();
00073 };
00074 
00075 void PQXX_LIBEXPORT freemem_result_data(const result_data *) throw ();
00076 } // namespace internal
00077 
00078 
00079 namespace internal
00080 {
00081 namespace gate
00082 {
00083 class result_connection;
00084 class result_creation;
00085 class result_sql_cursor;
00086 } // namespace internal::gate
00087 } // namespace internal
00088 
00089 
00091 
00111 class PQXX_LIBEXPORT result :
00112   private internal::PQAlloc<
00113         const internal::result_data, internal::freemem_result_data>
00114 {
00115   typedef internal::PQAlloc<
00116         const internal::result_data, internal::freemem_result_data> super;
00117 public:
00118   class const_iterator;
00119   class const_fielditerator;
00120   class const_reverse_fielditerator;
00121   class tuple;
00122   class field;
00123   typedef unsigned long size_type;
00124   typedef signed long difference_type;
00125   typedef tuple reference;
00126   typedef const_iterator pointer;
00127 
00129 
00140   class PQXX_LIBEXPORT tuple
00141   {
00142   public:
00143     typedef unsigned int size_type;
00144     typedef signed int difference_type;
00145     typedef const_fielditerator const_iterator;
00146     typedef const_iterator iterator;
00147     typedef field reference;
00148     typedef const_fielditerator pointer;
00149     typedef const_reverse_fielditerator const_reverse_iterator;
00150     typedef const_reverse_iterator reverse_iterator;
00151 
00153     tuple(const result *r, result::size_type i) throw () :
00154       m_Home(r), m_Index(i), m_Begin(0), m_End(r ? r->columns() : 0) {}
00155 
00156     ~tuple() throw () {} // Yes Scott Meyers, you're absolutely right[1]
00157 
00162     bool operator==(const tuple &) const throw ();                      //[t75]
00163     bool operator!=(const tuple &rhs) const throw ()                    //[t75]
00164         { return !operator==(rhs); }
00166 
00167     const_iterator begin() const throw ()                               //[t82]
00168         { return const_iterator(*this, m_Begin); }
00169     const_iterator end() const throw ()                                 //[t82]
00170         { return const_iterator(*this, m_End); }
00171 
00176     reference front() const throw () { return field(*this, m_Begin); }  //[t74]
00177     reference back() const throw () { return field(*this, m_End-1); }   //[t75]
00178 
00179     const_reverse_fielditerator rbegin() const;                         //[t82]
00180     const_reverse_fielditerator rend() const;                           //[t82]
00181 
00182     reference operator[](size_type i) const throw ()                    //[t11]
00183         { return field(*this, m_Begin+i); }
00184     reference operator[](int i) const throw ()                          //[t2]
00185         { return operator[](size_type(i)); }
00186     reference operator[](const char f[]) const                          //[t11]
00187         { return at(f); }
00188     reference operator[](const PGSTD::string &s) const                  //[t11]
00189         { return operator[](s.c_str()); }
00190     reference at(size_type) const throw (range_error);                  //[t11]
00191     reference at(int i) const throw (range_error)                       //[t11]
00192         { return at(size_type(i)); }
00193     reference at(const char[]) const;                                   //[t11]
00194     reference at(const PGSTD::string &s) const                          //[t11]
00195         { return at(s.c_str()); }
00197 
00198     size_type size() const throw () { return m_End-m_Begin; }           //[t11]
00199 
00200     void swap(tuple &) throw ();                                        //[t11]
00201 
00202     result::size_type rownumber() const throw () { return m_Index; }    //[t11]
00203 
00208 
00209     size_type column_number(const PGSTD::string &ColName) const         //[t30]
00210         { return column_number(ColName.c_str()); }
00211 
00213     size_type column_number(const char[]) const;                        //[t30]
00214 
00216     oid column_type(size_type ColNum) const                             //[t7]
00217         { return m_Home->column_type(m_Begin+ColNum); }
00218 
00220     oid column_type(int ColNum) const                                   //[t7]
00221         { return column_type(size_type(ColNum)); }
00222 
00224     oid column_type(const PGSTD::string &ColName) const                 //[t7]
00225         { return column_type(column_number(ColName)); }
00226 
00228     oid column_type(const char ColName[]) const                         //[t7]
00229         { return column_type(column_number(ColName)); }
00230 
00232 
00239     oid column_table(size_type ColNum) const                            //[t2]
00240         { return m_Home->column_table(m_Begin+ColNum); }
00242 
00249     oid column_table(int ColNum) const                                  //[t2]
00250         { return column_table(size_type(ColNum)); }
00252 
00259     oid column_table(const PGSTD::string &ColName) const                //[t2]
00260         { return column_table(column_number(ColName)); }
00261 
00263 
00273     size_type table_column(size_type ColNum) const                      //[t93]
00274         { return m_Home->table_column(m_Begin+ColNum); }
00275 
00277     size_type table_column(int ColNum) const                            //[t93]
00278         { return table_column(size_type(ColNum)); }
00279 
00281     size_type table_column(const PGSTD::string &ColName) const          //[t93]
00282         { return table_column(column_number(ColName)); }
00284 
00285     result::size_type num() const { return rownumber(); }               //[t1]
00286 
00299     tuple slice(size_type Begin, size_type End) const;
00300 
00301     // Is this an empty slice?
00302     bool empty() const throw ();
00303 
00304   protected:
00305     friend class field;
00306     const result *m_Home;
00307     result::size_type m_Index;
00308     size_type m_Begin;
00309     size_type m_End;
00310 
00311   private:
00312     // Not allowed:
00313     tuple();
00314   };
00315 
00317 
00320   class PQXX_LIBEXPORT field
00321   {
00322   public:
00323     typedef size_t size_type;
00324 
00326 
00330     field(const tuple &T, tuple::size_type C) throw () :                //[t1]
00331         m_tup(T), m_col(C) {}
00332 
00337 
00338 
00354     bool operator==(const field &) const;                               //[t75]
00355 
00357 
00359     bool operator!=(const field &rhs) const {return !operator==(rhs);}  //[t82]
00361 
00366 
00367     const char *name() const { return home()->column_name(col()); }     //[t11]
00368 
00370     oid type() const { return home()->column_type(col()); }             //[t7]
00371 
00373 
00380     oid table() const { return home()->column_table(col()); }           //[t2]
00381 
00382     tuple::size_type num() const { return col(); }                      //[t82]
00383 
00385     tuple::size_type table_column() const                               //[t93]
00386         { return home()->table_column(col()); }
00388 
00393 
00394 
00399     const char *c_str() const { return home()->GetValue(idx(),col()); } //[t2]
00400 
00402     template<typename T> bool to(T &Obj) const                          //[t3]
00403     {
00404       const char *const bytes = c_str();
00405       if (!bytes[0] && is_null()) return false;
00406       from_string(bytes, Obj);
00407       return true;
00408     }
00409 
00411     template<typename T> bool operator>>(T &Obj) const                  //[t7]
00412         { return to(Obj); }
00413 
00414 #ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00416     template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00417 
00419 
00422     template<> bool to<const char *>(const char *&Obj) const;
00423 #endif
00424 
00426     template<typename T> bool to(T &Obj, const T &Default) const        //[t12]
00427     {
00428       const bool NotNull = to(Obj);
00429       if (!NotNull) Obj = Default;
00430       return NotNull;
00431     }
00432 
00434 
00437     template<typename T> T as(const T &Default) const                   //[t1]
00438     {
00439       T Obj;
00440       to(Obj, Default);
00441       return Obj;
00442     }
00443 
00445     template<typename T> T as() const                                   //[t45]
00446     {
00447       T Obj;
00448       const bool NotNull = to(Obj);
00449       if (!NotNull) Obj = string_traits<T>::null();
00450       return Obj;
00451     }
00452 
00453     bool is_null() const { return home()->GetIsNull(idx(), col()); }    //[t12]
00454     size_type size() const throw ()                                     //[t11]
00455         { return home()->GetLength(idx(),col()); }
00457 
00458 
00459   private:
00460     const result *home() const throw () { return m_tup.m_Home; }
00461     result::size_type idx() const throw () { return m_tup.m_Index; }
00462 
00463   protected:
00464     tuple::size_type col() const throw () { return m_col; }
00465     tuple m_tup;
00466     tuple::size_type m_col;
00467   };
00468 
00469   typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
00470                            const tuple,
00471                            result::difference_type,
00472                            const_iterator,
00473                            tuple>
00474         const_iterator_base;
00475 
00477 
00481   class PQXX_LIBEXPORT const_iterator :
00482     public const_iterator_base,
00483     public tuple
00484   {
00485   public:
00486     typedef const tuple *pointer;
00487     typedef tuple reference;
00488     typedef result::size_type size_type;
00489     typedef result::difference_type difference_type;
00490 
00491     const_iterator() throw () : tuple(0,0) {}
00492     const_iterator(const tuple &t) throw () : tuple(t) {}
00493 
00509     pointer operator->() const { return this; }                         //[t12]
00510     reference operator*() const { return tuple(*this); }                //[t12]
00512 
00517     const_iterator operator++(int);                                     //[t12]
00518     const_iterator &operator++() { ++m_Index; return *this; }           //[t1]
00519     const_iterator operator--(int);                                     //[t12]
00520     const_iterator &operator--() { --m_Index; return *this; }           //[t12]
00521 
00522     const_iterator &operator+=(difference_type i)                       //[t12]
00523         { m_Index+=i; return *this; }
00524     const_iterator &operator-=(difference_type i)                       //[t12]
00525         { m_Index-=i; return *this; }
00527 
00532     bool operator==(const const_iterator &i) const                      //[t12]
00533         {return m_Index==i.m_Index;}
00534     bool operator!=(const const_iterator &i) const                      //[t12]
00535         {return m_Index!=i.m_Index;}
00536     bool operator<(const const_iterator &i) const                       //[t12]
00537         {return m_Index<i.m_Index;}
00538     bool operator<=(const const_iterator &i) const                      //[t12]
00539         {return m_Index<=i.m_Index;}
00540     bool operator>(const const_iterator &i) const                       //[t12]
00541         {return m_Index>i.m_Index;}
00542     bool operator>=(const const_iterator &i) const                      //[t12]
00543         {return m_Index>=i.m_Index;}
00545 
00550     inline const_iterator operator+(difference_type) const;             //[t12]
00551     friend const_iterator
00552     operator+(difference_type, const_iterator);                         //[t12]
00553     inline const_iterator operator-(difference_type) const;             //[t12]
00554     inline difference_type operator-(const_iterator) const;             //[t12]
00556 
00557   private:
00558     friend class pqxx::result;
00559     const_iterator(const pqxx::result *r, result::size_type i) throw () :
00560         tuple(r, i) {}
00561   };
00562 
00563   typedef const_iterator iterator;
00564 
00565   class PQXX_LIBEXPORT const_reverse_iterator : private const_iterator
00566   {
00567   public:
00568     typedef pqxx::result::const_iterator super;
00569     typedef pqxx::result::const_iterator iterator_type;
00570     using iterator_type::iterator_category;
00571     using iterator_type::difference_type;
00572     using iterator_type::pointer;
00573 #ifndef _MSC_VER
00574     using iterator_type::value_type;
00575     using iterator_type::reference;
00576 #else
00577     // Workaround for Visual C++.NET 2003, which has access problems
00578     typedef const tuple &reference;
00579     typedef tuple value_type;
00580 #endif
00581 
00582     const_reverse_iterator(const const_reverse_iterator &rhs) :         //[t75]
00583       const_iterator(rhs) {}
00584     explicit const_reverse_iterator(const const_iterator &rhs) :        //[t75]
00585       const_iterator(rhs) { super::operator--(); }
00586 
00587     iterator_type base() const throw ();                                //[t75]
00588 
00593     using const_iterator::operator->;                                   //[t75]
00594     using const_iterator::operator*;                                    //[t75]
00596 
00601     const_reverse_iterator &operator=(const const_reverse_iterator &r)  //[t75]
00602         { iterator_type::operator=(r); return *this; }
00603     const_reverse_iterator operator++()                                 //[t75]
00604         { iterator_type::operator--(); return *this; }
00605     const_reverse_iterator operator++(int);                             //[t75]
00606     const_reverse_iterator &operator--()                                //[t75]
00607         { iterator_type::operator++(); return *this; }
00608     const_reverse_iterator operator--(int);                             //[t75]
00609     const_reverse_iterator &operator+=(difference_type i)               //[t75]
00610         { iterator_type::operator-=(i); return *this; }
00611     const_reverse_iterator &operator-=(difference_type i)               //[t75]
00612         { iterator_type::operator+=(i); return *this; }
00614 
00619     const_reverse_iterator operator+(difference_type i) const           //[t75]
00620         { return const_reverse_iterator(base()-i); }
00621     const_reverse_iterator operator-(difference_type i)                 //[t75]
00622         { return const_reverse_iterator(base()+i); }
00623     difference_type operator-(const const_reverse_iterator &rhs) const  //[t75]
00624         { return rhs.const_iterator::operator-(*this); }
00626 
00631     bool operator==(const const_reverse_iterator &rhs) const throw ()   //[t75]
00632         { return iterator_type::operator==(rhs); }
00633     bool operator!=(const const_reverse_iterator &rhs) const throw ()   //[t75]
00634         { return !operator==(rhs); }
00635 
00636     bool operator<(const const_reverse_iterator &rhs) const             //[t75]
00637         { return iterator_type::operator>(rhs); }
00638     bool operator<=(const const_reverse_iterator &rhs) const            //[t75]
00639         { return iterator_type::operator>=(rhs); }
00640     bool operator>(const const_reverse_iterator &rhs) const             //[t75]
00641         { return iterator_type::operator<(rhs); }
00642     bool operator>=(const const_reverse_iterator &rhs) const            //[t75]
00643         { return iterator_type::operator<=(rhs); }
00645   };
00646 
00647   typedef const_reverse_iterator reverse_iterator;
00648 
00649   class PQXX_LIBEXPORT const_fielditerator :
00650     public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00651                            const field,
00652                            tuple::size_type>,
00653     public field
00654   {
00655     typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
00656                                   const field,
00657                                   tuple::size_type> it;
00658   public:
00659     using it::pointer;
00660     typedef tuple::size_type size_type;
00661     typedef tuple::difference_type difference_type;
00662     typedef field reference;
00663 
00664     const_fielditerator(const tuple &T, tuple::size_type C) throw () :  //[t82]
00665       field(T, C) {}
00666     const_fielditerator(const field &F) throw () : field(F) {}          //[t82]
00667 
00672     pointer operator->() const { return this; }                         //[t82]
00673     reference operator*() const { return field(*this); }                //[t82]
00675 
00680     const_fielditerator operator++(int);                                //[t82]
00681     const_fielditerator &operator++() { ++m_col; return *this; }        //[t82]
00682     const_fielditerator operator--(int);                                //[t82]
00683     const_fielditerator &operator--() { --m_col; return *this; }        //[t82]
00684 
00685     const_fielditerator &operator+=(difference_type i)                  //[t82]
00686         { m_col+=i; return *this; }
00687     const_fielditerator &operator-=(difference_type i)                  //[t82]
00688         { m_col-=i; return *this; }
00690 
00695     bool operator==(const const_fielditerator &i) const                 //[t82]
00696         {return col()==i.col();}
00697     bool operator!=(const const_fielditerator &i) const                 //[t82]
00698         {return col()!=i.col();}
00699     bool operator<(const const_fielditerator &i) const                  //[t82]
00700         {return col()<i.col();}
00701     bool operator<=(const const_fielditerator &i) const                 //[t82]
00702         {return col()<=i.col();}
00703     bool operator>(const const_fielditerator &i) const                  //[t82]
00704         {return col()>i.col();}
00705     bool operator>=(const const_fielditerator &i) const                 //[t82]
00706         {return col()>=i.col();}
00708 
00713     inline const_fielditerator operator+(difference_type) const;        //[t82]
00714 
00715     friend const_fielditerator operator+(difference_type,
00716                                           const_fielditerator);         //[t82]
00717 
00718     inline const_fielditerator operator-(difference_type) const;        //[t82]
00719     inline difference_type operator-(const_fielditerator) const;        //[t82]
00721   };
00722 
00723   class PQXX_LIBEXPORT const_reverse_fielditerator : private const_fielditerator
00724   {
00725   public:
00726     typedef const_fielditerator super;
00727     typedef const_fielditerator iterator_type;
00728     using iterator_type::iterator_category;
00729     using iterator_type::difference_type;
00730     using iterator_type::pointer;
00731 #ifndef _MSC_VER
00732     using iterator_type::value_type;
00733     using iterator_type::reference;
00734 #else
00735     // Workaround for Visual C++.NET 2003, which has access problems
00736     typedef field value_type;
00737     typedef const field &reference;
00738 #endif
00739 
00740     const_reverse_fielditerator(const const_reverse_fielditerator &r) : //[t82]
00741       const_fielditerator(r) {}
00742     explicit
00743       const_reverse_fielditerator(const super &rhs) throw() :           //[t82]
00744         const_fielditerator(rhs) { super::operator--(); }
00745 
00746     iterator_type base() const throw ();                                //[t82]
00747 
00752     using iterator_type::operator->;                                    //[t82]
00753     using iterator_type::operator*;                                     //[t82]
00755 
00760     const_reverse_fielditerator &
00761       operator=(const const_reverse_fielditerator &r)                   //[t82]
00762         { iterator_type::operator=(r); return *this; }
00763     const_reverse_fielditerator operator++()                            //[t82]
00764         { iterator_type::operator--(); return *this; }
00765     const_reverse_fielditerator operator++(int);                        //[t82]
00766     const_reverse_fielditerator &operator--()                           //[t82]
00767         { iterator_type::operator++(); return *this; }
00768     const_reverse_fielditerator operator--(int);                        //[t82]
00769     const_reverse_fielditerator &operator+=(difference_type i)          //[t82]
00770         { iterator_type::operator-=(i); return *this; }
00771     const_reverse_fielditerator &operator-=(difference_type i)          //[t82]
00772         { iterator_type::operator+=(i); return *this; }
00774 
00779     const_reverse_fielditerator operator+(difference_type i) const      //[t82]
00780         { return const_reverse_fielditerator(base()-i); }
00781     const_reverse_fielditerator operator-(difference_type i)            //[t82]
00782         { return const_reverse_fielditerator(base()+i); }
00783     difference_type
00784       operator-(const const_reverse_fielditerator &rhs) const           //[t82]
00785         { return rhs.const_fielditerator::operator-(*this); }
00787 
00792     bool
00793       operator==(const const_reverse_fielditerator &rhs) const throw () //[t82]
00794         { return iterator_type::operator==(rhs); }
00795     bool
00796       operator!=(const const_reverse_fielditerator &rhs) const throw () //[t82]
00797         { return !operator==(rhs); }
00798 
00799     bool operator<(const const_reverse_fielditerator &rhs) const        //[t82]
00800         { return iterator_type::operator>(rhs); }
00801     bool operator<=(const const_reverse_fielditerator &rhs) const       //[t82]
00802         { return iterator_type::operator>=(rhs); }
00803     bool operator>(const const_reverse_fielditerator &rhs) const        //[t82]
00804         { return iterator_type::operator<(rhs); }
00805     bool operator>=(const const_reverse_fielditerator &rhs) const       //[t82]
00806         { return iterator_type::operator<=(rhs); }
00808   };
00809 
00810 
00811   result() throw () : super(), m_data(0) {}                             //[t3]
00812   result(const result &rhs) throw () :                                  //[t1]
00813         super(rhs), m_data(rhs.m_data) {}
00814 
00815   result &operator=(const result &rhs) throw ()                         //[t10]
00816         { super::operator=(rhs); m_data=rhs.m_data; return *this; }
00817 
00822   bool operator==(const result &) const throw ();                       //[t70]
00823   bool operator!=(const result &rhs) const throw ()                     //[t70]
00824         { return !operator==(rhs); }
00826 
00827   const_reverse_iterator rbegin() const                                 //[t75]
00828         { return const_reverse_iterator(end()); }
00829   const_reverse_iterator rend() const                                   //[t75]
00830         { return const_reverse_iterator(begin()); }
00831 
00832   const_iterator begin() const throw ()                                 //[t1]
00833         { return const_iterator(this, 0); }
00834   inline const_iterator end() const throw ();                           //[t1]
00835 
00836   reference front() const throw () { return tuple(this,0); }            //[t74]
00837   reference back() const throw () {return tuple(this,size()-1);}        //[t75]
00838 
00839   size_type size() const throw ();                                      //[t2]
00840   bool empty() const throw ();                                          //[t11]
00841   size_type capacity() const throw () { return size(); }                //[t20]
00842 
00843   void swap(result &) throw ();                                         //[t77]
00844 
00845   const tuple operator[](size_type i) const throw ()                    //[t2]
00846         { return tuple(this, i); }
00847   const tuple at(size_type) const throw (range_error);                  //[t10]
00848 
00849   void clear() throw () { super::reset(); m_data = 0; }                 //[t20]
00850 
00855 
00856   tuple::size_type columns() const throw ();                            //[t11]
00857 
00859   tuple::size_type column_number(const char ColName[]) const;           //[t11]
00860 
00862   tuple::size_type column_number(const PGSTD::string &Name) const       //[t11]
00863         {return column_number(Name.c_str());}
00864 
00866   const char *column_name(tuple::size_type Number) const;               //[t11]
00867 
00869   oid column_type(tuple::size_type ColNum) const;                       //[t7]
00871   oid column_type(int ColNum) const                                     //[t7]
00872         { return column_type(tuple::size_type(ColNum)); }
00873 
00875   oid column_type(const PGSTD::string &ColName) const                   //[t7]
00876         { return column_type(column_number(ColName)); }
00877 
00879   oid column_type(const char ColName[]) const                           //[t7]
00880         { return column_type(column_number(ColName)); }
00881 
00883 
00890   oid column_table(tuple::size_type ColNum) const;                      //[t2]
00891 
00893 
00900   oid column_table(int ColNum) const                                    //[t2]
00901         { return column_table(tuple::size_type(ColNum)); }
00902 
00904 
00911   oid column_table(const PGSTD::string &ColName) const                  //[t2]
00912         { return column_table(column_number(ColName)); }
00913 
00915   tuple::size_type table_column(tuple::size_type ColNum) const;         //[t93]
00916 
00918   tuple::size_type table_column(int ColNum) const                       //[t93]
00919         { return table_column(tuple::size_type(ColNum)); }
00920 
00922   tuple::size_type table_column(const PGSTD::string &ColName) const     //[t93]
00923         { return table_column(column_number(ColName)); }
00925 
00927   const PGSTD::string &query() const throw ();                          //[t70]
00928 
00930 
00933   oid inserted_oid() const;                                             //[t13]
00934 
00935 
00937 
00940   size_type affected_rows() const;                                      //[t7]
00941 
00942 
00943 private:
00944   friend class pqxx::result::field;
00945   const char *GetValue(size_type Row, tuple::size_type Col) const;
00946   bool GetIsNull(size_type Row, tuple::size_type Col) const;
00947   field::size_type GetLength(size_type, tuple::size_type) const throw ();
00948 
00949   friend class pqxx::internal::gate::result_creation;
00950   result(internal::pq::PGresult *rhs,
00951         int protocol,
00952         const PGSTD::string &Query,
00953         int encoding_code);
00954   void PQXX_PRIVATE CheckStatus() const;
00955 
00956   friend class pqxx::internal::gate::result_connection;
00957   bool operator!() const throw () { return !m_data; }
00958   operator bool() const throw () { return m_data != 0; }
00959 
00960   void PQXX_PRIVATE ThrowSQLError(const PGSTD::string &Err,
00961         const PGSTD::string &Query) const;
00962   int PQXX_PRIVATE errorposition() const throw ();
00963   PGSTD::string PQXX_PRIVATE StatusError() const;
00964 
00965   friend class pqxx::internal::gate::result_sql_cursor;
00966   const char *CmdStatus() const throw ();
00967 
00969   pqxx::internal::pq::PGresult *m_data;
00970 
00971   static const PGSTD::string PQXX_PRIVATE s_empty_string;
00972 };
00973 
00974 
00976 
00996 template<typename CHAR>
00997 inline PGSTD::basic_ostream<CHAR> &operator<<(
00998         PGSTD::basic_ostream<CHAR> &S, const pqxx::result::field &F)    //[t46]
00999 {
01000   S.write(F.c_str(), F.size());
01001   return S;
01002 }
01003 
01004 
01006 template<typename T>
01007 inline void from_string(const result::field &F, T &Obj)                 //[t46]
01008         { from_string(F.c_str(), Obj, F.size()); }
01009 
01011 template<>
01012 inline PGSTD::string to_string(const result::field &Obj)                //[t74]
01013         { return PGSTD::string(Obj.c_str(), Obj.size()); }
01014 
01015 
01017 template<>
01018 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
01019 {
01020   const char *const bytes = c_str();
01021   if (!bytes[0] && is_null()) return false;
01022   Obj = PGSTD::string(bytes, size());
01023   return true;
01024 }
01025 
01027 
01032 template<>
01033 inline bool result::field::to<const char *>(const char *&Obj) const
01034 {
01035   if (is_null()) return false;
01036   Obj = c_str();
01037   return true;
01038 }
01039 
01040 
01041 inline result::tuple::const_reverse_iterator result::tuple::rbegin() const
01042         { return const_reverse_fielditerator(end()); }
01043 inline result::tuple::const_reverse_iterator result::tuple::rend() const
01044         { return const_reverse_fielditerator(begin()); }
01045 
01046 inline result::const_iterator
01047 result::const_iterator::operator+(difference_type o) const
01048         { return const_iterator(m_Home, m_Index + o); }
01049 
01050 inline result::const_iterator
01051 operator+(result::const_iterator::difference_type o, result::const_iterator i)
01052         { return i + o; }
01053 
01054 inline result::const_iterator
01055 result::const_iterator::operator-(difference_type o) const
01056         { return const_iterator(m_Home, m_Index - o); }
01057 
01058 inline result::const_iterator::difference_type
01059 result::const_iterator::operator-(const_iterator i) const
01060         { return num()-i.num(); }
01061 
01062 inline result::const_iterator result::end() const throw ()
01063         { return const_iterator(this, size()); }
01064 
01065 
01066 inline result::const_reverse_iterator
01067 operator+(result::const_reverse_iterator::difference_type n,
01068           const result::const_reverse_iterator &i)
01069         { return result::const_reverse_iterator(i.base() - n); }
01070 
01071 inline result::const_fielditerator
01072 result::const_fielditerator::operator+(difference_type o) const
01073         { return const_fielditerator(m_tup, col() + o); }
01074 
01075 inline result::const_fielditerator
01076 operator+(result::const_fielditerator::difference_type o,
01077           result::const_fielditerator i)
01078         { return i + o; }
01079 
01080 inline result::const_fielditerator
01081 result::const_fielditerator::operator-(difference_type o) const
01082         { return const_fielditerator(m_tup, col() - o); }
01083 
01084 inline result::const_fielditerator::difference_type
01085 result::const_fielditerator::operator-(const_fielditerator i) const
01086         { return num()-i.num(); }
01087 
01088 
01089 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
01090   class field_streambuf :
01091 #ifdef PQXX_HAVE_STREAMBUF
01092   public PGSTD::basic_streambuf<CHAR, TRAITS>
01093 #else
01094   public PGSTD::streambuf
01095 #endif
01096 {
01097 public:
01098   typedef CHAR char_type;
01099   typedef TRAITS traits_type;
01100   typedef typename traits_type::int_type int_type;
01101 #ifdef PQXX_HAVE_STREAMBUF
01102   typedef typename traits_type::pos_type pos_type;
01103   typedef typename traits_type::off_type off_type;
01104 #else
01105   typedef streamoff off_type;
01106   typedef streampos pos_type;
01107 #endif
01108   typedef PGSTD::ios::openmode openmode;
01109   typedef PGSTD::ios::seekdir seekdir;
01110 
01111   explicit field_streambuf(const result::field &F) :                    //[t74]
01112     m_Field(F)
01113   {
01114     initialize();
01115   }
01116 
01117 #ifdef PQXX_HAVE_STREAMBUF
01118 protected:
01119 #endif
01120   virtual int sync() { return traits_type::eof(); }
01121 
01122 protected:
01123   virtual pos_type seekoff(off_type, seekdir, openmode)
01124         { return traits_type::eof(); }
01125   virtual pos_type seekpos(pos_type, openmode) {return traits_type::eof();}
01126   virtual int_type overflow(int_type) { return traits_type::eof(); }
01127   virtual int_type underflow() { return traits_type::eof(); }
01128 
01129 private:
01130   const result::field &m_Field;
01131 
01132   int_type initialize()
01133   {
01134     char_type *G =
01135       reinterpret_cast<char_type *>(const_cast<char *>(m_Field.c_str()));
01136     setg(G, G, G + m_Field.size());
01137     return int_type(m_Field.size());
01138   }
01139 };
01140 
01141 
01143 
01151 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
01152   class basic_fieldstream :
01153 #ifdef PQXX_HAVE_STREAMBUF
01154     public PGSTD::basic_istream<CHAR, TRAITS>
01155 #else
01156     public PGSTD::istream
01157 #endif
01158 {
01159 #ifdef PQXX_HAVE_STREAMBUF
01160   typedef PGSTD::basic_istream<CHAR, TRAITS> super;
01161 #else
01162   typedef PGSTD::istream super;
01163 #endif
01164 
01165 public:
01166   typedef CHAR char_type;
01167   typedef TRAITS traits_type;
01168   typedef typename traits_type::int_type int_type;
01169   typedef typename traits_type::pos_type pos_type;
01170   typedef typename traits_type::off_type off_type;
01171 
01172   basic_fieldstream(const result::field &F) : super(0), m_Buf(F)
01173         { super::init(&m_Buf); }
01174 
01175 private:
01176   field_streambuf<CHAR, TRAITS> m_Buf;
01177 };
01178 
01179 typedef basic_fieldstream<char> fieldstream;
01180 
01181 } // namespace pqxx
01182 
01183 
01184 
01185 /*
01186 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More
01187 Effective C++", points out that it is good style to have any class containing
01188 a member of pointer type define a destructor--just to show that it knows what it
01189 is doing with the pointer.  This helps prevent nasty memory leak / double
01190 deletion bugs typically resulting from programmers' omission to deal with such
01191 issues in their destructors.
01192 
01193 The @c -Weffc++ option in gcc generates warnings for noncompliance with Scott's
01194 style guidelines, and hence necessitates the definition of this destructor,
01195 trivial as it may be.
01196 */
01197 
01198 
01199 #include "pqxx/compiler-internal-post.hxx"
01200 
01201 #endif
01202 

Generated on Mon Feb 15 18:22:41 2010 for libpqxx by  doxygen 1.5.5