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
00045 class PQXX_LIBEXPORT CachedResult
00046 {
00047 public:
00048 typedef Result::size_type size_type;
00049 typedef size_type blocknum;
00050 typedef Result::Tuple Tuple;
00051
00056 explicit CachedResult(pqxx::TransactionItf &,
00057 const char Query[],
00058 PGSTD::string BaseName="query",
00059 size_type Granularity=100);
00060
00061
00062
00063
00064
00065 const Tuple operator[](size_type i) const
00066 {
00067 return GetBlock(BlockFor(i))[Offset(i)];
00068 }
00069
00070 const Tuple at(size_type i) const
00071 {
00072 return GetBlock(BlockFor(i)).at(Offset(i));
00073 }
00074
00076
00081 size_type size() const
00082 {
00083 if (m_Size == -1) DetermineSize();
00084 return m_Size;
00085 }
00086
00087
00089 bool empty() const
00090 {
00091 return (m_Size == 0) || (m_Cache.empty() && GetBlock(0).empty());
00092 }
00093
00095 void clear();
00096
00098 class const_iterator
00099 {
00100 const CachedResult &m_Home;
00101 CachedResult::size_type m_Row;
00102 public:
00103 explicit const_iterator(const CachedResult &Home) : m_Home(Home), m_Row(0){}
00104
00105 private:
00106
00107 const_iterator();
00108 };
00109
00110 private:
00111
00112 class CacheEntry
00113 {
00114 int m_RefCount;
00115 Result m_Data;
00116
00117 public:
00118 CacheEntry() : m_RefCount(0), m_Data() {}
00119 explicit CacheEntry(const Result &R) : m_RefCount(0), m_Data(R) {}
00120
00121 const Result &Data() const { return m_Data; }
00122 int RefCount() const { return m_RefCount; }
00123 };
00124
00125
00126 blocknum BlockFor(size_type Row) const { return Row / m_Granularity; }
00127 size_type Offset(size_type Row) const { return Row % m_Granularity; }
00128
00129 void MoveTo(blocknum) const;
00130
00132 Result Fetch() const;
00133
00134 Result GetBlock(blocknum b) const
00135 {
00136 CacheMap::const_iterator i = m_Cache.find(b);
00137 if (i != m_Cache.end()) return i->second.Data();
00138
00139 MoveTo(b);
00140 return Fetch();
00141 }
00142
00148 void DetermineSize() const;
00149
00151 size_type m_Granularity;
00152
00153 typedef PGSTD::map<blocknum, CacheEntry> CacheMap;
00154 mutable CacheMap m_Cache;
00155
00156 mutable Cursor m_Cursor;
00157
00159 mutable blocknum m_Pos;
00160
00162 mutable size_type m_Size;
00163
00169 mutable blocknum m_Lower, m_Upper;
00170
00171
00172 CachedResult();
00173 CachedResult(const CachedResult &);
00174 CachedResult &operator=(const CachedResult &);
00175 };
00176
00177
00178 }
00179
00180 #endif
00181