1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "sqlitebasestatement.h"
27
28 #include "sqlitedatabase.h"
29 #include "sqlitedatabasebackend.h"
30 #include "sqliteexception.h"
31
32 #include "sqlite.h"
33
34 #include <condition_variable>
35 #include <mutex>
36
37 #if defined(__GNUC__)
38 # pragma GCC diagnostic ignored "-Wignored-qualifiers"
39 #endif
40
41 #define CARRAY_INT32 0 /* Data is 32-bit signed integers */
42 #define CARRAY_INT64 1 /* Data is 64-bit signed integers */
43 #define CARRAY_DOUBLE 2 /* Data is doubles */
44 #define CARRAY_TEXT 3 /* Data is char* */
45
46 extern "C" int sqlite3_carray_bind(
47 sqlite3_stmt *pStmt, int idx, void *aData, int nData, int mFlags, void (*xDestroy)(void *));
48
49 namespace Sqlite {
50
BaseStatement(Utils::SmallStringView sqlStatement,Database & database)51 BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &database)
52 : m_compiledStatement(nullptr, deleteCompiledStatement)
53 , m_database(database)
54 , m_bindingParameterCount(0)
55 , m_columnCount(0)
56 {
57 prepare(sqlStatement);
58 setBindingParameterCount();
59 setColumnCount();
60 }
61
deleteCompiledStatement(sqlite3_stmt * compiledStatement)62 void BaseStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
63 {
64 sqlite3_finalize(compiledStatement);
65 }
66
67 class UnlockNotification
68 {
69 public:
unlockNotifyCallBack(void ** arguments,int argumentCount)70 static void unlockNotifyCallBack(void **arguments, int argumentCount)
71 {
72 for (int index = 0; index < argumentCount; index++) {
73 UnlockNotification *unlockNotification = static_cast<UnlockNotification *>(arguments[index]);
74 unlockNotification->wakeupWaitCondition();
75 }
76 }
77
wakeupWaitCondition()78 void wakeupWaitCondition()
79 {
80 {
81 std::lock_guard<std::mutex> lock(m_mutex);
82 m_fired = 1;
83 }
84 m_waitCondition.notify_all();
85 }
86
wait()87 void wait()
88 {
89 std::unique_lock<std::mutex> lock(m_mutex);
90
91 m_waitCondition.wait(lock, [&] () { return m_fired; });
92 }
93
94 private:
95 bool m_fired = false;
96 std::condition_variable m_waitCondition;
97 std::mutex m_mutex;
98 };
99
waitForUnlockNotify() const100 void BaseStatement::waitForUnlockNotify() const
101 {
102 UnlockNotification unlockNotification;
103 int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(),
104 UnlockNotification::unlockNotifyCallBack,
105 &unlockNotification);
106
107 if (resultCode == SQLITE_LOCKED)
108 throw DeadLock("SqliteStatement::waitForUnlockNotify: database is in a dead lock!");
109
110 unlockNotification.wait();
111 }
112
reset() const113 void BaseStatement::reset() const noexcept
114 {
115 sqlite3_reset(m_compiledStatement.get());
116 }
117
next() const118 bool BaseStatement::next() const
119 {
120 int resultCode;
121
122 do {
123 resultCode = sqlite3_step(m_compiledStatement.get());
124 if (resultCode == SQLITE_LOCKED) {
125 waitForUnlockNotify();
126 sqlite3_reset(m_compiledStatement.get());
127 }
128
129 } while (resultCode == SQLITE_LOCKED);
130
131 if (resultCode == SQLITE_ROW)
132 return true;
133 else if (resultCode == SQLITE_DONE)
134 return false;
135
136 checkForStepError(resultCode);
137 }
138
step() const139 void BaseStatement::step() const
140 {
141 next();
142 }
143
columnCount() const144 int BaseStatement::columnCount() const
145 {
146 return m_columnCount;
147 }
148
bind(int index,NullValue)149 void BaseStatement::bind(int index, NullValue)
150 {
151 int resultCode = sqlite3_bind_null(m_compiledStatement.get(), index);
152 if (resultCode != SQLITE_OK)
153 checkForBindingError(resultCode);
154 }
155
bind(int index,int value)156 void BaseStatement::bind(int index, int value)
157 {
158 int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
159 if (resultCode != SQLITE_OK)
160 checkForBindingError(resultCode);
161 }
162
bind(int index,long long value)163 void BaseStatement::bind(int index, long long value)
164 {
165 int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
166 if (resultCode != SQLITE_OK)
167 checkForBindingError(resultCode);
168 }
169
bind(int index,double value)170 void BaseStatement::bind(int index, double value)
171 {
172 int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value);
173 if (resultCode != SQLITE_OK)
174 checkForBindingError(resultCode);
175 }
176
bind(int index,void * pointer)177 void BaseStatement::bind(int index, void *pointer)
178 {
179 int resultCode = sqlite3_bind_pointer(m_compiledStatement.get(),
180 index,
181 pointer,
182 "carray",
183 nullptr);
184 if (resultCode != SQLITE_OK)
185 checkForBindingError(resultCode);
186 }
187
bind(int index,Utils::span<int> values)188 void BaseStatement::bind(int index, Utils::span<int> values)
189 {
190 int resultCode = sqlite3_carray_bind(m_compiledStatement.get(),
191 index,
192 values.data(),
193 static_cast<int>(values.size()),
194 CARRAY_INT32,
195 SQLITE_STATIC);
196 if (resultCode != SQLITE_OK)
197 checkForBindingError(resultCode);
198 }
199
bind(int index,Utils::span<long long> values)200 void BaseStatement::bind(int index, Utils::span<long long> values)
201 {
202 int resultCode = sqlite3_carray_bind(m_compiledStatement.get(),
203 index,
204 values.data(),
205 static_cast<int>(values.size()),
206 CARRAY_INT64,
207 SQLITE_STATIC);
208 if (resultCode != SQLITE_OK)
209 checkForBindingError(resultCode);
210 }
211
bind(int index,Utils::span<double> values)212 void BaseStatement::bind(int index, Utils::span<double> values)
213 {
214 int resultCode = sqlite3_carray_bind(m_compiledStatement.get(),
215 index,
216 values.data(),
217 static_cast<int>(values.size()),
218 CARRAY_DOUBLE,
219 SQLITE_STATIC);
220 if (resultCode != SQLITE_OK)
221 checkForBindingError(resultCode);
222 }
223
bind(int index,Utils::span<const char * > values)224 void BaseStatement::bind(int index, Utils::span<const char *> values)
225 {
226 int resultCode = sqlite3_carray_bind(m_compiledStatement.get(),
227 index,
228 values.data(),
229 static_cast<int>(values.size()),
230 CARRAY_TEXT,
231 SQLITE_STATIC);
232 if (resultCode != SQLITE_OK)
233 checkForBindingError(resultCode);
234 }
235
bind(int index,Utils::SmallStringView text)236 void BaseStatement::bind(int index, Utils::SmallStringView text)
237 {
238 int resultCode = sqlite3_bind_text(m_compiledStatement.get(),
239 index,
240 text.data(),
241 int(text.size()),
242 SQLITE_STATIC);
243 if (resultCode != SQLITE_OK)
244 checkForBindingError(resultCode);
245 }
246
bind(int index,BlobView blobView)247 void BaseStatement::bind(int index, BlobView blobView)
248 {
249 int resultCode = SQLITE_OK;
250
251 if (blobView.empty()) {
252 sqlite3_bind_null(m_compiledStatement.get(), index);
253 } else {
254 resultCode = sqlite3_bind_blob64(m_compiledStatement.get(),
255 index,
256 blobView.data(),
257 blobView.size(),
258 SQLITE_STATIC);
259 }
260
261 if (resultCode != SQLITE_OK)
262 checkForBindingError(resultCode);
263 }
264
bind(int index,const Value & value)265 void BaseStatement::bind(int index, const Value &value)
266 {
267 switch (value.type()) {
268 case ValueType::Integer:
269 bind(index, value.toInteger());
270 break;
271 case ValueType::Float:
272 bind(index, value.toFloat());
273 break;
274 case ValueType::String:
275 bind(index, value.toStringView());
276 break;
277 case ValueType::Blob:
278 bind(index, value.toBlobView());
279 break;
280 case ValueType::Null:
281 bind(index, NullValue{});
282 break;
283 }
284 }
285
bind(int index,ValueView value)286 void BaseStatement::bind(int index, ValueView value)
287 {
288 switch (value.type()) {
289 case ValueType::Integer:
290 bind(index, value.toInteger());
291 break;
292 case ValueType::Float:
293 bind(index, value.toFloat());
294 break;
295 case ValueType::String:
296 bind(index, value.toStringView());
297 break;
298 case ValueType::Blob:
299 bind(index, value.toBlobView());
300 break;
301 case ValueType::Null:
302 bind(index, NullValue{});
303 break;
304 }
305 }
306
prepare(Utils::SmallStringView sqlStatement)307 void BaseStatement::prepare(Utils::SmallStringView sqlStatement)
308 {
309 int resultCode;
310
311 do {
312 sqlite3_stmt *sqliteStatement = nullptr;
313 resultCode = sqlite3_prepare_v2(sqliteDatabaseHandle(),
314 sqlStatement.data(),
315 int(sqlStatement.size()),
316 &sqliteStatement,
317 nullptr);
318 m_compiledStatement.reset(sqliteStatement);
319
320 if (resultCode == SQLITE_LOCKED)
321 waitForUnlockNotify();
322
323 } while (resultCode == SQLITE_LOCKED);
324
325
326 if (resultCode != SQLITE_OK)
327 checkForPrepareError(resultCode);
328 }
329
sqliteDatabaseHandle() const330 sqlite3 *BaseStatement::sqliteDatabaseHandle() const
331 {
332 return m_database.backend().sqliteDatabaseHandle();
333 }
334
checkForStepError(int resultCode) const335 void BaseStatement::checkForStepError(int resultCode) const
336 {
337 switch (resultCode) {
338 case SQLITE_BUSY_RECOVERY:
339 case SQLITE_BUSY_SNAPSHOT:
340 case SQLITE_BUSY_TIMEOUT:
341 case SQLITE_BUSY:
342 throwStatementIsBusy("SqliteStatement::stepStatement: database engine was unable to "
343 "acquire the database locks!");
344 case SQLITE_ERROR_MISSING_COLLSEQ:
345 case SQLITE_ERROR_RETRY:
346 case SQLITE_ERROR_SNAPSHOT:
347 case SQLITE_ERROR:
348 throwStatementHasError("SqliteStatement::stepStatement: run-time error (such as a "
349 "constraint violation) has occurred!");
350 case SQLITE_MISUSE:
351 throwStatementIsMisused("SqliteStatement::stepStatement: was called inappropriately!");
352 case SQLITE_CONSTRAINT_CHECK:
353 case SQLITE_CONSTRAINT_COMMITHOOK:
354 case SQLITE_CONSTRAINT_FOREIGNKEY:
355 case SQLITE_CONSTRAINT_FUNCTION:
356 case SQLITE_CONSTRAINT_NOTNULL:
357 case SQLITE_CONSTRAINT_PINNED:
358 case SQLITE_CONSTRAINT_PRIMARYKEY:
359 case SQLITE_CONSTRAINT_ROWID:
360 case SQLITE_CONSTRAINT_TRIGGER:
361 case SQLITE_CONSTRAINT_UNIQUE:
362 case SQLITE_CONSTRAINT_VTAB:
363 case SQLITE_CONSTRAINT:
364 throwConstraintPreventsModification(
365 "SqliteStatement::stepStatement: contraint prevent insert or update!");
366 case SQLITE_TOOBIG:
367 throwTooBig("SqliteStatement::stepStatement: Some is to bigger than SQLITE_MAX_LENGTH.");
368 case SQLITE_SCHEMA:
369 throwSchemaChangeError("SqliteStatement::stepStatement: Schema changed but the statement "
370 "cannot be recompiled.");
371 case SQLITE_READONLY_CANTINIT:
372 case SQLITE_READONLY_CANTLOCK:
373 case SQLITE_READONLY_DBMOVED:
374 case SQLITE_READONLY_DIRECTORY:
375 case SQLITE_READONLY_RECOVERY:
376 case SQLITE_READONLY_ROLLBACK:
377 case SQLITE_READONLY:
378 throwCannotWriteToReadOnlyConnection(
379 "SqliteStatement::stepStatement: Cannot write to read only connection");
380 case SQLITE_PROTOCOL:
381 throwProtocolError(
382 "SqliteStatement::stepStatement: Something strang with the file locking happened.");
383 case SQLITE_NOMEM:
384 throw std::bad_alloc();
385 case SQLITE_NOLFS:
386 throwDatabaseExceedsMaximumFileSize(
387 "SqliteStatement::stepStatement: Database exceeds maximum file size.");
388 case SQLITE_MISMATCH:
389 throwDataTypeMismatch(
390 "SqliteStatement::stepStatement: Most probably you used not an integer for a rowid.");
391 case SQLITE_LOCKED_SHAREDCACHE:
392 case SQLITE_LOCKED_VTAB:
393 case SQLITE_LOCKED:
394 throwConnectionIsLocked("SqliteStatement::stepStatement: Database connection is locked.");
395 case SQLITE_IOERR_AUTH:
396 case SQLITE_IOERR_BEGIN_ATOMIC:
397 case SQLITE_IOERR_BLOCKED:
398 case SQLITE_IOERR_CHECKRESERVEDLOCK:
399 case SQLITE_IOERR_CLOSE:
400 case SQLITE_IOERR_COMMIT_ATOMIC:
401 case SQLITE_IOERR_CONVPATH:
402 case SQLITE_IOERR_DATA:
403 case SQLITE_IOERR_DELETE:
404 case SQLITE_IOERR_DELETE_NOENT:
405 case SQLITE_IOERR_DIR_CLOSE:
406 case SQLITE_IOERR_DIR_FSYNC:
407 case SQLITE_IOERR_FSTAT:
408 case SQLITE_IOERR_FSYNC:
409 case SQLITE_IOERR_GETTEMPPATH:
410 case SQLITE_IOERR_LOCK:
411 case SQLITE_IOERR_MMAP:
412 case SQLITE_IOERR_NOMEM:
413 case SQLITE_IOERR_RDLOCK:
414 case SQLITE_IOERR_READ:
415 case SQLITE_IOERR_ROLLBACK_ATOMIC:
416 case SQLITE_IOERR_SEEK:
417 case SQLITE_IOERR_SHMLOCK:
418 case SQLITE_IOERR_SHMMAP:
419 case SQLITE_IOERR_SHMOPEN:
420 case SQLITE_IOERR_SHMSIZE:
421 case SQLITE_IOERR_SHORT_READ:
422 case SQLITE_IOERR_TRUNCATE:
423 case SQLITE_IOERR_UNLOCK:
424 case SQLITE_IOERR_VNODE:
425 case SQLITE_IOERR_WRITE:
426 case SQLITE_IOERR:
427 throwInputOutputError("SqliteStatement::stepStatement: An IO error happened.");
428 case SQLITE_INTERRUPT:
429 throwExecutionInterrupted("SqliteStatement::stepStatement: Execution was interrupted.");
430 case SQLITE_CORRUPT_INDEX:
431 case SQLITE_CORRUPT_SEQUENCE:
432 case SQLITE_CORRUPT_VTAB:
433 case SQLITE_CORRUPT:
434 throwDatabaseIsCorrupt("SqliteStatement::stepStatement: Database is corrupt.");
435 case SQLITE_CANTOPEN_CONVPATH:
436 case SQLITE_CANTOPEN_DIRTYWAL:
437 case SQLITE_CANTOPEN_FULLPATH:
438 case SQLITE_CANTOPEN_ISDIR:
439 case SQLITE_CANTOPEN_NOTEMPDIR:
440 case SQLITE_CANTOPEN_SYMLINK:
441 case SQLITE_CANTOPEN:
442 throwCannotOpen("SqliteStatement::stepStatement: Cannot open database or temporary file.");
443 }
444
445 throwUnknowError("SqliteStatement::stepStatement: unknown error has happened");
446 }
447
checkForPrepareError(int resultCode) const448 void BaseStatement::checkForPrepareError(int resultCode) const
449 {
450 switch (resultCode) {
451 case SQLITE_BUSY_RECOVERY:
452 case SQLITE_BUSY_SNAPSHOT:
453 case SQLITE_BUSY_TIMEOUT:
454 case SQLITE_BUSY:
455 throwStatementIsBusy("SqliteStatement::prepareStatement: database engine was unable to "
456 "acquire the database locks!");
457 case SQLITE_ERROR_MISSING_COLLSEQ:
458 case SQLITE_ERROR_RETRY:
459 case SQLITE_ERROR_SNAPSHOT:
460 case SQLITE_ERROR:
461 throwStatementHasError("SqliteStatement::prepareStatement: run-time error (such as a "
462 "constraint violation) has occurred!");
463 case SQLITE_MISUSE:
464 throwStatementIsMisused("SqliteStatement::prepareStatement: was called inappropriately!");
465 case SQLITE_IOERR_AUTH:
466 case SQLITE_IOERR_BEGIN_ATOMIC:
467 case SQLITE_IOERR_BLOCKED:
468 case SQLITE_IOERR_CHECKRESERVEDLOCK:
469 case SQLITE_IOERR_CLOSE:
470 case SQLITE_IOERR_COMMIT_ATOMIC:
471 case SQLITE_IOERR_CONVPATH:
472 case SQLITE_IOERR_DATA:
473 case SQLITE_IOERR_DELETE:
474 case SQLITE_IOERR_DELETE_NOENT:
475 case SQLITE_IOERR_DIR_CLOSE:
476 case SQLITE_IOERR_DIR_FSYNC:
477 case SQLITE_IOERR_FSTAT:
478 case SQLITE_IOERR_FSYNC:
479 case SQLITE_IOERR_GETTEMPPATH:
480 case SQLITE_IOERR_LOCK:
481 case SQLITE_IOERR_MMAP:
482 case SQLITE_IOERR_NOMEM:
483 case SQLITE_IOERR_RDLOCK:
484 case SQLITE_IOERR_READ:
485 case SQLITE_IOERR_ROLLBACK_ATOMIC:
486 case SQLITE_IOERR_SEEK:
487 case SQLITE_IOERR_SHMLOCK:
488 case SQLITE_IOERR_SHMMAP:
489 case SQLITE_IOERR_SHMOPEN:
490 case SQLITE_IOERR_SHMSIZE:
491 case SQLITE_IOERR_SHORT_READ:
492 case SQLITE_IOERR_TRUNCATE:
493 case SQLITE_IOERR_UNLOCK:
494 case SQLITE_IOERR_VNODE:
495 case SQLITE_IOERR_WRITE:
496 case SQLITE_IOERR:
497 throwInputOutputError("SqliteStatement::prepareStatement: IO error happened!");
498 }
499
500 throwUnknowError("SqliteStatement::prepareStatement: unknown error has happened");
501 }
502
checkForBindingError(int resultCode) const503 void BaseStatement::checkForBindingError(int resultCode) const
504 {
505 switch (resultCode) {
506 case SQLITE_TOOBIG: throwBingingTooBig("SqliteStatement::bind: string or blob are over size limits(SQLITE_LIMIT_LENGTH)!");
507 case SQLITE_RANGE : throwBindingIndexIsOutOfRange("SqliteStatement::bind: binding index is out of range!");
508 case SQLITE_NOMEM: throw std::bad_alloc();
509 case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::bind: was called inappropriately!");
510 }
511
512 throwUnknowError("SqliteStatement::bind: unknown error has happened");
513 }
514
checkColumnCount(int columnCount) const515 void BaseStatement::checkColumnCount(int columnCount) const
516 {
517 if (columnCount != m_columnCount)
518 throw ColumnCountDoesNotMatch("SqliteStatement::values: column count does not match!");
519 }
520
checkBindingName(int index) const521 void BaseStatement::checkBindingName(int index) const
522 {
523 if (index <= 0 || index > m_bindingParameterCount)
524 throwWrongBingingName("SqliteStatement::bind: binding name are not exists in this statement!");
525 }
526
setBindingParameterCount()527 void BaseStatement::setBindingParameterCount()
528 {
529 m_bindingParameterCount = sqlite3_bind_parameter_count(m_compiledStatement.get());
530 }
531
chopFirstLetter(const char * rawBindingName)532 Utils::SmallStringView chopFirstLetter(const char *rawBindingName)
533 {
534 if (rawBindingName != nullptr)
535 return Utils::SmallStringView(++rawBindingName);
536
537 return Utils::SmallStringView("");
538 }
539
setColumnCount()540 void BaseStatement::setColumnCount()
541 {
542 m_columnCount = sqlite3_column_count(m_compiledStatement.get());
543 }
544
isReadOnlyStatement() const545 bool BaseStatement::isReadOnlyStatement() const
546 {
547 return sqlite3_stmt_readonly(m_compiledStatement.get());
548 }
549
throwStatementIsBusy(const char * whatHasHappened) const550 void BaseStatement::throwStatementIsBusy(const char *whatHasHappened) const
551 {
552 throw StatementIsBusy(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
553 }
554
throwStatementHasError(const char * whatHasHappened) const555 void BaseStatement::throwStatementHasError(const char *whatHasHappened) const
556 {
557 throw StatementHasError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
558 }
559
throwStatementIsMisused(const char * whatHasHappened) const560 void BaseStatement::throwStatementIsMisused(const char *whatHasHappened) const
561 {
562 throw StatementIsMisused(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
563 }
564
throwInputOutputError(const char * whatHasHappened) const565 void BaseStatement::throwInputOutputError(const char *whatHasHappened) const
566 {
567 throw InputOutputError(whatHasHappened);
568 }
569
throwConstraintPreventsModification(const char * whatHasHappened) const570 void BaseStatement::throwConstraintPreventsModification(const char *whatHasHappened) const
571 {
572 throw ConstraintPreventsModification(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
573 }
574
throwNoValuesToFetch(const char * whatHasHappened) const575 void BaseStatement::throwNoValuesToFetch(const char *whatHasHappened) const
576 {
577 throw NoValuesToFetch(whatHasHappened);
578 }
579
throwBindingIndexIsOutOfRange(const char * whatHasHappened) const580 void BaseStatement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const
581 {
582 throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
583 }
584
throwWrongBingingName(const char * whatHasHappened) const585 void BaseStatement::throwWrongBingingName(const char *whatHasHappened) const
586 {
587 throw WrongBindingName(whatHasHappened);
588 }
589
throwUnknowError(const char * whatHasHappened) const590 void BaseStatement::throwUnknowError(const char *whatHasHappened) const
591 {
592 if (sqliteDatabaseHandle())
593 throw UnknowError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
594 else
595 throw UnknowError(whatHasHappened);
596 }
597
throwBingingTooBig(const char * whatHasHappened) const598 void BaseStatement::throwBingingTooBig(const char *whatHasHappened) const
599 {
600 throw BindingTooBig(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
601 }
602
throwTooBig(const char * whatHasHappened) const603 void BaseStatement::throwTooBig(const char *whatHasHappened) const
604 {
605 throw TooBig{whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())};
606 }
607
throwSchemaChangeError(const char * whatHasHappened) const608 void BaseStatement::throwSchemaChangeError(const char *whatHasHappened) const
609 {
610 throw SchemeChangeError{whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())};
611 }
612
throwCannotWriteToReadOnlyConnection(const char * whatHasHappened) const613 void BaseStatement::throwCannotWriteToReadOnlyConnection(const char *whatHasHappened) const
614 {
615 throw CannotWriteToReadOnlyConnection{whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())};
616 }
617
throwProtocolError(const char * whatHasHappened) const618 void BaseStatement::throwProtocolError(const char *whatHasHappened) const
619 {
620 throw ProtocolError{whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())};
621 }
622
throwDatabaseExceedsMaximumFileSize(const char * whatHasHappened) const623 void BaseStatement::throwDatabaseExceedsMaximumFileSize(const char *whatHasHappened) const
624 {
625 throw DatabaseExceedsMaximumFileSize{whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())};
626 }
627
throwDataTypeMismatch(const char * whatHasHappened) const628 void BaseStatement::throwDataTypeMismatch(const char *whatHasHappened) const
629 {
630 throw DataTypeMismatch{whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())};
631 }
632
throwConnectionIsLocked(const char * whatHasHappened) const633 void BaseStatement::throwConnectionIsLocked(const char *whatHasHappened) const
634 {
635 throw ConnectionIsLocked{whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())};
636 }
637
throwExecutionInterrupted(const char * whatHasHappened) const638 void BaseStatement::throwExecutionInterrupted(const char *whatHasHappened) const
639 {
640 throw ExecutionInterrupted{whatHasHappened};
641 }
642
throwDatabaseIsCorrupt(const char * whatHasHappened) const643 void BaseStatement::throwDatabaseIsCorrupt(const char *whatHasHappened) const
644 {
645 throw DatabaseIsCorrupt{whatHasHappened};
646 }
647
throwCannotOpen(const char * whatHasHappened) const648 void BaseStatement::throwCannotOpen(const char *whatHasHappened) const
649 {
650 throw CannotOpen{whatHasHappened};
651 }
652
columnName(int column) const653 QString BaseStatement::columnName(int column) const
654 {
655 return QString::fromUtf8(sqlite3_column_name(m_compiledStatement.get(), column));
656 }
657
database() const658 Database &BaseStatement::database() const
659 {
660 return m_database;
661 }
662
663 namespace {
664 template<typename StringType>
textForColumn(sqlite3_stmt * sqlStatment,int column)665 StringType textForColumn(sqlite3_stmt *sqlStatment, int column)
666 {
667 const char *text = reinterpret_cast<const char*>(sqlite3_column_text(sqlStatment, column));
668 std::size_t size = std::size_t(sqlite3_column_bytes(sqlStatment, column));
669
670 return StringType(text, size);
671 }
672
blobForColumn(sqlite3_stmt * sqlStatment,int column)673 BlobView blobForColumn(sqlite3_stmt *sqlStatment, int column)
674 {
675 const std::byte *blob = reinterpret_cast<const std::byte *>(
676 sqlite3_column_blob(sqlStatment, column));
677 std::size_t size = std::size_t(sqlite3_column_bytes(sqlStatment, column));
678
679 return {blob, size};
680 }
681
convertToBlobForColumn(sqlite3_stmt * sqlStatment,int column)682 BlobView convertToBlobForColumn(sqlite3_stmt *sqlStatment, int column)
683 {
684 int dataType = sqlite3_column_type(sqlStatment, column);
685 if (dataType == SQLITE_BLOB)
686 return blobForColumn(sqlStatment, column);
687
688 return {};
689 }
690
691 template<typename StringType>
convertToTextForColumn(sqlite3_stmt * sqlStatment,int column)692 StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
693 {
694 int dataType = sqlite3_column_type(sqlStatment, column);
695 switch (dataType) {
696 case SQLITE_INTEGER:
697 case SQLITE_FLOAT:
698 case SQLITE3_TEXT:
699 return textForColumn<StringType>(sqlStatment, column);
700 case SQLITE_BLOB:
701 case SQLITE_NULL:
702 break;
703 }
704
705 return {};
706 }
707 } // namespace
708
fetchType(int column) const709 Type BaseStatement::fetchType(int column) const
710 {
711 auto dataType = sqlite3_column_type(m_compiledStatement.get(), column);
712
713 switch (dataType) {
714 case SQLITE_INTEGER:
715 return Type::Integer;
716 case SQLITE_FLOAT:
717 return Type::Float;
718 case SQLITE3_TEXT:
719 return Type::Text;
720 case SQLITE_BLOB:
721 return Type::Blob;
722 case SQLITE_NULL:
723 return Type::Null;
724 }
725
726 return Type::Invalid;
727 }
728
fetchIntValue(int column) const729 int BaseStatement::fetchIntValue(int column) const
730 {
731 return sqlite3_column_int(m_compiledStatement.get(), column);
732 }
733
734 template<>
fetchValue(int column) const735 int BaseStatement::fetchValue<int>(int column) const
736 {
737 return fetchIntValue(column);
738 }
739
fetchLongValue(int column) const740 long BaseStatement::fetchLongValue(int column) const
741 {
742 return long(fetchValue<long long>(column));
743 }
744
745 template<>
fetchValue(int column) const746 long BaseStatement::fetchValue<long>(int column) const
747 {
748 return fetchLongValue(column);
749 }
750
fetchLongLongValue(int column) const751 long long BaseStatement::fetchLongLongValue(int column) const
752 {
753 return sqlite3_column_int64(m_compiledStatement.get(), column);
754 }
755
756 template<>
fetchValue(int column) const757 long long BaseStatement::fetchValue<long long>(int column) const
758 {
759 return fetchLongLongValue(column);
760 }
761
fetchDoubleValue(int column) const762 double BaseStatement::fetchDoubleValue(int column) const
763 {
764 return sqlite3_column_double(m_compiledStatement.get(), column);
765 }
766
fetchBlobValue(int column) const767 BlobView BaseStatement::fetchBlobValue(int column) const
768 {
769 return convertToBlobForColumn(m_compiledStatement.get(), column);
770 }
771
772 template<>
fetchValue(int column) const773 double BaseStatement::fetchValue<double>(int column) const
774 {
775 return fetchDoubleValue(column);
776 }
777
778 template<typename StringType>
fetchValue(int column) const779 StringType BaseStatement::fetchValue(int column) const
780 {
781 return convertToTextForColumn<StringType>(m_compiledStatement.get(), column);
782 }
783
784 template SQLITE_EXPORT Utils::SmallStringView BaseStatement::fetchValue<Utils::SmallStringView>(
785 int column) const;
786 template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue<Utils::SmallString>(
787 int column) const;
788 template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue<Utils::PathString>(
789 int column) const;
790
fetchSmallStringViewValue(int column) const791 Utils::SmallStringView BaseStatement::fetchSmallStringViewValue(int column) const
792 {
793 return fetchValue<Utils::SmallStringView>(column);
794 }
795
fetchValueView(int column) const796 ValueView BaseStatement::fetchValueView(int column) const
797 {
798 int dataType = sqlite3_column_type(m_compiledStatement.get(), column);
799 switch (dataType) {
800 case SQLITE_NULL:
801 return ValueView::create(NullValue{});
802 case SQLITE_INTEGER:
803 return ValueView::create(fetchLongLongValue(column));
804 case SQLITE_FLOAT:
805 return ValueView::create(fetchDoubleValue(column));
806 case SQLITE3_TEXT:
807 return ValueView::create(fetchValue<Utils::SmallStringView>(column));
808 case SQLITE_BLOB:
809 break;
810 }
811
812 return ValueView::create(NullValue{});
813 }
814
815 } // namespace Sqlite
816