00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef PQXX_CACHEDRESULT_H
00015 #define PQXX_CACHEDRESULT_H
00016
00017 #include <map>
00018
00019 #include "pqxx/cursor.h"
00020 #include "pqxx/result.h"
00021
00022 namespace pqxx
00023 {
00024
00025 class TransactionItf;
00026
00027
00028
00046 class PQXX_LIBEXPORT CachedResult
00047 {
00048 public:
00049 typedef Result::size_type size_type;
00050 typedef size_type blocknum;
00051 typedef Result::Tuple Tuple;
00052
00062 explicit CachedResult(pqxx::TransactionItf &T,
00063 const char Query[],
00064 const PGSTD::string &BaseName="query",
00065 size_type Granularity=100);
00066
00067
00068
00069
00070
00071 const Tuple operator[](size_type i) const
00072 { return GetBlock(BlockFor(i))[Offset(i)]; }
00073
00074 const Tuple at(size_type i) const
00075 { return GetBlock(BlockFor(i)).at(Offset(i)); }
00076
00078 size_type size() const;
00079
00081 bool empty() const;
00082
00084 void clear();
00085
00087 class const_iterator
00088 {
00089 const CachedResult &m_Home;
00090 CachedResult::size_type m_Row;
00091 public:
00092 explicit const_iterator(const CachedResult &Home) : m_Home(Home), m_Row(0){}
00093
00094 private:
00095
00096 const_iterator();
00097 };
00098
00099 private:
00100
00101 typedef Cursor::pos pos;
00102
00103 class CacheEntry
00104 {
00105 int m_RefCount;
00106 Result m_Data;
00107
00108 public:
00109 CacheEntry() : m_RefCount(0), m_Data() {}
00110 explicit CacheEntry(const Result &R) : m_RefCount(0), m_Data(R) {}
00111
00112 const Result &Data() const { return m_Data; }
00113 int RefCount() const { return m_RefCount; }
00114 };
00115
00116
00117 blocknum BlockFor(size_type Row) const throw ()
00118 { return Row / m_Granularity; }
00119 size_type Offset(size_type Row) const throw ()
00120 { return Row % m_Granularity; }
00121 Cursor::size_type FirstRowOf(blocknum Block) const throw ()
00122 { return Block*m_Granularity; }
00123
00124 void MoveTo(blocknum) const;
00125
00127 Result Fetch() const;
00128
00129 Result GetBlock(blocknum b) const
00130 {
00131 CacheMap::const_iterator i = m_Cache.find(b);
00132 if (i != m_Cache.end()) return i->second.Data();
00133
00134 MoveTo(b);
00135 return Fetch();
00136 }
00137
00139 size_type m_Granularity;
00140
00141 typedef PGSTD::map<blocknum, CacheEntry> CacheMap;
00142 mutable CacheMap m_Cache;
00143
00144 mutable Cursor m_Cursor;
00145 mutable Result m_EmptyResult;
00146 mutable bool m_HaveEmpty;
00147
00148
00149 CachedResult();
00150 CachedResult(const CachedResult &);
00151 CachedResult &operator=(const CachedResult &);
00152 };
00153
00154
00155 }
00156
00157 #endif
00158