File indexing completed on 2025-01-12 04:38:55
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