libpqxx: cursor.hxx Source File

libpqxx 4.0.1

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes

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:
55 typedef result::size_type size_type;
56 typedef result::difference_type difference_type;
57
59
62 enum accesspolicy
63 {
65 forward_only,
67 random_access
68 };
69
71
74 enum updatepolicy
75 {
77 read_only,
79 update
80 };
81
83
101 enum ownershippolicy
102 {
104 owned,
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:
142 cursor_base(connection_base &,
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
158 inline cursor_base::difference_type cursor_base::all() throw ()
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
167 inline cursor_base::difference_type cursor_base::backward_all() throw ()
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:
197 sql_cursor(transaction_base &t,
198 const PGSTD::string &query,
199 const PGSTD::string &cname,
200 cursor_base::accesspolicy ap,
201 cursor_base::updatepolicy up,
202 cursor_base::ownershippolicy op,
203 bool hold);
204
205 sql_cursor(transaction_base &t,
206 const PGSTD::string &cname,
207 cursor_base::ownershippolicy op);
208
209 ~sql_cursor() throw () { close(); }
210
211 result fetch(difference_type rows, difference_type &displacement);
212 result fetch(difference_type rows)
213 { difference_type d=0; return fetch(rows, d); }
214 difference_type move(difference_type rows, difference_type &displacement);
215 difference_type move(difference_type rows)
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>
290 class stateless_cursor
291 {
292 public:
293 typedef result::size_type size_type;
294 typedef result::difference_type difference_type;
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 {
338 return internal::stateless_cursor_retrieve(
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:
384 typedef cursor_base::size_type size_type;
385 typedef cursor_base::difference_type difference_type;
386
388
399 icursorstream(transaction_base &context,
400 const PGSTD::string &query,
401 const PGSTD::string &basename,
402 difference_type sstride=1); //[t81]
403
405
429 icursorstream(transaction_base &context,
430 const field &cname,
431 difference_type sstride=1,
432 cursor_base::ownershippolicy op=cursor_base::owned); //[t84]
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,
518 cursor_base::size_type,
519 const result *,
520 const result &>
521 {
522 public:
523 typedef icursorstream istream_type;
524 typedef istream_type::size_type size_type;
525 typedef istream_type::difference_type difference_type;
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