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