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-2006, 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/compiler-public.hxx"
00020 #include "pqxx/compiler-internal-pre.hxx"
00021 
00022 #ifdef PQXX_HAVE_LIMITS
00023 #include <limits>
00024 #endif
00025 
00026 #include "pqxx/result"
00027 #include "pqxx/transaction_base"
00028 
00029 
00030 namespace pqxx
00031 {
00032 class dbtransaction;
00033 
00035 
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 &Name,
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) const { }
00201 
00202 #if defined(_MSC_VER)
00203   /* Visual C++ won't accept this specialization declaration unless it's in
00204    * here!  See below for the "standard" alternative.
00205    */
00206   template<>
00207     void check_displacement<cursor_base::forward_only>(difference_type) const;
00208 #endif
00209 
00210 private:
00211   PGSTD::string m_name;
00212   bool m_adopted;
00213   ownershippolicy m_ownership;
00214 
00215   struct cachedquery
00216   {
00217     difference_type dist;
00218     PGSTD::string query;
00219 
00220     cachedquery() : dist(0), query() {}
00221   };
00222   cachedquery m_lastfetch, m_lastmove;
00223 
00225   cursor_base();
00227   cursor_base(const cursor_base &);
00229   cursor_base &operator=(const cursor_base &);
00230 };
00231 
00232 /* Visual C++ demands that this specialization be declared inside the class,
00233  * which gcc claims is illegal.  There seems to be no single universally
00234  * accepted way to do this.
00235  */
00236 #if !defined(_MSC_VER)
00237 template<> void
00238   cursor_base::check_displacement<cursor_base::forward_only>(difference_type)
00239         const;
00240 #endif
00241 
00242 
00243 inline cursor_base::difference_type cursor_base::all() throw ()
00244 {
00245   // Microsoft Visual C++ sabotages numeric limits by defining min() and max()
00246   // as preprocessor macros; some other compilers just don't have numeric_limits
00247 #if defined(PQXX_HAVE_LIMITS)
00248   return PGSTD::numeric_limits<difference_type>::max();
00249 #else
00250   return INT_MAX;
00251 #endif
00252 }
00253 
00254 inline cursor_base::difference_type cursor_base::backward_all() throw ()
00255 {
00256 #if defined(PQXX_HAVE_LIMITS)
00257   return PGSTD::numeric_limits<difference_type>::min() + 1;
00258 #else
00259   return INT_MIN + 1;
00260 #endif
00261 }
00262 
00263 
00264 // TODO: How do we work updates into the scheme?
00266 template<cursor_base::accesspolicy ACCESS, cursor_base::updatepolicy UPDATE>
00267 class basic_cursor : public cursor_base
00268 {
00269 public:
00271 
00281   basic_cursor(transaction_base *t,
00282       const PGSTD::string &query,
00283       const PGSTD::string &cname,
00284       ownershippolicy op=owned) :                                       //[t3]
00285     cursor_base(t, cname, true)
00286   {
00287     declare(query,
00288         ACCESS,
00289         UPDATE,
00290         op,
00291         op==loose || !dynamic_cast<dbtransaction *>(t));
00292   }
00293 
00295 
00303   basic_cursor(transaction_base *t,
00304       const PGSTD::string &cname,
00305       ownershippolicy op=owned) :                                       //[t45]
00306     cursor_base(t, cname, false)
00307   {
00308     adopt(op);
00309   }
00310 
00312 
00328   virtual result fetch(difference_type n)                               //[t3]
00329   {
00330     check_displacement<ACCESS>(n);
00331     return cursor_base::fetch(n);
00332   }
00333 
00334   virtual result fetch(difference_type n, difference_type &d)           //[]
00335   {
00336     check_displacement<ACCESS>(n);
00337     return cursor_base::fetch(n, d);
00338   }
00339 
00341 
00345   virtual difference_type move(difference_type n)                       //[t3]
00346   {
00347     check_displacement<ACCESS>(n);
00348     return cursor_base::move(n);
00349   }
00350 
00351   virtual difference_type move(difference_type n, difference_type &d)   //[t42]
00352   {
00353     check_displacement<ACCESS>(n);
00354     return cursor_base::move(n, d);
00355   }
00356 
00357   using cursor_base::close;
00358 };
00359 
00360 
00362 template<cursor_base::accesspolicy ACCESS, cursor_base::updatepolicy UPDATE>
00363 class absolute_cursor : public basic_cursor<ACCESS,UPDATE>
00364 {
00365   typedef basic_cursor<ACCESS,UPDATE> super;
00366 public:
00367   typedef cursor_base::size_type size_type;
00368   typedef cursor_base::difference_type difference_type;
00369 
00371 
00379   absolute_cursor(transaction_base *t,
00380       const PGSTD::string &query,
00381       const PGSTD::string &cname) :                                     //[]
00382     super(t, query, cname, cursor_base::owned),
00383     m_pos(0),
00384     m_size(0),
00385     m_size_known(false)
00386   {
00387   }
00388 
00389   virtual result fetch(difference_type n)                               //[]
00390   {
00391     difference_type m;
00392     return fetch(n, m);
00393   }
00394 
00395   virtual difference_type move(difference_type n)                       //[]
00396   {
00397     difference_type m;
00398     return move(n, m);
00399   }
00400 
00401   virtual difference_type move(difference_type d, difference_type &m)   //[]
00402   {
00403     const difference_type r(super::move(d, m));
00404     digest(d, m);
00405     return r;
00406   }
00407 
00408   virtual result fetch(difference_type d, difference_type &m)           //[]
00409   {
00410     const result r(super::fetch(d, m));
00411     digest(d, m);
00412     return r;
00413   }
00414 
00415   size_type pos() const throw () { return m_pos; }                      //[]
00416 
00417   difference_type move_to(cursor_base::size_type);                      //[]
00418 
00419 private:
00421   void digest(cursor_base::difference_type req,
00422       cursor_base::difference_type got) throw ()
00423   {
00424     m_pos += got;
00425 
00426     // This assumes that got < req can only happen if req < 0
00427     if (got < req && !m_size_known)
00428     {
00429       m_size = m_pos;
00430       m_size_known = true;
00431     }
00432   }
00433 
00434   cursor_base::size_type m_pos;
00435   cursor_base::size_type m_size;
00436   bool m_size_known;
00437 };
00438 
00439 
00441 typedef basic_cursor<cursor_base::random_access, cursor_base::read_only> cursor;
00442 
00443 
00444 class icursor_iterator;
00445 
00447 
00462 class PQXX_LIBEXPORT icursorstream :
00463   public basic_cursor<cursor_base::forward_only, cursor_base::read_only>
00464 {
00465   typedef basic_cursor<cursor_base::forward_only, cursor_base::read_only> super;
00466 public:
00468 
00479   icursorstream(transaction_base &Context,
00480       const PGSTD::string &Query,
00481       const PGSTD::string &Basename,
00482       difference_type Stride=1);                                        //[t81]
00483 
00485 
00507   icursorstream(transaction_base &Context,
00508       const result::field &Name,
00509       difference_type Stride=1);                                        //[t84]
00510 
00512 
00518   icursorstream &get(result &res) { res = fetchblock(); return *this; } //[t81]
00520 
00526   icursorstream &operator>>(result &res) { return get(res); }           //[t81]
00528 
00532   icursorstream &ignore(PGSTD::streamsize n=1);                         //[t81]
00533 
00535 
00538   void set_stride(difference_type stride);                              //[t81]
00539   difference_type stride() const throw () { return m_stride; }          //[t81]
00540 
00541 private:
00542   result fetchblock();
00543 
00544   friend class icursor_iterator;
00545   size_type forward(size_type n=1);
00546   void insert_iterator(icursor_iterator *) throw ();
00547   void remove_iterator(icursor_iterator *) const throw ();
00548 
00549   void service_iterators(size_type);
00550 
00551   difference_type m_stride;
00552   size_type m_realpos, m_reqpos;
00553 
00554   mutable icursor_iterator *m_iterators;
00555 };
00556 
00557 
00559 
00586 class PQXX_LIBEXPORT icursor_iterator :
00587   public PGSTD::iterator<PGSTD::input_iterator_tag,
00588         result,
00589         cursor_base::size_type,
00590         const result *,
00591         const result &>
00592 {
00593 public:
00594   typedef icursorstream istream_type;
00595   typedef istream_type::size_type size_type;
00596   typedef istream_type::difference_type difference_type;
00597 
00598   icursor_iterator() throw ();                                          //[t84]
00599   explicit icursor_iterator(istream_type &) throw ();                   //[t84]
00600   icursor_iterator(const icursor_iterator &) throw ();                  //[t84]
00601   ~icursor_iterator() throw ();
00602 
00603   const result &operator*() const { refresh(); return m_here; }         //[t84]
00604   const result *operator->() const { refresh(); return &m_here; }       //[t84]
00605   icursor_iterator &operator++();                                       //[t84]
00606   icursor_iterator operator++(int);                                     //[t84]
00607   icursor_iterator &operator+=(difference_type);                        //[t84]
00608   icursor_iterator &operator=(const icursor_iterator &) throw ();       //[t84]
00609 
00610   bool operator==(const icursor_iterator &rhs) const;                   //[t84]
00611   bool operator!=(const icursor_iterator &rhs) const throw ()           //[t84]
00612         { return !operator==(rhs); }
00613   bool operator<(const icursor_iterator &rhs) const;                    //[t84]
00614   bool operator>(const icursor_iterator &rhs) const                     //[t84]
00615         { return rhs < *this; }
00616   bool operator<=(const icursor_iterator &rhs) const                    //[t84]
00617         { return !(*this > rhs); }
00618   bool operator>=(const icursor_iterator &rhs) const                    //[t84]
00619         { return !(*this < rhs); }
00620 
00621 private:
00622   void refresh() const;
00623 
00624   friend class icursorstream;
00625   size_type pos() const throw () { return m_pos; }
00626   void fill(const result &);
00627 
00628   icursorstream *m_stream;
00629   result m_here;
00630   size_type m_pos;
00631   icursor_iterator *m_prev, *m_next;
00632 };
00633 
00634 
00635 } // namespace pqxx
00636 
00637 #include "pqxx/compiler-internal-post.hxx"

Generated on Sun Jun 18 14:51:00 2006 for libpqxx by  doxygen 1.4.6