Results 1 to 9 of 9

Thread: Does QDataWidgetMapper lock sqlite and prevent write by other applications?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Dec 2009
    Posts
    47
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android
    Thanks
    11
    Thanked 1 Time in 1 Post

    Default QSqlTableModel locks sqlite and prevents write by other applications

    Hi all

    It seems QSqlTableModel in some cases blocks SQLite databases, i.e., prevents write access by another process. When running the application below, the database given in the header of the QMessageBox is locked after the QMessageBox shows up. To try it, open a terminal window and type
    • sqlite3 </path/to/database> "UPDATE main SET colorcode=1 WHERE id=5;"

    If DBSIZE in the test application source code is sufficiently high (266 in my case, but could be different on other machines or operating systems), then I get "Error: database is locked".

    Once the QMessageBox has been closed, the database is open for write-access. And at that point, the database can be opened by several sqlite3 instances in parallel without blocking write-access. Thus, it is not a bug in sqlite but apparently a bug in Qt.

    Is anyone aware of a work-around? My application crucially depends on the database being accessible while my application runs.

    Best

    Al_

    PS: I have now reported this as bug, see https://bugreports.qt-project.org/browse/QTBUG-37348

    Test application (the .pro project file needs to include "QT += core widgets sql"):
    Qt Code:
    1. #include <QApplication>
    2. #include <QSqlDatabase>
    3. #include <QSqlTableModel>
    4. #include <QSqlQuery>
    5. #include <QSqlError>
    6. #include <QTemporaryFile>
    7. #include <QMessageBox>
    8. #include <QDebug>
    9.  
    10. #define DBSIZE 266
    11.  
    12. int main(int argc, char* argv[]){
    13. QApplication a(argc, argv);
    14. // create a database file in the temporary directory
    15. QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"));
    16. dbFile->setAutoRemove(false);
    17. bool ok = dbFile->open();
    18. Q_ASSERT(ok);
    19. db.setDatabaseName(dbFile->fileName());
    20. qDebug() << dbFile->fileName();
    21. dbFile->close();
    22. delete dbFile;
    23. ok = db.open();
    24. Q_ASSERT(ok);
    25. // create table 'main' in the database
    26. QSqlQuery query(db);
    27. ok = query.exec(QStringLiteral("CREATE TABLE main(id INTEGER PRIMARY KEY, colorcode INTEGER)"));
    28. Q_ASSERT(ok);
    29. // fill table 'main' with records
    30. ok = query.prepare(QStringLiteral("INSERT INTO main VALUES(:id, 0)"));
    31. Q_ASSERT(ok);
    32. for (int i(0); i < DBSIZE; ++i) {
    33. qDebug() << i;
    34. query.bindValue(0, i);
    35. query.exec();
    36. Q_ASSERT_X(ok, query.lastQuery().toLatin1(), query.lastError().text().toLatin1());}
    37. // use table 'main' in a QSqlTableModel; QSqlTableModel::select() will block the database
    38. QSqlTableModel* model = new QSqlTableModel(0, db);
    39. model->setTable(QStringLiteral("main"));
    40. ok = model->select();
    41. Q_ASSERT(ok);
    42. // show the filename of the database to the user
    43. QMessageBox::warning(0, db.databaseName(), QStringLiteral("With sufficiently high DBSIZE, the above database is now erroneously locked. On my Ubuntu machine, DBSIZE 266 is sufficient."));
    44. return 0;}
    To copy to clipboard, switch view to plain text mode 
    Last edited by Al_; 8th March 2014 at 14:44. Reason: updated contents

  2. #2
    Join Date
    Dec 2009
    Posts
    47
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android
    Thanks
    11
    Thanked 1 Time in 1 Post

    Default Re: QSqlTableModel locks sqlite and prevents write by other applications

    Hi all

    I found a work-around: prefetch the entire table. Obviously, this is only feasible for small database tables (small compared to available memory).

    Add the following statement after select()'ing the model (i.e., after line 42 in my example)
    Qt Code:
    1. while (model->canFetchMore()) model->fetchMore();
    To copy to clipboard, switch view to plain text mode 

  3. #3
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts

    Default Re: QSqlTableModel locks sqlite and prevents write by other applications

    Another option would be to implement your own QAbstractTableModel subclass and use QSqlQuery internally.

    Since you know which database you are using, this model might even use database specific features, e.g. paging.

    Cheers,
    _

Similar Threads

  1. Replies: 1
    Last Post: 25th April 2013, 14:55
  2. Replies: 2
    Last Post: 14th November 2011, 11:24
  3. sqlite read lock.
    By gilgm in forum Qt Programming
    Replies: 6
    Last Post: 18th June 2010, 05:58
  4. sqlite write security
    By lesat in forum Qt Programming
    Replies: 0
    Last Post: 28th April 2010, 05:05
  5. SQLite + journal + lock
    By NoRulez in forum Qt Programming
    Replies: 4
    Last Post: 14th December 2009, 08:25

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.