Qt 4.8
qsqlcachedresult.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtSql module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "private/qsqlcachedresult_p.h"
43 
44 #include <qvariant.h>
45 #include <qdatetime.h>
46 #include <qvector.h>
47 
49 
50 /*
51  QSqlCachedResult is a convenience class for databases that only allow
52  forward only fetching. It will cache all the results so we can iterate
53  backwards over the results again.
54 
55  All you need to do is to inherit from QSqlCachedResult and reimplement
56  gotoNext(). gotoNext() will have a reference to the internal cache and
57  will give you an index where you can start filling in your data. Special
58  case: If the user actually wants a forward-only query, idx will be -1
59  to indicate that we are not interested in the actual values.
60 */
61 
62 static const uint initial_cache_size = 128;
63 
65 {
66 public:
68  bool canSeek(int i) const;
69  inline int cacheCount() const;
70  void init(int count, bool fo);
71  void cleanup();
72  int nextIndex();
73  void revertLast();
74 
77  int colCount;
79  bool atEnd;
80 };
81 
83  rowCacheEnd(0), colCount(0), forwardOnly(false), atEnd(false)
84 {
85 }
86 
88 {
89  cache.clear();
90  forwardOnly = false;
91  atEnd = false;
92  colCount = 0;
93  rowCacheEnd = 0;
94 }
95 
96 void QSqlCachedResultPrivate::init(int count, bool fo)
97 {
98  Q_ASSERT(count);
99  cleanup();
100  forwardOnly = fo;
101  colCount = count;
102  if (fo) {
103  cache.resize(count);
104  rowCacheEnd = count;
105  } else {
107  }
108 }
109 
111 {
112  if (forwardOnly)
113  return 0;
114  int newIdx = rowCacheEnd;
115  if (newIdx + colCount > cache.size())
116  cache.resize(qMin(cache.size() * 2, cache.size() + 10000));
118 
119  return newIdx;
120 }
121 
123 {
124  if (forwardOnly || i < 0)
125  return false;
126  return rowCacheEnd >= (i + 1) * colCount;
127 }
128 
130 {
131  if (forwardOnly)
132  return;
134 }
135 
137 {
140  return rowCacheEnd / colCount;
141 }
142 
144 
146 {
147  d = new QSqlCachedResultPrivate();
148 }
149 
151 {
152  delete d;
153 }
154 
156 {
157  d->init(colCount, isForwardOnly());
158 }
159 
161 {
162  if ((!isActive()) || (i < 0))
163  return false;
164  if (at() == i)
165  return true;
166  if (d->forwardOnly) {
167  // speed hack - do not copy values if not needed
168  if (at() > i || at() == QSql::AfterLastRow)
169  return false;
170  while(at() < i - 1) {
171  if (!gotoNext(d->cache, -1))
172  return false;
173  setAt(at() + 1);
174  }
175  if (!gotoNext(d->cache, 0))
176  return false;
177  setAt(at() + 1);
178  return true;
179  }
180  if (d->canSeek(i)) {
181  setAt(i);
182  return true;
183  }
184  if (d->rowCacheEnd > 0)
185  setAt(d->cacheCount());
186  while (at() < i + 1) {
187  if (!cacheNext()) {
188  if (d->canSeek(i))
189  break;
190  return false;
191  }
192  }
193  setAt(i);
194 
195  return true;
196 }
197 
199 {
200  if (d->canSeek(at() + 1)) {
201  setAt(at() + 1);
202  return true;
203  }
204  return cacheNext();
205 }
206 
208 {
209  return fetch(at() - 1);
210 }
211 
213 {
214  if (d->forwardOnly && at() != QSql::BeforeFirstRow) {
215  return false;
216  }
217  if (d->canSeek(0)) {
218  setAt(0);
219  return true;
220  }
221  return cacheNext();
222 }
223 
225 {
226  if (d->atEnd) {
227  if (d->forwardOnly)
228  return false;
229  else
230  return fetch(d->cacheCount() - 1);
231  }
232 
233  int i = at();
234  while (fetchNext())
235  ++i; /* brute force */
236  if (d->forwardOnly && at() == QSql::AfterLastRow) {
237  setAt(i);
238  return true;
239  } else {
240  return fetch(i);
241  }
242 }
243 
245 {
246  int idx = d->forwardOnly ? i : at() * d->colCount + i;
247  if (i >= d->colCount || i < 0 || at() < 0 || idx >= d->rowCacheEnd)
248  return QVariant();
249 
250  return d->cache.at(idx);
251 }
252 
254 {
255  int idx = d->forwardOnly ? i : at() * d->colCount + i;
256  if (i >= d->colCount || i < 0 || at() < 0 || idx >= d->rowCacheEnd)
257  return true;
258 
259  return d->cache.at(idx).isNull();
260 }
261 
263 {
265  setActive(false);
266  d->cleanup();
267 }
268 
270 {
272  d->rowCacheEnd = 0;
273  d->atEnd = false;
274 }
275 
277 {
278  if (d->atEnd)
279  return false;
280 
281  if(isForwardOnly()) {
282  d->cache.clear();
283  d->cache.resize(d->colCount);
284  }
285 
286  if (!gotoNext(d->cache, d->nextIndex())) {
287  d->revertLast();
288  d->atEnd = true;
289  return false;
290  }
291  setAt(at() + 1);
292  return true;
293 }
294 
296 {
297  return d->colCount;
298 }
299 
301 {
302  return d->cache;
303 }
304 
306 {
307  switch (id) {
310  cleanup();
311  break;
312  default:
313  QSqlResult::virtual_hook(id, data);
314  }
315 }
316 
317 
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
QVariant data(int i)
Returns the data for field index in the current row as a QVariant.
bool isActive() const
Returns true if the result has records to be retrieved; otherwise returns false.
Definition: qsqlresult.cpp:340
QSqlCachedResult::ValueCache cache
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
bool fetchFirst()
Positions the result to the first record (row 0) in the result.
bool isForwardOnly() const
Returns true if you can only scroll forward through the result set; otherwise returns false...
Definition: qsqlresult.cpp:582
bool isNull() const
Returns true if this is a NULL variant, false otherwise.
Definition: qvariant.cpp:3102
The QSqlDriver class is an abstract base class for accessing specific SQL databases.
Definition: qsqldriver.h:68
int at() const
Returns the current (zero-based) row position of the result.
Definition: qsqlresult.cpp:306
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
bool fetchNext()
Positions the result to the next available record (row) in the result.
virtual void setAt(int at)
This function is provided for derived classes to set the internal (zero-based) row position to index...
Definition: qsqlresult.cpp:352
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QSqlCachedResultPrivate * d
void clear()
Removes all the elements from the vector and releases the memory used by the vector.
Definition: qvector.h:347
unsigned int uint
Definition: qglobal.h:996
bool isNull(int i)
Returns true if the field at position index in the current row is null; otherwise returns false...
void init(int count, bool fo)
bool fetch(int i)
Positions the result to an arbitrary (zero-based) row index.
bool fetchLast()
Positions the result to the last record (last row) in the result.
virtual void virtual_hook(int id, void *data)
Definition: qsqlresult.cpp:962
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
QSqlCachedResult(const QSqlDriver *db)
bool fetchPrevious()
Positions the result to the previous record (row) in the result.
static const uint initial_cache_size
virtual bool gotoNext(ValueCache &values, int index)=0
virtual void setActive(bool a)
This function is provided for derived classes to set the internal active state to active...
Definition: qsqlresult.cpp:402
ValueCache & cache()
void init(int colCount)
The QSqlResult class provides an abstract interface for accessing data from specific SQL databases...
Definition: qsqlresult.h:63
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
void virtual_hook(int id, void *data)