[processing] restore import into spatialite & spatialite execute sql

This commit is contained in:
Mathieu Pellerin 2017-06-26 10:22:51 +07:00 committed by GitHub
parent bfb41a1afb
commit fa8b216eb6
3 changed files with 84 additions and 64 deletions

View File

@ -29,14 +29,16 @@ from qgis.core import (QgsDataSourceUri,
QgsFeatureSink, QgsFeatureSink,
QgsVectorLayerExporter, QgsVectorLayerExporter,
QgsApplication, QgsApplication,
QgsProcessingUtils) QgsProcessingUtils,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterField,
QgsProcessingParameterString,
QgsProcessingParameterBoolean,
QgsWkbTypes)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterBoolean
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterString
from processing.core.parameters import ParameterTableField
from processing.tools import spatialite from processing.tools import spatialite
@ -59,17 +61,17 @@ class ImportIntoSpatialite(QgisAlgorithm):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.addParameter(ParameterVector(self.INPUT, self.tr('Layer to import'))) self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Layer to import')))
self.addParameter(ParameterVector(self.DATABASE, self.tr('File database'), False, False)) self.addParameter(QgsProcessingParameterVectorLayer(self.DATABASE, self.tr('File database'), False, False))
self.addParameter(ParameterString(self.TABLENAME, self.tr('Table to import to (leave blank to use layer name)'), optional=True)) self.addParameter(QgsProcessingParameterString(self.TABLENAME, self.tr('Table to import to (leave blank to use layer name)'), optional=True))
self.addParameter(ParameterTableField(self.PRIMARY_KEY, self.tr('Primary key field'), self.INPUT, optional=True)) self.addParameter(QgsProcessingParameterField(self.PRIMARY_KEY, self.tr('Primary key field'), self.INPUT, optional=True))
self.addParameter(ParameterString(self.GEOMETRY_COLUMN, self.tr('Geometry column'), 'geom')) self.addParameter(QgsProcessingParameterString(self.GEOMETRY_COLUMN, self.tr('Geometry column'), 'geom'))
self.addParameter(ParameterString(self.ENCODING, self.tr('Encoding'), 'UTF-8', optional=True)) self.addParameter(QgsProcessingParameterString(self.ENCODING, self.tr('Encoding'), 'UTF-8', optional=True))
self.addParameter(ParameterBoolean(self.OVERWRITE, self.tr('Overwrite'), True)) self.addParameter(QgsProcessingParameterBoolean(self.OVERWRITE, self.tr('Overwrite'), True))
self.addParameter(ParameterBoolean(self.CREATEINDEX, self.tr('Create spatial index'), True)) self.addParameter(QgsProcessingParameterBoolean(self.CREATEINDEX, self.tr('Create spatial index'), True))
self.addParameter(ParameterBoolean(self.LOWERCASE_NAMES, self.tr('Convert field names to lowercase'), True)) self.addParameter(QgsProcessingParameterBoolean(self.LOWERCASE_NAMES, self.tr('Convert field names to lowercase'), True))
self.addParameter(ParameterBoolean(self.DROP_STRING_LENGTH, self.tr('Drop length constraints on character fields'), False)) self.addParameter(QgsProcessingParameterBoolean(self.DROP_STRING_LENGTH, self.tr('Drop length constraints on character fields'), False))
self.addParameter(ParameterBoolean(self.FORCE_SINGLEPART, self.tr('Create single-part geometries instead of multi-part'), False)) self.addParameter(QgsProcessingParameterBoolean(self.FORCE_SINGLEPART, self.tr('Create single-part geometries instead of multi-part'), False))
def name(self): def name(self):
return 'importintospatialite' return 'importintospatialite'
@ -78,36 +80,37 @@ class ImportIntoSpatialite(QgisAlgorithm):
return self.tr('Import into Spatialite') return self.tr('Import into Spatialite')
def processAlgorithm(self, parameters, context, feedback): def processAlgorithm(self, parameters, context, feedback):
database = self.getParameterValue(self.DATABASE) database = self.parameterAsVectorLayer(parameters, self.DATABASE, context)
uri = QgsDataSourceUri(database) databaseuri = database.dataProvider().dataSourceUri()
uri = QgsDataSourceUri(databaseuri)
if uri.database() is '': if uri.database() is '':
if '|layerid' in database: if '|layerid' in databaseuri:
database = database[:database.find('|layerid')] databaseuri = databaseuri[:databaseuri.find('|layerid')]
uri = QgsDataSourceUri('dbname=\'%s\'' % (database)) uri = QgsDataSourceUri('dbname=\'%s\'' % (databaseuri))
db = spatialite.GeoDB(uri) db = spatialite.GeoDB(uri)
overwrite = self.getParameterValue(self.OVERWRITE) overwrite = self.parameterAsBool(parameters, self.OVERWRITE, context)
createIndex = self.getParameterValue(self.CREATEINDEX) createIndex = self.parameterAsBool(parameters, self.CREATEINDEX, context)
convertLowerCase = self.getParameterValue(self.LOWERCASE_NAMES) convertLowerCase = self.parameterAsBool(parameters, self.LOWERCASE_NAMES, context)
dropStringLength = self.getParameterValue(self.DROP_STRING_LENGTH) dropStringLength = self.parameterAsBool(parameters, self.DROP_STRING_LENGTH, context)
forceSinglePart = self.getParameterValue(self.FORCE_SINGLEPART) forceSinglePart = self.parameterAsBool(parameters, self.FORCE_SINGLEPART, context)
primaryKeyField = self.getParameterValue(self.PRIMARY_KEY) or 'id' primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id'
encoding = self.getParameterValue(self.ENCODING) encoding = self.parameterAsString(parameters, self.ENCODING, context)
layerUri = self.getParameterValue(self.INPUT) source = self.parameterAsSource(parameters, self.INPUT, context)
layer = QgsProcessingUtils.mapLayerFromString(layerUri, context)
table = self.getParameterValue(self.TABLENAME) table = self.parameterAsString(parameters, self.TABLENAME, context)
if table: if table:
table.strip() table.strip()
if not table or table == '': if not table or table == '':
table = layer.name() table = source.sourceName()
table = table.replace('.', '_')
table = table.replace(' ', '').lower() table = table.replace(' ', '').lower()
providerName = 'spatialite' providerName = 'spatialite'
geomColumn = self.getParameterValue(self.GEOMETRY_COLUMN) geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context)
if not geomColumn: if not geomColumn:
geomColumn = 'the_geom' geomColumn = 'geom'
options = {} options = {}
if overwrite: if overwrite:
@ -121,26 +124,39 @@ class ImportIntoSpatialite(QgisAlgorithm):
options['forceSinglePartGeometryType'] = True options['forceSinglePartGeometryType'] = True
# Clear geometry column for non-geometry tables # Clear geometry column for non-geometry tables
if not layer.hasGeometryType(): if source.wkbType() == QgsWkbTypes.NoGeometry:
geomColumn = None geomColumn = None
uri = db.uri uri = db.uri
uri.setDataSource('', table, geomColumn, '', primaryKeyField) uri.setDataSource('', table, geomColumn, '', primaryKeyField)
if encoding: if encoding:
layer.setProviderEncoding(encoding) options['fileEncoding'] = encoding
(ret, errMsg) = QgsVectorLayerExporter.exportLayer( exporter = QgsVectorLayerExporter(uri.uri(), providerName, source.fields(),
layer, source.wkbType(), source.sourceCrs(), overwrite, options)
uri.uri(),
providerName, if exporter.errorCode() != QgsVectorLayerExporter.NoError:
self.crs,
False,
options,
)
if ret != 0:
raise GeoAlgorithmExecutionException( raise GeoAlgorithmExecutionException(
self.tr('Error importing to Spatialite\n{0}').format(errMsg)) self.tr('Error importing to Spatialite\n{0}').format(exporter.errorMessage()))
features = source.getFeatures()
total = 100.0 / source.featureCount() if source.featureCount() else 0
for current, f in enumerate(features):
if feedback.isCanceled():
break
if not exporter.addFeature(f, QgsFeatureSink.FastInsert):
feedback.reportError(exporter.errorMessage())
feedback.setProgress(int(current * total))
exporter.flushBuffer()
if exporter.errorCode() != QgsVectorLayerExporter.NoError:
raise GeoAlgorithmExecutionException(
self.tr('Error importing to Spatialite\n{0}').format(exporter.errorMessage()))
if geomColumn and createIndex: if geomColumn and createIndex:
db.create_spatial_index(table, geomColumn) db.create_spatial_index(table, geomColumn)
return {}

