When or how to use fetchMore() on QSqlTableModel with a SQLite database for rowCount() to work?

别来无恙 提交于 2019-12-04 09:59:37

From my experience, Qt's SQLite driver inserts rows into the model in steps of 256 rows. At the end of data fetching QSqlTableModel::rowCount() will return correct value, there is no need to call fetchMore(). It just depends where and when you are calling rowCount().

For example, if user is doing some calculations on rowsInserted() signal, his slot method will be called multiple times, and every time index of last row will be incremented for up to value of 256.

So, you need to use rowCount() in the end of data fetching (in some overridden QSqlTableModel methods, fetching is often not finished), or to not rely on intermediate row count value and to repeat calculations every time it changes.

This is a general answer, because you didn't post any code where we can see what are you exactly trying to do, but you can see where I am pointing to.

EDIT:

After QSqlTableModel::submitAll() call, model is repopulated and that is the reason why fetchMore() is needed to repeat again. Where to call fetchMore() depends on the use case. It could be called after the submitAll() or in some slot, there is no a general answer here. I would probably try to use dataChanged signal. However, the goal of fetching data always should be primary to display it in the view, and view does it on its own most of the cases.

In one of my applications, I was relying on a table view to fetch data for me. After setting model to table view, I either call QTableView::scrollToBottom() which fetches data for me (user should see latest data on the bottom anyway in my case, row count has a correct value after the scroll) or do calculations in rowsInserted() slot when user scrolls table, and data is again fetched automatically in steps of 256 rows.

And it is very important to know, if application needs to show somewhere number of rows in the table, or e.g. summary value of one column data, it is often much more efficient to use additional QSqlQuery to fetch additional information (like: select count(*) from xyz) then to read data from large table model. Table models are primary intended for providing data to table view.

The current answer does not fully answer the question (mentions dataChanged() signal but not the other signals), so I'm writing my own answer.

It's been a while and I believe I have covered all cases: I ended up connecting a slot that calls fetchMore() to the relevant signals AND asserting that everything has been fetched in my DataTable::rowCount() method: assert(!sql_model->canFetchMore())

(Of course rowCount() is a const method, so I couldn't fetch if nothing has been fetched yet, but that wouldn't be the job a getter anyway; the assertion is fine because canFetchMore() is also const.)

Signals: dataChanged(const QModelIndex&, const QModelIndex&), rowsInserted(const QModelIndex&, int, int), rowsRemoved(const QModelIndex&, int, int) and layoutChanged()

I'm using the assertion to make sure my model receives the correct row count or else the application would crash (which happens if not all of the mentioned signals are connected, for example layoutChanged()). This is important in my case, as an incorrect row count might lead to data loss in my case.

So far, the assertion hasn't failed, so I'm assuming this solves it.

RicoRicochet

The dilemma you were facing was similar to what I encountered recently. I wrote a QT gui program which did the following--

i. Connect to and Query an Oracle Database ii. Show the query result in a QTableView iii. export the result of QTableView to a .csv file iv. import the .csv file to a loacl sqlite3 database v. Connect to and query the local sqlite3 database vi. perform query and show result in another QTableview

During Step ii., (i.e. export the result to .csv) what I observed was that although 543 records were getting generated on the QTableView, only 256 odd were getting exported to the .csv file.

I was using,

int rows=model->rowCount();
int columns=model->columnCount();

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < columns; j++)
        {
            textData += model->data(model->index(i,j)).toString();
            textData += ", ";      // for .csv file format
        }
        textData += "\n";             // (optional: for new line segmentation)
    }

    QFile csvfile("/home/aj/ora_exported.csv");
    if(csvfile.open(QIODevice::WriteOnly|QIODevice::Truncate))
    {
        QTextStream out(&csvfile);
        out<<textData;
    }
    csvfile.close();

as it turned out, the model read the model->rowcount before all the results were fetched.

So as suggested by SO community, I used---

while (model->canFetchMore())
       model->fetchMore();

    int rows=model->rowCount();
    int columns=model->columnCount();

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < columns; j++)
        {
            textData += model->data(model->index(i,j)).toString();
            textData += ", ";      // for .csv file format
        }
        textData += "\n";             // (optional: for new line segmentation)
    }

and all the records got populated (all 543) in the .csv file.

You can refer to my question at here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!