如何取消长时间运行的QSqlQuery?

时间:2018-08-11 16:11:22

标签: c++ qt5 qsqlquery qsqldatabase

如何取消长时间运行的QSqlQuery?

数据库返回3M +行,并在QTableView控件中显示。我希望能够强制停止这两个长时间的操作:

  1. 数据库运行长时间时
  2. 如果数据库速度很快,但是有大量行要返回,则处理/复制/显示这些行会花费很多时间

第二个项目符号,可以通过不使用QSqlQueryModel来解决。在这种情况下,可以分阶段手动完成查询结果的解析并将予以实现,但是我还想知道是否可以中断和取消移动数据DB-> QTableView的过程。

我尝试了以下操作但未成功:

  • QSqlQuery :: finish()
  • QFuture :: cancel()
  • QSqlDatabase.close()-这使应用程序崩溃

如果需要完整的上下文,则为here。有问题的方法是

on_button_stopQuery_released

1 个答案:

答案 0 :(得分:2)

在执行过程中中止查询(而不是获取,这是QSqlQuery :: finish所做的)在所有数据库中都是碰碰运气。 Qt本身不支持这一点。解决方法将特定于后端。

例如,对于PostgreSQL,您可以执行以下操作:

  • 在原始连接中,获取连接ID(SELECT pg_backend_pid();)并保存
  • 要中止查询时,请打开第二个连接并通过发出SELECT pg_cancel_backend(saved_id);
  • 终止查询。

SQLite具有sqlite3_interrupt(sqlite3*)。这会中断查询,并且不会关闭连接。

MySQL与PostgreSQL类似:

  • 首先获取连接ID(SELECT CONNECTION_ID();
  • 然后通过另一个连接(KILL [CONNECTION|QUERY] $connection_id)杀死它。

如您所见,即使提供的功能也是特定于后端的。 Postgres只能中止连接,而SQLite只能中止查询。因此,最简单的实现方法是如果查询中止并且连接仍然有效,则放弃连接。然后,您可以使用简单的双向API接口进行取消管理(伪代码,即Python):

class IConnectionCancellation:
    def register(connection):
        # save/retrieve connection ID

    def cancel():
        # open second connection, send backend-specific query

对于较大的结果集,请考虑在模型中使用canFetchMorefetchMore。这样,您无需在向用户显示一些结果之前就处理整个结果集;使用起来可能会感觉更流畅。由于以下原因而无助于固有的查询执行延迟当然,按子句排序或分组。