libpqxx 4.0
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-2011, 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/internal/result_data.hxx"
00032 
00033 #include "pqxx/except"
00034 #include "pqxx/field"
00035 #include "pqxx/tuple"
00036 #include "pqxx/util"
00037 
00038 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
00039  */
00040 
00041 // TODO: Support SQL arrays
00042 
00043 namespace pqxx
00044 {
00045 namespace internal
00046 {
00047 namespace gate
00048 {
00049 class result_connection;
00050 class result_creation;
00051 class result_sql_cursor;
00052 } // namespace internal::gate
00053 } // namespace internal
00054 
00055 
00056 class const_result_iterator;
00057 class const_reverse_result_iterator;
00058 
00059 
00061 
00081 class PQXX_LIBEXPORT result :
00082   private internal::PQAlloc<
00083         const internal::result_data, internal::freemem_result_data>
00084 {
00085   typedef internal::PQAlloc<
00086         const internal::result_data, internal::freemem_result_data> super;
00087 public:
00088   typedef unsigned long size_type;
00089   typedef signed long difference_type;
00090   typedef tuple reference;
00091   typedef const_result_iterator const_iterator;
00092   typedef const_iterator pointer;
00093   typedef const_iterator iterator;
00094   typedef const_reverse_result_iterator const_reverse_iterator;
00095   typedef const_reverse_iterator reverse_iterator;
00096 
00097   result() throw () : super(), m_data(0) {}                             //[t3]
00098   result(const result &rhs) throw () :                                  //[t1]
00099         super(rhs), m_data(rhs.m_data) {}
00100 
00101   result &operator=(const result &rhs) throw ()                         //[t10]
00102         { super::operator=(rhs); m_data=rhs.m_data; return *this; }
00103 
00108   bool operator==(const result &) const throw ();                       //[t70]
00109   bool operator!=(const result &rhs) const throw ()                     //[t70]
00110         { return !operator==(rhs); }
00112 
00113   const_reverse_iterator rbegin() const;                                //[t75]
00114   const_reverse_iterator rend() const;                                  //[t75]
00115 
00116   const_iterator begin() const throw ();                                //[t1]
00117   inline const_iterator end() const throw ();                           //[t1]
00118 
00119   reference front() const throw () { return tuple(this,0); }            //[t74]
00120   reference back() const throw () {return tuple(this,size()-1);}        //[t75]
00121 
00122   size_type PQXX_PURE size() const throw ();                            //[t2]
00123   bool PQXX_PURE empty() const throw ();                                //[t11]
00124   size_type capacity() const throw () { return size(); }                //[t20]
00125 
00126   void swap(result &) throw ();                                         //[t77]
00127 
00128   const tuple operator[](size_type i) const throw ()                    //[t2]
00129         { return tuple(this, i); }
00130   const tuple at(size_type) const throw (range_error);                  //[t10]
00131 
00132   void clear() throw () { super::reset(); m_data = 0; }                 //[t20]
00133 
00138 
00139   tuple::size_type PQXX_PURE columns() const throw ();                  //[t11]
00140 
00142   tuple::size_type column_number(const char ColName[]) const;           //[t11]
00143 
00145   tuple::size_type column_number(const PGSTD::string &Name) const       //[t11]
00146         {return column_number(Name.c_str());}
00147 
00149   const char *column_name(tuple::size_type Number) const;               //[t11]
00150 
00152   oid column_type(tuple::size_type ColNum) const;                       //[t7]
00154   oid column_type(int ColNum) const                                     //[t7]
00155         { return column_type(tuple::size_type(ColNum)); }
00156 
00158   oid column_type(const PGSTD::string &ColName) const                   //[t7]
00159         { return column_type(column_number(ColName)); }
00160 
00162   oid column_type(const char ColName[]) const                           //[t7]
00163         { return column_type(column_number(ColName)); }
00164 
00166   oid column_table(tuple::size_type ColNum) const;                      //[t2]
00167 
00169   oid column_table(int ColNum) const                                    //[t2]
00170         { return column_table(tuple::size_type(ColNum)); }
00171 
00173   oid column_table(const PGSTD::string &ColName) const                  //[t2]
00174         { return column_table(column_number(ColName)); }
00175 
00177   tuple::size_type table_column(tuple::size_type ColNum) const;         //[t93]
00178 
00180   tuple::size_type table_column(int ColNum) const                       //[t93]
00181         { return table_column(tuple::size_type(ColNum)); }
00182 
00184   tuple::size_type table_column(const PGSTD::string &ColName) const     //[t93]
00185         { return table_column(column_number(ColName)); }
00187 
00189   const PGSTD::string & PQXX_PURE query() const throw ();               //[t70]
00190 
00192 
00195   oid PQXX_PURE inserted_oid() const;                                   //[t13]
00196 
00198 
00201   size_type PQXX_PURE affected_rows() const;                            //[t7]
00202 
00203 
00204 private:
00205   friend class pqxx::field;
00206   const char * PQXX_PURE GetValue(size_type Row, tuple::size_type Col) const;
00207   bool PQXX_PURE GetIsNull(size_type Row, tuple::size_type Col) const;
00208   field::size_type PQXX_PURE GetLength(
00209         size_type,
00210         tuple::size_type) const throw ();
00211 
00212   friend class pqxx::internal::gate::result_creation;
00213   result(internal::pq::PGresult *rhs,
00214         int protocol,
00215         const PGSTD::string &Query,
00216         int encoding_code);
00217   void PQXX_PRIVATE CheckStatus() const;
00218 
00219   friend class pqxx::internal::gate::result_connection;
00220   bool operator!() const throw () { return !m_data; }
00221   operator bool() const throw () { return m_data != 0; }
00222 
00223   void PQXX_PRIVATE PQXX_NORETURN ThrowSQLError(
00224         const PGSTD::string &Err,
00225         const PGSTD::string &Query) const;
00226   int PQXX_PRIVATE PQXX_PURE errorposition() const throw ();
00227   PGSTD::string PQXX_PRIVATE StatusError() const;
00228 
00229   friend class pqxx::internal::gate::result_sql_cursor;
00230   const char * PQXX_PURE CmdStatus() const throw ();
00231 
00233   pqxx::internal::pq::PGresult *m_data;
00234 
00235   static const PGSTD::string PQXX_PRIVATE s_empty_string;
00236 };
00237 
00238 
00240 
00244 class PQXX_LIBEXPORT const_result_iterator :
00245   public PGSTD::iterator<
00246         PGSTD::random_access_iterator_tag,
00247         const tuple,
00248         result::difference_type,
00249         const_result_iterator,
00250         tuple>,
00251   public tuple
00252 {
00253 public:
00254   typedef const tuple *pointer;
00255   typedef tuple reference;
00256   typedef result::size_type size_type;
00257   typedef result::difference_type difference_type;
00258 
00259   const_result_iterator() throw () : tuple(0,0) {}
00260   const_result_iterator(const tuple &t) throw () : tuple(t) {}
00261 
00277   pointer operator->() const { return this; }                           //[t12]
00278   reference operator*() const { return tuple(*this); }                  //[t12]
00280 
00285   const_result_iterator operator++(int);                                //[t12]
00286   const_result_iterator &operator++() { ++m_Index; return *this; }      //[t1]
00287   const_result_iterator operator--(int);                                //[t12]
00288   const_result_iterator &operator--() { --m_Index; return *this; }      //[t12]
00289 
00290   const_result_iterator &operator+=(difference_type i)                  //[t12]
00291       { m_Index = size_type(difference_type(m_Index) + i); return *this; }
00292   const_result_iterator &operator-=(difference_type i)                  //[t12]
00293       { m_Index = size_type(difference_type (m_Index) - i); return *this; }
00295 
00300   bool operator==(const const_result_iterator &i) const                 //[t12]
00301       {return m_Index==i.m_Index;}
00302   bool operator!=(const const_result_iterator &i) const                 //[t12]
00303       {return m_Index!=i.m_Index;}
00304   bool operator<(const const_result_iterator &i) const                  //[t12]
00305       {return m_Index<i.m_Index;}
00306   bool operator<=(const const_result_iterator &i) const                 //[t12]
00307       {return m_Index<=i.m_Index;}
00308   bool operator>(const const_result_iterator &i) const                  //[t12]
00309       {return m_Index>i.m_Index;}
00310   bool operator>=(const const_result_iterator &i) const                 //[t12]
00311       {return m_Index>=i.m_Index;}
00313 
00318   inline const_result_iterator operator+(difference_type) const;        //[t12]
00319   friend const_result_iterator operator+(                               //[t12]
00320         difference_type,
00321         const_result_iterator);
00322   inline const_result_iterator operator-(difference_type) const;        //[t12]
00323   inline difference_type operator-(const_result_iterator) const;        //[t12]
00325 
00326 private:
00327   friend class pqxx::result;
00328   const_result_iterator(const pqxx::result *r, result::size_type i) throw () :
00329       tuple(r, i) {}
00330 };
00331 
00332 
00334 class PQXX_LIBEXPORT const_reverse_result_iterator :
00335   private const_result_iterator
00336 {
00337 public:
00338   typedef const_result_iterator super;
00339   typedef const_result_iterator iterator_type;
00340   using iterator_type::iterator_category;
00341   using iterator_type::difference_type;
00342   using iterator_type::pointer;
00343 #ifndef _MSC_VER
00344   using iterator_type::value_type;
00345   using iterator_type::reference;
00346 #else
00347   // Workaround for Visual C++.NET 2003, which has access problems
00348   typedef const tuple &reference;
00349   typedef tuple value_type;
00350 #endif
00351 
00352   const_reverse_result_iterator(                                        //[t75]
00353         const const_reverse_result_iterator &rhs) :
00354     const_result_iterator(rhs) {}
00355   explicit const_reverse_result_iterator(                               //[t75]
00356         const const_result_iterator &rhs) :
00357     const_result_iterator(rhs) { super::operator--(); }
00358 
00359   const_result_iterator PQXX_PURE base() const throw ();                //[t75]
00360 
00365   using const_result_iterator::operator->;                              //[t75]
00366   using const_result_iterator::operator*;                               //[t75]
00368 
00373   const_reverse_result_iterator &operator=(                             //[t75]
00374         const const_reverse_result_iterator &r)
00375       { iterator_type::operator=(r); return *this; }
00376   const_reverse_result_iterator operator++()                            //[t75]
00377       { iterator_type::operator--(); return *this; }
00378   const_reverse_result_iterator operator++(int);                        //[t75]
00379   const_reverse_result_iterator &operator--()                           //[t75]
00380       { iterator_type::operator++(); return *this; }
00381   const_reverse_result_iterator operator--(int);                        //[t75]
00382   const_reverse_result_iterator &operator+=(difference_type i)          //[t75]
00383       { iterator_type::operator-=(i); return *this; }
00384   const_reverse_result_iterator &operator-=(difference_type i)          //[t75]
00385       { iterator_type::operator+=(i); return *this; }
00387 
00392   const_reverse_result_iterator operator+(difference_type i) const      //[t75]
00393       { return const_reverse_result_iterator(base() - i); }
00394   const_reverse_result_iterator operator-(difference_type i)            //[t75]
00395       { return const_reverse_result_iterator(base() + i); }
00396   difference_type operator-(                                            //[t75]
00397         const const_reverse_result_iterator &rhs) const
00398       { return rhs.const_result_iterator::operator-(*this); }
00400 
00405   bool operator==(                                                      //[t75]
00406         const const_reverse_result_iterator &rhs) const throw ()
00407       { return iterator_type::operator==(rhs); }
00408   bool operator!=(                                                      //[t75]
00409         const const_reverse_result_iterator &rhs) const throw ()
00410       { return !operator==(rhs); }
00411 
00412   bool operator<(const const_reverse_result_iterator &rhs) const        //[t75]
00413       { return iterator_type::operator>(rhs); }
00414   bool operator<=(const const_reverse_result_iterator &rhs) const       //[t75]
00415       { return iterator_type::operator>=(rhs); }
00416   bool operator>(const const_reverse_result_iterator &rhs) const        //[t75]
00417       { return iterator_type::operator<(rhs); }
00418   bool operator>=(const const_reverse_result_iterator &rhs) const       //[t75]
00419       { return iterator_type::operator<=(rhs); }
00421 };
00422 
00423 
00424 
00426 
00446 template<typename CHAR>
00447 inline PGSTD::basic_ostream<CHAR> &operator<<(
00448         PGSTD::basic_ostream<CHAR> &S, const pqxx::field &F)            //[t46]
00449 {
00450   S.write(F.c_str(), PGSTD::streamsize(F.size()));
00451   return S;
00452 }
00453 
00454 
00456 template<typename T>
00457 inline void from_string(const field &F, T &Obj)                         //[t46]
00458         { from_string(F.c_str(), Obj, F.size()); }
00459 
00461 template<>
00462 inline PGSTD::string to_string(const field &Obj)                        //[t74]
00463         { return PGSTD::string(Obj.c_str(), Obj.size()); }
00464 
00465 
00466 inline const_result_iterator
00467 const_result_iterator::operator+(result::difference_type o) const
00468 {
00469   return const_result_iterator(
00470         m_Home, size_type(result::difference_type(m_Index) + o));
00471 }
00472 
00473 inline const_result_iterator
00474 operator+(result::difference_type o, const_result_iterator i)
00475         { return i + o; }
00476 
00477 inline const_result_iterator
00478 const_result_iterator::operator-(result::difference_type o) const
00479 {
00480   return const_result_iterator(
00481         m_Home,
00482         result::size_type(result::difference_type(m_Index) - o));
00483 }
00484 
00485 inline result::difference_type
00486 const_result_iterator::operator-(const_result_iterator i) const
00487         { return result::difference_type(num() - i.num()); }
00488 
00489 inline const_result_iterator result::end() const throw ()
00490         { return const_result_iterator(this, size()); }
00491 
00492 
00493 inline const_reverse_result_iterator
00494 operator+(result::difference_type n,
00495           const const_reverse_result_iterator &i)
00496         { return const_reverse_result_iterator(i.base() - n); }
00497 
00498 } // namespace pqxx
00499 
00500 
00501 #include "pqxx/compiler-internal-post.hxx"
00502 
00503 #endif