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
00050 class PQXX_LIBEXPORT cachedresult
00051 {
00052 public:
00053 typedef result::size_type size_type;
00054 typedef size_type blocknum;
00055
00057 typedef result::tuple tuple;
00058
00060 typedef tuple Tuple;
00061
00073 template<typename TRANSACTION> explicit
00074 cachedresult(TRANSACTION &T,
00075 const char Query[],
00076 const PGSTD::string &BaseName="query",
00077 size_type Granularity=100) :
00078 m_Granularity(Granularity),
00079 m_Cache(),
00080 m_Cursor(T, Query, BaseName, Granularity),
00081 m_EmptyResult(),
00082 m_HaveEmpty(false)
00083 {
00084
00085 error_permitted_isolation_level(PQXX_TYPENAME TRANSACTION::isolation_tag());
00086 init();
00087 }
00088
00089
00091
00099 const tuple operator[](size_type i) const
00100 { return GetBlock(BlockFor(i))[Offset(i)]; }
00101
00103
00114 const tuple at(size_type i) const
00115 { return GetBlock(BlockFor(i)).at(Offset(i)); }
00116
00118 size_type size() const;
00119
00121 bool empty() const;
00122
00123 private:
00124 typedef Cursor::pos pos;
00125
00126 #ifndef PQXX_WORKAROUND_VC7
00127
00128
00133 template<typename ISOLATIONTAG>
00134 static inline void error_permitted_isolation_level(ISOLATIONTAG) throw ();
00135
00136 #if defined(__SUNPRO_CC)
00137
00138 template<> static void
00139 error_permitted_level(isolation_traits<serializable>) throw() {}
00140 #endif // __SUNPRO_CC
00141 #else
00142
00143 template<> static inline void
00144 error_permitted_isolation_level(isolation_traits<serializable>) throw ();
00145 #endif
00146
00147 void init();
00148
00149 blocknum BlockFor(size_type Row) const throw ()
00150 { return Row / m_Granularity; }
00151 size_type Offset(size_type Row) const throw ()
00152 { return Row % m_Granularity; }
00153 Cursor::size_type FirstRowOf(blocknum Block) const throw ()
00154 { return Block*m_Granularity; }
00155
00156 void MoveTo(blocknum) const;
00157
00159 const result &Fetch() const;
00160
00161 const result &GetBlock(blocknum b) const
00162 {
00163 CacheMap::const_iterator i = m_Cache.find(b);
00164 if (i != m_Cache.end()) return i->second;
00165
00166 MoveTo(b);
00167 return Fetch();
00168 }
00169
00171 size_type m_Granularity;
00172
00173 typedef PGSTD::map<blocknum, result> CacheMap;
00174 mutable CacheMap m_Cache;
00175
00176 mutable Cursor m_Cursor;
00177 mutable result m_EmptyResult;
00178 mutable bool m_HaveEmpty;
00179
00180
00181 cachedresult();
00182 cachedresult(const cachedresult &);
00183 cachedresult &operator=(const cachedresult &);
00184 };
00185
00187 typedef cachedresult CachedResult;
00188
00189 template<> inline void
00190 cachedresult::error_permitted_isolation_level(isolation_traits<serializable>)
00191 throw () {}
00192
00193 }
00194
00195 #endif
00196