Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

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-2005, 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 #include "pqxx/libcompiler.h"
00020 
00021 #ifdef PQXX_HAVE_LIMITS
00022 #include <limits>
00023 #endif
00024 
00025 #include "pqxx/result"
00026 #include "pqxx/transaction_base"
00027 
00028 
00029 namespace pqxx
00030 {
00031 class dbtransaction;
00032 
00034 
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;}              //[t81]
00111 
00113 
00116   bool operator!() const { return m_done; }                             //[t81]
00117 
00122 
00123 
00126   static difference_type all() throw ();                                //[t81]
00128 
00130   static difference_type next() throw () { return 1; }                  //[t81]
00132 
00134   static difference_type prior() throw () { return -1; }                //[t0]
00136 
00138   static difference_type backward_all() throw ();                       //[t0]
00140 
00142 
00147   const PGSTD::string &name() const throw () { return m_name; }         //[t81]
00148 
00150   virtual result fetch(difference_type);                                //[]
00151 
00153 
00164   virtual result fetch(difference_type, difference_type &);             //[]
00165 
00167 
00174   virtual difference_type move(difference_type);                        //[]
00175 
00177 
00180   virtual difference_type move(difference_type, difference_type &);     //[]
00181 
00182   void close() throw ();                                                //[]
00183 
00184 protected:
00185   cursor_base(transaction_base *,
00186       const PGSTD::string &cname,
00187       bool embellish_name = true);
00188 
00189   void declare(const PGSTD::string &query,
00190       accesspolicy,
00191       updatepolicy,
00192       ownershippolicy,
00193       bool hold);
00194   void adopt(ownershippolicy);
00195 
00196   static PGSTD::string stridestring(difference_type);
00197   transaction_base *m_context;
00198   bool m_done;
00199 
00200   template<accesspolicy A> void check_displacement(difference_type) { }
00201 
00202 private:
00203   int PQXX_PRIVATE get_unique_cursor_num();
00204 
00205   PGSTD::string m_name;
00206   bool m_adopted;
00207   ownershippolicy m_ownership;
00208 
00209   struct cachedquery
00210   {
00211     difference_type dist;
00212     PGSTD::string query;
00213 
00214     cachedquery() : dist(0), query() {}
00215   };
00216   cachedquery m_lastfetch, m_lastmove;
00217 
00219   cursor_base();
00221   cursor_base(const cursor_base &);
00223   cursor_base &operator=(const cursor_base &);
00224 };
00225 
00226 
00227 template<> void
00228   cursor_base::check_displacement<cursor_base::forward_only>(difference_type);
00229 
00230 
00231 inline cursor_base::difference_type cursor_base::all() throw ()
00232 {
00233   // Microsoft Visual C++ sabotages numeric limits by defining min() and max()
00234   // as preprocessor macros; some other compilers just don't have numeric_limits
00235 #if defined(PQXX_HAVE_LIMITS)
00236   return PGSTD::numeric_limits<difference_type>::max();
00237 #else
00238   return INT_MAX;
00239 #endif
00240 }
00241 
00242 inline cursor_base::difference_type cursor_base::backward_all() throw ()
00243 {
00244 #if defined(PQXX_HAVE_LIMITS)
00245   return PGSTD::numeric_limits<difference_type>::min() + 1;
00246 #else
00247   return INT_MIN + 1;
00248 #endif
00249 }
00250 
00251 
00252 // TODO: How do we work updates into the scheme?
00254 template<cursor_base::accesspolicy ACCESS, cursor_base::updatepolicy UPDATE>
00255 class PQXX_LIBEXPORT basic_cursor : public cursor_base
00256 {
00257 public:
00259 
00269   basic_cursor(transaction_base *t,
00270       const PGSTD::string &query,
00271       const PGSTD::string &cname,
00272       ownershippolicy op=owned) :                                       //[t3]
00273     cursor_base(t, cname, true)
00274   {
00275     declare(query,
00276         ACCESS,
00277         UPDATE,
00278         op,
00279         op==loose || !dynamic_cast<dbtransaction *>(t));
00280   }
00281 
00283 
00291   basic_cursor(transaction_base *t,
00292       const PGSTD::string &cname,
00293       ownershippolicy op=owned) :                                       //[t45]
00294     cursor_base(t, cname, false)
00295   {
00296     adopt(op);
00297   }
00298 
00300 
00316   virtual result fetch(difference_type n)                               //[t3]
00317   {
00318     check_displacement<ACCESS>(n);
00319     return cursor_base::fetch(n);
00320   }
00321 
00322   virtual result fetch(difference_type n, difference_type &d)           //[]
00323   {
00324     check_displacement<ACCESS>(n);
00325     return cursor_base::fetch(n, d);
00326   }
00327 
00329 
00333   virtual difference_type move(difference_type n)                       //[t3]
00334   {
00335     check_displacement<ACCESS>(n);
00336     return cursor_base::move(n);
00337   }
00338 
00339   virtual difference_type move(difference_type n, difference_type &d)   //[t42]
00340   {
00341     check_displacement<ACCESS>(n);
00342     return cursor_base::move(n, d);
00343   }
00344 
00345   using cursor_base::close;
00346 };
00347 
00348 
00350 template<cursor_base::accesspolicy ACCESS, cursor_base::updatepolicy UPDATE>
00351 class PQXX_LIBEXPORT absolute_cursor : public basic_cursor<ACCESS,UPDATE>
00352 {
00353   typedef basic_cursor<ACCESS,UPDATE> super;
00354 public:
00355   typedef cursor_base::size_type size_type;
00356   typedef cursor_base::difference_type difference_type;
00357 
00359 
00367   absolute_cursor(transaction_base *t,
00368       const PGSTD::string &query,
00369       const PGSTD::string &cname) :                                     //[]
00370     super(t, query, cname, cursor_base::owned),
00371     m_pos(0),
00372     m_size(0),
00373     m_size_known(false)
00374   {
00375   }
00376 
00377   virtual result fetch(difference_type n)                               //[]
00378   {
00379     difference_type m;
00380     return fetch(n, m);
00381   }
00382 
00383   virtual difference_type move(difference_type n)                       //[]
00384   {
00385     difference_type m;
00386     return move(n, m);
00387   }
00388 
00389   virtual difference_type move(difference_type d, difference_type &m)   //[]
00390   {
00391     const difference_type r(super::move(d, m));
00392     digest(d, m);
00393     return r;
00394   }
00395 
00396   virtual result fetch(difference_type d, difference_type &m)           //[]
00397   {
00398     const result r(super::fetch(d, m));
00399     digest(d, m);
00400     return r;
00401   }
00402 
00403   size_type pos() const throw () { return m_pos; }                      //[]
00404 
00405   difference_type move_to(cursor_base::size_type);                      //[]
00406 
00407 private:
00409   void digest(cursor_base::difference_type req,
00410       cursor_base::difference_type got) throw ()
00411   {
00412     m_pos += got;
00413 
00414     // This assumes that got < req can only happen if req < 0
00415     if (got < req && !m_size_known)
00416     {
00417       m_size = m_pos;
00418       m_size_known = true;
00419     }
00420   }
00421 
00422   cursor_base::size_type m_pos;
00423   cursor_base::size_type m_size;
00424   bool m_size_known;
00425 };
00426 
00427 
00429 typedef basic_cursor<cursor_base::random_access, cursor_base::read_only> cursor;
00430 
00431 
00432 class icursor_iterator;
00433 
00435 
00450 class PQXX_LIBEXPORT icursorstream :
00451   public basic_cursor<cursor_base::forward_only, cursor_base::read_only>
00452 {
00453   typedef basic_cursor<cursor_base::forward_only, cursor_base::read_only> super;
00454 public:
00456 
00467   icursorstream(transaction_base &Context,
00468       const PGSTD::string &Query,
00469       const PGSTD::string &Basename,
00470       difference_type Stride=1);                                        //[t81]
00471 
00473 
00495   icursorstream(transaction_base &Context,
00496       const result::field &Name,
00497       difference_type Stride=1);                                        //[t84]
00498 
00500 
00506   icursorstream &get(result &res) { res = fetchblock(); return *this; } //[t81]
00508 
00514   icursorstream &operator>>(result &res) { return get(res); }           //[t81]
00516 
00520   icursorstream &ignore(PGSTD::streamsize n=1);                         //[t81]
00521 
00523 
00526   void set_stride(difference_type stride);                              //[t81]
00527   difference_type stride() const throw () { return m_stride; }          //[t81]
00528 
00529 private:
00530   result fetchblock();
00531 
00532   friend class icursor_iterator;
00533   size_type forward(size_type n=1);
00534   void insert_iterator(icursor_iterator *) throw ();
00535   void remove_iterator(icursor_iterator *) const throw ();
00536 
00537   void service_iterators(size_type);
00538 
00539   difference_type m_stride;
00540   size_type m_realpos, m_reqpos;
00541 
00542   mutable icursor_iterator *m_iterators;
00543 };
00544 
00545 
00547 
00573 class PQXX_LIBEXPORT icursor_iterator :
00574   public PGSTD::iterator<PGSTD::input_iterator_tag,
00575         result,
00576         cursor_base::size_type,
00577         const result *,
00578         const result &>
00579 {
00580 public:
00581   typedef icursorstream istream_type;
00582   typedef istream_type::size_type size_type;
00583   typedef istream_type::difference_type difference_type;
00584 
00585   icursor_iterator() throw ();                                          //[t84]
00586   explicit icursor_iterator(istream_type &) throw ();                   //[t84]
00587   icursor_iterator(const icursor_iterator &) throw ();                  //[t84]
00588   ~icursor_iterator() throw ();
00589 
00590   const result &operator*() const { refresh(); return m_here; }         //[t84]
00591   const result *operator->() const { refresh(); return &m_here; }       //[t84]
00592   icursor_iterator &operator++();                                       //[t84]
00593   icursor_iterator operator++(int);                                     //[t84]
00594   icursor_iterator &operator+=(difference_type);                        //[t84]
00595   icursor_iterator &operator=(const icursor_iterator &) throw ();       //[t84]
00596 
00597   bool operator==(const icursor_iterator &rhs) const;                   //[t84]
00598   bool operator!=(const icursor_iterator &rhs) const throw ()           //[t84]
00599         { return !operator==(rhs); }
00600   bool operator<(const icursor_iterator &rhs) const;                    //[t84]
00601   bool operator>(const icursor_iterator &rhs) const                     //[t84]
00602         { return rhs < *this; }
00603   bool operator<=(const icursor_iterator &rhs) const                    //[t84]
00604         { return !(*this > rhs); }
00605   bool operator>=(const icursor_iterator &rhs) const                    //[t84]
00606         { return !(*this < rhs); }
00607 
00608 private:
00609   void refresh() const;
00610 
00611   friend class icursorstream;
00612   size_type pos() const throw () { return m_pos; }
00613   void fill(const result &);
00614 
00615   icursorstream *m_stream;
00616   result m_here;
00617   size_type m_pos;
00618   icursor_iterator *m_prev, *m_next;
00619 };
00620 
00621 
00622 } // namespace pqxx
00623 

Generated on Mon Oct 3 20:28:58 2005 for libpqxx by  doxygen 1.4.2