00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
#ifdef PQXX_HAVE_IOS
00020 
#include <ios>
00021 
#endif
00022 
00023 
#include <stdexcept>
00024 
00025 
#include "pqxx/util"
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
namespace pqxx
00035 {
00036 
00038 
00045 class PQXX_LIBEXPORT result
00046 {
00047 
public:
00048   result() throw () : m_Result(0), m_l(this), m_r(this) {}              
00049   result(
const result &rhs) 
throw () :                                  
00050           m_Result(0), m_l(
this), m_r(
this) { MakeRef(rhs); }
00051   ~result() { LoseRef(); }                                              
00052   
00053   result &operator=(
const result &) throw ();                           
00054 
00055   typedef 
result_size_type size_type;
00056   class 
field;
00057 
00058   
00059  
00061 
00069   class PQXX_LIBEXPORT 
tuple
00070   {
00071   
public:
00072     typedef tuple_size_type size_type;
00073     tuple(
const result *r, 
result::size_type i) 
throw () : 
00074       m_Home(r), m_Index(i) {}
00075     ~tuple() throw () {} 
00076 
00077     
inline field operator[](size_type) const throw ();                  
00078     field operator[](const 
char[]) const;                               
00079     field operator[](const PGSTD::string &s) const                      
00080         { 
return operator[](s.c_str()); }
00081     field at(size_type) const throw (PGSTD::out_of_range);              
00082     field at(const 
char[]) const;                                       
00083     field at(const PGSTD::string &s)
 const { 
return at(s.c_str()); }    
00084 
00085     
inline size_type size() const throw ();                             
00086 
00087     result::size_type rownumber() const throw () { 
return m_Index; }    
00088 
00090     size_type column_number(
const PGSTD::string &ColName) 
const         
00091         { 
return m_Home->column_number(ColName); }
00092 
00094     size_type column_number(
const char ColName[]) 
const                 
00095         { 
return m_Home->column_number(ColName); }
00096 
00098     oid column_type(size_type ColNum) 
const                             
00099         { 
return m_Home->column_type(ColNum); }
00100 
00102     oid column_type(
const PGSTD::string &ColName) 
const                 
00103         { 
return column_type(column_number(ColName)); }
00104 
00106     oid column_type(
const char ColName[]) 
const                         
00107         { 
return column_type(column_number(ColName)); }
00108 
00109 
#ifdef PQXX_HAVE_PQFTABLE
00110 
    oid column_table(size_type ColNum) 
const                            
00111         { 
return m_Home->column_table(ColNum); }
00112     
oid column_table(
const PGSTD::string &ColName) 
const                
00113         { 
return column_table(column_number(ColName)); }
00114 
#endif
00115 
00116 
00117 
#ifdef PQXX_DEPRECATED_HEADERS
00118 
00119     result::size_type Row()
 const { 
return rownumber(); }
00120 
00122     size_type ColumnNumber(
const PGSTD::string &ColName)
 const 
00123 
        { 
return m_Home->ColumnNumber(ColName); }
00124 
00126     size_type ColumnNumber(
const char ColName[])
 const 
00127 
        { 
return m_Home->ColumnNumber(ColName); }
00128 
#endif
00129 
00130 
00131   
protected:
00132     const result *m_Home;
00133     result::size_type m_Index;
00134 
00135     
00136     tuple();
00137   };
00138 
00140 
00143   class PQXX_LIBEXPORT field : 
private tuple
00144   {
00145   
public:
00146     typedef size_t size_type;
00147 
00149 
00153     field(
const tuple &R, 
tuple::size_type C) 
throw () :                
00154         tuple(R), m_Col(C) {}
00155 
00157 
00162     const char *c_str()
 const {
return m_Home->GetValue(m_Index,m_Col);} 
00163 
00165     
inline const char *name() const;                                    
00166 
00168     oid type() const                                                    
00169         { 
return m_Home->column_type(m_Col); }
00170 
00171 
#ifdef PQXX_HAVE_PQFTABLE
00172 
00173 
00175     
oid table()
 const { 
return m_Home->column_table(m_Col); }           
00176 
#endif
00177 
00179 
00188     template<
typename T> 
bool to(T &Obj) 
const                          
00189     {
00190       
if (is_null())
00191         
return false;
00192 
00193       
try
00194       {
00195         
from_string(c_str(), Obj);
00196       }
00197       
catch (
const PGSTD::exception &e)
00198       {
00199         
throw PGSTD::domain_error(
"Error reading field " + 
00200                                   PGSTD::string(name()) +
00201                                   
": " +
00202                                   e.what());
00203       }
00204       
return true;
00205     }
00206 
00207 
00208 
#ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00209 
00210     
template<> 
bool to<PGSTD::string>(PGSTD::string &Obj) 
const;
00211 
00213 
00216     
template<> 
bool to<const char *>(
const char *&Obj) 
const;
00217 
#endif
00218 
00219 
00221     template<
typename T> 
bool to(T &Obj, 
const T &Default) 
const        
00222     {
00223       
const bool NotNull = to(Obj);
00224       
if (!NotNull)
00225         Obj = Default;
00226       
return NotNull;
00227     }
00228 
00230 
00233     template<
typename T> T as(
const T &Default) 
const                   
00234     {
00235       T Obj;
00236       to(Obj, Default);
00237       
return Obj;
00238     }
00239 
00241     template<
typename T> T as() const                                   
00242     {
00243       T Obj;
00244       
const bool NotNull = to(Obj);
00245       
if (!NotNull) 
throw PGSTD::domain_error(
"Attempt to read null field");
00246       
return Obj;
00247     }
00248 
00249     bool is_null()
 const { 
return m_Home->GetIsNull(m_Index,m_Col); }   
00250 
00251     size_type size()
 const { 
return m_Home->GetLength(m_Index,m_Col); } 
00252 
00253 
#ifdef PQXX_DEPRECATED_HEADERS
00254 
00255     
const char *Name()
 const {
return name();}
00256 
#endif
00257 
00258   
private:
00259     tuple::size_type m_Col;
00260   };
00261 
00263 
00267   class PQXX_LIBEXPORT const_iterator : 
00268     
public PGSTD::iterator<PGSTD::random_access_iterator_tag, 
00269                          const tuple,
00270                          result::size_type>, 
00271     
public tuple
00272   {
00273   
public:
00274     const_iterator() : tuple(0,0) {}
00275 
00282     pointer operator->()  const { 
return this; }                        
00283     reference operator*()
 const { 
return *operator->(); }               
00284 
00285     const_iterator operator++(
int);                                     
00286     const_iterator &operator++() { ++m_Index; 
return *
this; }           
00287     const_iterator operator--(
int);                                     
00288     const_iterator &operator--() { --m_Index; 
return *
this; }           
00289 
00290     const_iterator &operator+=(difference_type i)                       
00291         { m_Index+=i; 
return *
this; }
00292     const_iterator &operator-=(difference_type i)                       
00293         { m_Index-=i; 
return *
this; }
00294 
00295     bool operator==(
const const_iterator &i) 
const                      
00296         {
return m_Index==i.m_Index;}
00297     bool operator!=(
const const_iterator &i) 
const                      
00298         {
return m_Index!=i.m_Index;}
00299     bool operator<(
const const_iterator &i) 
const                       
00300          {
return m_Index<i.m_Index;}
00301     bool operator<=(
const const_iterator &i) 
const                      
00302         {
return m_Index<=i.m_Index;}
00303     bool operator>(
const const_iterator &i) 
const                       
00304         {
return m_Index>i.m_Index;}
00305     bool operator>=(
const const_iterator &i) 
const                      
00306         {
return m_Index>=i.m_Index;}
00307 
00308     
inline const_iterator 
operator+(difference_type o) 
const;           
00309 
00310     
friend const_iterator 
operator+(difference_type o, 
00311                                     const_iterator i);                  
00312 
00313     
inline const_iterator operator-(difference_type o) 
const;           
00314 
00315     
inline difference_type operator-(const_iterator i) 
const;           
00316 
00317     result::size_type num()
 const { 
return rownumber(); }               
00318 
00319   
private:
00320     
friend class result;
00321     const_iterator(
const result *r, 
result::size_type i) : tuple(r, i) {}
00322   };
00323 
00324 
#ifdef PQXX_HAVE_REVERSE_ITERATOR
00325 
  typedef PGSTD::reverse_iterator<const_iterator> const_reverse_iterator;
00326   const_reverse_iterator rbegin() const                                 
00327         { 
return const_reverse_iterator(end()); }
00328   const_reverse_iterator rend() const                                   
00329         { 
return const_reverse_iterator(begin()); }
00330 
#endif
00331 
00332   const_iterator begin()
 const { 
return const_iterator(
this, 0); }      
00333   
inline const_iterator end() const;                                    
00334 
00335   size_type size() const                                                
00336         { 
return m_Result ? internal::pq::PQntuples(m_Result) : 0; }
00337   bool empty() const                                                    
00338         { 
return !m_Result || !internal::pq::PQntuples(m_Result); }
00339   size_type capacity()
 const { 
return size(); }                         
00340 
00341   
void swap(result &other) 
throw ();                                    
00342 
00343   const tuple operator[](size_type i) 
const throw ()                    
00344         { 
return tuple(
this, i); }
00345   
const tuple at(size_type) const throw (PGSTD::out_of_range);          
00346 
00347   void clear() throw () { LoseRef(); }                                  
00348 
00350   tuple::size_type columns() const throw ()                             
00351         { 
return PQnfields(m_Result); }
00352 
00354   tuple::size_type column_number(
const char ColName[]) 
const;           
00355 
00357   tuple::size_type column_number(
const PGSTD::string &Name) 
const       
00358         {
return column_number(Name.c_str());}
00359 
00361   
const char *column_name(tuple::size_type Number) 
const;               
00362 
00364   
inline oid column_type(tuple::size_type ColNum) 
const;                
00365 
00367   oid column_type(
const PGSTD::string &ColName) 
const                   
00368         { 
return column_type(column_number(ColName)); }
00369 
00371   oid column_type(
const char ColName[]) 
const                           
00372         { 
return column_type(column_number(ColName)); }
00373 
00374 
#ifdef PQXX_HAVE_PQFTABLE
00375 
00376   
oid column_table(tuple::size_type ColNum) 
const;                      
00377 
00379   
oid column_table(
const PGSTD::string &ColName) 
const                  
00380         { 
return column_table(column_number(ColName)); }
00381 
#endif
00382 
00384 
00386   oid inserted_oid()
 const { 
return PQoidValue(m_Result); }             
00387 
00388 
00390   
00391   size_type affected_rows() const;                                      
00392 
00393 
00394 #ifdef PQXX_DEPRECATED_HEADERS
00396   typedef tuple Tuple;
00398   typedef field Field;
00400   
oid InsertedOid()
 const { 
return inserted_oid(); }
00402   size_type AffectedRows()
 const { 
return affected_rows(); }
00404   tuple::size_type Columns()
 const { 
return columns(); }
00406   tuple::size_type ColumnNumber(
const char Name[])
 const
00407 
        {
return PQfnumber(m_Result,Name);}
00409   tuple::size_type ColumnNumber(
const PGSTD::string &Name)
 const
00410 
        {
return ColumnNumber(Name.c_str());}
00412   
const char *ColumnName(tuple::size_type Number)
 const
00413 
        {
return PQfname(m_Result,Number);}
00414 
#endif
00415 
00416 
00417 
private:
00418   internal::pq::PGresult *m_Result;
00419   
mutable const result *m_l, *m_r;
00420 
00421   
friend class result::field;
00422   
const char *GetValue(size_type Row, tuple::size_type Col) 
const;
00423   
bool GetIsNull(size_type Row, tuple::size_type Col) 
const;
00424   field::size_type GetLength(size_type Row, tuple::size_type Col) 
const;
00425 
00426   
friend class connection_base;
00427   
friend class pipeline;
00428   
explicit result(internal::pq::PGresult *rhs) 
throw () : 
00429     m_Result(0), m_l(
this), m_r(
this) {MakeRef(rhs);}
00430   result &operator=(internal::pq::PGresult *) throw ();
00431   
bool operator!() const throw () { 
return !m_Result; }
00432   operator bool() const throw () { 
return m_Result != 0; }
00433   
void CheckStatus(
const PGSTD::string &Query) 
const;
00434   
void CheckStatus(
const char Query[]) 
const;
00435   
int errorposition() const throw ();
00436   PGSTD::string StatusError() const;
00437 
00438   friend class Cursor;
00439   const 
char *CmdStatus() const throw () { 
return PQcmdStatus(m_Result); }
00440 
00441 
00442   
void MakeRef(internal::pq::PGresult *) throw ();
00443   
void MakeRef(const result &) throw ();
00444   
void LoseRef() throw ();
00445 };
00446 
00447 
00449 
00466 template<typename STREAM>
00467 inline STREAM &operator<<(STREAM &S, const pqxx::result::field &F)      
00468 {
00469   S.write(F.c_str(), F.size());
00470   
return S;
00471 }
00472 
00473 
00475 
template<
typename T>
00476 inline void from_string(
const result::field &F, T &Obj)                 
00477         { 
from_string(F.
c_str(), Obj); }
00478 
00480 
template<>
00481 inline PGSTD::string 
to_string(
const result::field &Obj)                
00482         { 
return to_string(Obj.
c_str()); }
00483 
00484 
inline result::field 
00485 result::tuple::operator[](
result::tuple::size_type i) 
const  throw ()
00486 { 
00487   
return field(*
this, i); 
00488 }
00489 
00490 inline result::tuple::size_type result::tuple::size() const throw ()
00491 { 
00492   
return m_Home->
columns(); 
00493 }
00494 
00495 inline const char *result::field::name()
 const 
00496 
{ 
00497   
return m_Home->
column_name(m_Col); 
00498 }
00499 
00501 
template<> 
00502 
inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) 
const
00503 {
00504   
if (is_null()) 
return false;
00505   Obj = c_str();
00506   
return true;
00507 }
00508 
00510 
00513 
template<> 
00514 
inline bool result::field::to<const char *>(
const char *&Obj) 
const
00515 {
00516   
if (is_null()) 
return false;
00517   Obj = c_str();
00518   
return true;
00519 }
00520 
00521 
00522 
inline result::const_iterator 
00523 result::const_iterator::operator+(difference_type o)
 const