View File

@ -57,6 +57,7 @@ from .ExtentFromLayer import ExtentFromLayer
from .FixGeometry import FixGeometry from .FixGeometry import FixGeometry
from .GridPolygon import GridPolygon from .GridPolygon import GridPolygon
from .ImportIntoPostGIS import ImportIntoPostGIS from .ImportIntoPostGIS import ImportIntoPostGIS
from .ImportIntoSpatialite import ImportIntoSpatialite
from .Merge import Merge from .Merge import Merge
from .PostGISExecuteSQL import PostGISExecuteSQL from .PostGISExecuteSQL import PostGISExecuteSQL
from .RandomExtract import RandomExtract from .RandomExtract import RandomExtract
@ -64,6 +65,7 @@ from .RandomExtractWithinSubsets import RandomExtractWithinSubsets
from .RegularPoints import RegularPoints from .RegularPoints import RegularPoints
from .SimplifyGeometries import SimplifyGeometries from .SimplifyGeometries import SimplifyGeometries
from .Smooth import Smooth from .Smooth import Smooth
from .SpatialiteExecuteSQL import SpatialiteExecuteSQL
from .SymmetricalDifference import SymmetricalDifference from .SymmetricalDifference import SymmetricalDifference
from .VectorSplit import VectorSplit from .VectorSplit import VectorSplit
@ -124,8 +126,6 @@ from .VectorSplit import VectorSplit
# from .RandomPointsPolygonsVariable import RandomPointsPolygonsVariable # from .RandomPointsPolygonsVariable import RandomPointsPolygonsVariable
# from .RandomPointsAlongLines import RandomPointsAlongLines # from .RandomPointsAlongLines import RandomPointsAlongLines
# from .PointsToPaths import PointsToPaths # from .PointsToPaths import PointsToPaths
# from .SpatialiteExecuteSQL import SpatialiteExecuteSQL
# from .ImportIntoSpatialite import ImportIntoSpatialite
# from .SetVectorStyle import SetVectorStyle # from .SetVectorStyle import SetVectorStyle
# from .SetRasterStyle import SetRasterStyle # from .SetRasterStyle import SetRasterStyle
# from .SelectByExpression import SelectByExpression # from .SelectByExpression import SelectByExpression
@ -216,7 +216,6 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
# RandomPointsLayer(), RandomPointsPolygonsFixed(), # RandomPointsLayer(), RandomPointsPolygonsFixed(),
# RandomPointsPolygonsVariable(), # RandomPointsPolygonsVariable(),
# RandomPointsAlongLines(), PointsToPaths(), # RandomPointsAlongLines(), PointsToPaths(),
# SpatialiteExecuteSQL(), ImportIntoSpatialite(),
# SetVectorStyle(), SetRasterStyle(), # SetVectorStyle(), SetRasterStyle(),
# SelectByExpression(), HypsometricCurves(), # SelectByExpression(), HypsometricCurves(),
# SplitWithLines(), CreateConstantRaster(), # SplitWithLines(), CreateConstantRaster(),
@ -260,6 +259,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
FixGeometry(), FixGeometry(),
GridPolygon(), GridPolygon(),
ImportIntoPostGIS(), ImportIntoPostGIS(),
ImportIntoSpatialite(),
Merge(), Merge(),
PostGISExecuteSQL(), PostGISExecuteSQL(),
RandomExtract(), RandomExtract(),
@ -267,6 +267,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
RegularPoints(), RegularPoints(),
SimplifyGeometries(), SimplifyGeometries(),
Smooth(), Smooth(),
SpatialiteExecuteSQL(),
SymmetricalDifference(), SymmetricalDifference(),
VectorSplit() VectorSplit()
] ]

