00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef PQXX_CACHEDRESULT_H
00019 #define PQXX_CACHEDRESULT_H
00020
00021 #include <map>
00022
00023 #include "pqxx/cursor.h"
00024 #include "pqxx/result.h"
00025
00026 namespace pqxx
00027 {
00028
00029
00030
00052 class PQXX_LIBEXPORT cachedresult
00053 {
00054 public:
00055 typedef result::size_type size_type;
00056 typedef size_type blocknum;
00057
00059 typedef result::tuple tuple;
00060
00062 typedef tuple Tuple;
00063
00075 template<typename TRANSACTION> explicit
00076 cachedresult(TRANSACTION &T,
00077 const char Query[],
00078 const PGSTD::string &BaseName="query",
00079 size_type Granularity=100) :
00080 m_Granularity(Granularity),
00081 m_Cache(),
00082 m_Cursor(T, Query, BaseName, Granularity),
00083 m_EmptyResult(),
00084 m_HaveEmpty(false)
00085 {
00086
00087 error_permitted_isolation_level(PQXX_TYPENAME TRANSACTION::isolation_tag());
00088 init();
00089 }
00090
00091
00093
00101 const tuple operator[](size_type i) const
00102 { return GetBlock(BlockFor(i))[Offset(i)]; }
00103
00105
00116 const tuple at(size_type i) const
00117 { return GetBlock(BlockFor(i)).at(Offset(i)); }
00118
00120 size_type size() const;
00121
00123 bool empty() const;
00124
00125 private:
00126 typedef Cursor::pos pos;
00127
00128 #ifndef PQXX_WORKAROUND_VC7
00129
00130
00135 template<typename ISOLATIONTAG>
00136 static inline void error_permitted_isolation_level(ISOLATIONTAG) throw();
00137 #else
00138
00139 template<> static inline void
00140 error_permitted_isolation_level(isolation_traits<serializable>) throw ();
00141 #endif
00142
00143 void init();
00144
00145 blocknum BlockFor(size_type Row) const throw ()
00146 { return Row / m_Granularity; }
00147 size_type Offset(size_type Row) const throw ()
00148 { return Row % m_Granularity; }
00149 Cursor::size_type FirstRowOf(blocknum Block) const throw ()
00150 { return Block*m_Granularity; }
00151
00152 void MoveTo(blocknum) const;
00153
00155 const result &Fetch() const;
00156
00157 const result &GetBlock(blocknum b) const
00158 {
00159 CacheMap::const_iterator i = m_Cache.find(b);
00160 if (i != m_Cache.end()) return i->second;
00161
00162 MoveTo(b);
00163 return Fetch();
00164 }
00165
00167 size_type m_Granularity;
00168
00169 typedef PGSTD::map<blocknum, const result> CacheMap;
00170 mutable CacheMap m_Cache;
00171
00172 mutable Cursor m_Cursor;
00173 mutable result m_EmptyResult;
00174 mutable bool m_HaveEmpty;
00175
00176
00177 cachedresult();
00178 cachedresult(const cachedresult &);
00179 cachedresult &operator=(const cachedresult &);
00180 };
00181
00183 typedef cachedresult CachedResult;
00184
00185 template<> inline void
00186 cachedresult::error_permitted_isolation_level(isolation_traits<serializable>)
00187 throw () {}
00188
00189 }
00190
00191 #endif
00192