Skip to content

Commit a3af1f9

Browse files
committed
[processing][gdal] Add unit tests for Dissolve algorithm
Also: Thanks to @agiudiceandrea: Fixes #19900 Statistics were erroneously computed on the dissolve field, rather than on the statistic attribute field as it should be. Fixes #19307 Handle filenames with white spaces (in the same way as Buffer, OffsetCurve, OneSideBuffer, PintsAlongLines algs).
1 parent 6e06c32 commit a3af1f9

File tree

2 files changed

+151
-5
lines changed

2 files changed

+151
-5
lines changed

python/plugins/processing/algs/gdal/Dissolve.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -154,21 +154,21 @@ def getConsoleCommands(self, parameters, context, feedback, executing=True):
154154
if self.parameterAsBool(parameters, self.COMPUTE_AREA, context):
155155
tokens.append("SUM(ST_Area({0})) AS area, ST_Perimeter(ST_Union({0})) AS perimeter".format(geometry))
156156

157-
statsField = self.parameterAsString(parameters, self.FIELD, context)
157+
statsField = self.parameterAsString(parameters, self.STATISTICS_ATTRIBUTE, context)
158158
if statsField and self.parameterAsBool(parameters, self.COMPUTE_STATISTICS, context):
159159
tokens.append("SUM({0}) AS sum, MIN({0}) AS min, MAX({0}) AS max, AVG({0}) AS avg".format(statsField))
160160

161161
params = ','.join(tokens)
162162
if params:
163163
if self.parameterAsBool(parameters, self.KEEP_ATTRIBUTES, context):
164-
sql = "SELECT ST_Union({}) AS {}{}, {} FROM {} GROUP BY {}".format(geometry, geometry, other_fields, params, layerName, fieldName)
164+
sql = "SELECT ST_Union({}) AS {}{}, {} FROM '{}' GROUP BY {}".format(geometry, geometry, other_fields, params, layerName, fieldName)
165165
else:
166-
sql = "SELECT ST_Union({}) AS {}, {}, {} FROM {} GROUP BY {}".format(geometry, geometry, fieldName, params, layerName, fieldName)
166+
sql = "SELECT ST_Union({}) AS {}, {}, {} FROM '{}' GROUP BY {}".format(geometry, geometry, fieldName, params, layerName, fieldName)
167167
else:
168168
if self.parameterAsBool(parameters, self.KEEP_ATTRIBUTES, context):
169-
sql = "SELECT ST_Union({}) AS {}{} FROM {} GROUP BY {}".format(geometry, geometry, other_fields, layerName, fieldName)
169+
sql = "SELECT ST_Union({}) AS {}{} FROM '{}' GROUP BY {}".format(geometry, geometry, other_fields, layerName, fieldName)
170170
else:
171-
sql = "SELECT ST_Union({}) AS {}, {} FROM {} GROUP BY {}".format(geometry, geometry, fieldName, layerName, fieldName)
171+
sql = "SELECT ST_Union({}) AS {}, {} FROM '{}' GROUP BY {}".format(geometry, geometry, fieldName, layerName, fieldName)
172172

173173
arguments.append(sql)
174174

python/plugins/processing/tests/GdalAlgorithmsTest.py

+146
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from processing.algs.gdal.AssignProjection import AssignProjection
3232
from processing.algs.gdal.ClipRasterByExtent import ClipRasterByExtent
3333
from processing.algs.gdal.ClipRasterByMask import ClipRasterByMask
34+
from processing.algs.gdal.Dissolve import Dissolve
3435
from processing.algs.gdal.gdal2tiles import gdal2tiles
3536
from processing.algs.gdal.gdalcalc import gdalcalc
3637
from processing.algs.gdal.gdaltindex import gdaltindex
@@ -611,6 +612,151 @@ def testContour(self):
611612
source + ' ' +
612613
outdir + '/check.shp'])
613614