00524 
{
00525   
return const_iterator(m_Home, m_Index + o);
00526 }
00527 
00528 
inline result::const_iterator 
00529 operator+(result::const_iterator::difference_type o, 
00530           
result::const_iterator i)
00531 {
00532   
return i + o;
00533 }
00534 
00535 
inline result::const_iterator 
00536 result::const_iterator::operator-(difference_type o)
 const
00537 
{
00538   
return const_iterator(m_Home, m_Index - o);
00539 }
00540 
00541 
inline result::const_iterator::difference_type 
00542 result::const_iterator::operator-(const_iterator i)
 const
00543 
{ 
00544   
return num()-i.
num(); 
00545 }
00546 
00547 inline result::const_iterator result::end()
 const 
00548 
{ 
00549   
return const_iterator(
this, 
size()); 
00550 }
00551 
00552 inline oid result::column_type(
tuple::size_type ColNum)
 const
00553 
{
00554   
const oid T = PQftype(m_Result, ColNum);
00555   
if (T == 
oid_none)
00556     
throw PGSTD::invalid_argument(
00557                 
"Attempt to retrieve type of nonexistant column " +
00558                 
to_string(ColNum) + 
" "
00559                 
"of query result");
00560   
return T;
00561 }
00562 
00563 
00564 
#ifdef PQXX_HAVE_PQFTABLE
00565 
inline oid result::column_table(tuple::size_type ColNum)
 const
