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