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

View File

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

View File

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