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