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