00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pqxx/libcompiler.h"
00020
00021 #ifdef PQXX_HAVE_LIMITS
00022 #include <limits>
00023 #endif
00024
00025 #include "pqxx/result"
00026 #include "pqxx/transaction_base"
00027
00028
00029 namespace pqxx
00030 {
00031 class dbtransaction;
00032
00034
00046 class PQXX_LIBEXPORT cursor_base
00047 {
00048 public:
00049 typedef result::size_type size_type;
00050 typedef result::difference_type difference_type;
00051
00052 virtual ~cursor_base() throw () { close(); }
00053
00055
00058 enum accesspolicy
00059 {
00061 forward_only,
00063 random_access
00064 };
00065
00067
00070 enum updatepolicy
00071 {
00073 read_only,
00075 update
00076 };
00077
00079
00097 enum ownershippolicy
00098 {
00100 owned,
00102 loose
00103 };
00104
00106
00110 operator void *() const {return m_done ? 0 : m_context;}
00111
00113
00116 bool operator!() const { return m_done; }
00117
00122
00123
00126 static difference_type all() throw ();
00128
00130 static difference_type next() throw () { return 1; }
00132
00134 static difference_type prior() throw () { return -1; }
00136
00138 static difference_type backward_all() throw ();
00140
00142
00147 const PGSTD::string &name() const throw () { return m_name; }
00148
00150 virtual result fetch(difference_type);
00151
00153
00164 virtual result fetch(difference_type, difference_type &);
00165
00167
00174 virtual difference_type move(difference_type);
00175
00177
00180 virtual difference_type move(difference_type, difference_type &);
00181
00182 void close() throw ();
00183
00184 protected:
00185 cursor_base(transaction_base *,
00186 const PGSTD::string &cname,
00187 bool embellish_name = true);
00188
00189 void declare(const PGSTD::string &query,
00190 accesspolicy,
00191 updatepolicy,
00192 ownershippolicy,
00193 bool hold);
00194 void adopt(ownershippolicy);
00195
00196 static PGSTD::string stridestring(difference_type);
00197 transaction_base *m_context;
00198 bool m_done;
00199
00200 template<accesspolicy A> void check_displacement(difference_type) { }
00201
00202 private:
00203 int PQXX_PRIVATE get_unique_cursor_num();
00204
00205 PGSTD::string m_name;
00206 bool m_adopted;
00207 ownershippolicy m_ownership;
00208
00209 struct cachedquery
00210 {
00211 difference_type dist;
00212 PGSTD::string query;
00213
00214 cachedquery() : dist(0), query() {}
00215 };
00216 cachedquery m_lastfetch, m_lastmove;
00217
00219 cursor_base();
00221 cursor_base(const cursor_base &);
00223 cursor_base &operator=(const cursor_base &);
00224 };
00225
00226
00227 template<> void
00228 cursor_base::check_displacement<cursor_base::forward_only>(difference_type);
00229
00230
00231 inline cursor_base::difference_type cursor_base::all() throw ()
00232 {
00233
00234
00235 #if defined(PQXX_HAVE_LIMITS)
00236 return PGSTD::numeric_limits<difference_type>::max();
00237 #else
00238 return INT_MAX;
00239 #endif
00240 }
00241
00242 inline cursor_base::difference_type cursor_base::backward_all() throw ()
00243 {
00244 #if defined(PQXX_HAVE_LIMITS)
00245 return PGSTD::numeric_limits<difference_type>::min() + 1;
00246 #else
00247 return INT_MIN + 1;
00248 #endif
00249 }
00250
00251
00252
00254 template<cursor_base::accesspolicy ACCESS, cursor_base::updatepolicy UPDATE>
00255 class PQXX_LIBEXPORT basic_cursor : public cursor_base
00256 {
00257 public:
00259
00269 basic_cursor(transaction_base *t,
00270 const PGSTD::string &query,
00271 const PGSTD::string &cname,
00272 ownershippolicy op=owned) :
00273 cursor_base(t, cname, true)
00274 {
00275 declare(query,
00276 ACCESS,
00277 UPDATE,
00278 op,
00279 op==loose || !dynamic_cast<dbtransaction *>(t));
00280 }
00281
00283
00291 basic_cursor(transaction_base *t,
00292 const PGSTD::string &cname,
00293 ownershippolicy op=owned) :
00294 cursor_base(t, cname, false)
00295 {
00296 adopt(op);
00297 }
00298
00300
00316 virtual result fetch(difference_type n)
00317 {
00318 check_displacement<ACCESS>(n);
00319 return cursor_base::fetch(n);
00320 }
00321
00322 virtual result fetch(difference_type n, difference_type &d)
00323 {
00324 check_displacement<ACCESS>(n);
00325 return cursor_base::fetch(n, d);
00326 }
00327
00329
00333 virtual difference_type move(difference_type n)
00334 {
00335 check_displacement<ACCESS>(n);
00336 return cursor_base::move(n);
00337 }
00338
00339 virtual difference_type move(difference_type n, difference_type &d)
00340 {
00341 check_displacement<ACCESS>(n);
00342 return cursor_base::move(n, d);
00343 }
00344
00345 using cursor_base::close;
00346 };
00347
00348
00350 template<cursor_base::accesspolicy ACCESS, cursor_base::updatepolicy UPDATE>
00351 class PQXX_LIBEXPORT absolute_cursor : public basic_cursor<ACCESS,UPDATE>
00352 {
00353 typedef basic_cursor<ACCESS,UPDATE> super;
00354 public:
00355 typedef cursor_base::size_type size_type;
00356 typedef cursor_base::difference_type difference_type;
00357
00359
00367 absolute_cursor(transaction_base *t,
00368 const PGSTD::string &query,
00369 const PGSTD::string &cname) :
00370 super(t, query, cname, cursor_base::owned),
00371 m_pos(0),
00372 m_size(0),
00373 m_size_known(false)
00374 {
00375 }
00376
00377 virtual result fetch(difference_type n)
00378 {
00379 difference_type m;
00380 return fetch(n, m);
00381 }
00382
00383 virtual difference_type move(difference_type n)
00384 {
00385 difference_type m;
00386 return move(n, m);
00387 }
00388
00389 virtual difference_type move(difference_type d, difference_type &m)
00390 {
00391 const difference_type r(super::move(d, m));
00392 digest(d, m);
00393 return r;
00394 }
00395
00396 virtual result fetch(difference_type d, difference_type &m)
00397 {
00398 const result r(super::fetch(d, m));
00399 digest(d, m);
00400 return r;
00401 }
00402
00403 size_type pos() const throw () { return m_pos; }
00404
00405 difference_type move_to(cursor_base::size_type);
00406
00407 private:
00409 void digest(cursor_base::difference_type req,
00410 cursor_base::difference_type got) throw ()
00411 {
00412 m_pos += got;
00413
00414
00415 if (got < req && !m_size_known)
00416 {
00417 m_size = m_pos;
00418 m_size_known = true;
00419 }
00420 }
00421
00422 cursor_base::size_type m_pos;
00423 cursor_base::size_type m_size;
00424 bool m_size_known;
00425 };
00426
00427
00429 typedef basic_cursor<cursor_base::random_access, cursor_base::read_only> cursor;
00430
00431
00432 class icursor_iterator;
00433
00435
00450 class PQXX_LIBEXPORT icursorstream :
00451 public basic_cursor<cursor_base::forward_only, cursor_base::read_only>
00452 {
00453 typedef basic_cursor<cursor_base::forward_only, cursor_base::read_only> super;
00454 public:
00456
00467 icursorstream(transaction_base &Context,
00468 const PGSTD::string &Query,
00469 const PGSTD::string &Basename,
00470 difference_type Stride=1);
00471
00473
00495 icursorstream(transaction_base &Context,
00496 const result::field &Name,
00497 difference_type Stride=1);
00498
00500
00506 icursorstream &get(result &res) { res = fetchblock(); return *this; }
00508
00514 icursorstream &operator>>(result &res) { return get(res); }
00516
00520 icursorstream &ignore(PGSTD::streamsize n=1);
00521
00523
00526 void set_stride(difference_type stride);
00527 difference_type stride() const throw () { return m_stride; }
00528
00529 private:
00530 result fetchblock();
00531
00532 friend class icursor_iterator;
00533 size_type forward(size_type n=1);
00534 void insert_iterator(icursor_iterator *) throw ();
00535 void remove_iterator(icursor_iterator *) const throw ();
00536
00537 void service_iterators(size_type);
00538
00539 difference_type m_stride;
00540 size_type m_realpos, m_reqpos;
00541
00542 mutable icursor_iterator *m_iterators;
00543 };
00544
00545
00547
00573 class PQXX_LIBEXPORT icursor_iterator :
00574 public PGSTD::iterator<PGSTD::input_iterator_tag,
00575 result,
00576 cursor_base::size_type,
00577 const result *,
00578 const result &>
00579 {
00580 public:
00581 typedef icursorstream istream_type;
00582 typedef istream_type::size_type size_type;
00583 typedef istream_type::difference_type difference_type;
00584
00585 icursor_iterator() throw ();
00586 explicit icursor_iterator(istream_type &) throw ();
00587 icursor_iterator(const icursor_iterator &) throw ();
00588 ~icursor_iterator() throw ();
00589
00590 const result &operator*() const { refresh(); return m_here; }
00591 const result *operator->() const { refresh(); return &m_here; }
00592 icursor_iterator &operator++();
00593 icursor_iterator operator++(int);
00594 icursor_iterator &operator+=(difference_type);
00595 icursor_iterator &operator=(const icursor_iterator &) throw ();
00596
00597 bool operator==(const icursor_iterator &rhs) const;
00598 bool operator!=(const icursor_iterator &rhs) const throw ()
00599 { return !operator==(rhs); }
00600 bool operator<(const icursor_iterator &rhs) const;
00601 bool operator>(const icursor_iterator &rhs) const
00602 { return rhs < *this; }
00603 bool operator<=(const icursor_iterator &rhs) const
00604 { return !(*this > rhs); }
00605 bool operator>=(const icursor_iterator &rhs) const
00606 { return !(*this < rhs); }
00607
00608 private:
00609 void refresh() const;
00610
00611 friend class icursorstream;
00612 size_type pos() const throw () { return m_pos; }
00613 void fill(const result &);
00614
00615 icursorstream *m_stream;
00616 result m_here;
00617 size_type m_pos;
00618 icursor_iterator *m_prev, *m_next;
00619 };
00620
00621
00622 }
00623