615+
def testDissolve(self):
616+
context = QgsProcessingContext()
617+
feedback = QgsProcessingFeedback()
618+
source = os.path.join(testDataPath, 'polys.gml')
619+
source_with_space = os.path.join(testDataPath, 'filename with spaces.gml')
620+
alg = Dissolve()
621+
alg.initAlgorithm()
622+
623+
with tempfile.TemporaryDirectory() as outdir:
624+
self.assertEqual(
625+
alg.getConsoleCommands({'INPUT': source,
626+
'FIELD': 'my_field',
627+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
628+
['ogr2ogr',
629+
outdir + '/check.shp ' +
630+
source + ' ' +
631+
'-dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, my_field FROM \'polys2\' ' +
632+
'GROUP BY my_field" -f "ESRI Shapefile"'])
633+
634+
self.assertEqual(
635+
alg.getConsoleCommands({'INPUT': source_with_space,
636+
'FIELD': 'my_field',
637+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
638+
['ogr2ogr',
639+
outdir + '/check.shp ' +
640+
'"' + source_with_space + '" ' +
641+
'-dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, my_field FROM \'filename_with_spaces\' ' +
642+
'GROUP BY my_field" -f "ESRI Shapefile"'])
643+
644+
self.assertEqual(
645+
alg.getConsoleCommands({'INPUT': source,
646+
'FIELD': 'my_field',
647+
'GEOMETRY': 'the_geom',
648+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
649+
['ogr2ogr',
650+
outdir + '/check.shp ' +
651+
source + ' ' +
652+
'-dialect sqlite -sql "SELECT ST_Union(the_geom) AS the_geom, my_field FROM \'polys2\' ' +
653+
'GROUP BY my_field" -f "ESRI Shapefile"'])
654+
655+
self.assertEqual(
656+
alg.getConsoleCommands({'INPUT': source,
657+
'FIELD': 'my_field',
658+
'EXPLODE_COLLECTIONS': True,
659+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
660+
['ogr2ogr',
661+
outdir + '/check.shp ' +
662+
source + ' ' +
663+
'-dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, my_field FROM \'polys2\' ' +
664+
'GROUP BY my_field" -explodecollections -f "ESRI Shapefile"'])
665+
666+
self.assertEqual(
667+
alg.getConsoleCommands({'INPUT': source,
668+
'FIELD': 'my_field',
669+
'COUNT_FEATURES': True,
670+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
671+
['ogr2ogr',
672+
outdir + '/check.shp ' +
673+
source + ' ' +
674+
'-dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, my_field, COUNT(geometry) AS count FROM \'polys2\' ' +
675+
'GROUP BY my_field" -f "ESRI Shapefile"'])
676+
677+
self.assertEqual(
678+
alg.getConsoleCommands({'INPUT': source,
679+
'FIELD': 'my_field',
680+
'COUNT_FEATURES': True,
681+
'GEOMETRY': 'the_geom',
682+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
683+
['ogr2ogr',
684+
outdir + '/check.shp ' +
685+
source + ' ' +
686+
'-dialect sqlite -sql "SELECT ST_Union(the_geom) AS the_geom, my_field, COUNT(the_geom) AS count FROM \'polys2\' ' +
687+
'GROUP BY my_field" -f "ESRI Shapefile"'])
688+
689+
self.assertEqual(
690+
alg.getConsoleCommands({'INPUT': source,
691+
'FIELD': 'my_field',
692+
'COMPUTE_AREA': True,
693+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
694+
['ogr2ogr',
695+
outdir + '/check.shp ' +
696+
source + ' ' +
697+
'-dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, my_field, SUM(ST_Area(geometry)) AS area, ' +
698+
'ST_Perimeter(ST_Union(geometry)) AS perimeter FROM \'polys2\' ' +
699+
'GROUP BY my_field" -f "ESRI Shapefile"'])
700+
701+
self.assertEqual(
702+
alg.getConsoleCommands({'INPUT': source,
703+
'FIELD': 'my_field',
704+
'COMPUTE_AREA': True,
705+
'GEOMETRY': 'the_geom',
706+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
707+
['ogr2ogr',
708+
outdir + '/check.shp ' +
709+
source + ' ' +
710+
'-dialect sqlite -sql "SELECT ST_Union(the_geom) AS the_geom, my_field, SUM(ST_Area(the_geom)) AS area, ' +
711+
'ST_Perimeter(ST_Union(the_geom)) AS perimeter FROM \'polys2\' ' +
712+
'GROUP BY my_field" -f "ESRI Shapefile"'])
713+
714+
self.assertEqual(
715+
alg.getConsoleCommands({'INPUT': source,
716+
'FIELD': 'my_field',
717+
'COMPUTE_STATISTICS': True,
718+
'STATISTICS_ATTRIBUTE': 'my_val',
719+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
720+
['ogr2ogr',
721+
outdir + '/check.shp ' +
722+
source + ' ' +
723+
'-dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, my_field, ' +
724+
'SUM(my_val) AS sum, MIN(my_val) AS min, MAX(my_val) AS max, AVG(my_val) AS avg FROM \'polys2\' ' +
725+
'GROUP BY my_field" -f "ESRI Shapefile"'])
726+
727+
# compute stats without stats attribute, and vice versa (should be ignored)
728+
self.assertEqual(
729+
alg.getConsoleCommands({'INPUT': source,
730+
'FIELD': 'my_field',
731+
'COMPUTE_STATISTICS': True,
732+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
733+
['ogr2ogr',
734+
outdir + '/check.shp ' +
735+
source + ' ' +
736+
'-dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, my_field FROM \'polys2\' ' +
737+
'GROUP BY my_field" -f "ESRI Shapefile"'])
738+
self.assertEqual(
739+
alg.getConsoleCommands({'INPUT': source,
740+
'FIELD': 'my_field',
741+
'STATISTICS_ATTRIBUTE': 'my_val',
742+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
743+
['ogr2ogr',
744+
outdir + '/check.shp ' +
745+
source + ' ' +
746+
'-dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, my_field FROM \'polys2\' ' +
747+
'GROUP BY my_field" -f "ESRI Shapefile"'])
748+
749+
self.assertEqual(
750+
alg.getConsoleCommands({'INPUT': source,
751+
'FIELD': 'my_field',
752+
'OPTIONS': 'my opts',
753+
'OUTPUT': outdir + '/check.shp'}, context, feedback),
754+
['ogr2ogr',
755+
outdir + '/check.shp ' +
756+
source + ' ' +
757+
'-dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, my_field FROM \'polys2\' ' +
758+
'GROUP BY my_field" "my opts" -f "ESRI Shapefile"'])
759+
614760
def testGdal2Tiles(self):
615761
context = QgsProcessingContext()
616762
feedback = QgsProcessingFeedback()

0 commit comments

Comments
 (0)