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