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
00038 class PQXX_LIBEXPORT CachedResult
00039 {
00040 public:
00041 typedef Result::size_type size_type;
00042 typedef size_type blocknum;
00043 typedef Result::Tuple Tuple;
00044
00049 explicit CachedResult(pqxx::TransactionItf &,
00050 const char Query[],
00051 PGSTD::string BaseName="query",
00052 size_type Granularity=100);
00053
00054
00055
00056
00057
00058 const Tuple operator[](size_type i) const
00059 {
00060 return GetBlock(BlockFor(i))[Offset(i)];
00061 }
00062
00063 const Tuple at(size_type i) const
00064 {
00065 return GetBlock(BlockFor(i)).at(Offset(i));
00066 }
00067
00069
00074 size_type size() const
00075 {
00076 if (m_Size == -1) DetermineSize();
00077 return m_Size;
00078 }
00079
00080
00082 bool empty() const
00083 {
00084 return (m_Size == 0) || (m_Cache.empty() && GetBlock(0).empty());
00085 }
00086
00088 void clear();
00089
00091 class const_iterator
00092 {
00093 const CachedResult &m_Home;
00094 CachedResult::size_type m_Row;
00095 public:
00096 explicit const_iterator(const CachedResult &Home) : m_Home(Home), m_Row(0){}
00097
00098 private:
00099
00100 const_iterator();
00101 };
00102
00103 private:
00104
00105 class CacheEntry
00106 {
00107 int m_RefCount;
00108 Result m_Data;
00109
00110 public:
00111 CacheEntry() : m_RefCount(0), m_Data() {}
00112 explicit CacheEntry(const Result &R) : m_RefCount(0), m_Data(R) {}
00113
00114 const Result &Data() const { return m_Data; }
00115 int RefCount() const { return m_RefCount; }
00116 };
00117
00118
00119 blocknum BlockFor(size_type Row) const { return Row / m_Granularity; }
00120 size_type Offset(size_type Row) const { return Row % m_Granularity; }
00121
00122 void MoveTo(blocknum) const;
00123
00125 Result Fetch() const;
00126
00127 Result GetBlock(blocknum b) const
00128 {
00129 CacheMap::const_iterator i = m_Cache.find(b);
00130 if (i != m_Cache.end()) return i->second.Data();
00131
00132 MoveTo(b);
00133 return Fetch();
00134 }
00135
00141 void DetermineSize() const;
00142
00144 size_type m_Granularity;
00145
00146 typedef PGSTD::map<blocknum, CacheEntry> CacheMap;
00147 mutable CacheMap m_Cache;
00148
00149 mutable Cursor m_Cursor;
00150
00152 mutable blocknum m_Pos;
00153
00155 mutable size_type m_Size;
00156
00162 mutable blocknum m_Lower, m_Upper;
00163
00164
00165 CachedResult();
00166 CachedResult(const CachedResult &);
00167 CachedResult &operator=(const CachedResult &);
00168 };
00169
00170
00171 }
00172
00173 #endif
00174