00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef PQXX_H_CURSOR
00020 #define PQXX_H_CURSOR
00021
00022 #include "pqxx/compiler-public.hxx"
00023 #include "pqxx/compiler-internal-pre.hxx"
00024
00025 #include <stdexcept>
00026
00027 #ifdef PQXX_HAVE_LIMITS
00028 #include <limits>
00029 #endif
00030
00031 #include "pqxx/result"
00032 #include "pqxx/transaction_base"
00033
00034
00035 namespace pqxx
00036 {
00037 class dbtransaction;
00038
00039
00041
00052 class PQXX_LIBEXPORT cursor_base
00053 {
00054 public:
00055 typedef result::size_type size_type;
00056 typedef result::difference_type difference_type;
00057
00059
00062 enum accesspolicy
00063 {
00065 forward_only,
00067 random_access
00068 };
00069
00071
00074 enum updatepolicy
00075 {
00077 read_only,
00079 update
00080 };
00081
00083
00101 enum ownershippolicy
00102 {
00104 owned,
00106 loose
00107 };
00108
00113
00114
00117 static difference_type all() throw ();
00119
00121 static difference_type next() throw () { return 1; }
00123
00125 static difference_type prior() throw () { return -1; }
00127
00129 static difference_type backward_all() throw ();
00130
00132
00134
00139 const PGSTD::string &name() const throw () { return m_name; }
00140
00141 protected:
00142 cursor_base(connection_base &,
00143 const PGSTD::string &Name,
00144 bool embellish_name=true);
00145
00146 const PGSTD::string m_name;
00147
00148 private:
00150 cursor_base();
00152 cursor_base(const cursor_base &);
00154 cursor_base &operator=(const cursor_base &);
00155 };
00156
00157
00158 inline cursor_base::difference_type cursor_base::all() throw ()
00159 {
00160 #ifdef PQXX_HAVE_LIMITS
00161 return PGSTD::numeric_limits<int>::max()-1;
00162 #else
00163 return INT_MAX-1;
00164 #endif
00165 }
00166
00167 inline cursor_base::difference_type cursor_base::backward_all() throw ()
00168 {
00169 #ifdef PQXX_HAVE_LIMITS
00170 return PGSTD::numeric_limits<int>::min()+1;
00171 #else
00172 return INT_MIN+1;
00173 #endif
00174 }
00175
00176
00177 namespace internal
00178 {
00180
00194 class PQXX_LIBEXPORT sql_cursor : public cursor_base
00195 {
00196 public:
00197 sql_cursor(transaction_base &t,
00198 const PGSTD::string &query,
00199 const PGSTD::string &cname,
00200 cursor_base::accesspolicy ap,
00201 cursor_base::updatepolicy up,
00202 cursor_base::ownershippolicy op,
00203 bool hold);
00204
00205 sql_cursor(transaction_base &t,
00206 const PGSTD::string &cname,
00207 cursor_base::ownershippolicy op);
00208
00209 ~sql_cursor() throw () { close(); }
00210
00211 result fetch(difference_type rows, difference_type &displacement);
00212 result fetch(difference_type rows)
00213 { difference_type d=0; return fetch(rows, d); }
00214 difference_type move(difference_type rows, difference_type &displacement);
00215 difference_type move(difference_type rows)
00216 { difference_type d=0; return move(rows, d); }
00217
00219
00225 difference_type pos() const throw () { return m_pos; }
00226
00228
00234 difference_type endpos() const throw () { return m_endpos; }
00235
00237 const result &empty_result() const throw () { return m_empty_result; }
00238
00239 void close() throw ();
00240
00241 private:
00242 difference_type adjust(difference_type hoped, difference_type actual);
00243 static PGSTD::string stridestring(difference_type);
00245 void init_empty_result(transaction_base &);
00246
00248 connection_base &m_home;
00249
00251 result m_empty_result;
00252
00253 result m_cached_current_row;
00254
00256 bool m_adopted;
00257
00259 cursor_base::ownershippolicy m_ownership;
00260
00262 int m_at_end;
00263
00265 difference_type m_pos;
00266
00268 difference_type m_endpos;
00269 };
00270
00271
00272 result::size_type obtain_stateless_cursor_size(sql_cursor &);
00273 result stateless_cursor_retrieve(
00274 sql_cursor &,
00275 result::difference_type size,
00276 result::difference_type begin_pos,
00277 result::difference_type end_pos);
00278
00279 }
00280
00281
00283
00289 template<cursor_base::updatepolicy up, cursor_base::ownershippolicy op>
00290 class stateless_cursor
00291 {
00292 public:
00293 typedef result::size_type size_type;
00294 typedef result::difference_type difference_type;
00295
00297 stateless_cursor(
00298 transaction_base &trans,
00299 const PGSTD::string &query,
00300 const PGSTD::string &cname,
00301 bool hold) :
00302 m_cur(trans, query, cname, cursor_base::random_access, up, op, hold)
00303 {
00304 }
00305
00307 stateless_cursor(
00308 transaction_base &trans,
00309 const PGSTD::string adopted_cursor) :
00310 m_cur(trans, adopted_cursor, up, op)
00311 {
00312
00313 m_cur.move(cursor_base::backward_all());
00314 }
00315
00316 void close() throw () { m_cur.close(); }
00317
00319
00322 size_type size() { return internal::obtain_stateless_cursor_size(m_cur); }
00323
00325
00336 result retrieve(difference_type begin_pos, difference_type end_pos)
00337 {
00338 return internal::stateless_cursor_retrieve(
00339 m_cur,
00340 size(),
00341 begin_pos,
00342 end_pos);
00343 }
00344
00345 const PGSTD::string &name() const throw () { return m_cur.name(); }
00346
00347 private:
00348 internal::sql_cursor m_cur;
00349 };
00350
00351
00352 class icursor_iterator;
00353
00355
00370 class PQXX_LIBEXPORT icursorstream
00371 {
00372 public:
00373 typedef cursor_base::size_type size_type;
00374 typedef cursor_base::difference_type difference_type;
00375
00377
00388 icursorstream(transaction_base &context,
00389 const PGSTD::string &query,
00390 const PGSTD::string &basename,
00391 difference_type sstride=1);
00392
00394
00416 icursorstream(transaction_base &context,
00417 const result::field &cname,
00418 difference_type sstride=1,
00419 cursor_base::ownershippolicy op=cursor_base::owned);
00420
00421 operator bool() const throw () { return !m_done; }
00422
00424
00430 icursorstream &get(result &res) { res = fetchblock(); return *this; }
00432
00438 icursorstream &operator>>(result &res) { return get(res); }
00439
00441
00445 icursorstream &ignore(PGSTD::streamsize n=1);
00446
00448
00451 void set_stride(difference_type stride);
00452 difference_type stride() const throw () { return m_stride; }
00453
00454 private:
00455 result fetchblock();
00456
00457 friend class icursor_iterator;
00458 size_type forward(size_type n=1);
00459 void insert_iterator(icursor_iterator *) throw ();
00460 void remove_iterator(icursor_iterator *) const throw ();
00461
00462 void service_iterators(difference_type);
00463
00464 internal::sql_cursor m_cur;
00465
00466 difference_type m_stride;
00467 difference_type m_realpos, m_reqpos;
00468
00469 mutable icursor_iterator *m_iterators;
00470
00471 bool m_done;
00472 };
00473
00474
00476
00502 class PQXX_LIBEXPORT icursor_iterator :
00503 public PGSTD::iterator<PGSTD::input_iterator_tag,
00504 result,
00505 cursor_base::size_type,
00506 const result *,
00507 const result &>
00508 {
00509 public:
00510 typedef icursorstream istream_type;
00511 typedef istream_type::size_type size_type;
00512 typedef istream_type::difference_type difference_type;
00513
00514 icursor_iterator() throw ();
00515 explicit icursor_iterator(istream_type &) throw ();
00516 icursor_iterator(const icursor_iterator &) throw ();
00517 ~icursor_iterator() throw ();
00518
00519 const result &operator*() const { refresh(); return m_here; }
00520 const result *operator->() const { refresh(); return &m_here; }
00521 icursor_iterator &operator++();
00522 icursor_iterator operator++(int);
00523 icursor_iterator &operator+=(difference_type);
00524 icursor_iterator &operator=(const icursor_iterator &) throw ();
00525
00526 bool operator==(const icursor_iterator &rhs) const;
00527 bool operator!=(const icursor_iterator &rhs) const throw ()
00528 { return !operator==(rhs); }
00529 bool operator<(const icursor_iterator &rhs) const;
00530 bool operator>(const icursor_iterator &rhs) const
00531 { return rhs < *this; }
00532 bool operator<=(const icursor_iterator &rhs) const
00533 { return !(*this > rhs); }
00534 bool operator>=(const icursor_iterator &rhs) const
00535 { return !(*this < rhs); }
00536
00537 private:
00538 void refresh() const;
00539
00540 friend class icursorstream;
00541 difference_type pos() const throw () { return m_pos; }
00542 void fill(const result &);
00543
00544 icursorstream *m_stream;
00545 result m_here;
00546 difference_type m_pos;
00547 icursor_iterator *m_prev, *m_next;
00548 };
00549
00550
00551 }
00552
00553 #include "pqxx/compiler-internal-post.hxx"
00554
00555 #endif
00556