# cursor.hxx

    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-2008, 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
    00355
    00370 class PQXX_LIBEXPORT icursorstream
    00371 {
    00372 public:
    00373   typedef cursor_base::size_type size_type;
    00374   typedef cursor_base::difference_type difference_type;
    00375
    00377
    00388   icursorstream(transaction_base &context,
    00389       const PGSTD::string &query,
    00390       const PGSTD::string &basename,
    00391       difference_type sstride=1);                                       //[t81]
    00392
    00394
    00416   icursorstream(transaction_base &context,
    00417       const result::field &cname,
    00418       difference_type sstride=1,
    00419       cursor_base::ownershippolicy op=cursor_base::owned);              //[t84]
    00420
    00421   operator bool() const throw () { return !m_done; }
    00422
    00424
    00430   icursorstream &get(result &res) { res = fetchblock(); return *this; } //[t81]
    00432
    00438   icursorstream &operator>>(result &res) { return get(res); }           //[t81]
    00439
    00441
    00445   icursorstream &ignore(PGSTD::streamsize n=1);                         //[t81]
    00446
    00448
    00451   void set_stride(difference_type stride);                              //[t81]
    00452   difference_type stride() const throw () { return m_stride; }          //[t81]
    00453
    00454 private:
    00455   result fetchblock();
    00456
    00457   friend class icursor_iterator;
    00458   size_type forward(size_type n=1);
    00459   void insert_iterator(icursor_iterator *) throw ();
    00460   void remove_iterator(icursor_iterator *) const throw ();
    00461
    00462   void service_iterators(difference_type);
    00463
    00464   internal::sql_cursor m_cur;
    00465
    00466   difference_type m_stride;
    00467   difference_type m_realpos, m_reqpos;
    00468
    00469   mutable icursor_iterator *m_iterators;
    00470
    00471   bool m_done;
    00472 };
    00473
    00474
    00476
    00502 class PQXX_LIBEXPORT icursor_iterator :
    00503   public PGSTD::iterator<PGSTD::input_iterator_tag,
    00504         result,
    00505         cursor_base::size_type,
    00506         const result *,
    00507         const result &>
    00508 {
    00509 public:
    00510   typedef icursorstream istream_type;
    00511   typedef istream_type::size_type size_type;
    00512   typedef istream_type::difference_type difference_type;
    00513
    00514   icursor_iterator() throw ();                                          //[t84]
    00515   explicit icursor_iterator(istream_type &) throw ();                   //[t84]
    00516   icursor_iterator(const icursor_iterator &) throw ();                  //[t84]
    00517   ~icursor_iterator() throw ();
    00518
    00519   const result &operator*() const { refresh(); return m_here; }         //[t84]
    00520   const result *operator->() const { refresh(); return &m_here; }       //[t84]
    00521   icursor_iterator &operator++();                                       //[t84]
    00522   icursor_iterator operator++(int);                                     //[t84]
    00523   icursor_iterator &operator+=(difference_type);                        //[t84]
    00524   icursor_iterator &operator=(const icursor_iterator &) throw ();       //[t84]
    00525
    00526   bool operator==(const icursor_iterator &rhs) const;                   //[t84]
    00527   bool operator!=(const icursor_iterator &rhs) const throw ()           //[t84]
    00528         { return !operator==(rhs); }
    00529   bool operator<(const icursor_iterator &rhs) const;                    //[t84]
    00530   bool operator>(const icursor_iterator &rhs) const                     //[t84]
    00531         { return rhs < *this; }
    00532   bool operator<=(const icursor_iterator &rhs) const                    //[t84]
    00533         { return !(*this > rhs); }
    00534   bool operator>=(const icursor_iterator &rhs) const                    //[t84]
    00535         { return !(*this < rhs); }
    00536
    00537 private:
    00538   void refresh() const;
    00539
    00540   friend class icursorstream;
    00541   difference_type pos() const throw () { return m_pos; }
    00542   void fill(const result &);
    00543
    00544   icursorstream *m_stream;
    00545   result m_here;
    00546   difference_type m_pos;
    00547   icursor_iterator *m_prev, *m_next;
    00548 };
    00549
    00550
    00551 } // namespace pqxx
    00552
    00553 #include "pqxx/compiler-internal-post.hxx"
    00554
    00555 #endif
    00556