Line | Source Code | Coverage |
---|
1 | /**************************************************************************** | - |
2 | ** | - |
3 | ** Copyright (C) 2013 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 | | - |
48 | QT_BEGIN_NAMESPACE | - |
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 | | - |
64 | class QSqlCachedResultPrivate | - |
65 | { | - |
66 | public: | - |
67 | QSqlCachedResultPrivate(); | - |
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 | | - |
75 | QSqlCachedResult::ValueCache cache; | - |
76 | int rowCacheEnd; | - |
77 | int colCount; | - |
78 | bool forwardOnly; | - |
79 | bool atEnd; | - |
80 | }; | - |
81 | | - |
82 | QSqlCachedResultPrivate::QSqlCachedResultPrivate(): | - |
83 | rowCacheEnd(0), colCount(0), forwardOnly(false), atEnd(false) | - |
84 | { | - |
85 | } executed: } Execution Count:1924 | 1924 |
86 | | - |
87 | void QSqlCachedResultPrivate::cleanup() | - |
88 | { | - |
89 | cache.clear(); executed (the execution status of this line is deduced): cache.clear(); | - |
90 | forwardOnly = false; executed (the execution status of this line is deduced): forwardOnly = false; | - |
91 | atEnd = false; executed (the execution status of this line is deduced): atEnd = false; | - |
92 | colCount = 0; executed (the execution status of this line is deduced): colCount = 0; | - |
93 | rowCacheEnd = 0; executed (the execution status of this line is deduced): rowCacheEnd = 0; | - |
94 | } executed: } Execution Count:8611 | 8611 |
95 | | - |
96 | void QSqlCachedResultPrivate::init(int count, bool fo) | - |
97 | { | - |
98 | Q_ASSERT(count); executed (the execution status of this line is deduced): qt_noop(); | - |
99 | cleanup(); executed (the execution status of this line is deduced): cleanup(); | - |
100 | forwardOnly = fo; executed (the execution status of this line is deduced): forwardOnly = fo; | - |
101 | colCount = count; executed (the execution status of this line is deduced): colCount = count; | - |
102 | if (fo) { evaluated: fo yes Evaluation Count:638 | yes Evaluation Count:481 |
| 481-638 |
103 | cache.resize(count); executed (the execution status of this line is deduced): cache.resize(count); | - |
104 | rowCacheEnd = count; executed (the execution status of this line is deduced): rowCacheEnd = count; | - |
105 | } else { executed: } Execution Count:638 | 638 |
106 | cache.resize(initial_cache_size * count); executed (the execution status of this line is deduced): cache.resize(initial_cache_size * count); | - |
107 | } executed: } Execution Count:481 | 481 |
108 | } | - |
109 | | - |
110 | int QSqlCachedResultPrivate::nextIndex() | - |
111 | { | - |
112 | if (forwardOnly) evaluated: forwardOnly yes Evaluation Count:2500 | yes Evaluation Count:34594 |
| 2500-34594 |
113 | return 0; executed: return 0; Execution Count:2500 | 2500 |
114 | int newIdx = rowCacheEnd; executed (the execution status of this line is deduced): int newIdx = rowCacheEnd; | - |
115 | if (newIdx + colCount > cache.size()) evaluated: newIdx + colCount > cache.size() yes Evaluation Count:244 | yes Evaluation Count:34350 |
| 244-34350 |
116 | cache.resize(qMin(cache.size() * 2, cache.size() + 10000)); executed: cache.resize(qMin(cache.size() * 2, cache.size() + 10000)); Execution Count:244 | 244 |
117 | rowCacheEnd += colCount; executed (the execution status of this line is deduced): rowCacheEnd += colCount; | - |
118 | | - |
119 | return newIdx; executed: return newIdx; Execution Count:34594 | 34594 |
120 | } | - |
121 | | - |
122 | bool QSqlCachedResultPrivate::canSeek(int i) const | - |
123 | { | - |
124 | if (forwardOnly || i < 0) evaluated: forwardOnly yes Evaluation Count:2501 | yes Evaluation Count:3376 |
partially evaluated: i < 0 no Evaluation Count:0 | yes Evaluation Count:3376 |
| 0-3376 |
125 | return false; executed: return false; Execution Count:2501 | 2501 |
126 | return rowCacheEnd >= (i + 1) * colCount; executed: return rowCacheEnd >= (i + 1) * colCount; Execution Count:3376 | 3376 |
127 | } | - |
128 | | - |
129 | void QSqlCachedResultPrivate::revertLast() | - |
130 | { | - |
131 | if (forwardOnly) evaluated: forwardOnly yes Evaluation Count:569 | yes Evaluation Count:280 |
| 280-569 |
132 | return; executed: return; Execution Count:569 | 569 |
133 | rowCacheEnd -= colCount; executed (the execution status of this line is deduced): rowCacheEnd -= colCount; | - |
134 | } executed: } Execution Count:280 | 280 |
135 | | - |
136 | inline int QSqlCachedResultPrivate::cacheCount() const | - |
137 | { | - |
138 | Q_ASSERT(!forwardOnly); executed (the execution status of this line is deduced): qt_noop(); | - |
139 | Q_ASSERT(colCount); executed (the execution status of this line is deduced): qt_noop(); | - |
140 | return rowCacheEnd / colCount; executed: return rowCacheEnd / colCount; Execution Count:16 | 16 |
141 | } | - |
142 | | - |
143 | ////////////// | - |
144 | | - |
145 | QSqlCachedResult::QSqlCachedResult(const QSqlDriver * db): QSqlResult (db) | - |
146 | { | - |
147 | d = new QSqlCachedResultPrivate(); executed (the execution status of this line is deduced): d = new QSqlCachedResultPrivate(); | - |
148 | } executed: } Execution Count:1924 | 1924 |
149 | | - |
150 | QSqlCachedResult::~QSqlCachedResult() | - |
151 | { | - |
152 | delete d; executed (the execution status of this line is deduced): delete d; | - |
153 | } executed: } Execution Count:1924 | 1924 |
154 | | - |
155 | void QSqlCachedResult::init(int colCount) | - |
156 | { | - |
157 | d->init(colCount, isForwardOnly()); executed (the execution status of this line is deduced): d->init(colCount, isForwardOnly()); | - |
158 | } executed: } Execution Count:1119 | 1119 |
159 | | - |
160 | bool QSqlCachedResult::fetch(int i) | - |
161 | { | - |
162 | if ((!isActive()) || (i < 0)) partially evaluated: (!isActive()) no Evaluation Count:0 | yes Evaluation Count:2659 |
evaluated: (i < 0) yes Evaluation Count:2 | yes Evaluation Count:2657 |
| 0-2659 |
163 | return false; executed: return false; Execution Count:2 | 2 |
164 | if (at() == i) evaluated: at() == i yes Evaluation Count:1715 | yes Evaluation Count:942 |
| 942-1715 |
165 | return true; executed: return true; Execution Count:1715 | 1715 |
166 | if (d->forwardOnly) { evaluated: d->forwardOnly yes Evaluation Count:1 | yes Evaluation Count:941 |
| 1-941 |
167 | // speed hack - do not copy values if not needed | - |
168 | if (at() > i || at() == QSql::AfterLastRow) partially evaluated: at() > i no Evaluation Count:0 | yes Evaluation Count:1 |
partially evaluated: at() == QSql::AfterLastRow no Evaluation Count:0 | yes Evaluation Count:1 |
| 0-1 |
169 | return false; never executed: return false; | 0 |
170 | while(at() < i - 1) { evaluated: at() < i - 1 yes Evaluation Count:3 | yes Evaluation Count:1 |
| 1-3 |
171 | if (!gotoNext(d->cache, -1)) partially evaluated: !gotoNext(d->cache, -1) no Evaluation Count:0 | yes Evaluation Count:3 |
| 0-3 |
172 | return false; never executed: return false; | 0 |
173 | setAt(at() + 1); executed (the execution status of this line is deduced): setAt(at() + 1); | - |
174 | } executed: } Execution Count:3 | 3 |
175 | if (!gotoNext(d->cache, 0)) partially evaluated: !gotoNext(d->cache, 0) no Evaluation Count:0 | yes Evaluation Count:1 |
| 0-1 |
176 | return false; never executed: return false; | 0 |
177 | setAt(at() + 1); executed (the execution status of this line is deduced): setAt(at() + 1); | - |
178 | return true; executed: return true; Execution Count:1 | 1 |
179 | } | - |
180 | if (d->canSeek(i)) { evaluated: d->canSeek(i) yes Evaluation Count:537 | yes Evaluation Count:404 |
| 404-537 |
181 | setAt(i); executed (the execution status of this line is deduced): setAt(i); | - |
182 | return true; executed: return true; Execution Count:537 | 537 |
183 | } | - |
184 | if (d->rowCacheEnd > 0) evaluated: d->rowCacheEnd > 0 yes Evaluation Count:13 | yes Evaluation Count:391 |
| 13-391 |
185 | setAt(d->cacheCount()); executed: setAt(d->cacheCount()); Execution Count:13 | 13 |
186 | while (at() < i + 1) { evaluated: at() < i + 1 yes Evaluation Count:34438 | yes Evaluation Count:132 |
| 132-34438 |
187 | if (!cacheNext()) { evaluated: !cacheNext() yes Evaluation Count:272 | yes Evaluation Count:34166 |
| 272-34166 |
188 | if (d->canSeek(i)) evaluated: d->canSeek(i) yes Evaluation Count:2 | yes Evaluation Count:270 |
| 2-270 |
189 | break; executed: break; Execution Count:2 | 2 |
190 | return false; executed: return false; Execution Count:270 | 270 |
191 | } | - |
192 | } executed: } Execution Count:34166 | 34166 |
193 | setAt(i); executed (the execution status of this line is deduced): setAt(i); | - |
194 | | - |
195 | return true; executed: return true; Execution Count:134 | 134 |
196 | } | - |
197 | | - |
198 | bool QSqlCachedResult::fetchNext() | - |
199 | { | - |
200 | if (d->canSeek(at() + 1)) { evaluated: d->canSeek(at() + 1) yes Evaluation Count:1746 | yes Evaluation Count:2208 |
| 1746-2208 |
201 | setAt(at() + 1); executed (the execution status of this line is deduced): setAt(at() + 1); | - |
202 | return true; executed: return true; Execution Count:1746 | 1746 |
203 | } | - |
204 | return cacheNext(); executed: return cacheNext(); Execution Count:2208 | 2208 |
205 | } | - |
206 | | - |
207 | bool QSqlCachedResult::fetchPrevious() | - |
208 | { | - |
209 | return fetch(at() - 1); executed: return fetch(at() - 1); Execution Count:40 | 40 |
210 | } | - |
211 | | - |
212 | bool QSqlCachedResult::fetchFirst() | - |
213 | { | - |
214 | if (d->forwardOnly && at() != QSql::BeforeFirstRow) { evaluated: d->forwardOnly yes Evaluation Count:626 | yes Evaluation Count:84 |
partially evaluated: at() != QSql::BeforeFirstRow no Evaluation Count:0 | yes Evaluation Count:626 |
| 0-626 |
215 | return false; never executed: return false; | 0 |
216 | } | - |
217 | if (d->canSeek(0)) { evaluated: d->canSeek(0) yes Evaluation Count:1 | yes Evaluation Count:709 |
| 1-709 |
218 | setAt(0); executed (the execution status of this line is deduced): setAt(0); | - |
219 | return true; executed: return true; Execution Count:1 | 1 |
220 | } | - |
221 | return cacheNext(); executed: return cacheNext(); Execution Count:709 | 709 |
222 | } | - |
223 | | - |
224 | bool QSqlCachedResult::fetchLast() | - |
225 | { | - |
226 | if (d->atEnd) { evaluated: d->atEnd yes Evaluation Count:3 | yes Evaluation Count:6 |
| 3-6 |
227 | if (d->forwardOnly) partially evaluated: d->forwardOnly no Evaluation Count:0 | yes Evaluation Count:3 |
| 0-3 |
228 | return false; never executed: return false; | 0 |
229 | else | - |
230 | return fetch(d->cacheCount() - 1); executed: return fetch(d->cacheCount() - 1); Execution Count:3 | 3 |
231 | } | - |
232 | | - |
233 | int i = at(); executed (the execution status of this line is deduced): int i = at(); | - |
234 | while (fetchNext()) evaluated: fetchNext() yes Evaluation Count:22 | yes Evaluation Count:6 |
| 6-22 |
235 | ++i; /* brute force */ executed: ++i; Execution Count:22 | 22 |
236 | if (d->forwardOnly && at() == QSql::AfterLastRow) { evaluated: d->forwardOnly yes Evaluation Count:2 | yes Evaluation Count:4 |
partially evaluated: at() == QSql::AfterLastRow yes Evaluation Count:2 | no Evaluation Count:0 |
| 0-4 |
237 | setAt(i); executed (the execution status of this line is deduced): setAt(i); | - |
238 | return true; executed: return true; Execution Count:2 | 2 |
239 | } else { | - |
240 | return fetch(i); executed: return fetch(i); Execution Count:4 | 4 |
241 | } | - |
242 | } | - |
243 | | - |
244 | QVariant QSqlCachedResult::data(int i) | - |
245 | { | - |
246 | int idx = d->forwardOnly ? i : at() * d->colCount + i; evaluated: d->forwardOnly yes Evaluation Count:5889 | yes Evaluation Count:3473 |
| 3473-5889 |
247 | if (i >= d->colCount || i < 0 || at() < 0 || idx >= d->rowCacheEnd) partially evaluated: i >= d->colCount no Evaluation Count:0 | yes Evaluation Count:9362 |
partially evaluated: i < 0 no Evaluation Count:0 | yes Evaluation Count:9362 |
partially evaluated: at() < 0 no Evaluation Count:0 | yes Evaluation Count:9361 |
partially evaluated: idx >= d->rowCacheEnd no Evaluation Count:0 | yes Evaluation Count:9361 |
| 0-9362 |
248 | return QVariant(); never executed: return QVariant(); | 0 |
249 | | - |
250 | return d->cache.at(idx); executed: return d->cache.at(idx); Execution Count:9361 | 9361 |
251 | } | - |
252 | | - |
253 | bool QSqlCachedResult::isNull(int i) | - |
254 | { | - |
255 | int idx = d->forwardOnly ? i : at() * d->colCount + i; partially evaluated: d->forwardOnly no Evaluation Count:0 | yes Evaluation Count:5 |
| 0-5 |
256 | if (i > d->colCount || i < 0 || at() < 0 || idx >= d->rowCacheEnd) partially evaluated: i > d->colCount no Evaluation Count:0 | yes Evaluation Count:5 |
partially evaluated: i < 0 no Evaluation Count:0 | yes Evaluation Count:5 |
partially evaluated: at() < 0 no Evaluation Count:0 | yes Evaluation Count:5 |
partially evaluated: idx >= d->rowCacheEnd no Evaluation Count:0 | yes Evaluation Count:5 |
| 0-5 |
257 | return true; never executed: return true; | 0 |
258 | | - |
259 | return d->cache.at(idx).isNull(); executed: return d->cache.at(idx).isNull(); Execution Count:5 | 5 |
260 | } | - |
261 | | - |
262 | void QSqlCachedResult::cleanup() | - |
263 | { | - |
264 | setAt(QSql::BeforeFirstRow); executed (the execution status of this line is deduced): setAt(QSql::BeforeFirstRow); | - |
265 | setActive(false); executed (the execution status of this line is deduced): setActive(false); | - |
266 | d->cleanup(); executed (the execution status of this line is deduced): d->cleanup(); | - |
267 | } executed: } Execution Count:7492 | 7492 |
268 | | - |
269 | void QSqlCachedResult::clearValues() | - |
270 | { | - |
271 | setAt(QSql::BeforeFirstRow); executed (the execution status of this line is deduced): setAt(QSql::BeforeFirstRow); | - |
272 | d->rowCacheEnd = 0; executed (the execution status of this line is deduced): d->rowCacheEnd = 0; | - |
273 | d->atEnd = false; executed (the execution status of this line is deduced): d->atEnd = false; | - |
274 | } executed: } Execution Count:119104 | 119104 |
275 | | - |
276 | bool QSqlCachedResult::cacheNext() | - |
277 | { | - |
278 | if (d->atEnd) evaluated: d->atEnd yes Evaluation Count:261 | yes Evaluation Count:37094 |
| 261-37094 |
279 | return false; executed: return false; Execution Count:261 | 261 |
280 | | - |
281 | if(isForwardOnly()) { evaluated: isForwardOnly() yes Evaluation Count:2500 | yes Evaluation Count:34594 |
| 2500-34594 |
282 | d->cache.clear(); executed (the execution status of this line is deduced): d->cache.clear(); | - |
283 | d->cache.resize(d->colCount); executed (the execution status of this line is deduced): d->cache.resize(d->colCount); | - |
284 | } executed: } Execution Count:2500 | 2500 |
285 | | - |
286 | if (!gotoNext(d->cache, d->nextIndex())) { evaluated: !gotoNext(d->cache, d->nextIndex()) yes Evaluation Count:849 | yes Evaluation Count:36245 |
| 849-36245 |
287 | d->revertLast(); executed (the execution status of this line is deduced): d->revertLast(); | - |
288 | d->atEnd = true; executed (the execution status of this line is deduced): d->atEnd = true; | - |
289 | return false; executed: return false; Execution Count:849 | 849 |
290 | } | - |
291 | setAt(at() + 1); executed (the execution status of this line is deduced): setAt(at() + 1); | - |
292 | return true; executed: return true; Execution Count:36245 | 36245 |
293 | } | - |
294 | | - |
295 | int QSqlCachedResult::colCount() const | - |
296 | { | - |
297 | return d->colCount; never executed: return d->colCount; | 0 |
298 | } | - |
299 | | - |
300 | QSqlCachedResult::ValueCache &QSqlCachedResult::cache() | - |
301 | { | - |
302 | return d->cache; never executed: return d->cache; | 0 |
303 | } | - |
304 | | - |
305 | void QSqlCachedResult::virtual_hook(int id, void *data) | - |
306 | { | - |
307 | QSqlResult::virtual_hook(id, data); never executed (the execution status of this line is deduced): QSqlResult::virtual_hook(id, data); | - |
308 | } | 0 |
309 | | - |
310 | void QSqlCachedResult::detachFromResultSet() | - |
311 | { | - |
312 | cleanup(); never executed (the execution status of this line is deduced): cleanup(); | - |
313 | } | 0 |
314 | | - |
315 | void QSqlCachedResult::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy) | - |
316 | { | - |
317 | QSqlResult::setNumericalPrecisionPolicy(policy); executed (the execution status of this line is deduced): QSqlResult::setNumericalPrecisionPolicy(policy); | - |
318 | cleanup(); executed (the execution status of this line is deduced): cleanup(); | - |
319 | } executed: } Execution Count:2787 | 2787 |
320 | | - |
321 | | - |
322 | QT_END_NAMESPACE | - |
323 | | - |
| | |