00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdexcept>
00020
00021 #include "pqxx/util"
00022
00023
00024
00025
00026
00027
00028
00029 namespace pqxx
00030 {
00031
00033
00040 class PQXX_LIBEXPORT result
00041 {
00042 public:
00043 result() : m_Result(0), m_Refcount(0) {}
00044 result(const result &rhs) :
00045 m_Result(0), m_Refcount(0) { MakeRef(rhs); }
00046 ~result() { LoseRef(); }
00047
00048 result &operator=(const result &);
00049
00050 typedef result_size_type size_type;
00051 class field;
00052
00053
00054
00056
00064 class PQXX_LIBEXPORT tuple
00065 {
00066 public:
00067 typedef tuple_size_type size_type;
00068 tuple(const result *r, result::size_type i) : m_Home(r), m_Index(i) {}
00069 ~tuple() {}
00070
00071 inline field operator[](size_type) const;
00072 field operator[](const char[]) const;
00073 field operator[](const PGSTD::string &s) const
00074 { return operator[](s.c_str()); }
00075 field at(size_type) const;
00076 field at(const char[]) const;
00077 field at(const PGSTD::string &s) const { return at(s.c_str()); }
00078
00079 inline size_type size() const;
00080
00081 #ifdef PQXX_DEPRECATED_HEADERS
00082
00083 result::size_type Row() const { return rownumber(); }
00084
00086 size_type ColumnNumber(const PGSTD::string &ColName) const
00087 { return m_Home->ColumnNumber(ColName); }
00088
00090 size_type ColumnNumber(const char ColName[]) const
00091 { return m_Home->ColumnNumber(ColName); }
00092 #endif
00093
00094 result::size_type rownumber() const { return m_Index; }
00095
00097 size_type column_number(const PGSTD::string &ColName) const
00098 { return m_Home->column_number(ColName); }
00099
00101 size_type column_number(const char ColName[]) const
00102 { return m_Home->column_number(ColName); }
00103
00105 oid column_type(size_type ColNum) const
00106 { return m_Home->column_type(ColNum); }
00107
00109 oid column_type(const PGSTD::string &ColName) const
00110 { return column_type(column_number(ColName)); }
00111
00113 oid column_type(const char ColName[]) const
00114 { return column_type(column_number(ColName)); }
00115
00116 #ifdef HAVE_PQFTABLE
00117 oid column_table(size_type ColNum) const
00118 { return m_Home->column_table(ColNum); }
00119 oid column_table(PGSTD::string &ColName) const
00120 { return column_table(column_number(ColName)); }
00121 #endif
00122
00123 protected:
00124 const result *m_Home;
00125 result::size_type m_Index;
00126
00127
00128 tuple();
00129 };
00130
00131 #ifdef PQXX_DEPRECATED_HEADERS
00132
00133 typedef tuple Tuple;
00134 #endif
00135
00136
00138
00141 class PQXX_LIBEXPORT field : private tuple
00142 {
00143 public:
00144 typedef size_t size_type;
00145
00147
00151 field(const tuple &R, tuple::size_type C) : tuple(R), m_Col(C) {}
00152
00154
00159 const char *c_str() const {return m_Home->GetValue(m_Index,m_Col);}
00160
00161 #ifdef PQXX_DEPRECATED_HEADERS
00162
00163 const char *Name() const {return name();}
00164 #endif
00165
00167 inline const char *name() const;
00168
00170 oid type() const
00171 { return m_Home->column_type(m_Col); }
00172
00173 #ifdef HAVE_PQFTABLE
00174
00175
00177 oid table() const { return m_Home->column_table(m_Col); }
00178 #endif
00179
00181
00190 template<typename T> bool to(T &Obj) const
00191 {
00192 if (is_null())
00193 return false;
00194
00195 try
00196 {
00197 FromString(c_str(), Obj);
00198 }
00199 catch (const PGSTD::exception &e)
00200 {
00201 throw PGSTD::runtime_error("Error reading field " +
00202 PGSTD::string(name()) +
00203 ": " +
00204 e.what());
00205 }
00206 return true;
00207 }
00208
00209
00210 #ifdef NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
00211
00212 template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
00213
00215
00218 template<> bool to<const char *>(const char *&Obj) const;
00219 #endif
00220
00221
00223 template<typename T> bool to(T &Obj, const T &Default) const
00224 {
00225 const bool NotNull = to(Obj);
00226 if (!NotNull)
00227 Obj = Default;
00228 return NotNull;
00229 }
00230
00232
00235 template<typename T> T as(const T &Default) const
00236 {
00237 T Obj;
00238 to(Obj, Default);
00239 return Obj;
00240 }
00241
00242 bool is_null() const { return m_Home->GetIsNull(m_Index,m_Col); }
00243
00244 size_type size() const { return m_Home->GetLength(m_Index,m_Col); }
00245
00246 private:
00247
00248 tuple::size_type m_Col;
00249 };
00250
00251 #ifdef PQXX_DEPRECATED_HEADERS
00252
00253 typedef field Field;
00254 #endif
00255
00257
00261 class PQXX_LIBEXPORT const_iterator :
00262 public PGSTD::iterator<PGSTD::random_access_iterator_tag,
00263 const tuple,
00264 result::size_type>,
00265 public tuple
00266 {
00267 public:
00268 const_iterator() : tuple(0,0) {}
00269
00276 pointer operator->() const { return this; }
00277 reference operator*() const { return *operator->(); }
00278
00279 const_iterator operator++(int);
00280 const_iterator &operator++() { ++m_Index; return *this; }
00281 const_iterator operator--(int);
00282 const_iterator &operator--() { --m_Index; return *this; }
00283
00284 const_iterator &operator+=(difference_type i)
00285 { m_Index+=i; return *this; }
00286 const_iterator &operator-=(difference_type i)
00287 { m_Index-=i; return *this; }
00288
00289 bool operator==(const const_iterator &i) const
00290 {return m_Index==i.m_Index;}
00291 bool operator!=(const const_iterator &i) const
00292 {return m_Index!=i.m_Index;}
00293 bool operator<(const const_iterator &i) const
00294 {return m_Index<i.m_Index;}
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
00302 inline const_iterator operator+(difference_type o) const;
00303
00304 friend const_iterator operator+(difference_type o,
00305 const_iterator i);
00306
00307 inline const_iterator operator-(difference_type o) const;
00308
00309 inline difference_type operator-(const_iterator i) const;
00310
00311 result::size_type num() const { return rownumber(); }
00312
00313 private:
00314 friend class result;
00315 const_iterator(const result *r, result::size_type i) : tuple(r, i) {}
00316 };
00317
00318 const_iterator begin() const { return const_iterator(this, 0); }
00319 inline const_iterator end() const;
00320
00321
00322 size_type size() const { return m_Result ? PQntuples(m_Result) : 0; }
00323 bool empty() const { return !m_Result || !PQntuples(m_Result); }
00324 size_type capacity() const { return size(); }
00325
00326 const tuple operator[](size_type i) const { return tuple(this, i); }
00327 const tuple at(size_type) const;
00328
00329 void clear() { LoseRef(); }
00330
00331 #ifdef PQXX_DEPRECATED_HEADERS
00332
00333 tuple::size_type Columns() const { return columns(); }
00334
00336 tuple::size_type ColumnNumber(const char Name[]) const
00337 {return PQfnumber(m_Result,Name);}
00339 tuple::size_type ColumnNumber(const PGSTD::string &Name) const
00340 {return ColumnNumber(Name.c_str());}
00342 const char *ColumnName(tuple::size_type Number) const
00343 {return PQfname(m_Result,Number);}
00344 #endif
00345
00347 tuple::size_type columns() const { return PQnfields(m_Result); }
00348
00350 tuple::size_type column_number(const char ColName[]) const;
00351
00353 tuple::size_type column_number(const PGSTD::string &Name) const
00354 {return column_number(Name.c_str());}
00355
00357 const char *column_name(tuple::size_type Number) const;
00358
00360 inline oid column_type(tuple::size_type ColNum) const;
00361
00363 oid column_type(const PGSTD::string &ColName) const
00364 { return column_type(column_number(ColName)); }
00365
00367 oid column_type(const char ColName[]) const
00368 { return column_type(column_number(ColName)); }
00369
00370 #ifdef HAVE_PQFTABLE
00371
00372 oid column_table(tuple::size_type ColNum) const;
00373
00375 oid column_table(PGSTD::string &ColName) const
00376 { return column_table(column_number(ColName)); }
00377 #endif
00378
00379 #ifdef PQXX_DEPRECATED_HEADERS
00380
00381 oid InsertedOid() const { return inserted_oid(); }
00383 size_type AffectedRows() const { return affected_rows(); }
00384 #endif
00385
00387
00389 oid inserted_oid() const { return PQoidValue(m_Result); }
00390
00391
00393
00394 size_type affected_rows() const;
00395
00396 private:
00397 PGresult *m_Result;
00398 mutable int *m_Refcount;
00399
00400 friend class result::field;
00401 const char *GetValue(size_type Row, tuple::size_type Col) const;
00402 bool GetIsNull(size_type Row, tuple::size_type Col) const;
00403 field::size_type GetLength(size_type Row, tuple::size_type Col) const;
00404
00405 friend class connection_base;
00406 explicit result(PGresult *rhs) : m_Result(rhs), m_Refcount(0) {MakeRef(rhs);}
00407 result &operator=(PGresult *);
00408 bool operator!() const throw () { return !m_Result; }
00409 operator bool() const throw () { return m_Result != 0; }
00410 void CheckStatus(const PGSTD::string &Query) const;
00411
00412 friend class Cursor;
00413 const char *CmdStatus() const throw () { return PQcmdStatus(m_Result); }
00414
00415
00416 void MakeRef(PGresult *);
00417 void MakeRef(const result &);
00418 void LoseRef() throw ();
00419 };
00420
00421
00423
00430 class PQXX_LIBEXPORT binarystring : private PQAlloc<unsigned char>
00431 {
00432 typedef PQAlloc<unsigned char> super;
00433 public:
00434 typedef size_t size_type;
00435
00437
00440 explicit binarystring(const result::field &F) :
00441 super(),
00442 m_size(0)
00443 {
00444 super::operator=(PQunescapeBytea(reinterpret_cast<unsigned char *>(
00445 const_cast<char *>(F.c_str())), &m_size));
00446
00447
00448 if (!c_ptr())
00449 throw PGSTD::runtime_error("Unable to read bytea field");
00450 }
00451
00453 size_type size() const throw () { return m_size; }
00454
00456 const unsigned char *bytes() const throw () { return c_ptr(); }
00457
00458 private:
00459 size_type m_size;
00460 };
00461
00462
00463
00465
00482 template<typename STREAM>
00483 inline STREAM &operator<<(STREAM &S, const pqxx::result::field &F)
00484 {
00485 S << F.c_str();
00486 return S;
00487 }
00488
00489
00490
00491 inline result::field
00492 result::tuple::operator[](result::tuple::size_type i) const
00493 {
00494 return field(*this, i);
00495 }
00496
00497 inline result::tuple::size_type result::tuple::size() const
00498 {
00499 return m_Home->columns();
00500 }
00501
00502 inline const char *result::field::name() const
00503 {
00504 return m_Home->column_name(m_Col);
00505 }
00506
00508 template<>
00509 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
00510 {
00511 if (is_null()) return false;
00512 Obj = c_str();
00513 return true;
00514 }
00515
00517
00520 template<>
00521 inline bool result::field::to<const char *>(const char *&Obj) const
00522 {
00523 if (is_null()) return false;
00524 Obj = c_str();
00525 return true;
00526 }
00527
00528
00529 inline result::const_iterator
00530 result::const_iterator::operator+(difference_type o) const
00531 {
00532 return const_iterator(m_Home, m_Index + o);
00533 }
00534
00535 inline result::const_iterator
00536 operator+(result::const_iterator::difference_type o,
00537 result::const_iterator i)
00538 {
00539 return i + o;
00540 }
00541
00542 inline result::const_iterator
00543 result::const_iterator::operator-(difference_type o) const
00544 {
00545 return const_iterator(m_Home, m_Index - o);
00546 }
00547
00548 inline result::const_iterator::difference_type
00549 result::const_iterator::operator-(const_iterator i) const
00550 {
00551 return num()-i.num();
00552 }
00553
00554 inline result::const_iterator result::end() const
00555 {
00556 return const_iterator(this, size());
00557 }
00558
00559 inline oid result::column_type(tuple::size_type ColNum) const
00560 {
00561 const oid T = PQftype(m_Result, ColNum);
00562 if (T == oid_none)
00563 throw PGSTD::invalid_argument(
00564 "Attempt to retrieve type of nonexistant column " +
00565 ToString(ColNum) + " "
00566 "of query result");
00567 return T;
00568 }
00569
00570
00571 #ifdef HAVE_PQFTABLE
00572 inline oid result::column_table(tuple::size_type ColNum) const
00573 {
00574 const oid T = PQftable(m_Result, ColNum);
00575
00576
00577
00578
00579
00580 if ((T == InvalidOid) &&
00581 ((ColNum < 0) || (ColNum >= columns())))
00582 throw PGSTD::invalid_argument("Attempt to retrieve table ID for column " +
00583 ToString(ColNum) + " "
00584 "out of " + ToString(columns()));
00585 return T;
00586 }
00587 #endif
00588
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611