libpqxx 4.0
|
00001 /*------------------------------------------------------------------------- 00002 * 00003 * FILE 00004 * pqxx/cursor.hxx 00005 * 00006 * DESCRIPTION 00007 * definition of the iterator/container-style cursor classes 00008 * C++-style wrappers for SQL cursors 00009 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead. 00010 * 00011 * Copyright (c) 2004-2011, Jeroen T. Vermeulen <jtv@xs4all.nl> 00012 * 00013 * See COPYING for copyright license. If you did not receive a file called 00014 * COPYING with this source code, please notify the distributor of this mistake, 00015 * or contact the author. 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 (); //[t81] 00119 00121 static difference_type next() throw () { return 1; } //[t81] 00123 00125 static difference_type prior() throw () { return -1; } //[t0] 00127 00129 static difference_type backward_all() throw (); //[t0] 00130 00132 00134 00139 const PGSTD::string &name() const throw () { return m_name; } //[t81] 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 PQXX_LIBEXPORT obtain_stateless_cursor_size(sql_cursor &); 00273 result PQXX_LIBEXPORT 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 } // namespace internal 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, op) 00311 { 00312 // Put cursor in known position 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 result::difference_type(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 } // namespace internal::gate 00362 } // namespace internal 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); //[t81] 00403 00405 00429 icursorstream(transaction_base &context, 00430 const field &cname, 00431 difference_type sstride=1, 00432 cursor_base::ownershippolicy op=cursor_base::owned); //[t84] 00433 00434 operator bool() const throw () { return !m_done; } 00435 00437 00443 icursorstream &get(result &res) { res = fetchblock(); return *this; } //[t81] 00445 00451 icursorstream &operator>>(result &res) { return get(res); } //[t81] 00452 00454 00458 icursorstream &ignore(PGSTD::streamsize n=1); //[t81] 00459 00461 00464 void set_stride(difference_type stride); //[t81] 00465 difference_type stride() const throw () { return m_stride; } //[t81] 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 (); //[t84] 00528 explicit icursor_iterator(istream_type &) throw (); //[t84] 00529 icursor_iterator(const icursor_iterator &) throw (); //[t84] 00530 ~icursor_iterator() throw (); 00531 00532 const result &operator*() const { refresh(); return m_here; } //[t84] 00533 const result *operator->() const { refresh(); return &m_here; } //[t84] 00534 icursor_iterator &operator++(); //[t84] 00535 icursor_iterator operator++(int); //[t84] 00536 icursor_iterator &operator+=(difference_type); //[t84] 00537 icursor_iterator &operator=(const icursor_iterator &) throw (); //[t84] 00538 00539 bool operator==(const icursor_iterator &rhs) const; //[t84] 00540 bool operator!=(const icursor_iterator &rhs) const throw () //[t84] 00541 { return !operator==(rhs); } 00542 bool operator<(const icursor_iterator &rhs) const; //[t84] 00543 bool operator>(const icursor_iterator &rhs) const //[t84] 00544 { return rhs < *this; } 00545 bool operator<=(const icursor_iterator &rhs) const //[t84] 00546 { return !(*this > rhs); } 00547 bool operator>=(const icursor_iterator &rhs) const //[t84] 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 } // namespace pqxx 00565 00566 #include "pqxx/compiler-internal-post.hxx" 00567 00568 #endif 00569