File indexing completed on 2024-05-05 17:19:15

0001 //krazy:skip
0002 // clazy:skip
0003 /****************************************************************************
0004 **
0005 ** Copyright (C) 2016 The Qt Company Ltd.
0006 ** Contact: https://www.qt.io/licensing/
0007 **
0008 ** This file is part of the QtSql module of the Qt Toolkit.
0009 **
0010 ** $QT_BEGIN_LICENSE:LGPL$
0011 ** Commercial License Usage
0012 ** Licensees holding valid commercial Qt licenses may use this file in
0013 ** accordance with the commercial license agreement provided with the
0014 ** Software or, alternatively, in accordance with the terms contained in
0015 ** a written agreement between you and The Qt Company. For licensing terms
0016 ** and conditions see https://www.qt.io/terms-conditions. For further
0017 ** information use the contact form at https://www.qt.io/contact-us.
0018 **
0019 ** GNU Lesser General Public License Usage
0020 ** Alternatively, this file may be used under the terms of the GNU Lesser
0021 ** General Public License version 3 as published by the Free Software
0022 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
0023 ** packaging of this file. Please review the following information to
0024 ** ensure the GNU Lesser General Public License version 3 requirements
0025 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
0026 **
0027 ** GNU General Public License Usage
0028 ** Alternatively, this file may be used under the terms of the GNU
0029 ** General Public License version 2.0 or (at your option) the GNU General
0030 ** Public license version 3 or any later version approved by the KDE Free
0031 ** Qt Foundation. The licenses are as published by the Free Software
0032 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
0033 ** included in the packaging of this file. Please review the following
0034 ** information to ensure the GNU General Public License requirements will
0035 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
0036 ** https://www.gnu.org/licenses/gpl-3.0.html.
0037 **
0038 ** $QT_END_LICENSE$
0039 **
0040 ****************************************************************************/
0041 
0042 #include "qsql_sqlite_p.h"
0043 
0044 #include <QtSql/private/qsqlcachedresult_p.h>
0045 #include <QtSql/private/qsqldriver_p.h>
0046 #include <qcoreapplication.h>
0047 #include <qdatetime.h>
0048 #include <qdebug.h>
0049 #include <qsqlerror.h>
0050 #include <qsqlfield.h>
0051 #include <qsqlindex.h>
0052 #include <qsqlquery.h>
0053 #include <qstringlist.h>
0054 #include <qvariant.h>
0055 #include <qvector.h>
0056 
0057 #if defined Q_OS_WIN
0058 # include <qt_windows.h>
0059 #else
0060 # include <unistd.h>
0061 #endif
0062 
0063 #include <sqlite3.h>
0064 
0065 Q_DECLARE_OPAQUE_POINTER(sqlite3*)
0066 Q_DECLARE_METATYPE(sqlite3*)
0067 
0068 Q_DECLARE_OPAQUE_POINTER(sqlite3_stmt*)
0069 Q_DECLARE_METATYPE(sqlite3_stmt*)
0070 
0071 QT_BEGIN_NAMESPACE
0072 
0073 static QString _q_escapeIdentifier(const QString& identifier)
0074 {
0075     QString res = identifier;
0076     if (!identifier.isEmpty() && identifier.at(0) != QLatin1Char('"') && identifier.right(1) != QString(QLatin1Char('"'))) {
0077         res.replace(QLatin1Char('"'), QLatin1String("\"\""));
0078         res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
0079         res.replace(QLatin1Char('.'), QLatin1String("\".\""));
0080     }
0081     return res;
0082 }
0083 
0084 static QVariant::Type qGetColumnType(const QString& tpName)
0085 {
0086     const QString typeName = tpName.toLower();
0087 
0088     if (typeName == QLatin1String("integer")
0089         || typeName == QLatin1String("int")) {
0090         return QVariant::Int;
0091     }
0092     if (typeName == QLatin1String("double")
0093         || typeName == QLatin1String("float")
0094         || typeName == QLatin1String("real")
0095         || typeName.startsWith(QLatin1String("numeric"))) {
0096         return QVariant::Double;
0097     }
0098     if (typeName == QLatin1String("blob")) {
0099         return QVariant::ByteArray;
0100     }
0101     if (typeName == QLatin1String("boolean")
0102         || typeName == QLatin1String("bool")) {
0103         return QVariant::Bool;
0104     }
0105     return QVariant::String;
0106 }
0107 
0108 static QSqlError qMakeError(sqlite3* access, const QString& descr, QSqlError::ErrorType type,
0109                             int errorCode = -1)
0110 {
0111     return QSqlError(descr,
0112                      QString(reinterpret_cast<const QChar*>(sqlite3_errmsg16(access))),
0113                      type, QString::number(errorCode));
0114 }
0115 
0116 class QSQLiteResultPrivate;
0117 
0118 class QSQLiteResult : public QSqlCachedResult
0119 {
0120     Q_DECLARE_PRIVATE(QSQLiteResult)
0121     friend class QSQLiteDriver;
0122 
0123 public:
0124     explicit QSQLiteResult(const QSQLiteDriver* db);
0125     ~QSQLiteResult() override;
0126     QVariant handle() const Q_DECL_OVERRIDE;
0127 
0128 protected:
0129     bool gotoNext(QSqlCachedResult::ValueCache& row, int idx) Q_DECL_OVERRIDE;
0130     bool reset(const QString& query) Q_DECL_OVERRIDE;
0131     bool prepare(const QString& query) Q_DECL_OVERRIDE;
0132     bool exec() Q_DECL_OVERRIDE;
0133     int size() Q_DECL_OVERRIDE;
0134     int numRowsAffected() Q_DECL_OVERRIDE;
0135     QVariant lastInsertId() const Q_DECL_OVERRIDE;
0136     QSqlRecord record() const Q_DECL_OVERRIDE;
0137     void detachFromResultSet() Q_DECL_OVERRIDE;
0138     void virtual_hook(int id, void* data) Q_DECL_OVERRIDE;
0139 };
0140 
0141 class QSQLiteDriverPrivate : public QSqlDriverPrivate
0142 {
0143     Q_DECLARE_PUBLIC(QSQLiteDriver)
0144 
0145 public:
0146     inline QSQLiteDriverPrivate()
0147     {
0148         dbmsType = QSqlDriver::SQLite;
0149     }
0150     sqlite3* access{nullptr};
0151     QList <QSQLiteResult*> results;
0152 };
0153 
0154 
0155 class QSQLiteResultPrivate: public QSqlCachedResultPrivate
0156 {
0157     Q_DECLARE_PUBLIC(QSQLiteResult)
0158 
0159 public:
0160     Q_DECLARE_SQLDRIVER_PRIVATE(QSQLiteDriver)
0161     explicit QSQLiteResultPrivate(QSQLiteResult* q, const QSQLiteDriver* drv);
0162     void cleanup();
0163     bool fetchNext(QSqlCachedResult::ValueCache& values, int idx, bool initialFetch);
0164     // initializes the recordInfo and the cache
0165     void initColumns(bool emptyResultset);
0166     void finalize();
0167 
0168     sqlite3_stmt* stmt;
0169 
0170     bool skippedStatus; // the status of the fetchNext() that's skipped
0171     bool skipRow; // skip the next fetchNext()?
0172     QSqlRecord rInf;
0173     QVector<QVariant> firstRow;
0174 };
0175 
0176 QSQLiteResultPrivate::QSQLiteResultPrivate(QSQLiteResult* q, const QSQLiteDriver* drv)
0177     : QSqlCachedResultPrivate(q, drv),
0178       stmt(nullptr),
0179       skippedStatus(false),
0180       skipRow(false)
0181 {
0182 }
0183 
0184 void QSQLiteResultPrivate::cleanup()
0185 {
0186     Q_Q(QSQLiteResult);
0187     finalize();
0188     rInf.clear();
0189     skippedStatus = false;
0190     skipRow = false;
0191     q->setAt(QSql::BeforeFirstRow);
0192     q->setActive(false);
0193     q->cleanup();
0194 }
0195 
0196 void QSQLiteResultPrivate::finalize()
0197 {
0198     if (stmt == nullptr) {
0199         return;
0200     }
0201 
0202     sqlite3_finalize(stmt);
0203     stmt = nullptr;
0204 }
0205 
0206 void QSQLiteResultPrivate::initColumns(bool emptyResultset)
0207 {
0208     Q_Q(QSQLiteResult);
0209     int nCols = sqlite3_column_count(stmt);
0210     if (nCols <= 0) {
0211         return;
0212     }
0213 
0214     q->init(nCols);
0215 
0216     for (int i = 0; i < nCols; ++i) {
0217         QString colName = QString(reinterpret_cast<const QChar*>(
0218                                       sqlite3_column_name16(stmt, i))
0219                                  ).remove(QLatin1Char('"'));
0220 
0221         // must use typeName for resolving the type to match QSqliteDriver::record
0222         QString typeName = QString(reinterpret_cast<const QChar*>(
0223                                        sqlite3_column_decltype16(stmt, i)));
0224         // sqlite3_column_type is documented to have undefined behavior if the result set is empty
0225         int stp = emptyResultset ? -1 : sqlite3_column_type(stmt, i);
0226 
0227         QVariant::Type fieldType;
0228 
0229         if (!typeName.isEmpty()) {
0230             fieldType = qGetColumnType(typeName);
0231         } else {
0232             // Get the proper type for the field based on stp value
0233             switch (stp) {
0234             case SQLITE_INTEGER:
0235                 fieldType = QVariant::Int;
0236                 break;
0237             case SQLITE_FLOAT:
0238                 fieldType = QVariant::Double;
0239                 break;
0240             case SQLITE_BLOB:
0241                 fieldType = QVariant::ByteArray;
0242                 break;
0243             case SQLITE_TEXT:
0244                 fieldType = QVariant::String;
0245                 break;
0246             case SQLITE_NULL:
0247             default:
0248                 fieldType = QVariant::Invalid;
0249                 break;
0250             }
0251         }
0252 
0253         QSqlField fld(colName, fieldType);
0254         fld.setSqlType(stp);
0255         rInf.append(fld);
0256     }
0257 }
0258 
0259 bool QSQLiteResultPrivate::fetchNext(QSqlCachedResult::ValueCache& values, int idx, bool initialFetch)
0260 {
0261     Q_Q(QSQLiteResult);
0262     int res;
0263     int i;
0264 
0265     if (skipRow) {
0266         // already fetched
0267         Q_ASSERT(!initialFetch);
0268         skipRow = false;
0269         for (int i = 0; i < firstRow.count(); i++) {
0270             values[i] = firstRow[i];
0271         }
0272         return skippedStatus;
0273     }
0274     skipRow = initialFetch;
0275 
0276     if (initialFetch) {
0277         firstRow.clear();
0278         firstRow.resize(sqlite3_column_count(stmt));
0279     }
0280 
0281     if (stmt == nullptr) {
0282         q->setLastError(QSqlError(QCoreApplication::translate("QSQLiteResult", "Unable to fetch row"),
0283                                   QCoreApplication::translate("QSQLiteResult", "No query"), QSqlError::ConnectionError));
0284         q->setAt(QSql::AfterLastRow);
0285         return false;
0286     }
0287     res = sqlite3_step(stmt);
0288 
0289     switch (res) {
0290     case SQLITE_ROW:
0291         // check to see if should fill out columns
0292         if (rInf.isEmpty())
0293             // must be first call.
0294         {
0295             initColumns(false);
0296         }
0297         if (idx < 0 && !initialFetch) {
0298             return true;
0299         }
0300         for (i = 0; i < rInf.count(); ++i) {
0301             switch (sqlite3_column_type(stmt, i)) {
0302             case SQLITE_BLOB:
0303                 values[i + idx] = QByteArray(static_cast<const char*>(
0304                                                  sqlite3_column_blob(stmt, i)),
0305                                              sqlite3_column_bytes(stmt, i));
0306                 break;
0307             case SQLITE_INTEGER:
0308                 values[i + idx] = sqlite3_column_int64(stmt, i);
0309                 break;
0310             case SQLITE_FLOAT:
0311                 switch (q->numericalPrecisionPolicy()) {
0312                 case QSql::LowPrecisionInt32:
0313                     values[i + idx] = sqlite3_column_int(stmt, i);
0314                     break;
0315                 case QSql::LowPrecisionInt64:
0316                     values[i + idx] = sqlite3_column_int64(stmt, i);
0317                     break;
0318                 case QSql::LowPrecisionDouble:
0319                 case QSql::HighPrecision:
0320                 default:
0321                     values[i + idx] = sqlite3_column_double(stmt, i);
0322                     break;
0323                 };
0324                 break;
0325             case SQLITE_NULL:
0326                 values[i + idx] = QVariant(QVariant::String);
0327                 break;
0328             default:
0329                 values[i + idx] = QString(reinterpret_cast<const QChar*>(
0330                                               sqlite3_column_text16(stmt, i)),
0331                                           sqlite3_column_bytes16(stmt, i) / sizeof(QChar));
0332                 break;
0333             }
0334         }
0335         return true;
0336     case SQLITE_DONE:
0337         if (rInf.isEmpty())
0338             // must be first call.
0339         {
0340             initColumns(true);
0341         }
0342         q->setAt(QSql::AfterLastRow);
0343         sqlite3_reset(stmt);
0344         return false;
0345     case SQLITE_CONSTRAINT:
0346     case SQLITE_ERROR:
0347         // SQLITE_ERROR is a generic error code and we must call sqlite3_reset()
0348         // to get the specific error message.
0349         res = sqlite3_reset(stmt);
0350         q->setLastError(qMakeError(drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
0351                                    "Unable to fetch row"), QSqlError::ConnectionError, res));
0352         q->setAt(QSql::AfterLastRow);
0353         return false;
0354     case SQLITE_MISUSE:
0355     case SQLITE_BUSY:
0356     default:
0357         // something wrong, don't get col info, but still return false
0358         q->setLastError(qMakeError(drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
0359                                    "Unable to fetch row"), QSqlError::ConnectionError, res));
0360         sqlite3_reset(stmt);
0361         q->setAt(QSql::AfterLastRow);
0362         return false;
0363     }
0364     return false;
0365 }
0366 
0367 QSQLiteResult::QSQLiteResult(const QSQLiteDriver* db)
0368     : QSqlCachedResult(*new QSQLiteResultPrivate(this, db))
0369 {
0370     Q_D(QSQLiteResult);
0371     const_cast<QSQLiteDriverPrivate*>(d->drv_d_func())->results.append(this);
0372 }
0373 
0374 QSQLiteResult::~QSQLiteResult()
0375 {
0376     Q_D(QSQLiteResult);
0377     if (d->drv_d_func() != nullptr) {
0378         const_cast<QSQLiteDriverPrivate*>(d->drv_d_func())->results.removeOne(this);
0379     }
0380     d->cleanup();
0381 }
0382 
0383 void QSQLiteResult::virtual_hook(int id, void* data)
0384 {
0385     QSqlCachedResult::virtual_hook(id, data);
0386 }
0387 
0388 bool QSQLiteResult::reset(const QString& query)
0389 {
0390     if (!prepare(query)) {
0391         return false;
0392     }
0393     return exec();
0394 }
0395 
0396 bool QSQLiteResult::prepare(const QString& query)
0397 {
0398     Q_D(QSQLiteResult);
0399     if ((driver() == nullptr) || !driver()->isOpen() || driver()->isOpenError()) {
0400         return false;
0401     }
0402 
0403     d->cleanup();
0404 
0405     setSelect(false);
0406 
0407     const void* pzTail = nullptr;
0408 
0409 #if (SQLITE_VERSION_NUMBER >= 3003011)
0410     int res = sqlite3_prepare16_v2(d->drv_d_func()->access, query.constData(), (query.size() + 1) * sizeof(QChar),
0411                                    &d->stmt, &pzTail);
0412 #else
0413     int res = sqlite3_prepare16(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),
0414                                 &d->stmt, &pzTail);
0415 #endif
0416 
0417     if (res != SQLITE_OK) {
0418         setLastError(qMakeError(d->drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
0419                                 "Unable to execute statement"), QSqlError::StatementError, res));
0420         d->finalize();
0421         return false;
0422     }
0423     if ((pzTail != nullptr) && !QString(reinterpret_cast<const QChar*>(pzTail)).trimmed().isEmpty()) {
0424         setLastError(qMakeError(d->drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
0425                                 "Unable to execute multiple statements at a time"), QSqlError::StatementError, SQLITE_MISUSE));
0426         d->finalize();
0427         return false;
0428     }
0429     return true;
0430 }
0431 
0432 bool QSQLiteResult::exec()
0433 {
0434     Q_D(QSQLiteResult);
0435     const QVector<QVariant> values = boundValues();
0436 
0437     d->skippedStatus = false;
0438     d->skipRow = false;
0439     d->rInf.clear();
0440     clearValues();
0441     setLastError(QSqlError());
0442 
0443     int res = sqlite3_reset(d->stmt);
0444     if (res != SQLITE_OK) {
0445         setLastError(qMakeError(d->drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
0446                                 "Unable to reset statement"), QSqlError::StatementError, res));
0447         d->finalize();
0448         return false;
0449     }
0450     int paramCount = sqlite3_bind_parameter_count(d->stmt);
0451     if (paramCount == values.count()) {
0452         for (int i = 0; i < paramCount; ++i) {
0453             res = SQLITE_OK;
0454             const QVariant& value = values.at(i);
0455 
0456             if (value.isNull()) {
0457                 res = sqlite3_bind_null(d->stmt, i + 1);
0458             } else {
0459                 switch (value.type()) {
0460                 case QVariant::ByteArray: {
0461                     const auto* ba = static_cast<const QByteArray*>(value.constData());
0462                     res = sqlite3_bind_blob(d->stmt, i + 1, ba->constData(),
0463                                             ba->size(), SQLITE_STATIC);
0464                     break;
0465                 }
0466                 case QVariant::Int:
0467                 case QVariant::Bool:
0468                     res = sqlite3_bind_int(d->stmt, i + 1, value.toInt());
0469                     break;
0470                 case QVariant::Double:
0471                     res = sqlite3_bind_double(d->stmt, i + 1, value.toDouble());
0472                     break;
0473                 case QVariant::UInt:
0474                 case QVariant::LongLong:
0475                     res = sqlite3_bind_int64(d->stmt, i + 1, value.toLongLong());
0476                     break;
0477                 case QVariant::DateTime: {
0478                     const QDateTime dateTime = value.toDateTime();
0479                     const QString str = dateTime.toString(QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz"));
0480                     res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
0481                                               str.size() * sizeof(ushort), SQLITE_TRANSIENT);
0482                     break;
0483                 }
0484                 case QVariant::Time: {
0485                     const QTime time = value.toTime();
0486                     const QString str = time.toString(QStringLiteral("hh:mm:ss.zzz"));
0487                     res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
0488                                               str.size() * sizeof(ushort), SQLITE_TRANSIENT);
0489                     break;
0490                 }
0491                 case QVariant::String: {
0492                     // lifetime of string == lifetime of its qvariant
0493                     const auto* str = static_cast<const QString*>(value.constData());
0494                     res = sqlite3_bind_text16(d->stmt, i + 1, str->utf16(),
0495                                               (str->size()) * sizeof(QChar), SQLITE_STATIC);
0496                     break;
0497                 }
0498                 default: {
0499                     QString str = value.toString();
0500                     // SQLITE_TRANSIENT makes sure that sqlite buffers the data
0501                     res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
0502                                               (str.size()) * sizeof(QChar), SQLITE_TRANSIENT);
0503                     break;
0504                 }
0505                 }
0506             }
0507             if (res != SQLITE_OK) {
0508                 setLastError(qMakeError(d->drv_d_func()->access, QCoreApplication::translate("QSQLiteResult",
0509                                         "Unable to bind parameters"), QSqlError::StatementError, res));
0510                 d->finalize();
0511                 return false;
0512             }
0513         }
0514     } else {
0515         setLastError(QSqlError(QCoreApplication::translate("QSQLiteResult",
0516                                "Parameter count mismatch"), QString(), QSqlError::StatementError));
0517         return false;
0518     }
0519     d->skippedStatus = d->fetchNext(d->firstRow, 0, true);
0520     if (lastError().isValid()) {
0521         setSelect(false);
0522         setActive(false);
0523         return false;
0524     }
0525     setSelect(!d->rInf.isEmpty());
0526     setActive(true);
0527     return true;
0528 }
0529 
0530 bool QSQLiteResult::gotoNext(QSqlCachedResult::ValueCache& row, int idx)
0531 {
0532     Q_D(QSQLiteResult);
0533     return d->fetchNext(row, idx, false);
0534 }
0535 
0536 int QSQLiteResult::size()
0537 {
0538     return -1;
0539 }
0540 
0541 int QSQLiteResult::numRowsAffected()
0542 {
0543     Q_D(const QSQLiteResult);
0544     return sqlite3_changes(d->drv_d_func()->access);
0545 }
0546 
0547 QVariant QSQLiteResult::lastInsertId() const
0548 {
0549     Q_D(const QSQLiteResult);
0550     if (isActive()) {
0551         qint64 id = sqlite3_last_insert_rowid(d->drv_d_func()->access);
0552         if (id != 0) {
0553             return id;
0554         }
0555     }
0556     return QVariant();
0557 }
0558 
0559 QSqlRecord QSQLiteResult::record() const
0560 {
0561     Q_D(const QSQLiteResult);
0562     if (!isActive() || !isSelect()) {
0563         return QSqlRecord();
0564     }
0565     return d->rInf;
0566 }
0567 
0568 void QSQLiteResult::detachFromResultSet()
0569 {
0570     Q_D(QSQLiteResult);
0571     if (d->stmt != nullptr) {
0572         sqlite3_reset(d->stmt);
0573     }
0574 }
0575 
0576 QVariant QSQLiteResult::handle() const
0577 {
0578     Q_D(const QSQLiteResult);
0579     return QVariant::fromValue(d->stmt);
0580 }
0581 
0582 /////////////////////////////////////////////////////////
0583 
0584 QSQLiteDriver::QSQLiteDriver(QObject* parent)
0585     : QSqlDriver(*new QSQLiteDriverPrivate, parent)
0586 {
0587 }
0588 
0589 QSQLiteDriver::QSQLiteDriver(sqlite3* connection, QObject* parent)
0590     : QSqlDriver(*new QSQLiteDriverPrivate, parent)
0591 {
0592     Q_D(QSQLiteDriver);
0593     d->access = connection;
0594     setOpen(true);
0595     setOpenError(false);
0596 }
0597 
0598 
0599 QSQLiteDriver::~QSQLiteDriver()
0600     = default;
0601 
0602 bool QSQLiteDriver::hasFeature(DriverFeature f) const
0603 {
0604     switch (f) {
0605     case BLOB:
0606     case Transactions:
0607     case Unicode:
0608     case LastInsertId:
0609     case PreparedQueries:
0610     case PositionalPlaceholders:
0611     case SimpleLocking:
0612     case FinishQuery:
0613     case LowPrecisionNumbers:
0614         return true;
0615     case QuerySize:
0616     case NamedPlaceholders:
0617     case BatchOperations:
0618     case EventNotifications:
0619     case MultipleResultSets:
0620     case CancelQuery:
0621         return false;
0622     }
0623     return false;
0624 }
0625 
0626 /*
0627    SQLite dbs have no user name, passwords, hosts or ports.
0628    just file names.
0629 */
0630 bool QSQLiteDriver::open(const QString& db, const QString& /*user*/, const QString& /*password*/, const QString& /*host*/, int /*port*/, const QString& conOpts)
0631 {
0632     Q_D(QSQLiteDriver);
0633     if (isOpen()) {
0634         close();
0635     }
0636 
0637 
0638     int timeOut = 5000;
0639     bool sharedCache = false;
0640     bool openReadOnlyOption = false;
0641     bool openUriOption = false;
0642 
0643     const auto opts = conOpts.splitRef(QLatin1Char(';'));
0644     for (auto option : opts) {
0645         option = option.trimmed();
0646         if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT"))) {
0647             option = option.mid(20).trimmed();
0648             if (option.startsWith(QLatin1Char('='))) {
0649                 bool ok;
0650                 const int nt = option.mid(1).trimmed().toInt(&ok);
0651                 if (ok) {
0652                     timeOut = nt;
0653                 }
0654             }
0655         } else if (option == QLatin1String("QSQLITE_OPEN_READONLY")) {
0656             openReadOnlyOption = true;
0657         } else if (option == QLatin1String("QSQLITE_OPEN_URI")) {
0658             openUriOption = true;
0659         } else if (option == QLatin1String("QSQLITE_ENABLE_SHARED_CACHE")) {
0660             sharedCache = true;
0661         }
0662     }
0663 
0664     int openMode = (openReadOnlyOption ? SQLITE_OPEN_READONLY : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE));
0665     if (openUriOption) {
0666         openMode |= SQLITE_OPEN_URI;
0667     }
0668 
0669     sqlite3_enable_shared_cache(static_cast<int>(sharedCache));
0670 
0671     if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, nullptr) == SQLITE_OK) {
0672         sqlite3_busy_timeout(d->access, timeOut);
0673         setOpen(true);
0674         setOpenError(false);
0675         return true;
0676     }
0677     if (d->access != nullptr) {
0678         sqlite3_close(d->access);
0679         d->access = nullptr;
0680     }
0681 
0682     setLastError(qMakeError(d->access, tr("Error opening database"),
0683                             QSqlError::ConnectionError));
0684     setOpenError(true);
0685     return false;
0686 
0687 }
0688 
0689 void QSQLiteDriver::close()
0690 {
0691     Q_D(QSQLiteDriver);
0692     if (isOpen()) {
0693         for (QSQLiteResult* result : qAsConst(d->results)) {
0694             result->d_func()->finalize();
0695         }
0696 
0697         if (sqlite3_close(d->access) != SQLITE_OK) {
0698             setLastError(qMakeError(d->access, tr("Error closing database"),
0699                                     QSqlError::ConnectionError));
0700         }
0701         d->access = nullptr;
0702         setOpen(false);
0703         setOpenError(false);
0704     }
0705 }
0706 
0707 QSqlResult* QSQLiteDriver::createResult() const
0708 {
0709     return new QSQLiteResult(this);
0710 }
0711 
0712 bool QSQLiteDriver::beginTransaction()
0713 {
0714     if (!isOpen() || isOpenError()) {
0715         return false;
0716     }
0717 
0718     QSqlQuery q(createResult());
0719     if (!q.exec(QStringLiteral("BEGIN"))) {
0720         setLastError(QSqlError(tr("Unable to begin transaction"),
0721                                q.lastError().databaseText(), QSqlError::TransactionError));
0722         return false;
0723     }
0724 
0725     return true;
0726 }
0727 
0728 bool QSQLiteDriver::commitTransaction()
0729 {
0730     if (!isOpen() || isOpenError()) {
0731         return false;
0732     }
0733 
0734     QSqlQuery q(createResult());
0735     if (!q.exec(QStringLiteral("COMMIT"))) {
0736         setLastError(QSqlError(tr("Unable to commit transaction"),
0737                                q.lastError().databaseText(), QSqlError::TransactionError));
0738         return false;
0739     }
0740 
0741     return true;
0742 }
0743 
0744 bool QSQLiteDriver::rollbackTransaction()
0745 {
0746     if (!isOpen() || isOpenError()) {
0747         return false;
0748     }
0749 
0750     QSqlQuery q(createResult());
0751     if (!q.exec(QStringLiteral("ROLLBACK"))) {
0752         setLastError(QSqlError(tr("Unable to rollback transaction"),
0753                                q.lastError().databaseText(), QSqlError::TransactionError));
0754         return false;
0755     }
0756 
0757     return true;
0758 }
0759 
0760 QStringList QSQLiteDriver::tables(QSql::TableType type) const
0761 {
0762     QStringList res;
0763     if (!isOpen()) {
0764         return res;
0765     }
0766 
0767     QSqlQuery q(createResult());
0768     q.setForwardOnly(true);
0769 
0770     QString sql = QStringLiteral("SELECT name FROM sqlite_master WHERE %1 "
0771                                  "UNION ALL SELECT name FROM sqlite_temp_master WHERE %1");
0772     if (((type & QSql::Tables) != 0) && ((type & QSql::Views) != 0)) {
0773         sql = sql.arg(QStringLiteral("type='table' OR type='view'"));
0774     } else if ((type & QSql::Tables) != 0) {
0775         sql = sql.arg(QStringLiteral("type='table'"));
0776     } else if ((type & QSql::Views) != 0) {
0777         sql = sql.arg(QStringLiteral("type='view'"));
0778     } else {
0779         sql.clear();
0780     }
0781 
0782     if (!sql.isEmpty() && q.exec(sql)) {
0783         while (q.next()) {
0784             res.append(q.value(0).toString());
0785         }
0786     }
0787 
0788     if ((type & QSql::SystemTables) != 0) {
0789         // there are no internal tables beside this one:
0790         res.append(QStringLiteral("sqlite_master"));
0791     }
0792 
0793     return res;
0794 }
0795 
0796 static QSqlIndex qGetTableInfo(QSqlQuery& q, const QString& tableName, bool onlyPIndex = false)
0797 {
0798     QString schema;
0799     QString table(tableName);
0800     int indexOfSeparator = tableName.indexOf(QLatin1Char('.'));
0801     if (indexOfSeparator > -1) {
0802         schema = tableName.left(indexOfSeparator).append(QLatin1Char('.'));
0803         table = tableName.mid(indexOfSeparator + 1);
0804     }
0805     q.exec(QLatin1String("PRAGMA ") + schema + QLatin1String("table_info (") + _q_escapeIdentifier(table) + QLatin1Char(')'));
0806 
0807     QSqlIndex ind;
0808     while (q.next()) {
0809         bool isPk = q.value(5).toInt() != 0;
0810         if (onlyPIndex && !isPk) {
0811             continue;
0812         }
0813         QString typeName = q.value(2).toString().toLower();
0814         QSqlField fld(q.value(1).toString(), qGetColumnType(typeName));
0815         if (isPk && (typeName == QLatin1String("integer")))
0816             // INTEGER PRIMARY KEY fields are auto-generated in sqlite
0817             // INT PRIMARY KEY is not the same as INTEGER PRIMARY KEY!
0818         {
0819             fld.setAutoValue(true);
0820         }
0821         fld.setRequired(q.value(3).toInt() != 0);
0822         fld.setDefaultValue(q.value(4));
0823         ind.append(fld);
0824     }
0825     return ind;
0826 }
0827 
0828 QSqlIndex QSQLiteDriver::primaryIndex(const QString& tblname) const
0829 {
0830     if (!isOpen()) {
0831         return QSqlIndex();
0832     }
0833 
0834     QString table = tblname;
0835     if (isIdentifierEscaped(table, QSqlDriver::TableName)) {
0836         table = stripDelimiters(table, QSqlDriver::TableName);
0837     }
0838 
0839     QSqlQuery q(createResult());
0840     q.setForwardOnly(true);
0841     return qGetTableInfo(q, table, true);
0842 }
0843 
0844 QSqlRecord QSQLiteDriver::record(const QString& tbl) const
0845 {
0846     if (!isOpen()) {
0847         return QSqlRecord();
0848     }
0849 
0850     QString table = tbl;
0851     if (isIdentifierEscaped(table, QSqlDriver::TableName)) {
0852         table = stripDelimiters(table, QSqlDriver::TableName);
0853     }
0854 
0855     QSqlQuery q(createResult());
0856     q.setForwardOnly(true);
0857     return qGetTableInfo(q, table);
0858 }
0859 
0860 QVariant QSQLiteDriver::handle() const
0861 {
0862     Q_D(const QSQLiteDriver);
0863     return QVariant::fromValue(d->access);
0864 }
0865 
0866 QString QSQLiteDriver::escapeIdentifier(const QString& identifier, IdentifierType type) const
0867 {
0868     Q_UNUSED(type)
0869     return _q_escapeIdentifier(identifier);
0870 }
0871 
0872 QT_END_NAMESPACE