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
00057 explicit CachedResult(pqxx::TransactionItf &,
00058 const char Query[],
00059 const PGSTD::string &BaseName="query",
00060 size_type Granularity=100);
00061
00062
00063
00064
00065
00066 const Tuple operator[](size_type i) const
00067 {
00068 return GetBlock(BlockFor(i))[Offset(i)];
00069 }
00070
00071 const Tuple at(size_type i) const
00072 {
00073 return GetBlock(BlockFor(i)).at(Offset(i));
00074 }
00075
00077 size_type size() const;
00078
00080 bool empty() const;
00081
00083 void clear();
00084
00086 class const_iterator
00087 {
00088 const CachedResult &m_Home;
00089 CachedResult::size_type m_Row;
00090 public:
00091 explicit const_iterator(const CachedResult &Home) : m_Home(Home), m_Row(0){}
00092
00093 private:
00094
00095 const_iterator();
00096 };
00097
00098 private:
00099
00100 typedef Cursor::pos pos;
00101
00102 class CacheEntry
00103 {
00104 int m_RefCount;
00105 Result m_Data;
00106
00107 public:
00108 CacheEntry() : m_RefCount(0), m_Data() {}
00109 explicit CacheEntry(const Result &R) : m_RefCount(0), m_Data(R) {}
00110
00111 const Result &Data() const { return m_Data; }
00112 int RefCount() const { return m_RefCount; }
00113 };
00114
00115
00116 blocknum BlockFor(size_type Row) const throw ()
00117 { return Row / m_Granularity; }
00118 size_type Offset(size_type Row) const throw ()
00119 { return Row % m_Granularity; }
00120 Cursor::size_type FirstRowOf(blocknum Block) const throw ()
00121 { return Block*m_Granularity; }
00122
00123 void MoveTo(blocknum) const;
00124
00126 Result Fetch() const;
00127
00128 Result GetBlock(blocknum b) const
00129 {
00130 CacheMap::const_iterator i = m_Cache.find(b);
00131 if (i != m_Cache.end()) return i->second.Data();
00132
00133 MoveTo(b);
00134 return Fetch();
00135 }
00136
00138 size_type m_Granularity;
00139
00140 typedef PGSTD::map<blocknum, CacheEntry> CacheMap;
00141 mutable CacheMap m_Cache;
00142
00143 mutable Cursor m_Cursor;
00144
00145
00146 CachedResult();
00147 CachedResult(const CachedResult &);
00148 CachedResult &operator=(const CachedResult &);
00149 };
00150
00151
00152 }
00153
00154 #endif
00155