Skip to content

Commit

Permalink
Merge pull request #31810 from elpaso/bugfix-gh31634-processing-in-pl…
Browse files Browse the repository at this point in the history
…ace-unique-constraints-3_4-backport

Bugfix gh31634 processing in place unique constraints 3 4 backport
  • Loading branch information
elpaso committed Sep 17, 2019
2 parents 207de75 + 81056e6 commit ab955a1
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
9 changes: 7 additions & 2 deletions python/plugins/processing/gui/AlgorithmExecutor.py
Expand Up @@ -184,8 +184,13 @@ def execute_in_place_run(alg, parameters, context=None, feedback=None, raise_exc
active_layer.deleteFeature(f.id())
# Get the new ids
old_ids = set([f.id() for f in active_layer.getFeatures(req)])
if not active_layer.addFeatures(new_features):
raise QgsProcessingException(tr("Error adding processed features back into the layer."))
# If multiple new features were created, we need to pass
# them to createFeatures to manage constraints correctly
for f in new_features:
new_feature = QgsVectorLayerUtils.createFeature(active_layer, f.geometry(), dict(enumerate(f.attributes())), context.expressionContext())
if not active_layer.addFeatures([new_feature]):
raise QgsProcessingException(tr("Error adding processed features back into the layer."))

new_ids = set([f.id() for f in active_layer.getFeatures(req)])
new_feature_ids += list(new_ids - old_ids)

Expand Down
60 changes: 57 additions & 3 deletions tests/src/python/test_qgsprocessinginplace.py
Expand Up @@ -12,18 +12,36 @@
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

from qgis.PyQt.QtCore import QCoreApplication, QVariant
import re
import os
from qgis.PyQt.QtCore import QCoreApplication, QVariant, QTemporaryDir
from qgis.core import (
QgsFeature, QgsGeometry, QgsSettings, QgsApplication, QgsMemoryProviderUtils, QgsWkbTypes, QgsField, QgsFields, QgsProcessingFeatureSourceDefinition, QgsProcessingContext, QgsProcessingFeedback, QgsCoordinateReferenceSystem, QgsProject, QgsProcessingException
QgsFeature,
QgsGeometry,
QgsSettings,
QgsApplication,
QgsMemoryProviderUtils,
QgsWkbTypes,
QgsField,
QgsFields,
QgsProcessingFeatureSourceDefinition,
QgsProcessingContext,
QgsProcessingFeedback,
QgsCoordinateReferenceSystem,
QgsProject,
QgsProcessingException,
QgsVectorLayer,
QgsVectorLayerUtils,
)
from processing.core.Processing import Processing
from processing.core.ProcessingConfig import ProcessingConfig
from processing.tools import dataobjects
from processing.gui.AlgorithmExecutor import execute_in_place_run
from qgis.testing import start_app, unittest
from utilities import unitTestDataPath
from qgis.PyQt.QtTest import QSignalSpy
from qgis.analysis import QgsNativeAlgorithms
from qgis.core import QgsVectorLayerUtils
import shutil

start_app()

Expand Down Expand Up @@ -821,6 +839,42 @@ def test_difference_on_invalid_geometries(self):
old_features, new_features = self._test_difference_on_invalid_geometries(2)
self.assertEqual(len(new_features), 1)

def test_unique_constraints(self):
"""Test issue #31634"""
temp_dir = QTemporaryDir()
temp_path = temp_dir.path()
gpkg_name = 'bug_31634_Multi_to_Singleparts_FID.gpkg'
gpkg_path = os.path.join(temp_path, gpkg_name)
shutil.copyfile(os.path.join(unitTestDataPath(), gpkg_name), gpkg_path)

gpkg_layer = QgsVectorLayer(gpkg_path + '|layername=Multi_to_Singleparts_FID_bug', 'lyr', 'ogr')
self.assertTrue(gpkg_layer.isValid())
QgsProject.instance().addMapLayers([gpkg_layer])

# Test that makeFeaturesCompatible set to NULL unique constraint fields
feature = next(gpkg_layer.getFeatures())

feedback = ConsoleFeedBack()
context = dataobjects.createContext(feedback)
context.setProject(QgsProject.instance())

alg = self.registry.createAlgorithmById('native:multiparttosingleparts')
self.assertIsNotNone(alg)

parameters = {
'INPUT': gpkg_layer,
'OUTPUT': ':memory',
}

ok, _ = execute_in_place_run(
alg, parameters, context=context, feedback=feedback, raise_exceptions=True)

pks = set()
for f in gpkg_layer.getFeatures():
pks.add(f.attribute(0))

self.assertTrue(gpkg_layer.commitChanges())


if __name__ == '__main__':
unittest.main()
Binary file not shown.

0 comments on commit ab955a1

Please sign in to comment.