libpqxx  4.0.1
cursor.hxx
1 /*-------------------------------------------------------------------------
2  *
3  * FILE
4  * pqxx/cursor.hxx
5  *
6  * DESCRIPTION
7  * definition of the iterator/container-style cursor classes
8  * C++-style wrappers for SQL cursors
9  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead.
10  *
11  * Copyright (c) 2004-2011, Jeroen T. Vermeulen <jtv@xs4all.nl>
12  *
13  * See COPYING for copyright license. If you did not receive a file called
14  * COPYING with this source code, please notify the distributor of this mistake,
15  * or contact the author.
16  *
17  *-------------------------------------------------------------------------
18  */
19 #ifndef PQXX_H_CURSOR
20 #define PQXX_H_CURSOR
21 
22 #include "pqxx/compiler-public.hxx"
23 #include "pqxx/compiler-internal-pre.hxx"
24 
25 #include <stdexcept>
26 
27 #ifdef PQXX_HAVE_LIMITS
28 #include <limits>
29 #endif
30 
31 #include "pqxx/result"
32 #include "pqxx/transaction_base"
33 
34 
35 namespace pqxx
36 {
37 class dbtransaction;
38 
39 
41 
52 class PQXX_LIBEXPORT cursor_base
53 {
54 public:
57 
59 
63  {
67  random_access
68  };
69 
71 
75  {
79  update
80  };
81 
83 
102  {
106  loose
107  };
108 
113 
114 
117  static difference_type all() throw (); //[t81]
119 
121  static difference_type next() throw () { return 1; } //[t81]
123 
125  static difference_type prior() throw () { return -1; } //[t0]
127 
129  static difference_type backward_all() throw (); //[t0]
130 
132 
134 
139  const PGSTD::string &name() const throw () { return m_name; } //[t81]
140 
141 protected:
143  const PGSTD::string &Name,
144  bool embellish_name=true);
145 
146  const PGSTD::string m_name;
147 
148 private:
150  cursor_base();
152  cursor_base(const cursor_base &);
154  cursor_base &operator=(const cursor_base &);
155 };
156 
157 
159 {
160 #ifdef PQXX_HAVE_LIMITS
161  return PGSTD::numeric_limits<int>::max()-1;
162 #else
163  return INT_MAX-1;
164 #endif
165 }
166 
168 {
169 #ifdef PQXX_HAVE_LIMITS
170  return PGSTD::numeric_limits<int>::min()+1;
171 #else
172  return INT_MIN+1;
173 #endif
174 }
175 
176 
177 namespace internal
178 {
180 
194 class PQXX_LIBEXPORT sql_cursor : public cursor_base
195 {
196 public:
198  const PGSTD::string &query,
199  const PGSTD::string &cname,
203  bool hold);
204 
206  const PGSTD::string &cname,
208 
209  ~sql_cursor() throw () { close(); }
210 
211  result fetch(difference_type rows, difference_type &displacement);
213  { difference_type d=0; return fetch(rows, d); }
214  difference_type move(difference_type rows, difference_type &displacement);
216  { difference_type d=0; return move(rows, d); }
217 
219 
225  difference_type pos() const throw () { return m_pos; }
226 
228 
234  difference_type endpos() const throw () { return m_endpos; }
235 
237  const result &empty_result() const throw () { return m_empty_result; }
238 
239  void close() throw ();
240 
241 private:
242  difference_type adjust(difference_type hoped, difference_type actual);
243  static PGSTD::string stridestring(difference_type);
245  void init_empty_result(transaction_base &);
246 
248  connection_base &m_home;
249 
251  result m_empty_result;
252 
253  result m_cached_current_row;
254 
256  bool m_adopted;
257 
259  cursor_base::ownershippolicy m_ownership;
260 
262  int m_at_end;
263 
265  difference_type m_pos;
266 
268  difference_type m_endpos;
269 };
270 
271 
272 result::size_type PQXX_LIBEXPORT obtain_stateless_cursor_size(sql_cursor &);
273 result PQXX_LIBEXPORT stateless_cursor_retrieve(
274  sql_cursor &,
275  result::difference_type size,
276  result::difference_type begin_pos,
277  result::difference_type end_pos);
278 
279 } // namespace internal
280 
281 
283 
289 template<cursor_base::updatepolicy up, cursor_base::ownershippolicy op>
291 {
292 public:
295 
297  stateless_cursor(
298  transaction_base &trans,
299  const PGSTD::string &query,
300  const PGSTD::string &cname,
301  bool hold) :
302  m_cur(trans, query, cname, cursor_base::random_access, up, op, hold)
303  {
304  }
305 
307  stateless_cursor(
308  transaction_base &trans,
309  const PGSTD::string adopted_cursor) :
310  m_cur(trans, adopted_cursor, op)
311  {
312  // Put cursor in known position
313  m_cur.move(cursor_base::backward_all());
314  }
315 
316  void close() throw () { m_cur.close(); }
317 
319 
322  size_type size() { return internal::obtain_stateless_cursor_size(m_cur); }
323 
325 
336  result retrieve(difference_type begin_pos, difference_type end_pos)
337  {
339  m_cur,
340  result::difference_type(size()),
341  begin_pos,
342  end_pos);
343  }
344 
345  const PGSTD::string &name() const throw () { return m_cur.name(); }
346 
347 private:
348  internal::sql_cursor m_cur;
349 };
350 
351 
352 class icursor_iterator;
353 
354 
355 namespace internal
356 {
357 namespace gate
358 {
359 class icursor_iterator_icursorstream;
360 class icursorstream_icursor_iterator;
361 } // namespace internal::gate
362 } // namespace internal
363 
364 
366 
381 class PQXX_LIBEXPORT icursorstream
382 {
383 public:
386 
388 
400  const PGSTD::string &query,
401  const PGSTD::string &basename,
402  difference_type sstride=1); //[t81]
403 
405 
430  const field &cname,
431  difference_type sstride=1,
433 
434  operator bool() const throw () { return !m_done; }
435 
437 
443  icursorstream &get(result &res) { res = fetchblock(); return *this; } //[t81]
445 
451  icursorstream &operator>>(result &res) { return get(res); } //[t81]
452 
454 
458  icursorstream &ignore(PGSTD::streamsize n=1); //[t81]
459 
461 
464  void set_stride(difference_type stride); //[t81]
465  difference_type stride() const throw () { return m_stride; } //[t81]
466 
467 private:
468  result fetchblock();
469 
470  friend class internal::gate::icursorstream_icursor_iterator;
471  size_type forward(size_type n=1);
472  void insert_iterator(icursor_iterator *) throw ();
473  void remove_iterator(icursor_iterator *) const throw ();
474 
475  void service_iterators(difference_type);
476 
477  internal::sql_cursor m_cur;
478 
479  difference_type m_stride;
480  difference_type m_realpos, m_reqpos;
481 
482  mutable icursor_iterator *m_iterators;
483 
484  bool m_done;
485 };
486 
487 
489 
515 class PQXX_LIBEXPORT icursor_iterator :
516  public PGSTD::iterator<PGSTD::input_iterator_tag,
517  result,
519  const result *,
520  const result &>
521 {
522 public:
526 
527  icursor_iterator() throw (); //[t84]
528  explicit icursor_iterator(istream_type &) throw (); //[t84]
529  icursor_iterator(const icursor_iterator &) throw (); //[t84]
530  ~icursor_iterator() throw ();
531 
532  const result &operator*() const { refresh(); return m_here; } //[t84]
533  const result *operator->() const { refresh(); return &m_here; } //[t84]
534  icursor_iterator &operator++(); //[t84]
535  icursor_iterator operator++(int); //[t84]
536  icursor_iterator &operator+=(difference_type); //[t84]
537  icursor_iterator &operator=(const icursor_iterator &) throw (); //[t84]
538 
539  bool operator==(const icursor_iterator &rhs) const; //[t84]
540  bool operator!=(const icursor_iterator &rhs) const throw () //[t84]
541  { return !operator==(rhs); }
542  bool operator<(const icursor_iterator &rhs) const; //[t84]
543  bool operator>(const icursor_iterator &rhs) const //[t84]
544  { return rhs < *this; }
545  bool operator<=(const icursor_iterator &rhs) const //[t84]
546  { return !(*this > rhs); }
547  bool operator>=(const icursor_iterator &rhs) const //[t84]
548  { return !(*this < rhs); }
549 
550 private:
551  void refresh() const;
552 
553  friend class internal::gate::icursor_iterator_icursorstream;
554  difference_type pos() const throw () { return m_pos; }
555  void fill(const result &);
556 
557  icursorstream *m_stream;
558  result m_here;
559  difference_type m_pos;
560  icursor_iterator *m_prev, *m_next;
561 };
562 
563 
564 } // namespace pqxx
565 
566 #include "pqxx/compiler-internal-post.hxx"
567 
568 #endif
569