def processAlgorithm(self, parameters, context, feedback): connection = self.parameterAsString(parameters, self.DATABASE, context) db = postgis.GeoDB.from_name(connection) schema = self.parameterAsString(parameters, self.SCHEMA, context) overwrite = self.parameterAsBoolean(parameters, self.OVERWRITE, context) createIndex = self.parameterAsBoolean(parameters, self.CREATEINDEX, context) convertLowerCase = self.parameterAsBoolean(parameters, self.LOWERCASE_NAMES, context) dropStringLength = self.parameterAsBoolean(parameters, self.DROP_STRING_LENGTH, context) forceSinglePart = self.parameterAsBoolean(parameters, self.FORCE_SINGLEPART, context) primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id' encoding = self.parameterAsString(parameters, self.ENCODING, context) source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) table = self.parameterAsString(parameters, self.TABLENAME, context) if table: table.strip() if not table or table == '': table = source.sourceName() table = table.replace('.', '_') table = table.replace(' ', '').lower()[0:62] providerName = 'postgres' geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context) if not geomColumn: geomColumn = 'geom' options = {} if overwrite: options['overwrite'] = True if convertLowerCase: options['lowercaseFieldNames'] = True geomColumn = geomColumn.lower() if dropStringLength: options['dropStringConstraints'] = True if forceSinglePart: options['forceSinglePartGeometryType'] = True # Clear geometry column for non-geometry tables if source.wkbType() == QgsWkbTypes.NoGeometry: geomColumn = None uri = db.uri uri.setDataSource(schema, table, geomColumn, '', primaryKeyField) if encoding: options['fileEncoding'] = encoding exporter = QgsVectorLayerExporter(uri.uri(), providerName, source.fields(), source.wkbType(), source.sourceCrs(), overwrite, options) if exporter.errorCode() != QgsVectorLayerExporter.NoError: raise QgsProcessingException( self.tr('Error importing to PostGIS\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 QgsProcessingException( 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 testExportLayerToExistingDatabase(self): fields = QgsFields() fields.append(QgsField('f1', QVariant.Int)) tmpfile = os.path.join(self.basetestpath, 'testCreateNewGeopackage.gpkg') options = {} options['update'] = True options['driverName'] = 'GPKG' options['layerName'] = 'table1' exporter = QgsVectorLayerExporter(tmpfile, "ogr", fields, QgsWkbTypes.Polygon, QgsCoordinateReferenceSystem(3111), False, options) self.assertFalse(exporter.errorCode(), 'unexpected export error {}: {}'.format(exporter.errorCode(), exporter.errorMessage())) options['layerName'] = 'table2' exporter = QgsVectorLayerExporter(tmpfile, "ogr", fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem(3113), False, options) self.assertFalse(exporter.errorCode(), 'unexpected export error {} : {}'.format(exporter.errorCode(), exporter.errorMessage())) del exporter # make sure layers exist lyr = QgsVectorLayer('{}|layername=table1'.format(tmpfile), "lyr1", "ogr") self.assertTrue(lyr.isValid()) self.assertEqual(lyr.crs().authid(), 'EPSG:3111') self.assertEqual(lyr.wkbType(), QgsWkbTypes.Polygon) lyr2 = QgsVectorLayer('{}|layername=table2'.format(tmpfile), "lyr2", "ogr") self.assertTrue(lyr2.isValid()) self.assertEqual(lyr2.crs().authid(), 'EPSG:3113') self.assertEqual(lyr2.wkbType(), QgsWkbTypes.Point)
def processAlgorithm(self, parameters, context, feedback): connection = self.parameterAsString(parameters, self.DATABASE, context) db = postgis.GeoDB.from_name(connection) 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) source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) table = self.parameterAsString(parameters, self.TABLENAME, context) if table: table.strip() if not table or table == '': table = source.sourceName() table = table.replace('.', '_') table = table.replace(' ', '').lower()[0:62] providerName = 'postgres' geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context) if not geomColumn: geomColumn = 'geom' options = {} if overwrite: options['overwrite'] = True if convertLowerCase: options['lowercaseFieldNames'] = True geomColumn = geomColumn.lower() if dropStringLength: options['dropStringConstraints'] = True if forceSinglePart: options['forceSinglePartGeometryType'] = True # Clear geometry column for non-geometry tables if source.wkbType() == QgsWkbTypes.NoGeometry: geomColumn = None uri = db.uri uri.setDataSource(schema, table, geomColumn, '', primaryKeyField) if encoding: options['fileEncoding'] = encoding exporter = QgsVectorLayerExporter(uri.uri(), providerName, source.fields(), source.wkbType(), source.sourceCrs(), overwrite, options) if exporter.errorCode() != QgsVectorLayerExporter.NoError: raise QgsProcessingException( self.tr('Error importing to PostGIS\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 QgsProcessingException( 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 processAlgorithm(self, parameters, context, feedback): connection_name = self.parameterAsConnectionName( parameters, self.DATABASE, context) # resolve connection details to uri try: md = QgsProviderRegistry.instance().providerMetadata('postgres') conn = md.createConnection(connection_name) except QgsProviderConnectionException: raise QgsProcessingException( self.tr('Could not retrieve connection details for {}').format( connection_name)) schema = self.parameterAsSchema(parameters, self.SCHEMA, context) overwrite = self.parameterAsBoolean(parameters, self.OVERWRITE, context) createIndex = self.parameterAsBoolean(parameters, self.CREATEINDEX, context) convertLowerCase = self.parameterAsBoolean(parameters, self.LOWERCASE_NAMES, context) dropStringLength = self.parameterAsBoolean(parameters, self.DROP_STRING_LENGTH, context) forceSinglePart = self.parameterAsBoolean(parameters, self.FORCE_SINGLEPART, context) primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id' encoding = self.parameterAsString(parameters, self.ENCODING, context) source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) table = self.parameterAsDatabaseTableName(parameters, self.TABLENAME, context) if table: table.strip() if not table or table == '': table = source.sourceName() table = table.replace('.', '_') table = table.replace(' ', '')[0:62] providerName = 'postgres' geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context) if not geomColumn: geomColumn = 'geom' options = {} if overwrite: options['overwrite'] = True if convertLowerCase: options['lowercaseFieldNames'] = True geomColumn = geomColumn.lower() if dropStringLength: options['dropStringConstraints'] = True if forceSinglePart: options['forceSinglePartGeometryType'] = True # Clear geometry column for non-geometry tables if source.wkbType() == QgsWkbTypes.NoGeometry: geomColumn = None uri = QgsDataSourceUri(conn.uri()) uri.setSchema(schema) uri.setTable(table) uri.setKeyColumn(primaryKeyField) uri.setGeometryColumn(geomColumn) if encoding: options['fileEncoding'] = encoding exporter = QgsVectorLayerExporter(uri.uri(), providerName, source.fields(), source.wkbType(), source.sourceCrs(), overwrite, options) if exporter.errorCode() != QgsVectorLayerExporter.NoError: raise QgsProcessingException( self.tr('Error importing to PostGIS\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 QgsProcessingException( self.tr('Error importing to PostGIS\n{0}').format( exporter.errorMessage())) if geomColumn and createIndex: try: options = QgsAbstractDatabaseProviderConnection.SpatialIndexOptions( ) options.geometryColumnName = geomColumn conn.createSpatialIndex(schema, table, options) except QgsProviderConnectionException as e: raise QgsProcessingException( self.tr('Error creating spatial index:\n{0}').format(e)) try: conn.vacuum(schema, table) except QgsProviderConnectionException as e: feedback.reportError( self.tr('Error vacuuming table:\n{0}').format(e)) return {}