00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pqxx/compiler-public.hxx"
00020 #include "pqxx/compiler-internal-pre.hxx"
00021
00022 #ifdef PQXX_HAVE_LIMITS
00023 #include <limits>
00024 #endif
00025
00026 #include "pqxx/result"
00027 #include "pqxx/transaction_base"
00028
00029
00030 namespace pqxx
00031 {
00032 class dbtransaction;
00033
00035
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 &Name,
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) const { }
00201
00202 #if defined(_MSC_VER)
00203
00204
00205
00206 template<>
00207 void check_displacement<cursor_base::forward_only>(difference_type) const;
00208 #endif
00209
00210 private:
00211 PGSTD::string m_name;
00212 bool m_adopted;
00213 ownershippolicy m_ownership;
00214
00215 struct cachedquery
00216 {
00217 difference_type dist;
00218 PGSTD::string query;
00219
00220 cachedquery() : dist(0), query() {}
00221 };
00222 cachedquery m_lastfetch, m_lastmove;
00223
00225 cursor_base();
00227 cursor_base(const cursor_base &);
00229 cursor_base &operator=(const cursor_base &);
00230 };
00231
00232
00233
00234
00235
00236 #if !defined(_MSC_VER)
00237 template<> void
00238 cursor_base::check_displacement<cursor_base::forward_only>(difference_type)
00239 const;
00240 #endif
00241
00242
00243 inline cursor_base::difference_type cursor_base::all() throw ()
00244 {
00245
00246
00247 #if defined(PQXX_HAVE_LIMITS)
00248 return PGSTD::numeric_limits<difference_type>::max();
00249 #else
00250 return INT_MAX;
00251 #endif
00252 }
00253
00254 inline cursor_base::difference_type cursor_base::backward_all() throw ()
00255 {
00256 #if defined(PQXX_HAVE_LIMITS)
00257 return PGSTD::numeric_limits<difference_type>::min() + 1;
00258 #else
00259 return INT_MIN + 1;
00260 #endif
00261 }
00262
00263
00264
00266 template<cursor_base::accesspolicy ACCESS, cursor_base::updatepolicy UPDATE>
00267 class basic_cursor : public cursor_base
00268 {
00269 public:
00271
00281 basic_cursor(transaction_base *t,
00282 const PGSTD::string &query,
00283 const PGSTD::string &cname,
00284 ownershippolicy op=owned) :
00285 cursor_base(t, cname, true)
00286 {
00287 declare(query,
00288 ACCESS,
00289 UPDATE,
00290 op,
00291 op==loose || !dynamic_cast<dbtransaction *>(t));
00292 }
00293
00295
00303 basic_cursor(transaction_base *t,
00304 const PGSTD::string &cname,
00305 ownershippolicy op=owned) :
00306 cursor_base(t, cname, false)
00307 {
00308 adopt(op);
00309 }
00310
00312
00328 virtual result fetch(difference_type n)
00329 {
00330 check_displacement<ACCESS>(n);
00331 return cursor_base::fetch(n);
00332 }
00333
00334 virtual result fetch(difference_type n, difference_type &d)
00335 {
00336 check_displacement<ACCESS>(n);
00337 return cursor_base::fetch(n, d);
00338 }
00339
00341
00345 virtual difference_type move(difference_type n)
00346 {
00347 check_displacement<ACCESS>(n);
00348 return cursor_base::move(n);
00349 }
00350
00351 virtual difference_type move(difference_type n, difference_type &d)
00352 {
00353 check_displacement<ACCESS>(n);
00354 return cursor_base::move(n, d);
00355 }
00356
00357 using cursor_base::close;
00358 };
00359
00360
00362 template<cursor_base::accesspolicy ACCESS, cursor_base::updatepolicy UPDATE>
00363 class absolute_cursor : public basic_cursor<ACCESS,UPDATE>
00364 {
00365 typedef basic_cursor<ACCESS,UPDATE> super;
00366 public:
00367 typedef cursor_base::size_type size_type;
00368 typedef cursor_base::difference_type difference_type;
00369
00371
00379 absolute_cursor(transaction_base *t,
00380 const PGSTD::string &query,
00381 const PGSTD::string &cname) :
00382 super(t, query, cname, cursor_base::owned),
00383 m_pos(0),
00384 m_size(0),
00385 m_size_known(false)
00386 {
00387 }
00388
00389 virtual result fetch(difference_type n)
00390 {
00391 difference_type m;
00392 return fetch(n, m);
00393 }
00394
00395 virtual difference_type move(difference_type n)
00396 {
00397 difference_type m;
00398 return move(n, m);
00399 }
00400
00401 virtual difference_type move(difference_type d, difference_type &m)
00402 {
00403 const difference_type r(super::move(d, m));
00404 digest(d, m);
00405 return r;
00406 }
00407
00408 virtual result fetch(difference_type d, difference_type &m)
00409 {
00410 const result r(super::fetch(d, m));
00411 digest(d, m);
00412 return r;
00413 }
00414
00415 size_type pos() const throw () { return m_pos; }
00416
00417 difference_type move_to(cursor_base::size_type);
00418
00419 private:
00421 void digest(cursor_base::difference_type req,
00422 cursor_base::difference_type got) throw ()
00423 {
00424 m_pos += got;
00425
00426
00427 if (got < req && !m_size_known)
00428 {
00429 m_size = m_pos;
00430 m_size_known = true;
00431 }
00432 }
00433
00434 cursor_base::size_type m_pos;
00435 cursor_base::size_type m_size;
00436 bool m_size_known;
00437 };
00438
00439
00441 typedef basic_cursor<cursor_base::random_access, cursor_base::read_only> cursor;
00442
00443
00444 class icursor_iterator;
00445
00447
00462 class PQXX_LIBEXPORT icursorstream :
00463 public basic_cursor<cursor_base::forward_only, cursor_base::read_only>
00464 {
00465 typedef basic_cursor<cursor_base::forward_only, cursor_base::read_only> super;
00466 public:
00468
00479 icursorstream(transaction_base &Context,
00480 const PGSTD::string &Query,
00481 const PGSTD::string &Basename,
00482 difference_type Stride=1);
00483
00485
00507 icursorstream(transaction_base &Context,
00508 const result::field &Name,
00509 difference_type Stride=1);
00510
00512
00518 icursorstream &get(result &res) { res = fetchblock(); return *this; }
00520
00526 icursorstream &operator>>(result &res) { return get(res); }
00528
00532 icursorstream &ignore(PGSTD::streamsize n=1);
00533
00535
00538 void set_stride(difference_type stride);
00539 difference_type stride() const throw () { return m_stride; }
00540
00541 private:
00542 result fetchblock();
00543
00544 friend class icursor_iterator;
00545 size_type forward(size_type n=1);
00546 void insert_iterator(icursor_iterator *) throw ();
00547 void remove_iterator(icursor_iterator *) const throw ();
00548
00549 void service_iterators(size_type);
00550
00551 difference_type m_stride;
00552 size_type m_realpos, m_reqpos;
00553
00554 mutable icursor_iterator *m_iterators;
00555 };
00556
00557
00559
00586 class PQXX_LIBEXPORT icursor_iterator :
00587 public PGSTD::iterator<PGSTD::input_iterator_tag,
00588 result,
00589 cursor_base::size_type,
00590 const result *,
00591 const result &>
00592 {
00593 public:
00594 typedef icursorstream istream_type;
00595 typedef istream_type::size_type size_type;
00596 typedef istream_type::difference_type difference_type;
00597
00598 icursor_iterator() throw ();
00599 explicit icursor_iterator(istream_type &) throw ();
00600 icursor_iterator(const icursor_iterator &) throw ();
00601 ~icursor_iterator() throw ();
00602
00603 const result &operator*() const { refresh(); return m_here; }
00604 const result *operator->() const { refresh(); return &m_here; }
00605 icursor_iterator &operator++();
00606 icursor_iterator operator++(int);
00607 icursor_iterator &operator+=(difference_type);
00608 icursor_iterator &operator=(const icursor_iterator &) throw ();
00609
00610 bool operator==(const icursor_iterator &rhs) const;
00611 bool operator!=(const icursor_iterator &rhs) const throw ()
00612 { return !operator==(rhs); }
00613 bool operator<(const icursor_iterator &rhs) const;
00614 bool operator>(const icursor_iterator &rhs) const
00615 { return rhs < *this; }
00616 bool operator<=(const icursor_iterator &rhs) const
00617 { return !(*this > rhs); }
00618 bool operator>=(const icursor_iterator &rhs) const
00619 { return !(*this < rhs); }
00620
00621 private:
00622 void refresh() const;
00623
00624 friend class icursorstream;
00625 size_type pos() const throw () { return m_pos; }
00626 void fill(const result &);
00627
00628 icursorstream *m_stream;
00629 result m_here;
00630 size_type m_pos;
00631 icursor_iterator *m_prev, *m_next;
00632 };
00633
00634
00635 }
00636
00637 #include "pqxx/compiler-internal-post.hxx"