00566 
{
00567   
const oid T = PQftable(m_Result, ColNum);
00568 
00569   
00570 
00571 
00572   
00573   
if ((T == 
oid_none) &&
00574       ((ColNum < 0) || (ColNum >= 
columns())))
00575     
throw PGSTD::invalid_argument(
"Attempt to retrieve table ID for column " +
00576                                   
to_string(ColNum) + 
" "
00577                                   
"out of " + 
to_string(
columns()));
00578   
return T;
00579 }
00580 
#endif
00581 
00582 
00583 
template<
typename CHAR=
char, 
typename TRAITS=PGSTD::
char_traits<CHAR> >
00584   class field_streambuf :
00585 #ifdef 
PQXX_HAVE_STREAMBUF
00586   
public PGSTD::basic_streambuf<CHAR, TRAITS>
00587 #else
00588   
public PGSTD::streambuf
00589 #endif
00590 {
00591   
typedef long size_type;
00592 
public:
00593   typedef CHAR 
char_type;
00594   typedef TRAITS 
traits_type;
00595   typedef typename traits_type::int_type 
int_type;
00596 
#ifdef PQXX_HAVE_STREAMBUF
00597 
  typedef typename traits_type::pos_type 
pos_type;
00598   
typedef typename traits_type::off_type 
off_type;
00599 
#else
00600   typedef streamoff 
off_type;
00601   typedef streampos 
pos_type;
00602 
#endif
00603   typedef PGSTD::ios::openmode 
openmode;
00604   typedef PGSTD::ios::seekdir 
seekdir;
00605 
00606   explicit field_streambuf(
const result::field &F) :                    
00607     m_Field(F)
00608   {
00609     initialize();
00610   }
00611 
00612 
#ifdef PQXX_HAVE_STREAMBUF
00613 
protected:
00614 
#endif
00615   virtual int sync() { 
return traits_type::eof(); }
00616 
00617 
protected:
00618   virtual pos_type seekoff(
off_type, 
seekdir, 
openmode)
00619   {
00620     
return traits_type::eof();
00621   }
00622 
00623   virtual pos_type seekpos(
pos_type, 
openmode) {
return traits_type::eof();}
00624 
00625   virtual int_type overflow(
int_type) { 
return traits_type::eof(); }
00626 
00627   virtual int_type underflow() { 
return traits_type::eof(); }
00628 
00629 
private:
00630   
const result::field &m_Field;
00631 
00632   int_type initialize() throw ()
00633   {
00634     char_type *G = 
00635       reinterpret_cast<char_type *>(const_cast<char *>(m_Field.
c_str()));
00636     setg(G, G, G + m_Field.
size());
00637     
return m_Field.
size();
00638   }
00639 };
00640 
00641 
00643 
00657 
template<
typename CHAR=
char, 
typename TRAITS=PGSTD::
char_traits<CHAR> >
00658   class basic_fieldstream :
00659 #ifdef 
PQXX_HAVE_STREAMBUF
00660     
public PGSTD::basic_istream<CHAR, TRAITS>
00661 #else
00662     
public PGSTD::istream
00663 #endif
00664 {
00665 
#ifdef PQXX_HAVE_STREAMBUF
00666 
  typedef PGSTD::basic_istream<CHAR, TRAITS> super;
00667 
#else
00668 
  typedef PGSTD::istream super;
00669 
#endif
00670 
00671 
public:
00672   typedef CHAR 
char_type;
00673   typedef TRAITS 
traits_type;
00674   typedef typename traits_type::int_type 
int_type;
00675   typedef typename traits_type::pos_type 
pos_type;
00676   typedef typename traits_type::off_type 
off_type;
00677 
00678   basic_fieldstream(
const result::field &F) : super(&m_Buf), m_Buf(F) { }
00679 
00680 
private:
00681   
field_streambuf<CHAR, TRAITS> m_Buf;
00682 };
00683 
00684 typedef basic_fieldstream<char> fieldstream;
00685 
00686 } 
00687 
00688 
00689 
00690 
00691 
00692 
00693 
00694 
00695 
00696 
00697 
00698 
00699 
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00707 
00708