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) =0;
00151
00153
00164 virtual result fetch(difference_type, difference_type &) =0;
00165
00167
00174 virtual difference_type move(difference_type) =0;
00175
00177
00183 virtual difference_type move(difference_type, difference_type &) =0;
00184
00185 void close() throw ();
00186
00187 protected:
00188 cursor_base(transaction_base *,
00189 const PGSTD::string &Name,
00190 bool embellish_name = true);
00191
00192 void declare(const PGSTD::string &query,
00193 accesspolicy,
00194 updatepolicy,
00195 ownershippolicy,
00196 bool hold);
00197 void adopt(ownershippolicy);
00198
00199 static PGSTD::string stridestring(difference_type);
00200 transaction_base *m_context;
00201 bool m_done;
00202
00203 template<accesspolicy A> void check_displacement(difference_type) const { }
00204
00205 #if defined(_MSC_VER)
00206
00207
00208
00209 template<>
00210 void check_displacement<cursor_base::forward_only>(difference_type) const;
00211 #endif
00212
00213 private:
00214 PGSTD::string m_name;
00215 bool m_adopted;
00216 ownershippolicy m_ownership;
00217
00218 struct cachedquery
00219 {
00220 difference_type dist;
00221 PGSTD::string query;
00222
00223 cachedquery() : dist(0), query() {}
00224 };
00225 cachedquery m_lastfetch, m_lastmove;
00226
00228 cursor_base();
00230 cursor_base(const cursor_base &);
00232 cursor_base &operator=(const cursor_base &);
00233 };
00234
00235
00236
00237
00238
00239 #if !defined(_MSC_VER)
00240 template<> void
00241 cursor_base::check_displacement<cursor_base::forward_only>(difference_type)
00242 const;
00243 #endif
00244
00245
00246 inline cursor_base::difference_type cursor_base::all() throw ()
00247 {
00248
00249
00250 #if defined(PQXX_HAVE_LIMITS)
00251 return PGSTD::numeric_limits<difference_type>::max();
00252 #else
00253 return INT_MAX;
00254 #endif
00255 }
00256
00257 inline cursor_base::difference_type cursor_base::backward_all() throw ()
00258 {
00259 #if defined(PQXX_HAVE_LIMITS)
00260 return PGSTD::numeric_limits<difference_type>::min() + 1;
00261 #else
00262 return INT_MIN + 1;
00263 #endif
00264 }
00265
00266
00267
00269 template<cursor_base::accesspolicy ACCESS, cursor_base::updatepolicy UPDATE>
00270 class basic_cursor : public cursor_base
00271 {
00272 public:
00274
00284 basic_cursor(transaction_base *t,
00285 const PGSTD::string &query,
00286 const PGSTD::string &cname,
00287 ownershippolicy op=owned) :
00288 cursor_base(t, cname, true)
00289 {
00290 declare(query,
00291 ACCESS,
00292 UPDATE,
00293 op,
00294 op==loose || !dynamic_cast<dbtransaction *>(t));
00295 }
00296
00298
00306 basic_cursor(transaction_base *t,
00307 const PGSTD::string &cname,
00308 ownershippolicy op=owned) :
00309 cursor_base(t, cname, false)
00310 {
00311 adopt(op);
00312 }
00313
00315
00331 virtual result fetch(difference_type n)
00332 {
00333 check_displacement<ACCESS>(n);
00334 return cursor_base::fetch(n);
00335 }
00336
00337 virtual result fetch(difference_type n, difference_type &d)
00338 {
00339 check_displacement<ACCESS>(n);
00340 return cursor_base::fetch(n, d);
00341 }
00342
00344
00348 virtual difference_type move(difference_type n)
00349 {
00350 check_displacement<ACCESS>(n);
00351 return cursor_base::move(n);
00352 }
00353
00354 virtual difference_type move(difference_type n, difference_type &d)
00355 {
00356 check_displacement<ACCESS>(n);
00357 return cursor_base::move(n, d);
00358 }
00359
00360 using cursor_base::close;
00361 };
00362
00363
00365 template<cursor_base::accesspolicy ACCESS, cursor_base::updatepolicy UPDATE>
00366 class absolute_cursor : public basic_cursor<ACCESS,UPDATE>
00367 {
00368 typedef basic_cursor<ACCESS,UPDATE> super;
00369 public:
00370 typedef cursor_base::size_type size_type;
00371 typedef cursor_base::difference_type difference_type;
00372
00374
00382 absolute_cursor(transaction_base *t,
00383 const PGSTD::string &query,
00384 const PGSTD::string &cname) :
00385 super(t, query, cname, cursor_base::owned),
00386 m_pos(0),
00387 m_size(0),
00388 m_size_known(false)
00389 {
00390 }
00391
00392 virtual result fetch(difference_type n)
00393 {
00394 difference_type m;
00395 return absolute_cursor::fetch(n, m);
00396 }
00397
00398 virtual difference_type move(difference_type n)
00399 {
00400 difference_type m;
00401 return move(n, m);
00402 }
00403
00404 virtual difference_type move(difference_type d, difference_type &m)
00405 {
00406 const difference_type r(super::move(d, m));
00407 digest(d, m);
00408 return r;
00409 }
00410
00411 virtual result fetch(difference_type d, difference_type &m)
00412 {
00413 const result r(super::fetch(d, m));
00414 digest(d, m);
00415 return r;
00416 }
00417
00418 size_type pos() const throw () { return m_pos; }
00419
00420 difference_type move_to(cursor_base::size_type to)
00421 { return move(difference_type(to)-difference_type(pos())); }
00422
00423 difference_type move_to(cursor_base::size_type to,
00424 cursor_base::difference_type &d)
00425 { return move(difference_type(to)-difference_type(pos()), d); }
00426 private:
00428 void digest(cursor_base::difference_type req,
00429 cursor_base::difference_type got) throw ()
00430 {
00431 m_pos += got;
00432
00433
00434 if (got < req && !m_size_known)
00435 {
00436 m_size = m_pos;
00437 m_size_known = true;
00438 }
00439 }
00440
00441 cursor_base::size_type m_pos;
00442 cursor_base::size_type m_size;
00443 bool m_size_known;
00444 };
00445
00446
00448 typedef basic_cursor<cursor_base::random_access, cursor_base::read_only> cursor;
00449
00451 typedef absolute_cursor<cursor_base::random_access, cursor_base::read_only>
00452 abscursor;
00453
00454 class icursor_iterator;
00455
00457
00472 class PQXX_LIBEXPORT icursorstream :
00473 public basic_cursor<cursor_base::forward_only, cursor_base::read_only>
00474 {
00475 typedef basic_cursor<cursor_base::forward_only, cursor_base::read_only> super;
00476 public:
00478
00489 icursorstream(transaction_base &Context,
00490 const PGSTD::string &Query,
00491 const PGSTD::string &Basename,
00492 difference_type Stride=1);
00493
00495
00517 icursorstream(transaction_base &Context,
00518 const result::field &Name,
00519 difference_type Stride=1);
00520
00522
00528 icursorstream &get(result &res) { res = fetchblock(); return *this; }
00530
00536 icursorstream &operator>>(result &res) { return get(res); }
00538
00542 icursorstream &ignore(PGSTD::streamsize n=1);
00543
00545
00548 void set_stride(difference_type stride);
00549 difference_type stride() const throw () { return m_stride; }
00550
00551 private:
00552 result fetchblock();
00553
00554 friend class icursor_iterator;
00555 size_type forward(size_type n=1);
00556 void insert_iterator(icursor_iterator *) throw ();
00557 void remove_iterator(icursor_iterator *) const throw ();
00558
00559 void service_iterators(size_type);
00560
00561 difference_type m_stride;
00562 size_type m_realpos, m_reqpos;
00563
00564 mutable icursor_iterator *m_iterators;
00565 };
00566
00567
00569
00596 class PQXX_LIBEXPORT icursor_iterator :
00597 public PGSTD::iterator<PGSTD::input_iterator_tag,
00598 result,
00599 cursor_base::size_type,
00600 const result *,
00601 const result &>
00602 {
00603 public:
00604 typedef icursorstream istream_type;
00605 typedef istream_type::size_type size_type;
00606 typedef istream_type::difference_type difference_type;
00607
00608 icursor_iterator() throw ();
00609 explicit icursor_iterator(istream_type &) throw ();
00610 icursor_iterator(const icursor_iterator &) throw ();
00611 ~icursor_iterator() throw ();
00612
00613 const result &operator*() const { refresh(); return m_here; }
00614 const result *operator->() const { refresh(); return &m_here; }
00615 icursor_iterator &operator++();
00616 icursor_iterator operator++(int);
00617 icursor_iterator &operator+=(difference_type);
00618 icursor_iterator &operator=(const icursor_iterator &) throw ();
00619
00620 bool operator==(const icursor_iterator &rhs) const;
00621 bool operator!=(const icursor_iterator &rhs) const throw ()
00622 { return !operator==(rhs); }
00623 bool operator<(const icursor_iterator &rhs) const;
00624 bool operator>(const icursor_iterator &rhs) const
00625 { return rhs < *this; }
00626 bool operator<=(const icursor_iterator &rhs) const
00627 { return !(*this > rhs); }
00628 bool operator>=(const icursor_iterator &rhs) const
00629 { return !(*this < rhs); }
00630
00631 private:
00632 void refresh() const;
00633
00634 friend class icursorstream;
00635 size_type pos() const throw () { return m_pos; }
00636 void fill(const result &);
00637
00638 icursorstream *m_stream;
00639 result m_here;
00640 size_type m_pos;
00641 icursor_iterator *m_prev, *m_next;
00642 };
00643
00644
00645 }
00646
00647 #include "pqxx/compiler-internal-post.hxx"