Skip to content
Permalink
Browse files

Merge pull request #6268 from pblottiere/dbmanager_stop

[FEATURE][needs-docs] dbmanager stop
  • Loading branch information
pblottiere committed Mar 5, 2018
2 parents f2a6780 + e531052 commit 7c3ab9f1354053b07780c090ac6eea929f11636d
Showing with 891 additions and 61 deletions.
  1. +1 −0 python/core/core_auto.sip
  2. +12 −0 python/core/qgsvectordataprovider.sip.in
  3. +25 −0 python/core/qgsvirtuallayerdefinition.sip.in
  4. +71 −0 python/core/qgsvirtuallayertask.sip.in
  5. +3 −0 python/plugins/db_manager/db_plugins/connector.py
  6. +51 −4 python/plugins/db_manager/db_plugins/data_model.py
  7. +4 −0 python/plugins/db_manager/db_plugins/gpkg/connector.py
  8. +36 −1 python/plugins/db_manager/db_plugins/gpkg/data_model.py
  9. +5 −0 python/plugins/db_manager/db_plugins/gpkg/plugin.py
  10. +5 −0 python/plugins/db_manager/db_plugins/plugin.py
  11. +4 −0 python/plugins/db_manager/db_plugins/postgis/connector.py
  12. +35 −2 python/plugins/db_manager/db_plugins/postgis/data_model.py
  13. +5 −0 python/plugins/db_manager/db_plugins/postgis/plugin.py
  14. +6 −0 python/plugins/db_manager/db_plugins/spatialite/connector.py
  15. +40 −1 python/plugins/db_manager/db_plugins/spatialite/data_model.py
  16. +5 −0 python/plugins/db_manager/db_plugins/spatialite/plugin.py
  17. +74 −22 python/plugins/db_manager/db_plugins/vlayers/data_model.py
  18. +4 −0 python/plugins/db_manager/db_plugins/vlayers/plugin.py
  19. +81 −21 python/plugins/db_manager/dlg_sql_window.py
  20. +86 −0 python/plugins/db_manager/ui/DlgCancelTaskQuery.ui
  21. +21 −0 python/plugins/db_manager/ui/DlgSqlWindow.ui
  22. +2 −0 src/core/CMakeLists.txt
  23. +5 −0 src/core/qgsvectordataprovider.cpp
  24. +9 −0 src/core/qgsvectordataprovider.h
  25. +9 −0 src/core/qgsvirtuallayerdefinition.cpp
  26. +19 −0 src/core/qgsvirtuallayerdefinition.h
  27. +64 −0 src/core/qgsvirtuallayertask.cpp
  28. +76 −0 src/core/qgsvirtuallayertask.h
  29. +26 −10 src/providers/virtual/qgsvirtuallayerprovider.cpp
  30. +2 −0 src/providers/virtual/qgsvirtuallayerprovider.h
  31. +11 −0 src/providers/virtual/qgsvirtuallayersqlitehelper.cpp
  32. +1 −0 src/providers/virtual/qgsvirtuallayersqlitehelper.h
  33. +1 −0 tests/src/python/CMakeLists.txt
  34. +20 −0 tests/src/python/test_provider_virtual.py
  35. +72 −0 tests/src/python/test_qgsvirtuallayertask.py
@@ -347,6 +347,7 @@
%Include qgsvectorlayereditbuffer.sip
%Include qgsvectorlayereditpassthrough.sip
%Include qgsvectorlayer.sip
%Include qgsvirtuallayertask.sip
%Include qgsvectorlayerfeaturecounter.sip
%Include qgsvectorlayerjoinbuffer.sip
%Include qgsvectorlayertools.sip
@@ -50,6 +50,7 @@ of feature and attribute information from a spatial datasource.
FastTruncate,
ReadLayerMetadata,
WriteLayerMetadata,
CancelSupport,
};

typedef QFlags<QgsVectorDataProvider::Capability> Capabilities;
@@ -229,6 +230,17 @@ Providers with the FastTruncate capability will use an optimised method to trunc
.. versionadded:: 3.0

.. seealso:: :py:func:`deleteFeatures`
%End

virtual bool cancelReload();
%Docstring
Cancels the current reloading of data.

:return: true if the reloading has been correctly interrupted, false otherwise

.. versionadded:: 3.2

.. seealso:: :py:func:`reloadData`
%End

