123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- """
- /***************************************************************************
- Name : Virtual layers plugin for DB Manager
- Date : December 2015
- copyright : (C) 2015 by Hugo Mercier
- email : hugo dot mercier at oslandia dot com
- ***************************************************************************/
- /***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
- """
- from ..data_model import (TableDataModel,
- BaseTableModel,
- SqlResultModelAsync,
- SqlResultModelTask)
- from .connector import VLayerRegistry, getQueryGeometryName
- from .plugin import LVectorTable
- from ..plugin import DbError, BaseError
- from qgis.PyQt.QtCore import QTime, QTemporaryFile
- from qgis.core import (QgsVectorLayer,
- QgsWkbTypes,
- QgsVirtualLayerDefinition,
- QgsVirtualLayerTask,
- QgsTask)
- class LTableDataModel(TableDataModel):
- def __init__(self, table, parent=None):
- TableDataModel.__init__(self, table, parent)
- self.layer = None
- if isinstance(table, LVectorTable):
- self.layer = VLayerRegistry.instance().getLayer(table.name)
- else:
- self.layer = VLayerRegistry.instance().getLayer(table)
- if not self.layer:
- return
- # populate self.resdata
- self.resdata = []
- for f in self.layer.getFeatures():
- a = f.attributes()
- # add the geometry type
- if f.hasGeometry():
- a.append(QgsWkbTypes.displayString(f.geometry().wkbType()))
- else:
- a.append('None')
- self.resdata.append(a)
- self.fetchedFrom = 0
- self.fetchedCount = len(self.resdata)
- def rowCount(self, index=None):
- if self.layer:
- return self.layer.featureCount()
- return 0
- class LSqlResultModelTask(SqlResultModelTask):
- def __init__(self, db, sql, parent):
- super().__init__(db, sql, parent)
- tf = QTemporaryFile()
- tf.open()
- path = tf.fileName()
- tf.close()
- df = QgsVirtualLayerDefinition()
- df.setFilePath(path)
- df.setQuery(sql)
- self.subtask = QgsVirtualLayerTask(df)
- self.addSubTask(self.subtask, [], QgsTask.ParentDependsOnSubTask)
- def run(self):
- try:
- path = self.subtask.definition().filePath()
- sql = self.subtask.definition().query()
- self.model = LSqlResultModel(self.db, sql, None, self.subtask.layer(), path)
- except Exception as e:
- self.error = BaseError(str(e))
- return False
- return True
- def cancel(self):
- SqlResultModelTask.cancel(self)
- class LSqlResultModelAsync(SqlResultModelAsync):
- def __init__(self, db, sql, parent=None):
- super().__init__()
- self.task = LSqlResultModelTask(db, sql, parent)
- self.task.taskCompleted.connect(self.modelDone)
- self.task.taskTerminated.connect(self.modelDone)
- def modelDone(self):
- self.status = self.task.status
- self.model = self.task.model
- if self.task.subtask.exceptionText():
- self.error = BaseError(self.task.subtask.exceptionText())
- self.done.emit()
- class LSqlResultModel(BaseTableModel):
- def __init__(self, db, sql, parent=None, layer=None, path=None):
- t = QTime()
- t.start()
- if not layer:
- tf = QTemporaryFile()
- tf.open()
- path = tf.fileName()
- tf.close()
- df = QgsVirtualLayerDefinition()
- df.setFilePath(path)
- df.setQuery(sql)
- layer = QgsVectorLayer(df.toString(), "vv", "virtual")
- self._secs = t.elapsed() / 1000.0
- data = []
- header = []
- if not layer.isValid():
- raise DbError(layer.dataProvider().error().summary(), sql)
- else:
- header = [f.name() for f in layer.fields()]
- has_geometry = False
- if layer.geometryType() != QgsWkbTypes.NullGeometry:
- gn = getQueryGeometryName(path)
- if gn:
- has_geometry = True
- header += [gn]
- for f in layer.getFeatures():
- a = f.attributes()
- if has_geometry:
- if f.hasGeometry():
- a += [f.geometry().asWkt()]
- else:
- a += [None]
- data += [a]
- self._secs = 0
- self._affectedRows = len(data)
- BaseTableModel.__init__(self, header, data, parent)
- def secs(self):
- return self._secs
- def affectedRows(self):
- return self._affectedRows
|