Esempio n. 1
1
    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))'])
Esempio n. 2
0
    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
Esempio n. 3
0
 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])
Esempio n. 4
0
    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)'])
Esempio n. 5
0
        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)
Esempio n. 6
0
    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]])
Esempio n. 7
0
 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')
Esempio n. 8
0
    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)
Esempio n. 9
0
    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)
Esempio n. 10
0
    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)
Esempio n. 13
0
    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))
Esempio n. 14
0
    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)
Esempio n. 15
-1
    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)))'])