diff --git a/python/plugins/processing/algs/qgis/DeleteDuplicateGeometries.py b/python/plugins/processing/algs/qgis/DeleteDuplicateGeometries.py
index 122f420df2a..cc533b5cdd5 100644
--- a/python/plugins/processing/algs/qgis/DeleteDuplicateGeometries.py
+++ b/python/plugins/processing/algs/qgis/DeleteDuplicateGeometries.py
@@ -76,11 +76,16 @@ class DeleteDuplicateGeometries(QgisAlgorithm):
total = 100.0 / source.featureCount() if source.featureCount() else 0
geoms = dict()
+ null_geom_features = set()
index = QgsSpatialIndex()
for current, f in enumerate(features):
if feedback.isCanceled():
break
+ if not f.hasGeometry():
+ null_geom_features.add(f.id())
+ continue
+
geoms[f.id()] = f.geometry()
index.addFeature(f)
@@ -115,17 +120,20 @@ class DeleteDuplicateGeometries(QgisAlgorithm):
current += 1
feedback.setProgress(int(0.80 * current * total) + 10) # takes about 80% of time
- total = 100.0 / len(unique_features) if unique_features else 1
-
# now, fetch all the feature attributes for the unique features only
# be super-smart and don't re-fetch geometries
- request = QgsFeatureRequest().setFilterFids(list(unique_features.keys())).setFlags(QgsFeatureRequest.NoGeometry)
+ distinct_geoms = set(unique_features.keys())
+ output_feature_ids = distinct_geoms.union(null_geom_features)
+ total = 100.0 / len(output_feature_ids) if output_feature_ids else 1
+
+ request = QgsFeatureRequest().setFilterFids(list(output_feature_ids)).setFlags(QgsFeatureRequest.NoGeometry)
for current, f in enumerate(source.getFeatures(request)):
if feedback.isCanceled():
break
# use already fetched geometry
- f.setGeometry(unique_features[f.id()])
+ if f.id() not in null_geom_features:
+ f.setGeometry(unique_features[f.id()])
sink.addFeature(f, QgsFeatureSink.FastInsert)
feedback.setProgress(int(0.10 * current * total) + 90) # takes about 10% of time
diff --git a/python/plugins/processing/tests/testdata/expected/delete_duplicates_with_nulls.gml b/python/plugins/processing/tests/testdata/expected/delete_duplicates_with_nulls.gml
new file mode 100644
index 00000000000..7610daf5ed6
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/delete_duplicates_with_nulls.gml
@@ -0,0 +1,48 @@
+
+
+
+
+ -1-3
+ 115
+
+
+
+
+
+ 6,2 9,2 9,3 11,5
+
+
+
+
+ -1,-1 1,-1
+
+
+
+
+ 2,0 2,2 3,2 3,3
+
+
+
+
+ 3,1 5,1
+
+
+
+
+ 7,-3 10,-3
+
+
+
+
+ 6,-3 10,1
+
+
+
+
+
+
+
diff --git a/python/plugins/processing/tests/testdata/expected/delete_duplicates_with_nulls.xsd b/python/plugins/processing/tests/testdata/expected/delete_duplicates_with_nulls.xsd
new file mode 100644
index 00000000000..1bedff81946
--- /dev/null
+++ b/python/plugins/processing/tests/testdata/expected/delete_duplicates_with_nulls.xsd
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
index 1ef6a52172c..73ad4010cc9 100755
--- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
+++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
@@ -6396,5 +6396,16 @@ tests:
name: expected/split_linez_by_length.shp
type: vector
+ - algorithm: qgis:deleteduplicategeometries
+ name: Delete Duplicates with null geometries
+ params:
+ INPUT:
+ name: lines.gml|layername=lines
+ type: vector
+ results:
+ OUTPUT:
+ name: expected/delete_duplicates_with_nulls.gml
+ type: vector
+
# See ../README.md for a description of the file format