QSqlTableModel insertRecord() returns true but nothing is saved in database



  • I have two SSDs each with a 2GB partition containing a Debian Wheezy squashfs with Qt 4.8.2. The rest of the drive space are a RAID 1 with ext4. On boot up I launch 2 X screens. On the left screen one Qt application (say App1) is launched that connects to 2 databases, one of which is shared with another application (say App2) launched on the right X screen. Each Qt application has a database viewer built in (the shared database is only viewable in App2.

    On a separate computer these drives are wiped clean (squashfs removed, data on raid removed) and initialized with a new squashfs and new data on the raid.

    My problem is as follows:
    After inital boot up (1st boot after initialization mentioned above) App1 is launched. App1 saves stuff to it's database followed by saving a png file in the same directory as the database. Then it saves the same thing to the database shared with App2 with the png file in the same directory. App2 is then launched and the you can see that its shared database holds the same info as the App1 database.

    Now, close App2. App1 saves more stuff to it's database followed by a png file. Then it saves the exact same thing to the shared database with App2. Reopen App2. None of this new stuff is saved in App2's shared database except that the png files saved.

    The QSqlTableModel insertRecord() returns true even though nothing was saved in the shared database. QSqlTableModel lastError() prints out as QSqlError(-1, "", "" ). This only happens on the first initial boot. Doing the following make no difference either:
    @
    myDatabase = new QSqlDatabase();
    myDatabase->setConnectOptions("QSQLITE_ENABLE_SHARED_CACHE");
    @

    Code in question is as follows:

    @
    bool MyStuffDb::addStuff(const MyObject& myobject, QSqlRecord* record, QSqlTableModel* table)
    {
    record->setValue("id", myobject.id);
    record->setValue("timestamp", myobject.timestamp.toString(SQLITE_DATE_FORMAT));
    record->setValue("width", myobject.width);
    record->setValue("height", myobject.height);

    if (!table->insertRecord(-1, *record))
    {
        qCritical() << Q_FUNC_INFO << "mTable.insertRecord:" << table->lastError();
        return false;
    }
    
    // Save QImage
    myobject.snippet.save(getPathToSnippet(target.id), "PNG");
    
    return true;
    

    }
    @


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    The first thing that strikes is that you are not preparing your database following the recommended way:

    @
    QSqlDatabase db = QSqlDataBase::addDatabase("QSQLITE");
    db.setconnectionOptions("QSQLITE_ENABLE_SHARED_CACHE");
    @

    Out of curiosity, why pass QSqlRecord as pointer ?



  • Actually, I do that. Just didn't copy that part over.

    @
    bool MyStuffDb::open(const QString& path)
    {
    mPath = path;

    //create connection to database
    myDatabase = new QSqlDatabase();
    *myDatabase = QSqlDatabase::addDatabase( "QSQLITE", mConnectionName );
    myDatabase->setDatabaseName( path + "/myDatabase.db" );
    myDatabase->setConnectOptions("QSQLITE_ENABLE_SHARED_CACHE");
    
    if( !myDatabase->open() )
    {
        qCritical() << Q_FUNC_INFO << "myDatabase->open:" << myDatabase->lastError();
        return false;
    }
    
    return true;
    

    }
    @

    As for using QSqlRecord being passed as pointer, that's just how the original guy wrote it (I think he liked to pass as pointer if he modified it and by reference if he didn't).


  • Lifetime Qt Champion

    Then you have a memory leak since you overwrite myDataBase right after you created it. There's no need for a pointer here.

    Also, how is the QSqlRecord created ?



  • Fixed the memory leak, but didn't make a difference. QSqlRecord comes from:

    @
    bool MyStuffDb::addStuff(const MyObject& myobject)
    {
    QSqlTableModel table(NULL, myDatabase);
    table.setTable("myobjects");
    QSqlRecord record = myDatabase.record("myobjects");

    // Call to code in first post
    return addStuff(myobject, &record, &table);
    

    }
    @


  • Lifetime Qt Champion

    Did you check what edit strategy is used for the model ? If it's OnManualSubmit then you have to submit your changes



  • I've checked that and tried them all without success. After calling insertRecord() I can see the row was inserted in memory but just not saved to disk, ever. Is there anyway to flush it to disk?

    I even switched over to QSqlQuery instead of using QSqlRecord and QSqlTableModel and had the same result. Could this be a linux issue somehow? As I mentioned before I only see this behavior on the first boot off a drive. Works like a charm after that.


  • Lifetime Qt Champion

    And if you remove the QSQLITE_ENABLE_SHARED_CACHE option ?



  • Problem exists with or without that option.


  • Lifetime Qt Champion

    Can you create a minimal compilable example that shows this behavior ?



  • I will try and put one together. Been super busy with other things that need done asap.



  • What's the best way to post this? Can't add attachments and it's a lot of code to post in a reply.


  • Lifetime Qt Champion

    You can use e.g. "pastebin":http://pastebin.com



  • In that case check "here":https://gist.github.com/snow45/61cea39423b79c61e10f

    Remember I only see this behavior with the setup initially described.



  • I found the problem. I used the command lsattr to look at file attributes on my database files and found that when I opened App 2 for the first time I was deleting the shared database out from under App 1 and recreating it. Just had to fix that and everything works like I would expect.


  • Lifetime Qt Champion

    Out of curiosity, how was it doing it ?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.