virtual bool addAttributes( const QList<QgsField> &attributes );
@@ -148,6 +148,31 @@ Get the name of the field with unique identifiers
void setUid( const QString &uid );
%Docstring
Set the name of the field with unique identifiers
%End

void setLazy( bool lazy );
%Docstring
Sets the lazy mode. If ``lazy`` is true, then the loading is
delayed until an explicit reloading of the layer.

:param lazy: True to delay the loading, false otherwise

.. versionadded:: 3.2

.. seealso:: :py:func:`QgsDataProvider.reloadData`

.. seealso:: :py:func:`isLazy`
%End

bool isLazy() const;
%Docstring
Returns the lazy mode.

:return: True if the loading is delayed, false otherwise.

.. versionadded:: 3.2

.. seealso:: :py:func:`setLazy`
%End

QString geometryField() const;
@@ -0,0 +1,71 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsvirtuallayertask.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsVirtualLayerTask : QgsTask
{
%Docstring

Initializes a virtual layer with postpone mode activated and reloads the
data in a separated thread.

.. versionadded:: 3.2
%End

%TypeHeaderCode
#include "qgsvirtuallayertask.h"
%End
public:

QgsVirtualLayerTask( const QgsVirtualLayerDefinition &definition );
%Docstring
Constructor.

:param definition: The definition to use for initializing the virtual layer
%End

QgsVectorLayer *layer();
%Docstring
Returns the underlying virtual layer.
%End

QgsVectorLayer *takeLayer();
%Docstring
Returns the underlying virtual layer and ownership.
%End

QgsVirtualLayerDefinition definition() const;
%Docstring
Returns the virtual layer definition.
%End

virtual bool run();

%Docstring
Reloads the data.

:return: True if the virtual layer is valid, false otherwise.
%End

virtual void cancel();

%Docstring
Cancels the pending query and the parent task.
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsvirtuallayertask.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -42,6 +42,9 @@ def __del__(self):
def uri(self):
return QgsDataSourceUri(self._uri.uri(False))

def cancel(self):
pass

def publicUri(self):
publicUri = QgsDataSourceUri.removePassword(self._uri.uri(False))
return QgsDataSourceUri(publicUri)
@@ -22,11 +22,20 @@
from builtins import str
from builtins import range

from qgis.PyQt.QtCore import Qt, QTime, QRegExp, QAbstractTableModel
from qgis.PyQt.QtGui import QFont, QStandardItemModel, QStandardItem
from qgis.PyQt.QtCore import (Qt,
QTime,
QRegExp,
QAbstractTableModel,
pyqtSignal,
QObject)
from qgis.PyQt.QtGui import (QFont,
QStandardItemModel,
QStandardItem)
from qgis.PyQt.QtWidgets import QApplication

from .plugin import DbError
from qgis.core import QgsTask

from .plugin import DbError, BaseError


class BaseTableModel(QAbstractTableModel):
@@ -139,6 +148,44 @@ def rowCount(self, index=None):
return self.table.rowCount if self.table.rowCount is not None and self.columnCount(index) > 0 else 0


class SqlResultModelAsync(QObject):

done = pyqtSignal()

def __init__(self):
super().__init__()
self.error = BaseError('')
self.status = None
self.model = None
self.task = None
self.canceled = False

def cancel(self):
self.canceled = True
if self.task:
self.task.cancel()

def modelDone(self):
if self.task:
self.status = self.task.status
self.model = self.task.model
self.error = self.task.error
self.task = None

self.done.emit()


class SqlResultModelTask(QgsTask):

def __init__(self, db, sql, parent):
super().__init__()
self.db = db
self.sql = sql
self.parent = parent
self.error = BaseError('')
self.model = None


class SqlResultModel(BaseTableModel):

def __init__(self, db, sql, parent=None):
@@ -165,7 +212,7 @@ def __init__(self, db, sql, parent=None):
data = []
header = []

BaseTableModel.__init__(self, header, data, parent)
super().__init__(header, data, parent)

# commit before closing the cursor to make sure that the changes are stored
self.db._commit()
@@ -165,6 +165,10 @@ def _commit(self):
self._rollback()
raise DbError(e)

def cancel(self):
if self.connection:
self.connection.interrupt()

@classmethod
def isValidDatabase(cls, path):
if hasattr(gdal, 'OpenEx'):
@@ -20,7 +20,13 @@
***************************************************************************/
"""

from ..data_model import TableDataModel, SqlResultModel
from qgis.core import QgsMessageLog

from ..data_model import (TableDataModel,
SqlResultModel,
SqlResultModelAsync,
SqlResultModelTask)
from ..plugin import BaseError


class GPKGTableDataModel(TableDataModel):
@@ -47,5 +53,34 @@ def rowCount(self, index=None):
return self.fetchedCount


class GPKGSqlResultModelTask(SqlResultModelTask):

def __init__(self, db, sql, parent):
super().__init__(db, sql, parent)

def run(self):
try:
self.model = GPKGSqlResultModel(self.db, self.sql, None)
except BaseError as e:
self.error = e
QgsMessageLog.logMessage(e.msg)
return False
return True

def cancel(self):
self.db.connector.cancel()
SqlResultModelTask.cancel(self)


class GPKGSqlResultModelAsync(SqlResultModelAsync):

def __init__(self, db, sql, parent):
super().__init__()

self.task = GPKGSqlResultModelTask(db, sql, parent)
self.task.taskCompleted.connect(self.modelDone)
self.task.taskTerminated.connect(self.modelDone)


class GPKGSqlResultModel(SqlResultModel):
pass
@@ -132,6 +132,11 @@ def sqlResultModel(self, sql, parent):

return GPKGSqlResultModel(self, sql, parent)

def sqlResultModelAsync(self, sql, parent):
from .data_model import GPKGSqlResultModelAsync

return GPKGSqlResultModelAsync(self, sql, parent)

def registerDatabaseActions(self, mainWindow):
action = QAction(self.tr("Run &Vacuum"), self)
mainWindow.registerAction(action, self.tr("&Database"), self.runVacuumActionSlot)
@@ -256,6 +256,11 @@ def sqlResultModel(self, sql, parent):

return SqlResultModel(self, sql, parent)

def sqlResultModelAsync(self, sql, parent):
from .data_model import SqlResultModelAsync

return SqlResultModelAsync(self, sql, parent)

def columnUniqueValuesModel(self, col, table, limit=10):
l = ""
if limit is not None:
@@ -186,6 +186,10 @@ def _checkRasterColumnsTable(self):
self.has_raster_columns_access = self.getTablePrivileges('raster_columns')[0]
return self.has_raster_columns

def cancel(self):
if self.connection:
self.connection.cancel()

def getInfo(self):
c = self._execute(None, u"SELECT version()")
res = self._fetchone(c)
@@ -20,8 +20,12 @@
***************************************************************************/
"""


from ..data_model import TableDataModel, SqlResultModel
from qgis.core import QgsMessageLog
from ..plugin import BaseError
from ..data_model import (TableDataModel,
SqlResultModel,
SqlResultModelAsync,
SqlResultModelTask)


class PGTableDataModel(TableDataModel):
@@ -79,5 +83,34 @@ def fetchMoreData(self, row_start):
self.fetchedFrom = row_start


class PGSqlResultModelTask(SqlResultModelTask):

def __init__(self, db, sql, parent):
super().__init__(db, sql, parent)

def run(self):
try:
self.model = PGSqlResultModel(self.db, self.sql, None)
except BaseError as e:
self.error = e
QgsMessageLog.logMessage(e.msg)
return False
return True

def cancel(self):
self.db.connector.cancel()
SqlResultModelTask.cancel(self)


class PGSqlResultModelAsync(SqlResultModelAsync):

def __init__(self, db, sql, parent):
super().__init__()

self.task = PGSqlResultModelTask(db, sql, parent)
self.task.taskCompleted.connect(self.modelDone)
self.task.taskTerminated.connect(self.modelDone)


class PGSqlResultModel(SqlResultModel):
pass
@@ -134,6 +134,11 @@ def sqlResultModel(self, sql, parent):

return PGSqlResultModel(self, sql, parent)

def sqlResultModelAsync(self, sql, parent):
from .data_model import PGSqlResultModelAsync

return PGSqlResultModelAsync(self, sql, parent)

def registerDatabaseActions(self, mainWindow):
Database.registerDatabaseActions(self, mainWindow)

@@ -59,6 +59,12 @@ def __init__(self, uri):
def _connectionInfo(self):
return str(self.dbname)

def cancel(self):
# https://www.sqlite.org/c3ref/interrupt.html
# This function causes any pending database operation to abort and return at its earliest opportunity.
if self.connection:
self.connection.interrupt()

@classmethod
def isValidDatabase(self, path):
if not QFile.exists(path):

0 comments on commit 7c3ab9f

Please sign in to comment.
You can’t perform that action at this time.