cursor.hxx

Go to the documentation of this file.
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/pipeline instead.
00010  *
00011  * Copyright (c) 2004-2009, 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 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 } // 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, up, 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         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 result::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 

Generated on Mon Feb 15 18:22:41 2010 for libpqxx by  doxygen 1.5.5