[Solved] The "best" way to programmatically refresh a QSqlQueryModel when the content of the query changes



  • I was wondering what the appropriate way to refresh a QTableView using a QSqlQueryModel would be when the result of the query would change triggered by some external event outside the Qt app?

    I'm aware that:

    • QSqlQueryModel ::setQuery can be called but why should I parse a new query just to refresh it?
    • QTableView::setModel can be used but why should I set a new model only to refresh it?
    • QSqlQueryModel ::reset can be used but this is a protected method and would completely reset the model including information about the header line etc.

    The model/view architecture of Qt seems to have a very complex and well documented architecture but I just cannot seem to find the proper way to do this.



  • I think you'll have to stick to the setQuery method. At first, you say that the query would change because of some external event. Then why is it weird that you have to set it again? It is not refreshing if the query itself has changed, is it?
    How much that costs, would depend on your db engine I think. It may - I am not sure here - also depend on how you set your query. If you use setQuery (QSqlQuery) and bind the arguments that will change, your database may be able to optimize and not parse the SQL again. If not, using a view in your database could help too.



  • In my projects with mysql I use setQuery to update the data.
    With slow query, the first setQuery is slow but the next are very faster because mysql keep in cache the table used in query.



  • I would also guess that the performance impact very much depends on how the Qt database driver is implemented and the internals of the database itself.
    I also agree that setQuery typically should not have a huge performance impact but why should this not be encapsulated in the Qt model itself. In my impression a simple public refresh method just seems to be missing.
    To give a an example I use the situation I came across when issuing this message.
    I use a rather complex SQL query to an Oracle Database to retrieve data that will be used in a graph.
    The graph will be updated every second using a timer with the latest data and update the graph.
    The columns and the query are constant and I would only like to "refresh" the data will the latest values.



  • Another way is to prepare a database view of your complex query and then use a QSqlTableModel on the view. This class does expose an exec() method to re-run the query.



  • Oops sorry, the method is actually select() not exec(). /me should check the docs.



  • QSqlTableModel::select() use setQuery( QString, QSqlDatabase ) method refresh contents. I guess you could do it the same way.



  • Hi all
    I have similar question I am use QTableView + QSqlQuery when I set query at first time I allow fetch only first 10 rows from query, after that according user decides I can fetch next few rows, but my QTableView is not refreshed after fetch. I can't use setQuery because I do not what run sql yet one time to get result that I already have.
    I try to use something like this
    @emit dataChanged(createIndex(OldRowCnt, 1), createIndex(RowCount, HeaderCount));@
    but this has no result

    thank you for future help )



  • beginInsertRows solve my problem, I am call it after fetch

    @bool cOciQModel::fetch(int Cnt, bool SilentMode) {
    if (RowCount && !query->seek(RowCount - 1)) {
    LastError = QString("Can't goto [%1] position").arg(QString::number(RowCount - 1));
    return false;
    }
    int OldRowCnt = RowCount;
    int Count = Cnt + 1;
    while (--Count && !AllDataFetched) {
    AllDataFetched = !query->next();
    if (!AllDataFetched) {
    ++RowCount;
    }
    }

    if (!SilentMode) {
    beginInsertRows(QModelIndex(), OldRowCnt, RowCount);
    endInsertRows();
    }

    return true;
    

    }@



  • How I update QSqlQueryModel:

    QString queryStr = model->query().executedQuery();
    model->clear();
    model->query().clear();
    model->setQuery(queryStr);
    


  • @iamantony how to do it with Python?


  • Moderators

    @Gelo Replace -> with .



  • @jsulm

    QString queryStr = model->query().executedQuery();
    model->clear();
    model->query().clear();
    model->setQuery(queryStr);

    is that c++? for what is QString?


  • Moderators

    @Gelo Yes, it is C++.
    QString is a Qt data type for strings - no need to write it in Python.


Log in to reply
 

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