View File

@ -26,15 +26,15 @@ __copyright__ = '(C) 2016, Mathieu Pellerin'
__revision__ = '$Format:%H$' __revision__ = '$Format:%H$'
from qgis.core import (QgsDataSourceUri,
QgsApplication,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterString)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterString
from processing.tools import spatialite from processing.tools import spatialite
from qgis.core import (QgsApplication,
QgsDataSourceUri)
class SpatialiteExecuteSQL(QgisAlgorithm): class SpatialiteExecuteSQL(QgisAlgorithm):
@ -46,8 +46,8 @@ class SpatialiteExecuteSQL(QgisAlgorithm):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.addParameter(ParameterVector(self.DATABASE, self.tr('File Database'), False, False)) self.addParameter(QgsProcessingParameterVectorLayer(self.DATABASE, self.tr('File Database'), False, False))
self.addParameter(ParameterString(self.SQL, self.tr('SQL query'), '', True)) self.addParameter(QgsProcessingParameterString(self.SQL, self.tr('SQL query'), '', True))
def name(self): def name(self):
return 'spatialiteexecutesql' return 'spatialiteexecutesql'
@ -56,16 +56,19 @@ class SpatialiteExecuteSQL(QgisAlgorithm):
return self.tr('Spatialite execute SQL') return self.tr('Spatialite execute SQL')
def processAlgorithm(self, parameters, context, feedback): def processAlgorithm(self, parameters, context, feedback):
database = self.getParameterValue(self.DATABASE) database = self.parameterAsVectorLayer(parameters, self.DATABASE, context)
uri = QgsDataSourceUri(database) databaseuri = database.dataProvider().dataSourceUri()
uri = QgsDataSourceUri(databaseuri)
if uri.database() is '': if uri.database() is '':
if '|layerid' in database: if '|layerid' in databaseuri:
database = database[:database.find('|layerid')] databaseuri = databaseuri[:databaseuri.find('|layerid')]
uri = QgsDataSourceUri('dbname=\'%s\'' % (database)) uri = QgsDataSourceUri('dbname=\'%s\'' % (databaseuri))
self.db = spatialite.GeoDB(uri) db = spatialite.GeoDB(uri)
sql = self.getParameterValue(self.SQL).replace('\n', ' ') sql = self.parameterAsString(parameters, self.SQL, context).replace('\n', ' ')
try: try:
self.db._exec_sql_and_commit(str(sql)) db._exec_sql_and_commit(str(sql))
except spatialite.DbError as e: except spatialite.DbError as e:
raise GeoAlgorithmExecutionException( raise GeoAlgorithmExecutionException(
self.tr('Error executing SQL:\n{0}').format(str(e))) self.tr('Error executing SQL:\n{0}').format(str(e)))
return {}