1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
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 The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qsql_sqlite_p.h"
41 
42 #include <qcoreapplication.h>
43 #include <qdatetime.h>
44 #include <qvariant.h>
45 #include <qsqlerror.h>
46 #include <qsqlfield.h>
47 #include <qsqlindex.h>
48 #include <qsqlquery.h>
49 #include <QtSql/private/qsqlcachedresult_p.h>
50 #include <QtSql/private/qsqldriver_p.h>
51 #include <qstringlist.h>
52 #include <qvector.h>
53 #include <qdebug.h>
54 #if QT_CONFIG(regularexpression)
55 #include <qcache.h>
56 #include <qregularexpression.h>
57 #endif
58 #include <QScopedValueRollback>
59 
60 #if defined Q_OS_WIN
61 # include <qt_windows.h>
62 #else
63 # include <unistd.h>
64 #endif
65 
66 #include <sqlite3.h>
67 #include <functional>
68 
69 Q_DECLARE_OPAQUE_POINTER(sqlite3*)
Q_DECLARE_METATYPE(sqlite3 *)70 Q_DECLARE_METATYPE(sqlite3*)
71 
72 Q_DECLARE_OPAQUE_POINTER(sqlite3_stmt*)
73 Q_DECLARE_METATYPE(sqlite3_stmt*)
74 
75 QT_BEGIN_NAMESPACE
76 
77 static QString _q_escapeIdentifier(const QString &identifier)
78 {
79     QString res = identifier;
80     if (!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"'))) {
81         res.replace(QLatin1Char('"'), QLatin1String("\"\""));
82         res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
83         res.replace(QLatin1Char('.'), QLatin1String("\".\""));
84     }
85     return res;
86 }
87 
qGetColumnType(const QString & tpName)88 static QVariant::Type qGetColumnType(const QString &tpName)
89 {
90     const QString typeName = tpName.toLower();
91 
92     if (typeName == QLatin1String("integer")
93         || typeName == QLatin1String("int"))
94         return QVariant::Int;
95     if (typeName == QLatin1String("double")
96         || typeName == QLatin1String("float")
97         || typeName == QLatin1String("real")
98         || typeName.startsWith(QLatin1String("numeric")))
99         return QVariant::Double;
100     if (typeName == QLatin1String("blob"))
101         return QVariant::ByteArray;
102     if (typeName == QLatin1String("boolean")
103         || typeName == QLatin1String("bool"))
104         return QVariant::Bool;
105     return QVariant::String;
106 }
107 
qMakeError(sqlite3 * access,const QString & descr,QSqlError::ErrorType type,int errorCode)108 static QSqlError qMakeError(sqlite3 *access, const QString &descr, QSqlError::ErrorType type,
109                             int errorCode)
110 {
111     return QSqlError(descr,
112                      QString(reinterpret_cast<const QChar *>(sqlite3_errmsg16(access))),
113                      type, QString::number(errorCode));
114 }
115 
116 class QSQLiteResultPrivate;
117 
118 class QSQLiteResult : public QSqlCachedResult
119 {
120     Q_DECLARE_PRIVATE(QSQLiteResult)
121     friend class QSQLiteDriver;
122 
123 public:
124     explicit QSQLiteResult(const QSQLiteDriver* db);
125     ~QSQLiteResult();
126     QVariant handle() const override;
127 
128 protected:
129     bool gotoNext(QSqlCachedResult::ValueCache& row, int idx) override;
130     bool reset(const QString &query) override;
131     bool prepare(const QString &query) override;
132     bool execBatch(bool arrayBind) override;
133     bool exec() override;
134     int size() override;
135     int numRowsAffected() override;
136     QVariant lastInsertId() const override;
137     QSqlRecord record() const override;
138     void detachFromResultSet() override;
139     void virtual_hook(int id, void *data) override;
140 };
141 
142 class QSQLiteDriverPrivate : public QSqlDriverPrivate
143 {
144     Q_DECLARE_PUBLIC(QSQLiteDriver)
145 
146 public:
QSQLiteDriverPrivate()147     inline QSQLiteDriverPrivate() : QSqlDriverPrivate(QSqlDriver::SQLite) {}
148     sqlite3 *access = nullptr;
149     QVector<QSQLiteResult *> results;
150     QStringList notificationid;
151 };
152 
153 
154 class QSQLiteResultPrivate : public QSqlCachedResultPrivate
155 {
156     Q_DECLARE_PUBLIC(QSQLiteResult)
157 
158 public:
159     Q_DECLARE_SQLDRIVER_PRIVATE(QSQLiteDriver)
160     using QSqlCachedResultPrivate::QSqlCachedResultPrivate;
161     void cleanup();
162     bool fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch);
163     // initializes the recordInfo and the cache
164     void initColumns(bool emptyResultset);
165     void finalize();
166 
167     sqlite3_stmt *stmt = nullptr;
168     QSqlRecord rInf;
169     QVector<QVariant> firstRow;
170     bool skippedStatus = false; // the status of the fetchNext() that's skipped
171     bool skipRow = false; // skip the next fetchNext()?
172 };
173 
cleanup()174 void QSQLiteResultPrivate::cleanup()
175 {
176     Q_Q(QSQLiteResult);
177     finalize();
178     rInf.clear();
179     skippedStatus = false;
180     skipRow = false;
181     q->setAt(QSql::BeforeFirstRow);
182     q->setActive(false);
183     q->cleanup();
184 }
185 
finalize()186 void QSQLiteResultPrivate::finalize()
187 {
188     if (!stmt)
189         return;
190 
191     sqlite3_finalize(stmt);
192     stmt = 0;
193 }
194 
initColumns(bool emptyResultset)195 void QSQLiteResultPrivate::initColumns(bool emptyResultset)
196 {
197     Q_Q(QSQLiteResult);
198     int nCols = sqlite3_column_count(stmt);
199     if (nCols <= 0)
200         return;
201 
202     q->init(nCols);
203 
204     for (int i = 0; i < nCols; ++i) {
205         QString colName = QString(reinterpret_cast<const QChar *>(
206                     sqlite3_column_name16(stmt, i))
207                     ).remove(QLatin1Char('"'));
208         const QString tableName = QString(reinterpret_cast<const QChar *>(
209                             sqlite3_column_table_name16(stmt, i))
210                             ).remove(QLatin1Char('"'));
211         // must use typeName for resolving the type to match QSqliteDriver::record
212         QString typeName = QString(reinterpret_cast<const QChar *>(
213                     sqlite3_column_decltype16(stmt, i)));
214         // sqlite3_column_type is documented to have undefined behavior if the result set is empty
215         int stp = emptyResultset ? -1 : sqlite3_column_type(stmt, i);
216 
217         QVariant::Type fieldType;
218 
219         if (!typeName.isEmpty()) {
220             fieldType = qGetColumnType(typeName);
221         } else {
222             // Get the proper type for the field based on stp value
223             switch (stp) {
224             case SQLITE_INTEGER:
225                 fieldType = QVariant::Int;
226                 break;
227             case SQLITE_FLOAT:
228                 fieldType = QVariant::Double;
229                 break;
230             case SQLITE_BLOB:
231                 fieldType = QVariant::ByteArray;
232                 break;
233             case SQLITE_TEXT:
234                 fieldType = QVariant::String;
235                 break;
236             case SQLITE_NULL:
237             default:
238                 fieldType = QVariant::Invalid;
239                 break;
240             }
241         }
242 
243         QSqlField fld(colName, fieldType, tableName);
244         fld.setSqlType(stp);
245         rInf.append(fld);
246     }
247 }
248 
fetchNext(QSqlCachedResult::ValueCache & values,int idx,bool initialFetch)249 bool QSQLiteResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch)
250 {
251     Q_Q(QSQLiteResult);
252     int res;
253     int i;
254 
255     if (skipRow) {
256         // already fetched
257         Q_ASSERT(!initialFetch);
258         skipRow = false;
259         for(int i=0;i<firstRow.count();i++)
260             values[i]=firstRow[i];
261         return skippedStatus;
262     }
263     skipRow = initialFetch;
264 
265     if(initialFetch) {
266         firstRow.clear();
267         firstRow.resize(sqlite3_column_count(stmt));
268     }
269 
270     if (!stmt) {
271         q->setLastError(QSqlError(QCoreApplication::translate("QSQLiteResult", "Unable to fetch row"),
272                                   QCoreApplication::translate("QSQLiteResult", "No query"), QSqlError::ConnectionError));
273         q->setAt(QSql::AfterLastRow);
274         return false;
275     }
276     res = sqlite3_step(stmt);
277 
278     switch(res) {
279     case SQLITE_ROW:
280         // check to see if should fill out columns
281         if (rInf.isEmpty())
282             // must be first call.
283             initColumns(false);
284         if (idx < 0 && !initialFetch)
285             return true;
286         for (i = 0; i < rInf.count(); ++i) {
287             switch (sqlite3_column_type(stmt, i)) {
288             case SQLITE_BLOB:
289                 values[i + idx] = QByteArray(static_cast<const char *>(
290                             sqlite3_column_blob(stmt, i)),
291                             sqlite3_column_bytes(stmt, i));
292                 break;
293             case SQLITE_INTEGER:
294                 values[i + idx] = sqlite3_column_int64(stmt, i);
295                 break;
296             case SQLITE_FLOAT:
297                 switch(q->numericalPrecisionPolicy()) {
298                     case QSql::LowPrecisionInt32:
299                         values[i + idx] = sqlite3_column_int(stmt, i);
300                         break;
301                     case QSql::LowPrecisionInt64:
302                         values[i + idx] = sqlite3_column_int64(stmt, i);
303                         break;
304                     case QSql::LowPrecisionDouble:
305                     case QSql::HighPrecision:
306                     default:
307                         values[i + idx] = sqlite3_column_double(stmt, i);
308                         break;
309                 };
310                 break;
311             case SQLITE_NULL:
312                 values[i + idx] = QVariant(QVariant::String);
313                 break;
314             default:
315                 values[i + idx] = QString(reinterpret_cast<const QChar *>(
316                             sqlite3_column_text16(stmt, i)),
317                             sqlite3_column_bytes16(stmt, i) / sizeof(QChar));
318                 break;
319             }
320         }
321         return true;
322     case SQLITE_DONE:
323         if (rInf.isEmpty())
324             // must be first call.
325             initColumns(true);
326         q->setAt(QSql::AfterLastRow);
327         sqlite3_reset(stmt);
328         return false;
329     case SQLITE_CONSTRAINT:
330     case SQLITE_ERROR:
331         // SQLITE_ERROR is a generic error code and we must call sqlite3_reset()
332         // to get the specific error message.
333         res = sqlite3_reset(stmt);
334         q->setLastError(qMakeError(drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
335                         "Unable to fetch row"), QSqlError::ConnectionError, res));
336         q->setAt(QSql::AfterLastRow);
337         return false;
338     case SQLITE_MISUSE:
339     case SQLITE_BUSY:
340     default:
341         // something wrong, don't get col info, but still return false
342         q->setLastError(qMakeError(drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
343                         "Unable to fetch row"), QSqlError::ConnectionError, res));
344         sqlite3_reset(stmt);
345         q->setAt(QSql::AfterLastRow);
346         return false;
347     }
348     return false;
349 }
350 
QSQLiteResult(const QSQLiteDriver * db)351 QSQLiteResult::QSQLiteResult(const QSQLiteDriver* db)
352     : QSqlCachedResult(*new QSQLiteResultPrivate(this, db))
353 {
354     Q_D(QSQLiteResult);
355     const_cast<QSQLiteDriverPrivate*>(d->drv_d_func())->results.append(this);
356 }
357 
~QSQLiteResult()358 QSQLiteResult::~QSQLiteResult()
359 {
360     Q_D(QSQLiteResult);
361     if (d->drv_d_func())
362         const_cast<QSQLiteDriverPrivate*>(d->drv_d_func())->results.removeOne(this);
363     d->cleanup();
364 }
365 
virtual_hook(int id,void * data)366 void QSQLiteResult::virtual_hook(int id, void *data)
367 {
368     QSqlCachedResult::virtual_hook(id, data);
369 }
370 
reset(const QString & query)371 bool QSQLiteResult::reset(const QString &query)
372 {
373     if (!prepare(query))
374         return false;
375     return exec();
376 }
377 
prepare(const QString & query)378 bool QSQLiteResult::prepare(const QString &query)
379 {
380     Q_D(QSQLiteResult);
381     if (!driver() || !driver()->isOpen() || driver()->isOpenError())
382         return false;
383 
384     d->cleanup();
385 
386     setSelect(false);
387 
388     const void *pzTail = NULL;
389 
390 #if (SQLITE_VERSION_NUMBER >= 3003011)
391     int res = sqlite3_prepare16_v2(d->drv_d_func()->access, query.constData(), (query.size() + 1) * sizeof(QChar),
392                                    &d->stmt, &pzTail);
393 #else
394     int res = sqlite3_prepare16(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),
395                                 &d->stmt, &pzTail);
396 #endif
397 
398     if (res != SQLITE_OK) {
399         setLastError(qMakeError(d->drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
400                      "Unable to execute statement"), QSqlError::StatementError, res));
401         d->finalize();
402         return false;
403     } else if (pzTail && !QString(reinterpret_cast<const QChar *>(pzTail)).trimmed().isEmpty()) {
404         setLastError(qMakeError(d->drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
405             "Unable to execute multiple statements at a time"), QSqlError::StatementError, SQLITE_MISUSE));
406         d->finalize();
407         return false;
408     }
409     return true;
410 }
411 
execBatch(bool arrayBind)412 bool QSQLiteResult::execBatch(bool arrayBind)
413 {
414     Q_UNUSED(arrayBind);
415     Q_D(QSqlResult);
416     QScopedValueRollback<QVector<QVariant>> valuesScope(d->values);
417     QVector<QVariant> values = d->values;
418     if (values.count() == 0)
419         return false;
420 
421     for (int i = 0; i < values.at(0).toList().count(); ++i) {
422         d->values.clear();
423         QScopedValueRollback<QHash<QString, QVector<int>>> indexesScope(d->indexes);
424         QHash<QString, QVector<int>>::const_iterator it = d->indexes.constBegin();
425         while (it != d->indexes.constEnd()) {
426             bindValue(it.key(), values.at(it.value().first()).toList().at(i), QSql::In);
427             ++it;
428         }
429         if (!exec())
430             return false;
431     }
432     return true;
433 }
434 
exec()435 bool QSQLiteResult::exec()
436 {
437     Q_D(QSQLiteResult);
438     QVector<QVariant> values = boundValues();
439 
440     d->skippedStatus = false;
441     d->skipRow = false;
442     d->rInf.clear();
443     clearValues();
444     setLastError(QSqlError());
445 
446     int res = sqlite3_reset(d->stmt);
447     if (res != SQLITE_OK) {
448         setLastError(qMakeError(d->drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
449                      "Unable to reset statement"), QSqlError::StatementError, res));
450         d->finalize();
451         return false;
452     }
453 
454     int paramCount = sqlite3_bind_parameter_count(d->stmt);
455     bool paramCountIsValid = paramCount == values.count();
456 
457 #if (SQLITE_VERSION_NUMBER >= 3003011)
458     // In the case of the reuse of a named placeholder
459     // We need to check explicitly that paramCount is greater than or equal to 1, as sqlite
460     // can end up in a case where for virtual tables it returns 0 even though it
461     // has parameters
462     if (paramCount >= 1 && paramCount < values.count()) {
463         const auto countIndexes = [](int counter, const QVector<int> &indexList) {
464                                       return counter + indexList.length();
465                                   };
466 
467         const int bindParamCount = std::accumulate(d->indexes.cbegin(),
468                                                    d->indexes.cend(),
469                                                    0,
470                                                    countIndexes);
471 
472         paramCountIsValid = bindParamCount == values.count();
473         // When using named placeholders, it will reuse the index for duplicated
474         // placeholders. So we need to ensure the QVector has only one instance of
475         // each value as SQLite will do the rest for us.
476         QVector<QVariant> prunedValues;
477         QVector<int> handledIndexes;
478         for (int i = 0, currentIndex = 0; i < values.size(); ++i) {
479             if (handledIndexes.contains(i))
480                 continue;
481             const char *parameterName = sqlite3_bind_parameter_name(d->stmt, currentIndex + 1);
482             if (!parameterName) {
483                 paramCountIsValid = false;
484                 continue;
485             }
486             const auto placeHolder = QString::fromUtf8(parameterName);
487             const auto &indexes = d->indexes.value(placeHolder);
488             handledIndexes << indexes;
489             prunedValues << values.at(indexes.first());
490             ++currentIndex;
491         }
492         values = prunedValues;
493     }
494 #endif
495 
496     if (paramCountIsValid) {
497         for (int i = 0; i < paramCount; ++i) {
498             res = SQLITE_OK;
499             const QVariant value = values.at(i);
500 
501             if (value.isNull()) {
502                 res = sqlite3_bind_null(d->stmt, i + 1);
503             } else {
504                 switch (value.userType()) {
505                 case QVariant::ByteArray: {
506                     const QByteArray *ba = static_cast<const QByteArray*>(value.constData());
507                     res = sqlite3_bind_blob(d->stmt, i + 1, ba->constData(),
508                                             ba->size(), SQLITE_STATIC);
509                     break; }
510                 case QVariant::Int:
511                 case QVariant::Bool:
512                     res = sqlite3_bind_int(d->stmt, i + 1, value.toInt());
513                     break;
514                 case QVariant::Double:
515                     res = sqlite3_bind_double(d->stmt, i + 1, value.toDouble());
516                     break;
517                 case QVariant::UInt:
518                 case QVariant::LongLong:
519                     res = sqlite3_bind_int64(d->stmt, i + 1, value.toLongLong());
520                     break;
521                 case QVariant::DateTime: {
522                     const QDateTime dateTime = value.toDateTime();
523                     const QString str = dateTime.toString(Qt::ISODateWithMs);
524                     res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
525                                               str.size() * sizeof(ushort), SQLITE_TRANSIENT);
526                     break;
527                 }
528                 case QVariant::Time: {
529                     const QTime time = value.toTime();
530                     const QString str = time.toString(u"hh:mm:ss.zzz");
531                     res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
532                                               str.size() * sizeof(ushort), SQLITE_TRANSIENT);
533                     break;
534                 }
535                 case QVariant::String: {
536                     // lifetime of string == lifetime of its qvariant
537                     const QString *str = static_cast<const QString*>(value.constData());
538                     res = sqlite3_bind_text16(d->stmt, i + 1, str->utf16(),
539                                               (str->size()) * sizeof(QChar), SQLITE_STATIC);
540                     break; }
541                 default: {
542                     QString str = value.toString();
543                     // SQLITE_TRANSIENT makes sure that sqlite buffers the data
544                     res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
545                                               (str.size()) * sizeof(QChar), SQLITE_TRANSIENT);
546                     break; }
547                 }
548             }
549             if (res != SQLITE_OK) {
550                 setLastError(qMakeError(d->drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
551                              "Unable to bind parameters"), QSqlError::StatementError, res));
552                 d->finalize();
553                 return false;
554             }
555         }
556     } else {
557         setLastError(QSqlError(QCoreApplication::translate("QSQLiteResult",
558                         "Parameter count mismatch"), QString(), QSqlError::StatementError));
559         return false;
560     }
561     d->skippedStatus = d->fetchNext(d->firstRow, 0, true);
562     if (lastError().isValid()) {
563         setSelect(false);
564         setActive(false);
565         return false;
566     }
567     setSelect(!d->rInf.isEmpty());
568     setActive(true);
569     return true;
570 }
571 
gotoNext(QSqlCachedResult::ValueCache & row,int idx)572 bool QSQLiteResult::gotoNext(QSqlCachedResult::ValueCache& row, int idx)
573 {
574     Q_D(QSQLiteResult);
575     return d->fetchNext(row, idx, false);
576 }
577 
size()578 int QSQLiteResult::size()
579 {
580     return -1;
581 }
582 
numRowsAffected()583 int QSQLiteResult::numRowsAffected()
584 {
585     Q_D(const QSQLiteResult);
586     return sqlite3_changes(d->drv_d_func()->access);
587 }
588 
lastInsertId() const589 QVariant QSQLiteResult::lastInsertId() const
590 {
591     Q_D(const QSQLiteResult);
592     if (isActive()) {
593         qint64 id = sqlite3_last_insert_rowid(d->drv_d_func()->access);
594         if (id)
595             return id;
596     }
597     return QVariant();
598 }
599 
record() const600 QSqlRecord QSQLiteResult::record() const
601 {
602     Q_D(const QSQLiteResult);
603     if (!isActive() || !isSelect())
604         return QSqlRecord();
605     return d->rInf;
606 }
607 
detachFromResultSet()608 void QSQLiteResult::detachFromResultSet()
609 {
610     Q_D(QSQLiteResult);
611     if (d->stmt)
612         sqlite3_reset(d->stmt);
613 }
614 
handle() const615 QVariant QSQLiteResult::handle() const
616 {
617     Q_D(const QSQLiteResult);
618     return QVariant::fromValue(d->stmt);
619 }
620 
621 /////////////////////////////////////////////////////////
622 
623 #if QT_CONFIG(regularexpression)
_q_regexp(sqlite3_context * context,int argc,sqlite3_value ** argv)624 static void _q_regexp(sqlite3_context* context, int argc, sqlite3_value** argv)
625 {
626     if (Q_UNLIKELY(argc != 2)) {
627         sqlite3_result_int(context, 0);
628         return;
629     }
630 
631     const QString pattern = QString::fromUtf8(
632         reinterpret_cast<const char*>(sqlite3_value_text(argv[0])));
633     const QString subject = QString::fromUtf8(
634         reinterpret_cast<const char*>(sqlite3_value_text(argv[1])));
635 
636     auto cache = static_cast<QCache<QString, QRegularExpression>*>(sqlite3_user_data(context));
637     auto regexp = cache->object(pattern);
638     const bool wasCached = regexp;
639 
640     if (!wasCached)
641         regexp = new QRegularExpression(pattern, QRegularExpression::DontCaptureOption);
642 
643     const bool found = subject.contains(*regexp);
644 
645     if (!wasCached)
646         cache->insert(pattern, regexp);
647 
648     sqlite3_result_int(context, int(found));
649 }
650 
_q_regexp_cleanup(void * cache)651 static void _q_regexp_cleanup(void *cache)
652 {
653     delete static_cast<QCache<QString, QRegularExpression>*>(cache);
654 }
655 #endif
656 
QSQLiteDriver(QObject * parent)657 QSQLiteDriver::QSQLiteDriver(QObject * parent)
658     : QSqlDriver(*new QSQLiteDriverPrivate, parent)
659 {
660 }
661 
QSQLiteDriver(sqlite3 * connection,QObject * parent)662 QSQLiteDriver::QSQLiteDriver(sqlite3 *connection, QObject *parent)
663     : QSqlDriver(*new QSQLiteDriverPrivate, parent)
664 {
665     Q_D(QSQLiteDriver);
666     d->access = connection;
667     setOpen(true);
668     setOpenError(false);
669 }
670 
671 
~QSQLiteDriver()672 QSQLiteDriver::~QSQLiteDriver()
673 {
674     close();
675 }
676 
hasFeature(DriverFeature f) const677 bool QSQLiteDriver::hasFeature(DriverFeature f) const
678 {
679     switch (f) {
680     case BLOB:
681     case Transactions:
682     case Unicode:
683     case LastInsertId:
684     case PreparedQueries:
685     case PositionalPlaceholders:
686     case SimpleLocking:
687     case FinishQuery:
688     case LowPrecisionNumbers:
689     case EventNotifications:
690         return true;
691     case QuerySize:
692     case BatchOperations:
693     case MultipleResultSets:
694     case CancelQuery:
695         return false;
696     case NamedPlaceholders:
697 #if (SQLITE_VERSION_NUMBER < 3003011)
698         return false;
699 #else
700         return true;
701 #endif
702 
703     }
704     return false;
705 }
706 
707 /*
708    SQLite dbs have no user name, passwords, hosts or ports.
709    just file names.
710 */
open(const QString & db,const QString &,const QString &,const QString &,int,const QString & conOpts)711 bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, const QString &, int, const QString &conOpts)
712 {
713     Q_D(QSQLiteDriver);
714     if (isOpen())
715         close();
716 
717 
718     int timeOut = 5000;
719     bool sharedCache = false;
720     bool openReadOnlyOption = false;
721     bool openUriOption = false;
722 #if QT_CONFIG(regularexpression)
723     static const QLatin1String regexpConnectOption = QLatin1String("QSQLITE_ENABLE_REGEXP");
724     bool defineRegexp = false;
725     int regexpCacheSize = 25;
726 #endif
727 
728     const auto opts = conOpts.splitRef(QLatin1Char(';'));
729     for (auto option : opts) {
730         option = option.trimmed();
731         if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT"))) {
732             option = option.mid(20).trimmed();
733             if (option.startsWith(QLatin1Char('='))) {
734                 bool ok;
735                 const int nt = option.mid(1).trimmed().toInt(&ok);
736                 if (ok)
737                     timeOut = nt;
738             }
739         } else if (option == QLatin1String("QSQLITE_OPEN_READONLY")) {
740             openReadOnlyOption = true;
741         } else if (option == QLatin1String("QSQLITE_OPEN_URI")) {
742             openUriOption = true;
743         } else if (option == QLatin1String("QSQLITE_ENABLE_SHARED_CACHE")) {
744             sharedCache = true;
745         }
746 #if QT_CONFIG(regularexpression)
747         else if (option.startsWith(regexpConnectOption)) {
748             option = option.mid(regexpConnectOption.size()).trimmed();
749             if (option.isEmpty()) {
750                 defineRegexp = true;
751             } else if (option.startsWith(QLatin1Char('='))) {
752                 bool ok = false;
753                 const int cacheSize = option.mid(1).trimmed().toInt(&ok);
754                 if (ok) {
755                     defineRegexp = true;
756                     if (cacheSize > 0)
757                         regexpCacheSize = cacheSize;
758                 }
759             }
760         }
761 #endif
762     }
763 
764     int openMode = (openReadOnlyOption ? SQLITE_OPEN_READONLY : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE));
765     openMode |= (sharedCache ? SQLITE_OPEN_SHAREDCACHE : SQLITE_OPEN_PRIVATECACHE);
766     if (openUriOption)
767         openMode |= SQLITE_OPEN_URI;
768 
769     openMode |= SQLITE_OPEN_NOMUTEX;
770 
771     const int res = sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, NULL);
772 
773     if (res == SQLITE_OK) {
774         sqlite3_busy_timeout(d->access, timeOut);
775         setOpen(true);
776         setOpenError(false);
777 #if QT_CONFIG(regularexpression)
778         if (defineRegexp) {
779             auto cache = new QCache<QString, QRegularExpression>(regexpCacheSize);
780             sqlite3_create_function_v2(d->access, "regexp", 2, SQLITE_UTF8, cache, &_q_regexp, NULL,
781                                        NULL, &_q_regexp_cleanup);
782         }
783 #endif
784         return true;
785     } else {
786         setLastError(qMakeError(d->access, tr("Error opening database"),
787                      QSqlError::ConnectionError, res));
788         setOpenError(true);
789 
790         if (d->access) {
791             sqlite3_close(d->access);
792             d->access = 0;
793         }
794 
795         return false;
796     }
797 }
798 
close()799 void QSQLiteDriver::close()
800 {
801     Q_D(QSQLiteDriver);
802     if (isOpen()) {
803         for (QSQLiteResult *result : qAsConst(d->results))
804             result->d_func()->finalize();
805 
806         if (d->access && (d->notificationid.count() > 0)) {
807             d->notificationid.clear();
808             sqlite3_update_hook(d->access, NULL, NULL);
809         }
810 
811         const int res = sqlite3_close(d->access);
812 
813         if (res != SQLITE_OK)
814             setLastError(qMakeError(d->access, tr("Error closing database"), QSqlError::ConnectionError, res));
815         d->access = 0;
816         setOpen(false);
817         setOpenError(false);
818     }
819 }
820 
createResult() const821 QSqlResult *QSQLiteDriver::createResult() const
822 {
823     return new QSQLiteResult(this);
824 }
825 
beginTransaction()826 bool QSQLiteDriver::beginTransaction()
827 {
828     if (!isOpen() || isOpenError())
829         return false;
830 
831     QSqlQuery q(createResult());
832     if (!q.exec(QLatin1String("BEGIN"))) {
833         setLastError(QSqlError(tr("Unable to begin transaction"),
834                                q.lastError().databaseText(), QSqlError::TransactionError));
835         return false;
836     }
837 
838     return true;
839 }
840 
commitTransaction()841 bool QSQLiteDriver::commitTransaction()
842 {
843     if (!isOpen() || isOpenError())
844         return false;
845 
846     QSqlQuery q(createResult());
847     if (!q.exec(QLatin1String("COMMIT"))) {
848         setLastError(QSqlError(tr("Unable to commit transaction"),
849                                q.lastError().databaseText(), QSqlError::TransactionError));
850         return false;
851     }
852 
853     return true;
854 }
855 
rollbackTransaction()856 bool QSQLiteDriver::rollbackTransaction()
857 {
858     if (!isOpen() || isOpenError())
859         return false;
860 
861     QSqlQuery q(createResult());
862     if (!q.exec(QLatin1String("ROLLBACK"))) {
863         setLastError(QSqlError(tr("Unable to rollback transaction"),
864                                q.lastError().databaseText(), QSqlError::TransactionError));
865         return false;
866     }
867 
868     return true;
869 }
870 
tables(QSql::TableType type) const871 QStringList QSQLiteDriver::tables(QSql::TableType type) const
872 {
873     QStringList res;
874     if (!isOpen())
875         return res;
876 
877     QSqlQuery q(createResult());
878     q.setForwardOnly(true);
879 
880     QString sql = QLatin1String("SELECT name FROM sqlite_master WHERE %1 "
881                                 "UNION ALL SELECT name FROM sqlite_temp_master WHERE %1");
882     if ((type & QSql::Tables) && (type & QSql::Views))
883         sql = sql.arg(QLatin1String("type='table' OR type='view'"));
884     else if (type & QSql::Tables)
885         sql = sql.arg(QLatin1String("type='table'"));
886     else if (type & QSql::Views)
887         sql = sql.arg(QLatin1String("type='view'"));
888     else
889         sql.clear();
890 
891     if (!sql.isEmpty() && q.exec(sql)) {
892         while(q.next())
893             res.append(q.value(0).toString());
894     }
895 
896     if (type & QSql::SystemTables) {
897         // there are no internal tables beside this one:
898         res.append(QLatin1String("sqlite_master"));
899     }
900 
901     return res;
902 }
903 
qGetTableInfo(QSqlQuery & q,const QString & tableName,bool onlyPIndex=false)904 static QSqlIndex qGetTableInfo(QSqlQuery &q, const QString &tableName, bool onlyPIndex = false)
905 {
906     QString schema;
907     QString table(tableName);
908     int indexOfSeparator = tableName.indexOf(QLatin1Char('.'));
909     if (indexOfSeparator > -1) {
910         schema = tableName.left(indexOfSeparator).append(QLatin1Char('.'));
911         table = tableName.mid(indexOfSeparator + 1);
912     }
913     q.exec(QLatin1String("PRAGMA ") + schema + QLatin1String("table_info (") + _q_escapeIdentifier(table) + QLatin1Char(')'));
914 
915     QSqlIndex ind;
916     while (q.next()) {
917         bool isPk = q.value(5).toInt();
918         if (onlyPIndex && !isPk)
919             continue;
920         QString typeName = q.value(2).toString().toLower();
921         QString defVal = q.value(4).toString();
922         if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\'')) {
923             const int end = defVal.lastIndexOf(QLatin1Char('\''));
924             if (end > 0)
925                 defVal = defVal.mid(1, end - 1);
926         }
927 
928         QSqlField fld(q.value(1).toString(), qGetColumnType(typeName), tableName);
929         if (isPk && (typeName == QLatin1String("integer")))
930             // INTEGER PRIMARY KEY fields are auto-generated in sqlite
931             // INT PRIMARY KEY is not the same as INTEGER PRIMARY KEY!
932             fld.setAutoValue(true);
933         fld.setRequired(q.value(3).toInt() != 0);
934         fld.setDefaultValue(defVal);
935         ind.append(fld);
936     }
937     return ind;
938 }
939 
primaryIndex(const QString & tblname) const940 QSqlIndex QSQLiteDriver::primaryIndex(const QString &tblname) const
941 {
942     if (!isOpen())
943         return QSqlIndex();
944 
945     QString table = tblname;
946     if (isIdentifierEscaped(table, QSqlDriver::TableName))
947         table = stripDelimiters(table, QSqlDriver::TableName);
948 
949     QSqlQuery q(createResult());
950     q.setForwardOnly(true);
951     return qGetTableInfo(q, table, true);
952 }
953 
record(const QString & tbl) const954 QSqlRecord QSQLiteDriver::record(const QString &tbl) const
955 {
956     if (!isOpen())
957         return QSqlRecord();
958 
959     QString table = tbl;
960     if (isIdentifierEscaped(table, QSqlDriver::TableName))
961         table = stripDelimiters(table, QSqlDriver::TableName);
962 
963     QSqlQuery q(createResult());
964     q.setForwardOnly(true);
965     return qGetTableInfo(q, table);
966 }
967 
handle() const968 QVariant QSQLiteDriver::handle() const
969 {
970     Q_D(const QSQLiteDriver);
971     return QVariant::fromValue(d->access);
972 }
973 
escapeIdentifier(const QString & identifier,IdentifierType type) const974 QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const
975 {
976     Q_UNUSED(type);
977     return _q_escapeIdentifier(identifier);
978 }
979 
handle_sqlite_callback(void * qobj,int aoperation,char const * adbname,char const * atablename,sqlite3_int64 arowid)980 static void handle_sqlite_callback(void *qobj,int aoperation, char const *adbname, char const *atablename,
981                                    sqlite3_int64 arowid)
982 {
983     Q_UNUSED(aoperation);
984     Q_UNUSED(adbname);
985     QSQLiteDriver *driver = static_cast<QSQLiteDriver *>(qobj);
986     if (driver) {
987         QMetaObject::invokeMethod(driver, "handleNotification", Qt::QueuedConnection,
988                                   Q_ARG(QString, QString::fromUtf8(atablename)), Q_ARG(qint64, arowid));
989     }
990 }
991 
subscribeToNotification(const QString & name)992 bool QSQLiteDriver::subscribeToNotification(const QString &name)
993 {
994     Q_D(QSQLiteDriver);
995     if (!isOpen()) {
996         qWarning("Database not open.");
997         return false;
998     }
999 
1000     if (d->notificationid.contains(name)) {
1001         qWarning("Already subscribing to '%s'.", qPrintable(name));
1002         return false;
1003     }
1004 
1005     //sqlite supports only one notification callback, so only the first is registered
1006     d->notificationid << name;
1007     if (d->notificationid.count() == 1)
1008         sqlite3_update_hook(d->access, &handle_sqlite_callback, reinterpret_cast<void *> (this));
1009 
1010     return true;
1011 }
1012 
unsubscribeFromNotification(const QString & name)1013 bool QSQLiteDriver::unsubscribeFromNotification(const QString &name)
1014 {
1015     Q_D(QSQLiteDriver);
1016     if (!isOpen()) {
1017         qWarning("Database not open.");
1018         return false;
1019     }
1020 
1021     if (!d->notificationid.contains(name)) {
1022         qWarning("Not subscribed to '%s'.", qPrintable(name));
1023         return false;
1024     }
1025 
1026     d->notificationid.removeAll(name);
1027     if (d->notificationid.isEmpty())
1028         sqlite3_update_hook(d->access, NULL, NULL);
1029 
1030     return true;
1031 }
1032 
subscribedToNotifications() const1033 QStringList QSQLiteDriver::subscribedToNotifications() const
1034 {
1035     Q_D(const QSQLiteDriver);
1036     return d->notificationid;
1037 }
1038 
handleNotification(const QString & tableName,qint64 rowid)1039 void QSQLiteDriver::handleNotification(const QString &tableName, qint64 rowid)
1040 {
1041     Q_D(const QSQLiteDriver);
1042     if (d->notificationid.contains(tableName)) {
1043 #if QT_DEPRECATED_SINCE(5, 15)
1044 QT_WARNING_PUSH
1045 QT_WARNING_DISABLE_DEPRECATED
1046         emit notification(tableName);
1047 QT_WARNING_POP
1048 #endif
1049         emit notification(tableName, QSqlDriver::UnknownSource, QVariant(rowid));
1050     }
1051 }
1052 
1053 QT_END_NAMESPACE
1054