Skip to content

Commit

Permalink
Restore import into postgis algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 22, 2017
1 parent 22246dc commit 38f1d9c
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 70 deletions.
156 changes: 88 additions & 68 deletions python/plugins/processing/algs/qgis/ImportIntoPostGIS.py
Expand Up @@ -28,7 +28,12 @@
from qgis.core import (QgsVectorLayerExporter,
QgsSettings,
QgsApplication,
QgsProcessingUtils)
QgsProcessingUtils,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterString,
QgsProcessingParameterField,
QgsProcessingParameterBoolean,
QgsWkbTypes)

from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
Expand Down Expand Up @@ -65,49 +70,52 @@ def group(self):

def __init__(self):
super().__init__()
self.addParameter(ParameterVector(self.INPUT,
self.tr('Layer to import')))
self.addParameter(ParameterString(
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Layer to import')))

db_param = QgsProcessingParameterString(
self.DATABASE,
self.tr('Database (connection name)'),
metadata={
'widget_wrapper': {
'class': 'processing.gui.wrappers_postgis.ConnectionWidgetWrapper'}}))
self.addParameter(ParameterString(
self.tr('Database (connection name)'))
db_param.setMetadata({
'widget_wrapper': {
'class': 'processing.gui.wrappers_postgis.ConnectionWidgetWrapper'}})
self.addParameter(db_param)

schema_param = QgsProcessingParameterString(
self.SCHEMA,
self.tr('Schema (schema name)'),
'public',
optional=True,
metadata={
'widget_wrapper': {
'class': 'processing.gui.wrappers_postgis.SchemaWidgetWrapper',
'connection_param': self.DATABASE}}))
self.addParameter(ParameterString(
self.tr('Schema (schema name)'), 'public', False, True)
schema_param.setMetadata({
'widget_wrapper': {
'class': 'processing.gui.wrappers_postgis.SchemaWidgetWrapper',
'connection_param': self.DATABASE}})
self.addParameter(schema_param)

table_param = QgsProcessingParameterString(
self.TABLENAME,
self.tr('Table to import to (leave blank to use layer name)'),
'',
optional=True,
metadata={
'widget_wrapper': {
'class': 'processing.gui.wrappers_postgis.TableWidgetWrapper',
'schema_param': self.SCHEMA}}))
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.tr('Table to import to (leave blank to use layer name)'), '', False, True)
table_param.setMetadata({
'widget_wrapper': {
'class': 'processing.gui.wrappers_postgis.TableWidgetWrapper',
'schema_param': self.SCHEMA}})
self.addParameter(table_param)

self.addParameter(QgsProcessingParameterField(self.PRIMARY_KEY,
self.tr('Primary key field'), None, self.INPUT, QgsProcessingParameterField.Any, False, True))
self.addParameter(QgsProcessingParameterString(self.GEOMETRY_COLUMN,
self.tr('Geometry column'), 'geom'))
self.addParameter(QgsProcessingParameterString(self.ENCODING,
self.tr('Encoding'), 'UTF-8',
False, 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 'importintopostgis'
Expand All @@ -116,22 +124,21 @@ def displayName(self):
return self.tr('Import into PostGIS')

def processAlgorithm(self, parameters, context, feedback):
connection = self.getParameterValue(self.DATABASE)
connection = self.parameterAsString(parameters, self.DATABASE, context)
db = postgis.GeoDB.from_name(connection)

schema = self.getParameterValue(self.SCHEMA)
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)
schema = self.parameterAsString(parameters, self.SCHEMA, context)
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 == '':
Expand All @@ -140,9 +147,9 @@ def processAlgorithm(self, parameters, context, feedback):
table = table.replace(' ', '').lower()[0:62]
providerName = 'postgres'

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:
Expand All @@ -156,32 +163,45 @@ def processAlgorithm(self, parameters, context, feedback):
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(schema, table, geomColumn, '', primaryKeyField)

if encoding:
layer.setProviderEncoding(encoding)

(ret, errMsg) = QgsVectorLayerExporter.exportLayer(
layer,
uri.uri(),
providerName,
self.crs,
False,
options,
)
if ret != 0:
options['fileEncoding'] = encoding

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 PostGIS\n{0}').format(exporter.errorMessage()))

features = source.getFeatures()
total = 100.0 / source.featureCount()
for current, f in enumerate(features):
if feedback.isCanceled():
break

if not exporter.addFeature(f):
feedback.reportError(exporter.errorMessage())

feedback.setProgress(int(current * total))

exporter.flushBuffer()
if exporter.errorCode() != QgsVectorLayerExporter.NoError:
raise GeoAlgorithmExecutionException(
self.tr('Error importing to PostGIS\n{0}').format(errMsg))
self.tr('Error importing to PostGIS\n{0}').format(exporter.errorMessage()))

if geomColumn and createIndex:
db.create_spatial_index(table, schema, geomColumn)

db.vacuum_analyze(table, schema)

return {}

def dbConnectionNames(self):
settings = QgsSettings()
settings.beginGroup('/PostgreSQL/connections/')
Expand Down
5 changes: 3 additions & 2 deletions python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
Expand Up @@ -55,6 +55,7 @@
from .DropGeometry import DropGeometry
from .ExtentFromLayer import ExtentFromLayer
from .GridPolygon import GridPolygon
from .ImportIntoPostGIS import ImportIntoPostGIS
from .Merge import Merge

# from .RegularPoints import RegularPoints
Expand Down Expand Up @@ -123,7 +124,6 @@
# from .SpatialiteExecuteSQL import SpatialiteExecuteSQL
# from .PostGISExecuteSQL import PostGISExecuteSQL
# from .ImportIntoSpatialite import ImportIntoSpatialite
# from .ImportIntoPostGIS import ImportIntoPostGIS
# from .SetVectorStyle import SetVectorStyle
# from .SetRasterStyle import SetRasterStyle
# from .SelectByExpression import SelectByExpression
Expand Down Expand Up @@ -218,7 +218,7 @@ def getAlgs(self):
# RandomPointsPolygonsVariable(),
# RandomPointsAlongLines(), PointsToPaths(),
# SpatialiteExecuteSQL(), ImportIntoSpatialite(),
# PostGISExecuteSQL(), ImportIntoPostGIS(),
# PostGISExecuteSQL(),
# SetVectorStyle(), SetRasterStyle(),
# SelectByExpression(), HypsometricCurves(),
# SplitWithLines(), CreateConstantRaster(),
Expand Down Expand Up @@ -260,6 +260,7 @@ def getAlgs(self):
DropGeometry(),
ExtentFromLayer(),
GridPolygon(),
ImportIntoPostGIS(),
Merge()
]

Expand Down

0 comments on commit 38f1d9c

Please sign in to comment.