00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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 <limits>
00026 #include <stdexcept>
00027
00028 #include "pqxx/result"
00029 #include "pqxx/transaction_base"
00030
00031
00032 namespace pqxx
00033 {
00034 class dbtransaction;
00035
00036
00038
00049 class PQXX_LIBEXPORT cursor_base
00050 {
00051 public:
00052 typedef result::size_type size_type;
00053 typedef result::difference_type difference_type;
00054
00056
00059 enum accesspolicy
00060 {
00062 forward_only,
00064 random_access
00065 };
00066
00068
00071 enum updatepolicy
00072 {
00074 read_only,
00076 update
00077 };
00078
00080
00098 enum ownershippolicy
00099 {
00101 owned,
00103 loose
00104 };
00105
00110
00111
00114 static difference_type all() PQXX_NOEXCEPT;
00116
00118 static difference_type next() PQXX_NOEXCEPT { return 1; }
00120
00122 static difference_type prior() PQXX_NOEXCEPT { return -1; }
00124
00126 static difference_type backward_all() PQXX_NOEXCEPT;
00127
00129
00131
00136 const std::string &name() const PQXX_NOEXCEPT { return m_name; }
00137
00138 protected:
00139 cursor_base(connection_base &,
00140 const std::string &Name,
00141 bool embellish_name=true);
00142
00143 const std::string m_name;
00144
00145 private:
00147 cursor_base();
00149 cursor_base(const cursor_base &);
00151 cursor_base &operator=(const cursor_base &);
00152 };
00153
00154
00155 inline cursor_base::difference_type cursor_base::all() PQXX_NOEXCEPT
00156 {
00157 return std::numeric_limits<int>::max()-1;
00158 }
00159
00160 inline cursor_base::difference_type cursor_base::backward_all() PQXX_NOEXCEPT
00161 {
00162 return std::numeric_limits<int>::min()+1;
00163 }
00164
00165
00166 namespace internal
00167 {
00169
00183 class PQXX_LIBEXPORT sql_cursor : public cursor_base
00184 {
00185 public:
00186 sql_cursor(transaction_base &t,
00187 const std::string &query,
00188 const std::string &cname,
00189 cursor_base::accesspolicy ap,
00190 cursor_base::updatepolicy up,
00191 cursor_base::ownershippolicy op,
00192 bool hold);
00193
00194 sql_cursor(transaction_base &t,
00195 const std::string &cname,
00196 cursor_base::ownershippolicy op);
00197
00198 ~sql_cursor() PQXX_NOEXCEPT { close(); }
00199
00200 result fetch(difference_type rows, difference_type &displacement);
00201 result fetch(difference_type rows)
00202 { difference_type d=0; return fetch(rows, d); }
00203 difference_type move(difference_type rows, difference_type &displacement);
00204 difference_type move(difference_type rows)
00205 { difference_type d=0; return move(rows, d); }
00206
00208
00214 difference_type pos() const PQXX_NOEXCEPT { return m_pos; }
00215
00217
00223 difference_type endpos() const PQXX_NOEXCEPT { return m_endpos; }
00224
00226 const result &empty_result() const PQXX_NOEXCEPT { return m_empty_result; }
00227
00228 void close() PQXX_NOEXCEPT;
00229
00230 private:
00231 difference_type adjust(difference_type hoped, difference_type actual);
00232 static std::string stridestring(difference_type);
00234 void init_empty_result(transaction_base &);
00235
00237 connection_base &m_home;
00238
00240 result m_empty_result;
00241
00242 result m_cached_current_row;
00243
00245 bool m_adopted;
00246
00248 cursor_base::ownershippolicy m_ownership;
00249
00251 int m_at_end;
00252
00254 difference_type m_pos;
00255
00257 difference_type m_endpos;
00258 };
00259
00260
00261 PQXX_LIBEXPORT result::size_type obtain_stateless_cursor_size(sql_cursor &);
00262 PQXX_LIBEXPORT result stateless_cursor_retrieve(
00263 sql_cursor &,
00264 result::difference_type size,
00265 result::difference_type begin_pos,
00266 result::difference_type end_pos);
00267
00268 }
00269
00270
00272
00278 template<cursor_base::updatepolicy up, cursor_base::ownershippolicy op>
00279 class stateless_cursor
00280 {
00281 public:
00282 typedef result::size_type size_type;
00283 typedef result::difference_type difference_type;
00284
00286 stateless_cursor(
00287 transaction_base &trans,
00288 const std::string &query,
00289 const std::string &cname,
00290 bool hold) :
00291 m_cur(trans, query, cname, cursor_base::random_access, up, op, hold)
00292 {
00293 }
00294
00296 stateless_cursor(
00297 transaction_base &trans,
00298 const std::string adopted_cursor) :
00299 m_cur(trans, adopted_cursor, op)
00300 {
00301
00302 m_cur.move(cursor_base::backward_all());
00303 }
00304
00305 void close() PQXX_NOEXCEPT { m_cur.close(); }
00306
00308
00311 size_type size() { return internal::obtain_stateless_cursor_size(m_cur); }
00312
00314
00325 result retrieve(difference_type begin_pos, difference_type end_pos)
00326 {
00327 return internal::stateless_cursor_retrieve(
00328 m_cur,
00329 result::difference_type(size()),
00330 begin_pos,
00331 end_pos);
00332 }
00333
00334 const std::string &name() const PQXX_NOEXCEPT { return m_cur.name(); }
00335
00336 private:
00337 internal::sql_cursor m_cur;
00338 };
00339
00340
00341 class icursor_iterator;
00342
00343
00344 namespace internal
00345 {
00346 namespace gate
00347 {
00348 class icursor_iterator_icursorstream;
00349 class icursorstream_icursor_iterator;
00350 }
00351 }
00352
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 std::string &query,
00390 const std::string &basename,
00391 difference_type sstride=1);
00392
00394
00418 icursorstream(transaction_base &context,
00419 const field &cname,
00420 difference_type sstride=1,
00421 cursor_base::ownershippolicy op=cursor_base::owned);
00422
00423 operator bool() const PQXX_NOEXCEPT { return !m_done; }
00424
00426
00432 icursorstream &get(result &res) { res = fetchblock(); return *this; }
00434
00440 icursorstream &operator>>(result &res) { return get(res); }
00441
00443
00447 icursorstream &ignore(std::streamsize n=1);
00448
00450
00453 void set_stride(difference_type stride);
00454 difference_type stride() const PQXX_NOEXCEPT { return m_stride; }
00455
00456 private:
00457 result fetchblock();
00458
00459 friend class internal::gate::icursorstream_icursor_iterator;
00460 size_type forward(size_type n=1);
00461 void insert_iterator(icursor_iterator *) PQXX_NOEXCEPT;
00462 void remove_iterator(icursor_iterator *) const PQXX_NOEXCEPT;
00463
00464 void service_iterators(difference_type);
00465
00466 internal::sql_cursor m_cur;
00467
00468 difference_type m_stride;
00469 difference_type m_realpos, m_reqpos;
00470
00471 mutable icursor_iterator *m_iterators;
00472
00473 bool m_done;
00474 };
00475
00476
00478
00504 class PQXX_LIBEXPORT icursor_iterator :
00505 public std::iterator<std::input_iterator_tag,
00506 result,
00507 cursor_base::size_type,
00508 const result *,
00509 const result &>
00510 {
00511 public:
00512 typedef icursorstream istream_type;
00513 typedef istream_type::size_type size_type;
00514 typedef istream_type::difference_type difference_type;
00515
00516 icursor_iterator() PQXX_NOEXCEPT;
00517 explicit icursor_iterator(istream_type &) PQXX_NOEXCEPT;
00518 icursor_iterator(const icursor_iterator &) PQXX_NOEXCEPT;
00519 ~icursor_iterator() PQXX_NOEXCEPT;
00520
00521 const result &operator*() const { refresh(); return m_here; }
00522 const result *operator->() const { refresh(); return &m_here; }
00523 icursor_iterator &operator++();
00524 icursor_iterator operator++(int);
00525 icursor_iterator &operator+=(difference_type);
00526 icursor_iterator &operator=(const icursor_iterator &) PQXX_NOEXCEPT;
00527
00528 bool operator==(const icursor_iterator &rhs) const;
00529 bool operator!=(const icursor_iterator &rhs) const PQXX_NOEXCEPT
00530 { return !operator==(rhs); }
00531 bool operator<(const icursor_iterator &rhs) const;
00532 bool operator>(const icursor_iterator &rhs) const
00533 { return rhs < *this; }
00534 bool operator<=(const icursor_iterator &rhs) const
00535 { return !(*this > rhs); }
00536 bool operator>=(const icursor_iterator &rhs) const
00537 { return !(*this < rhs); }
00538
00539 private:
00540 void refresh() const;
00541
00542 friend class internal::gate::icursor_iterator_icursorstream;
00543 difference_type pos() const PQXX_NOEXCEPT { return m_pos; }
00544 void fill(const result &);
00545
00546 icursorstream *m_stream;
00547 result m_here;
00548 difference_type m_pos;
00549 icursor_iterator *m_prev, *m_next;
00550 };
00551
00552
00553 }
00554
00555 #include "pqxx/compiler-internal-post.hxx"
00556
00557 #endif
00558