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
00354
00355 namespace internal
00356 {
00357 namespace gate
00358 {
00359 class icursor_iterator_icursorstream;
00360 class icursorstream_icursor_iterator;
00361 }
00362 }
00363
00364
00366
00381 class PQXX_LIBEXPORT icursorstream
00382 {
00383 public:
00384 typedef cursor_base::size_type size_type;
00385 typedef cursor_base::difference_type difference_type;
00386
00388
00399 icursorstream(transaction_base &context,
00400 const PGSTD::string &query,
00401 const PGSTD::string &basename,
00402 difference_type sstride=1);
00403
00405
00429 icursorstream(transaction_base &context,
00430 const result::field &cname,
00431 difference_type sstride=1,
00432 cursor_base::ownershippolicy op=cursor_base::owned);
00433
00434 operator bool() const throw () { return !m_done; }
00435
00437
00443 icursorstream &get(result &res) { res = fetchblock(); return *this; }
00445
00451 icursorstream &operator>>(result &res) { return get(res); }
00452
00454
00458 icursorstream &ignore(PGSTD::streamsize n=1);
00459
00461
00464 void set_stride(difference_type stride);
00465 difference_type stride() const throw () { return m_stride; }
00466
00467 private:
00468 result fetchblock();
00469
00470 friend class internal::gate::icursorstream_icursor_iterator;
00471 size_type forward(size_type n=1);
00472 void insert_iterator(icursor_iterator *) throw ();
00473 void remove_iterator(icursor_iterator *) const throw ();
00474
00475 void service_iterators(difference_type);
00476
00477 internal::sql_cursor m_cur;
00478
00479 difference_type m_stride;
00480 difference_type m_realpos, m_reqpos;
00481
00482 mutable icursor_iterator *m_iterators;
00483
00484 bool m_done;
00485 };
00486
00487
00489
00515 class PQXX_LIBEXPORT icursor_iterator :
00516 public PGSTD::iterator<PGSTD::input_iterator_tag,
00517 result,
00518 cursor_base::size_type,
00519 const result *,
00520 const result &>
00521 {
00522 public:
00523 typedef icursorstream istream_type;
00524 typedef istream_type::size_type size_type;
00525 typedef istream_type::difference_type difference_type;
00526
00527 icursor_iterator() throw ();
00528 explicit icursor_iterator(istream_type &) throw ();
00529 icursor_iterator(const icursor_iterator &) throw ();
00530 ~icursor_iterator() throw ();
00531
00532 const result &operator*() const { refresh(); return m_here; }
00533 const result *operator->() const { refresh(); return &m_here; }
00534 icursor_iterator &operator++();
00535 icursor_iterator operator++(int);
00536 icursor_iterator &operator+=(difference_type);
00537 icursor_iterator &operator=(const icursor_iterator &) throw ();
00538
00539 bool operator==(const icursor_iterator &rhs) const;
00540 bool operator!=(const icursor_iterator &rhs) const throw ()
00541 { return !operator==(rhs); }
00542 bool operator<(const icursor_iterator &rhs) const;
00543 bool operator>(const icursor_iterator &rhs) const
00544 { return rhs < *this; }
00545 bool operator<=(const icursor_iterator &rhs) const
00546 { return !(*this > rhs); }
00547 bool operator>=(const icursor_iterator &rhs) const
00548 { return !(*this < rhs); }
00549
00550 private:
00551 void refresh() const;
00552
00553 friend class internal::gate::icursor_iterator_icursorstream;
00554 difference_type pos() const throw () { return m_pos; }
00555 void fill(const result &);
00556
00557 icursorstream *m_stream;
00558 result m_here;
00559 difference_type m_pos;
00560 icursor_iterator *m_prev, *m_next;
00561 };
00562
00563
00564 }
00565
00566 #include "pqxx/compiler-internal-post.hxx"
00567
00568 #endif
00569