def testCreateLayerMultiPoint(self): layer = QgsVectorLayer("MultiPoint?crs=epsg:3111&field=id:integer&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1, "test", 1]) f.setGeometry(QgsGeometry.fromWkt('MultiPoint(1 2, 3 4)')) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromWkt('MultiPoint(7 8)')) pr.addFeatures([f, f2, f3]) uri = '{} table="qgis_test"."new_table_multipoint" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:3111')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.MultiPoint) self.assertEqual(new_layer.crs().authid(), 'EPSG:3111') self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint']) features = [f.attributes() for f in new_layer.getFeatures()] self.assertEqual(features, [[1, 1, 'test', 1], [2, 2, 'test2', 3], [3, 3, 'test2', NULL]]) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['MultiPoint ((1 2),(3 4))', '', 'MultiPoint ((7 8))'])
def testSimulatedDBManagerImport(self): uri = 'point?field=f1:int' uri += '&field=f2:double(6,4)' uri += '&field=f3:string(20)' lyr = QgsVectorLayer(uri, "x", "memory") self.assertTrue(lyr.isValid()) f = QgsFeature(lyr.fields()) f['f1'] = 1 f['f2'] = 123.456 f['f3'] = '12345678.90123456789' f2 = QgsFeature(lyr.fields()) f2['f1'] = 2 lyr.dataProvider().addFeatures([f, f2]) tmpfile = os.path.join(self.basetestpath, 'testSimulatedDBManagerImport.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) ds = None options = {} options['update'] = True options['driverName'] = 'GPKG' options['layerName'] = 'my_out_table' err = QgsVectorLayerExporter.exportLayer(lyr, tmpfile, "ogr", lyr.crs(), False, options) self.assertEqual(err[0], QgsVectorLayerExporter.NoError, 'unexpected import error {0}'.format(err)) lyr = QgsVectorLayer(tmpfile + "|layername=my_out_table", "y", "ogr") self.assertTrue(lyr.isValid()) features = lyr.getFeatures() f = next(features) self.assertEqual(f['f1'], 1) self.assertEqual(f['f2'], 123.456) self.assertEqual(f['f3'], '12345678.90123456789') f = next(features) self.assertEqual(f['f1'], 2) features = None # Test overwriting without overwrite option err = QgsVectorLayerExporter.exportLayer(lyr, tmpfile, "ogr", lyr.crs(), False, options) self.assertEqual(err[0], QgsVectorLayerExporter.ErrCreateDataSource) # Test overwriting lyr = QgsVectorLayer(uri, "x", "memory") self.assertTrue(lyr.isValid()) f = QgsFeature(lyr.fields()) f['f1'] = 3 lyr.dataProvider().addFeatures([f]) options['overwrite'] = True err = QgsVectorLayerExporter.exportLayer(lyr, tmpfile, "ogr", lyr.crs(), False, options) self.assertEqual(err[0], QgsVectorLayerExporter.NoError, 'unexpected import error {0}'.format(err)) lyr = QgsVectorLayer(tmpfile + "|layername=my_out_table", "y", "ogr") self.assertTrue(lyr.isValid()) features = lyr.getFeatures() f = next(features) self.assertEqual(f['f1'], 3) features = None
def testKey(lyr, key, kfnames): self.execSQLCommand('DROP TABLE IF EXISTS qgis_test.import_test') uri = '%s table="qgis_test"."import_test" (g)' % self.dbconn if key is not None: uri += ' key=\'%s\'' % key err = QgsVectorLayerExporter.exportLayer(lyr, uri, "postgres", lyr.crs()) self.assertEqual(err[0], QgsVectorLayerExporter.NoError, 'unexpected import error {0}'.format(err)) olyr = QgsVectorLayer(uri, "y", "postgres") self.assertTrue(olyr.isValid()) flds = lyr.fields() oflds = olyr.fields() if key is None: # if the pkey was not given, it will create a pkey self.assertEqual(oflds.size(), flds.size() + 1) self.assertEqual(oflds[0].name(), kfnames[0]) for i in range(flds.size()): self.assertEqual(oflds[i + 1].name(), flds[i].name()) else: # pkey was given, no extra field generated self.assertEqual(oflds.size(), flds.size()) for i in range(oflds.size()): self.assertEqual(oflds[i].name(), flds[i].name()) pks = olyr.pkAttributeList() self.assertEqual(len(pks), len(kfnames)) for i in range(0, len(kfnames)): self.assertEqual(oflds[pks[i]].name(), kfnames[i])
def testCreateLayer(self): layer = QgsVectorLayer("Point?field=id:integer&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1, "test", 1]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2))) f4 = QgsFeature() f4.setAttributes([4, NULL, 3]) f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3))) pr.addFeatures([f, f2, f3, f4]) uri = '{} table="qgis_test"."new_table" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.Point) self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint']) features = [f.attributes() for f in new_layer.getFeatures()] self.assertEqual(features, [[1, 1, 'test', 1], [2, 2, 'test2', 3], [3, 3, 'test2', NULL], [4, 4, NULL, 3]]) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['Point (1 2)', '', 'Point (3 2)', 'Point (4 3)'])
def _test(table, schema=None): self.execSQLCommand('DROP TABLE IF EXISTS %s CASCADE' % table) uri = 'point?field=f1:int' uri += '&field=F2:double(6,4)' uri += '&field=f3:string(20)' lyr = QgsVectorLayer(uri, "x", "memory") self.assertTrue(lyr.isValid()) table = ("%s" % table) if schema is None else ("\"%s\".\"%s\"" % (schema, table)) dest_uri = "%s sslmode=disable table=%s (geom) sql" % (self.dbconn, table) err = QgsVectorLayerExporter.exportLayer(lyr, dest_uri, "postgres", lyr.crs()) olyr = QgsVectorLayer(dest_uri, "y", "postgres") self.assertTrue(olyr.isValid(), "Failed URI: %s" % dest_uri)
def testOverwriteExisting(self): layer = QgsVectorLayer("NoGeometry?field=pk:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([133]) pr.addFeatures([f]) uri = '{} table="qgis_test"."sacrificialLamb" sql='.format(self.dbconn) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual([f.attributes() for f in new_layer.getFeatures()], [[1]]) # try to overwrite error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem()) self.assertEqual(error, QgsVectorLayerExporter.ErrCreateLayer) # should not have overwritten features self.assertEqual([f.attributes() for f in new_layer.getFeatures()], [[1]])
def testNumericPrecision(self): uri = 'point?field=f1:int' uri += '&field=f2:double(6,4)' uri += '&field=f3:string(20)' lyr = QgsVectorLayer(uri, "x", "memory") self.assertTrue(lyr.isValid()) f = QgsFeature(lyr.fields()) f['f1'] = 1 f['f2'] = 123.456 f['f3'] = '12345678.90123456789' lyr.dataProvider().addFeatures([f]) uri = '%s table="qgis_test"."b18155" (g) key=\'f1\'' % (self.dbconn) self.execSQLCommand('DROP TABLE IF EXISTS qgis_test.b18155') err = QgsVectorLayerExporter.exportLayer(lyr, uri, "postgres", lyr.crs()) self.assertEqual(err[0], QgsVectorLayerExporter.NoError, 'unexpected import error {0}'.format(err)) lyr = QgsVectorLayer(uri, "y", "postgres") self.assertTrue(lyr.isValid()) f = next(lyr.getFeatures()) self.assertEqual(f['f1'], 1) self.assertEqual(f['f2'], 123.456) self.assertEqual(f['f3'], '12345678.90123456789')
def accept(self): if self.mode == self.ASK_FOR_INPUT_MODE: # create the input layer (if not already done) and # update available options self.reloadInputLayer() # sanity checks if self.inLayer is None: QMessageBox.critical(self, self.tr("Import to Database"), self.tr("Input layer missing or not valid.")) return if self.cboTable.currentText() == "": QMessageBox.critical(self, self.tr("Import to Database"), self.tr("Output table name is required.")) return if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked(): if not self.widgetSourceSrid.crs().isValid(): QMessageBox.critical(self, self.tr("Import to Database"), self.tr("Invalid source srid: must be a valid crs.")) return if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked(): if not self.widgetTargetSrid.crs().isValid(): QMessageBox.critical(self, self.tr("Import to Database"), self.tr("Invalid target srid: must be a valid crs.")) return with OverrideCursor(Qt.WaitCursor): # store current input layer crs and encoding, so I can restore it prevInCrs = self.inLayer.crs() prevInEncoding = self.inLayer.dataProvider().encoding() try: schema = self.outUri.schema() if not self.cboSchema.isEnabled() else self.cboSchema.currentText() table = self.cboTable.currentText() # get pk and geom field names from the source layer or use the # ones defined by the user srcUri = QgsDataSourceUri(self.inLayer.source()) pk = srcUri.keyColumn() if not self.chkPrimaryKey.isChecked() else self.editPrimaryKey.text() if not pk: pk = self.default_pk if self.inLayer.isSpatial() and self.chkGeomColumn.isEnabled(): geom = srcUri.geometryColumn() if not self.chkGeomColumn.isChecked() else self.editGeomColumn.text() if not geom: geom = self.default_geom else: geom = None options = {} if self.chkLowercaseFieldNames.isEnabled() and self.chkLowercaseFieldNames.isChecked(): pk = pk.lower() if geom: geom = geom.lower() options['lowercaseFieldNames'] = True # get output params, update output URI self.outUri.setDataSource(schema, table, geom, "", pk) typeName = self.db.dbplugin().typeName() providerName = self.db.dbplugin().providerName() if typeName == 'gpkg': uri = self.outUri.database() options['update'] = True options['driverName'] = 'GPKG' options['layerName'] = table else: uri = self.outUri.uri(False) if self.chkDropTable.isChecked(): options['overwrite'] = True if self.chkSinglePart.isEnabled() and self.chkSinglePart.isChecked(): options['forceSinglePartGeometryType'] = True outCrs = QgsCoordinateReferenceSystem() if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked(): outCrs = self.widgetTargetSrid.crs() # update input layer crs and encoding if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked(): inCrs = self.widgetSourceSrid.crs() self.inLayer.setCrs(inCrs) if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked(): enc = self.cboEncoding.currentText() self.inLayer.setProviderEncoding(enc) onlySelected = self.chkSelectedFeatures.isChecked() # do the import! ret, errMsg = QgsVectorLayerExporter.exportLayer(self.inLayer, uri, providerName, outCrs, onlySelected, options) except Exception as e: ret = -1 errMsg = str(e) finally: # restore input layer crs and encoding self.inLayer.setCrs(prevInCrs) self.inLayer.setProviderEncoding(prevInEncoding) if ret != 0: output = QgsMessageViewer() output.setTitle(self.tr("Import to Database")) output.setMessageAsPlainText(self.tr("Error {0}\n{1}").format(ret, errMsg)) output.showMessage() return # create spatial index if self.chkSpatialIndex.isEnabled() and self.chkSpatialIndex.isChecked(): self.db.connector.createSpatialIndex((schema, table), geom) # add comment on table supportCom = self.db.supportsComment() if self.chkCom.isEnabled() and self.chkCom.isChecked() and supportCom: # using connector executing COMMENT ON TABLE query (with editCome.text() value) com = self.editCom.text() self.db.connector.commentTable(schema, table, com) self.db.connection().reconnect() self.db.refresh() QMessageBox.information(self, self.tr("Import to Database"), self.tr("Import was successful.")) return QDialog.accept(self)
def processAlgorithm(self, parameters, context, feedback): database = self.getParameterValue(self.DATABASE) uri = QgsDataSourceUri(database) if uri.database() is '': if '|layerid' in database: database = database[:database.find('|layerid')] uri = QgsDataSourceUri('dbname=\'%s\'' % (database)) 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) layerUri = self.getParameterValue(self.INPUT) layer = QgsProcessingUtils.mapLayerFromString(layerUri, context) table = self.getParameterValue(self.TABLENAME) if table: table.strip() if not table or table == '': table = layer.name() table = table.replace(' ', '').lower() providerName = 'spatialite' geomColumn = self.getParameterValue(self.GEOMETRY_COLUMN) if not geomColumn: geomColumn = 'the_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 not layer.hasGeometryType(): geomColumn = None uri = db.uri uri.setDataSource('', table, geomColumn, '', primaryKeyField) if encoding: layer.setProviderEncoding(encoding) (ret, errMsg) = QgsVectorLayerExporter.exportLayer( layer, uri.uri(), providerName, self.crs, False, options, ) if ret != 0: raise GeoAlgorithmExecutionException( self.tr('Error importing to Spatialite\n{0}').format(errMsg)) if geomColumn and createIndex: db.create_spatial_index(table, geomColumn)
def accept(self): # sanity checks if self.editOutputFile.text() == "": QMessageBox.information(self, self.tr("Export to file"), self.tr("Output file name is required")) return if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked(): try: sourceSrid = int(self.editSourceSrid.text()) except ValueError: QMessageBox.information(self, self.tr("Export to file"), self.tr("Invalid source srid: must be an integer")) return if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked(): try: targetSrid = int(self.editTargetSrid.text()) except ValueError: QMessageBox.information(self, self.tr("Export to file"), self.tr("Invalid target srid: must be an integer")) return with OverrideCursor(Qt.WaitCursor): # store current input layer crs, so I can restore it later prevInCrs = self.inLayer.crs() try: uri = self.editOutputFile.text() providerName = "ogr" options = {} # set the OGR driver will be used driverName = self.cboFileFormat.currentData() options['driverName'] = driverName # set the output file encoding if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked(): enc = self.cboEncoding.currentText() options['fileEncoding'] = enc if self.chkDropTable.isChecked(): options['overwrite'] = True outCrs = QgsCoordinateReferenceSystem() if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked(): targetSrid = int(self.editTargetSrid.text()) outCrs = QgsCoordinateReferenceSystem(targetSrid) # update input layer crs if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked(): sourceSrid = int(self.editSourceSrid.text()) inCrs = QgsCoordinateReferenceSystem(sourceSrid) self.inLayer.setCrs(inCrs) # do the export! ret, errMsg = QgsVectorLayerExporter.exportLayer(self.inLayer, uri, providerName, outCrs, False, options) except Exception as e: ret = -1 errMsg = str(e) finally: # restore input layer crs and encoding self.inLayer.setCrs(prevInCrs) if ret != 0: QMessageBox.warning(self, self.tr("Export to file"), self.tr("Error {0}\n{1}").format(ret, errMsg)) return # create spatial index # if self.chkSpatialIndex.isEnabled() and self.chkSpatialIndex.isChecked(): # self.db.connector.createSpatialIndex( (schema, table), geom ) QMessageBox.information(self, self.tr("Export to file"), self.tr("Export finished.")) return QDialog.accept(self)
def newEntranceLayer(self): vl = QgsVectorLayer("Point?crs=", "memory:Entrances", "memory") provider = vl.dataProvider() provider.addAttributes([ QgsField(EntranceTool.id_attribute, QVariant.Int), QgsField(EntranceTool.category_attribute, QVariant.String), QgsField(EntranceTool.subcat_attribute, QVariant.String), QgsField(EntranceTool.level_attribute, QVariant.Double) ]) if vl.crs().toWkt() == "": vl.setCrs(QgsProject.instance().crs()) vl.updateFields() if self.entrancedlg.e_shp_radioButton.isChecked( ): # layer_type == 'shapefile': path = self.entrancedlg.lineEditEntrances.text() if path and path != '': filename = os.path.basename(path) location = os.path.abspath(path) crs = QgsCoordinateReferenceSystem() crs.createFromSrid(3857) shph.createShapeFile(vl, path, crs) vl = self.iface.addVectorLayer(location, filename[:-4], "ogr") else: vl = 'invalid data source' elif self.entrancedlg.e_postgis_radioButton.isChecked(): db_path = self.entrancedlg.lineEditEntrances.text() if db_path and db_path != '': (database, schema, table_name) = db_path.split(':') db_con_info = self.entrancedlg.dbsettings_dlg.available_dbs[ database] uri = QgsDataSourceUri() # passwords, usernames need to be empty if not provided or else connection will fail if 'service' in list(db_con_info.keys()): uri.setConnection(db_con_info['service'], '', '', '') elif 'password' in list(db_con_info.keys()): uri.setConnection(db_con_info['host'], db_con_info['port'], db_con_info['dbname'], db_con_info['user'], db_con_info['password']) else: print(db_con_info) # db_con_info['host'] uri.setConnection('', db_con_info['port'], db_con_info['dbname'], '', '') uri.setDataSource(schema, table_name, "geom") error = QgsVectorLayerExporter.exportLayer( vl, uri.uri(), "postgres", vl.crs()) if error[0] != QgsVectorLayerExporter.NoError: print("Error when creating postgis layer: ", error[1]) vl = 'duplicate' else: vl = QgsVectorLayer(uri.uri(), table_name, "postgres") else: vl = 'invalid data source' if vl == 'invalid data source': msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Specify output path!') msgBar.pushWidget(msg, Qgis.Info, 10) elif vl == 'duplicate': msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Fronatges layer already exists!') msgBar.pushWidget(msg, Qgis.Info, 10) elif not vl: msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Entrance layer failed to load!') msgBar.pushWidget(msg, Qgis.Info, 10) else: QgsProject.instance().addMapLayer(vl) msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Entrances layer created!') msgBar.pushWidget(msg, Qgis.Info, 10) vl.startEditing() self.updateEntranceLayer() self.entrancedlg.closePopUpEntrances()
def accept(self): if self.mode == self.ASK_FOR_INPUT_MODE: # create the input layer (if not already done) and # update available options self.reloadInputLayer() # sanity checks if self.inLayer is None: QMessageBox.critical(self, self.tr("Import to Database"), self.tr("Input layer missing or not valid.")) return if self.cboTable.currentText() == "": QMessageBox.critical(self, self.tr("Import to Database"), self.tr("Output table name is required.")) return if self.chkSourceSrid.isEnabled() and self.chkSourceSrid.isChecked(): if not self.widgetSourceSrid.crs().isValid(): QMessageBox.critical( self, self.tr("Import to Database"), self.tr("Invalid source srid: must be a valid crs.")) return if self.chkTargetSrid.isEnabled() and self.chkTargetSrid.isChecked(): if not self.widgetTargetSrid.crs().isValid(): QMessageBox.critical( self, self.tr("Import to Database"), self.tr("Invalid target srid: must be a valid crs.")) return with OverrideCursor(Qt.WaitCursor): # store current input layer crs and encoding, so I can restore it prevInCrs = self.inLayer.crs() prevInEncoding = self.inLayer.dataProvider().encoding() try: schema = self.outUri.schema() if not self.cboSchema.isEnabled( ) else self.cboSchema.currentText() table = self.cboTable.currentText() # get pk and geom field names from the source layer or use the # ones defined by the user srcUri = QgsDataSourceUri(self.inLayer.source()) pk = srcUri.keyColumn() if not self.chkPrimaryKey.isChecked( ) else self.editPrimaryKey.text() if not pk: pk = self.default_pk if self.inLayer.isSpatial() and self.chkGeomColumn.isEnabled(): geom = srcUri.geometryColumn( ) if not self.chkGeomColumn.isChecked( ) else self.editGeomColumn.text() if not geom: geom = self.default_geom else: geom = None options = {} if self.chkLowercaseFieldNames.isEnabled( ) and self.chkLowercaseFieldNames.isChecked(): pk = pk.lower() if geom: geom = geom.lower() options['lowercaseFieldNames'] = True # get output params, update output URI self.outUri.setDataSource(schema, table, geom, "", pk) typeName = self.db.dbplugin().typeName() providerName = self.db.dbplugin().providerName() if typeName == 'gpkg': uri = self.outUri.database() options['update'] = True options['driverName'] = 'GPKG' options['layerName'] = table else: uri = self.outUri.uri(False) if self.chkDropTable.isChecked(): options['overwrite'] = True if self.chkSinglePart.isEnabled( ) and self.chkSinglePart.isChecked(): options['forceSinglePartGeometryType'] = True outCrs = QgsCoordinateReferenceSystem() if self.chkTargetSrid.isEnabled( ) and self.chkTargetSrid.isChecked(): outCrs = self.widgetTargetSrid.crs() # update input layer crs and encoding if self.chkSourceSrid.isEnabled( ) and self.chkSourceSrid.isChecked(): inCrs = self.widgetSourceSrid.crs() self.inLayer.setCrs(inCrs) if self.chkEncoding.isEnabled() and self.chkEncoding.isChecked( ): enc = self.cboEncoding.currentText() self.inLayer.setProviderEncoding(enc) onlySelected = self.chkSelectedFeatures.isChecked() # do the import! ret, errMsg = QgsVectorLayerExporter.exportLayer( self.inLayer, uri, providerName, outCrs, onlySelected, options) except Exception as e: ret = -1 errMsg = str(e) finally: # restore input layer crs and encoding self.inLayer.setCrs(prevInCrs) self.inLayer.setProviderEncoding(prevInEncoding) if ret != 0: output = QgsMessageViewer() output.setTitle(self.tr("Import to Database")) output.setMessageAsPlainText( self.tr("Error {0}\n{1}").format(ret, errMsg)) output.showMessage() return # create spatial index if self.chkSpatialIndex.isEnabled() and self.chkSpatialIndex.isChecked( ): self.db.connector.createSpatialIndex((schema, table), geom) # add comment on table supportCom = self.db.supportsComment() if self.chkCom.isEnabled() and self.chkCom.isChecked() and supportCom: # using connector executing COMMENT ON TABLE query (with editCome.text() value) com = self.editCom.text() self.db.connector.commentTable(schema, table, com) self.db.connection().reconnect() self.db.refresh() QMessageBox.information(self, self.tr("Import to Database"), self.tr("Import was successful.")) return QDialog.accept(self)
def testExtentFromGeometryTable(self): """ Check if the behavior of the mssql provider if extent is defined in the geometry_column table """ # Create a layer layer = QgsVectorLayer( "Point?field=id:integer&field=fldtxt:string&field=fldint:integer", "layer", "memory") pr = layer.dataProvider() f1 = QgsFeature() f1.setAttributes([1, "test", 1]) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2))) f4 = QgsFeature() f4.setAttributes([4, NULL, 3]) f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3))) pr.addFeatures([f1, f2, f3, f4]) uri = '{} table="qgis_test"."layer_extent_in_geometry_table" sql='.format( self.dbconn) QgsVectorLayerExporter.exportLayer( layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) layerUri = QgsDataSourceUri(uri) # Load and check if the layer is valid loadedLayer = QgsVectorLayer(layerUri.uri(), "valid", "mssql") self.assertTrue(loadedLayer.isValid()) extent = loadedLayer.extent() self.assertEqual(extent.toString(1), QgsRectangle(1.0, 2.0, 4.0, 3.0).toString(1)) # Load with flag extent in geometry_columns table and check if the layer is still valid and extent doesn't change layerUri.setParam('extentInGeometryColumns', '1') loadedLayer = QgsVectorLayer(layerUri.uri(), "invalid", "mssql") self.assertTrue(loadedLayer.isValid()) extent = loadedLayer.extent() self.assertEqual(extent.toString(1), QgsRectangle(1.0, 2.0, 4.0, 3.0).toString(1)) md = QgsProviderRegistry.instance().providerMetadata('mssql') conn = md.createConnection(self.dbconn, {}) conn.addField(QgsField('qgis_xmin', QVariant.Double, 'FLOAT(24)'), 'dbo', 'geometry_columns') conn.addField(QgsField('qgis_xmax', QVariant.Double, 'FLOAT(24)'), 'dbo', 'geometry_columns') conn.addField(QgsField('qgis_ymin', QVariant.Double, 'FLOAT(24)'), 'dbo', 'geometry_columns') conn.addField(QgsField('qgis_ymax', QVariant.Double, 'FLOAT(24)'), 'dbo', 'geometry_columns') # try with empty attribute layerUri.setParam('extentInGeometryColumns', '1') loadedLayer = QgsVectorLayer(layerUri.uri(), "invalid", "mssql") self.assertTrue(loadedLayer.isValid()) self.assertTrue(loadedLayer.isValid()) extent = loadedLayer.extent() self.assertEqual(extent.toString(1), QgsRectangle(1.0, 2.0, 4.0, 3.0).toString(1)) conn.execSql( 'UPDATE dbo.geometry_columns SET qgis_xmin=0, qgis_xmax=5.5, qgis_ymin=0.5, qgis_ymax=6 WHERE f_table_name=\'layer_extent_in_geometry_table\'' ) # try with valid attribute layerUri.setParam('extentInGeometryColumns', '1') loadedLayer = QgsVectorLayer(layerUri.uri(), "valid", "mssql") self.assertTrue(loadedLayer.isValid()) extent = loadedLayer.extent() self.assertEqual(extent.toString(1), QgsRectangle(0.0, 0.5, 5.5, 6.0).toString(1))
def processAlgorithm(self, parameters, context, feedback): database = self.getParameterValue(self.DATABASE) uri = QgsDataSourceUri(database) if uri.database() is '': if '|layerid' in database: database = database[:database.find('|layerid')] uri = QgsDataSourceUri('dbname=\'%s\'' % (database)) 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) layerUri = self.getParameterValue(self.INPUT) layer = QgsProcessingUtils.mapLayerFromString(layerUri, context) table = self.getParameterValue(self.TABLENAME) if table: table.strip() if not table or table == '': table = layer.name() table = table.replace(' ', '').lower() providerName = 'spatialite' geomColumn = self.getParameterValue(self.GEOMETRY_COLUMN) if not geomColumn: geomColumn = 'the_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 not layer.hasGeometryType(): geomColumn = None uri = db.uri uri.setDataSource('', table, geomColumn, '', primaryKeyField) if encoding: layer.setProviderEncoding(encoding) (ret, errMsg) = QgsVectorLayerExporter.exportLayer( layer, uri.uri(), providerName, self.crs, False, options, ) if ret != 0: raise GeoAlgorithmExecutionException( self.tr('Error importing to Spatialite\n{0}').format(errMsg)) if geomColumn and createIndex: db.create_spatial_index(table, geomColumn)
def testInsertPolygonInMultiPolygon(self): layer = QgsVectorLayer("MultiPolygon?crs=epsg:4326&field=id:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1]) f.setGeometry(QgsGeometry.fromWkt('MultiPolygon(((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))')) pr.addFeatures([f]) uri = '{} table="qgis_test"."new_table_multipolygon" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.MultiPolygon) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))']) # add single part f2 = QgsFeature() f2.setAttributes([2]) f2.setGeometry(QgsGeometry.fromWkt('Polygon((30 0, 31 0, 31 1, 30 1, 30 0))')) self.assertTrue(new_layer.dataProvider().addFeatures([f2])) # should become multipart geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))', 'MultiPolygon (((30 0, 31 0, 31 1, 30 1, 30 0)))'])