|
Rex Dieter |
fcd69d |
diff --git a/qsqlite/src/qsql_sqlite.cpp b/qsqlite/src/qsql_sqlite.cpp
|
|
Rex Dieter |
fcd69d |
index c1e9508..5da232f 100644
|
|
Rex Dieter |
fcd69d |
--- a/qsqlite/src/qsql_sqlite.cpp
|
|
Rex Dieter |
fcd69d |
+++ b/qsqlite/src/qsql_sqlite.cpp
|
|
Rex Dieter |
fcd69d |
@@ -528,7 +528,7 @@ static int qGetSqliteOpenMode(QString opts)
|
|
Rex Dieter |
fcd69d |
return SQLITE_OPEN_READONLY;
|
|
Rex Dieter |
fcd69d |
}
|
|
Rex Dieter |
fcd69d |
// The SQLITE_OPEN_NOMUTEX flag causes the database connection to be in the multi-thread mode
|
|
Rex Dieter |
fcd69d |
- return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX;
|
|
Rex Dieter |
fcd69d |
+ return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE;
|
|
Rex Dieter |
fcd69d |
}
|
|
Rex Dieter |
fcd69d |
|
|
Rex Dieter |
fcd69d |
/*
|
|
Rex Dieter |
fcd69d |
@@ -543,8 +543,10 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c
|
|
Rex Dieter |
fcd69d |
if (db.isEmpty())
|
|
Rex Dieter |
fcd69d |
return false;
|
|
Rex Dieter |
fcd69d |
|
|
Rex Dieter |
fcd69d |
+ sqlite3_enable_shared_cache(1);
|
|
Rex Dieter |
fcd69d |
if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, qGetSqliteOpenMode(conOpts), NULL) == SQLITE_OK) {
|
|
Rex Dieter |
fcd69d |
sqlite3_busy_timeout(d->access, qGetSqliteTimeout(conOpts));
|
|
Rex Dieter |
fcd69d |
+ sqlite3_extended_result_codes(d->access, 1);
|
|
Rex Dieter |
fcd69d |
setOpen(true);
|
|
Rex Dieter |
fcd69d |
setOpenError(false);
|
|
Rex Dieter |
fcd69d |
return true;
|
|
Rex Dieter |
fcd69d |
diff --git a/qsqlite/src/sqlite_blocking.cpp b/qsqlite/src/sqlite_blocking.cpp
|
|
Rex Dieter |
fcd69d |
index c0fe3f2..180685c 100644
|
|
Rex Dieter |
fcd69d |
--- a/qsqlite/src/sqlite_blocking.cpp
|
|
Rex Dieter |
fcd69d |
+++ b/qsqlite/src/sqlite_blocking.cpp
|
|
Rex Dieter |
fcd69d |
@@ -1,63 +1,94 @@
|
|
Rex Dieter |
fcd69d |
+/*
|
|
Rex Dieter |
fcd69d |
+ Copyright (c) 2009 Bertjan Broeksema <broeksema@kde.org>
|
|
Rex Dieter |
fcd69d |
+ Copyright (c) 2014 Daniel Vrátil <dvratil@redhat.com>
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+ This library is free software; you can redistribute it and/or modify it
|
|
Rex Dieter |
fcd69d |
+ under the terms of the GNU Library General Public License as published by
|
|
Rex Dieter |
fcd69d |
+ the Free Software Foundation; either version 2 of the License, or (at your
|
|
Rex Dieter |
fcd69d |
+ option) any later version.
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+ This library is distributed in the hope that it will be useful, but WITHOUT
|
|
Rex Dieter |
fcd69d |
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Rex Dieter |
fcd69d |
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
|
Rex Dieter |
fcd69d |
+ License for more details.
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+ You should have received a copy of the GNU Library General Public License
|
|
Rex Dieter |
fcd69d |
+ along with this library; see the file COPYING.LIB. If not, write to the
|
|
Rex Dieter |
fcd69d |
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Rex Dieter |
fcd69d |
+ 02110-1301, USA.
|
|
Rex Dieter |
fcd69d |
+*/
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
#include "sqlite_blocking.h"
|
|
Rex Dieter |
fcd69d |
|
|
Rex Dieter |
fcd69d |
#include <sqlite3.h>
|
|
Rex Dieter |
fcd69d |
-#ifndef _WIN32
|
|
Rex Dieter |
fcd69d |
-#include <unistd.h>
|
|
Rex Dieter |
fcd69d |
-#else
|
|
Rex Dieter |
fcd69d |
-#include <Windows.h>
|
|
Rex Dieter |
fcd69d |
-#define usleep(x) Sleep(x/1000)
|
|
Rex Dieter |
fcd69d |
-#endif
|
|
Rex Dieter |
fcd69d |
-
|
|
Rex Dieter |
fcd69d |
-#include "qdebug.h"
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+#include <QMutex>
|
|
Rex Dieter |
fcd69d |
+#include <QWaitCondition>
|
|
Rex Dieter |
fcd69d |
#include "qstringbuilder.h"
|
|
Rex Dieter |
fcd69d |
#include "qthread.h"
|
|
Rex Dieter |
fcd69d |
+#include <QDateTime>
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+/* Based on example in http://www.sqlite.org/unlock_notify.html */
|
|
Rex Dieter |
fcd69d |
|
|
Rex Dieter |
fcd69d |
-QString debugString()
|
|
Rex Dieter |
fcd69d |
+struct UnlockNotification {
|
|
Rex Dieter |
fcd69d |
+ bool fired;
|
|
Rex Dieter |
fcd69d |
+ QWaitCondition cond;
|
|
Rex Dieter |
fcd69d |
+ QMutex mutex;
|
|
Rex Dieter |
fcd69d |
+};
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+static void qSqlite3UnlockNotifyCb(void **apArg, int nArg)
|
|
Rex Dieter |
fcd69d |
{
|
|
Rex Dieter |
fcd69d |
- return QString( QLatin1Literal("[QSQLITE3: ") + QString::number( quint64( QThread::currentThreadId() ) ) + QLatin1Literal("] ") );
|
|
Rex Dieter |
fcd69d |
+ for (int i = 0; i < nArg; ++i) {
|
|
Rex Dieter |
fcd69d |
+ UnlockNotification *ntf = static_cast<UnlockNotification*>(apArg[i]);
|
|
Rex Dieter |
fcd69d |
+ ntf->mutex.lock();
|
|
Rex Dieter |
fcd69d |
+ ntf->fired = true;
|
|
Rex Dieter |
fcd69d |
+ ntf->cond.wakeOne();
|
|
Rex Dieter |
fcd69d |
+ ntf->mutex.unlock();
|
|
Rex Dieter |
fcd69d |
+ }
|
|
Rex Dieter |
fcd69d |
}
|
|
Rex Dieter |
fcd69d |
|
|
Rex Dieter |
fcd69d |
-int sqlite3_blocking_step( sqlite3_stmt *pStmt )
|
|
Rex Dieter |
fcd69d |
+static int qSqlite3WaitForUnlockNotify(sqlite3 *db)
|
|
Rex Dieter |
fcd69d |
{
|
|
Rex Dieter |
fcd69d |
- // NOTE: The example at http://www.sqlite.org/unlock_notify.html says to wait
|
|
Rex Dieter |
fcd69d |
- // for SQLITE_LOCK but for some reason I don't understand I get
|
|
Rex Dieter |
fcd69d |
- // SQLITE_BUSY.
|
|
Rex Dieter |
fcd69d |
- int rc = sqlite3_step( pStmt );
|
|
Rex Dieter |
fcd69d |
-
|
|
Rex Dieter |
fcd69d |
- QThread::currentThreadId();
|
|
Rex Dieter |
fcd69d |
- if ( rc == SQLITE_BUSY )
|
|
Rex Dieter |
fcd69d |
- qDebug() << debugString() << "sqlite3_blocking_step: Entering while loop";
|
|
Rex Dieter |
fcd69d |
-
|
|
Rex Dieter |
fcd69d |
- while( rc == SQLITE_BUSY ) {
|
|
Rex Dieter |
fcd69d |
- usleep(5000);
|
|
Rex Dieter |
fcd69d |
- sqlite3_reset( pStmt );
|
|
Rex Dieter |
fcd69d |
- rc = sqlite3_step( pStmt );
|
|
Rex Dieter |
fcd69d |
-
|
|
Rex Dieter |
fcd69d |
- if ( rc != SQLITE_BUSY ) {
|
|
Rex Dieter |
fcd69d |
- qDebug() << debugString() << "sqlite3_blocking_step: Leaving while loop";
|
|
Rex Dieter |
fcd69d |
+ int rc;
|
|
Rex Dieter |
fcd69d |
+ UnlockNotification un;
|
|
Rex Dieter |
fcd69d |
+ un.fired = false;
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+ rc = sqlite3_unlock_notify(db, qSqlite3UnlockNotifyCb, (void *)&un;;
|
|
Rex Dieter |
fcd69d |
+ Q_ASSERT(rc == SQLITE_LOCKED || rc == SQLITE_OK);
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+ if (rc == SQLITE_OK) {
|
|
Rex Dieter |
fcd69d |
+ un.mutex.lock();
|
|
Rex Dieter |
fcd69d |
+ if (!un.fired) {
|
|
Rex Dieter |
fcd69d |
+ un.cond.wait(&un.mutex);
|
|
Rex Dieter |
fcd69d |
}
|
|
Rex Dieter |
fcd69d |
+ un.mutex.unlock();
|
|
Rex Dieter |
fcd69d |
}
|
|
Rex Dieter |
fcd69d |
|
|
Rex Dieter |
fcd69d |
return rc;
|
|
Rex Dieter |
fcd69d |
}
|
|
Rex Dieter |
fcd69d |
|
|
Rex Dieter |
fcd69d |
-int sqlite3_blocking_prepare16_v2( sqlite3 *db, /* Database handle. */
|
|
Rex Dieter |
fcd69d |
- const void *zSql, /* SQL statement, UTF-16 encoded */
|
|
Rex Dieter |
fcd69d |
- int nSql, /* Length of zSql in bytes. */
|
|
Rex Dieter |
fcd69d |
- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
|
|
Rex Dieter |
fcd69d |
- const void **pzTail /* OUT: Pointer to unused portion of zSql */ )
|
|
Rex Dieter |
fcd69d |
+int sqlite3_blocking_step(sqlite3_stmt *pStmt)
|
|
Rex Dieter |
fcd69d |
{
|
|
Rex Dieter |
fcd69d |
- int rc = sqlite3_prepare16_v2( db, zSql, nSql, ppStmt, pzTail );
|
|
Rex Dieter |
fcd69d |
-
|
|
Rex Dieter |
fcd69d |
- if ( rc == SQLITE_BUSY )
|
|
Rex Dieter |
fcd69d |
- qDebug() << debugString() << "sqlite3_blocking_prepare16_v2: Entering while loop";
|
|
Rex Dieter |
fcd69d |
+ int rc;
|
|
Rex Dieter |
fcd69d |
+ while (SQLITE_LOCKED_SHAREDCACHE == (rc = sqlite3_step(pStmt))) {
|
|
Rex Dieter |
fcd69d |
+ rc = qSqlite3WaitForUnlockNotify(sqlite3_db_handle(pStmt));
|
|
Rex Dieter |
fcd69d |
+ if (rc != SQLITE_OK) {
|
|
Rex Dieter |
fcd69d |
+ break;
|
|
Rex Dieter |
fcd69d |
+ }
|
|
Rex Dieter |
fcd69d |
+ sqlite3_reset(pStmt);
|
|
Rex Dieter |
fcd69d |
+ }
|
|
Rex Dieter |
fcd69d |
|
|
Rex Dieter |
fcd69d |
- while( rc == SQLITE_BUSY ) {
|
|
Rex Dieter |
fcd69d |
- usleep(500000);
|
|
Rex Dieter |
fcd69d |
- rc = sqlite3_prepare16_v2( db, zSql, nSql, ppStmt, pzTail );
|
|
Rex Dieter |
fcd69d |
+ return rc;
|
|
Rex Dieter |
fcd69d |
+}
|
|
Rex Dieter |
fcd69d |
|
|
Rex Dieter |
fcd69d |
- if ( rc != SQLITE_BUSY ) {
|
|
Rex Dieter |
fcd69d |
- qDebug() << debugString() << "sqlite3_prepare16_v2: Leaving while loop";
|
|
Rex Dieter |
fcd69d |
+int sqlite3_blocking_prepare16_v2(sqlite3 *db, const void *zSql, int nSql,
|
|
Rex Dieter |
fcd69d |
+ sqlite3_stmt **ppStmt, const void **pzTail)
|
|
Rex Dieter |
fcd69d |
+{
|
|
Rex Dieter |
fcd69d |
+ int rc;
|
|
Rex Dieter |
fcd69d |
+ while (SQLITE_LOCKED_SHAREDCACHE == (rc = sqlite3_prepare16_v2(db, zSql, nSql, ppStmt, pzTail))) {
|
|
Rex Dieter |
fcd69d |
+ rc = qSqlite3WaitForUnlockNotify(db);
|
|
Rex Dieter |
fcd69d |
+ if (rc != SQLITE_OK) {
|
|
Rex Dieter |
fcd69d |
+ break;
|
|
Rex Dieter |
fcd69d |
}
|
|
Rex Dieter |
fcd69d |
}
|
|
Rex Dieter |
fcd69d |
|
|
Rex Dieter |
fcd69d |
diff --git a/qsqlite/src/sqlite_blocking.h b/qsqlite/src/sqlite_blocking.h
|
|
Rex Dieter |
fcd69d |
index 0d6f6a0..9f13946 100644
|
|
Rex Dieter |
fcd69d |
--- a/qsqlite/src/sqlite_blocking.h
|
|
Rex Dieter |
fcd69d |
+++ b/qsqlite/src/sqlite_blocking.h
|
|
Rex Dieter |
fcd69d |
@@ -1,3 +1,22 @@
|
|
Rex Dieter |
fcd69d |
+/*
|
|
Rex Dieter |
fcd69d |
+ Copyright (c) 2009 Bertjan Broeksema <broeksema@kde.org>
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+ This library is free software; you can redistribute it and/or modify it
|
|
Rex Dieter |
fcd69d |
+ under the terms of the GNU Library General Public License as published by
|
|
Rex Dieter |
fcd69d |
+ the Free Software Foundation; either version 2 of the License, or (at your
|
|
Rex Dieter |
fcd69d |
+ option) any later version.
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+ This library is distributed in the hope that it will be useful, but WITHOUT
|
|
Rex Dieter |
fcd69d |
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Rex Dieter |
fcd69d |
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
|
Rex Dieter |
fcd69d |
+ License for more details.
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
+ You should have received a copy of the GNU Library General Public License
|
|
Rex Dieter |
fcd69d |
+ along with this library; see the file COPYING.LIB. If not, write to the
|
|
Rex Dieter |
fcd69d |
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Rex Dieter |
fcd69d |
+ 02110-1301, USA.
|
|
Rex Dieter |
fcd69d |
+*/
|
|
Rex Dieter |
fcd69d |
+
|
|
Rex Dieter |
fcd69d |
#ifndef SQLITE_BLOCKING_H
|
|
Rex Dieter |
fcd69d |
#define SQLITE_BLOCKING_H
|