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