From 96808065a45747a64235db17649be26b5d23f321 Mon Sep 17 00:00:00 2001 From: Alessandro Pasotti Date: Thu, 14 Oct 2021 12:09:27 +0200 Subject: [PATCH 1/4] Server getprint atlas: fix pk-less layers Fix #30817 --- src/server/services/wms/qgswmsrenderer.cpp | 32 +- .../test_qgsserver_wms_getprint_atlas.py | 23 +- .../qgis_server/bug_gh30817_atlas_pk.qgs | 808 ++++++++++++++++++ .../qgis_server/bug_gh30817_atlas_pk_data.csv | 4 + 4 files changed, 855 insertions(+), 12 deletions(-) create mode 100644 tests/testdata/qgis_server/bug_gh30817_atlas_pk.qgs create mode 100644 tests/testdata/qgis_server/bug_gh30817_atlas_pk_data.csv diff --git a/src/server/services/wms/qgswmsrenderer.cpp b/src/server/services/wms/qgswmsrenderer.cpp index 229ce83ac28e..767333baca4b 100644 --- a/src/server/services/wms/qgswmsrenderer.cpp +++ b/src/server/services/wms/qgswmsrenderer.cpp @@ -362,9 +362,10 @@ namespace QgsWms else { const QgsAttributeList pkIndexes = cLayer->primaryKeyAttributes(); - if ( pkIndexes.size() < 1 ) + const int pkIndexesSize {std::max( pkIndexes.size(), 1 )}; + if ( pkIndexesSize ) { - throw QgsException( QStringLiteral( "An error occurred during the Atlas print" ) ); + QgsDebugMsgLevel( QStringLiteral( "Atlas print: layer %1 has no primary key attributes" ).arg( cLayer->name() ), 2 ); } QStringList pkAttributeNames; for ( int pkIndex : pkIndexes ) @@ -372,8 +373,8 @@ namespace QgsWms pkAttributeNames.append( cLayer->fields().at( pkIndex ).name() ); } - int nAtlasFeatures = atlasPk.size() / pkIndexes.size(); - if ( nAtlasFeatures * pkIndexes.size() != atlasPk.size() ) //Test is atlasPk.size() is a multiple of pkIndexes.size(). Bail out if not + const int nAtlasFeatures = atlasPk.size() / pkIndexesSize; + if ( nAtlasFeatures * pkIndexesSize != atlasPk.size() ) //Test is atlasPk.size() is a multiple of pkIndexesSize. Bail out if not { throw QgsBadRequestException( QgsServiceException::QGIS_InvalidParameterValue, QStringLiteral( "Wrong number of ATLAS_PK parameters" ) ); @@ -383,7 +384,7 @@ namespace QgsWms if ( nAtlasFeatures > maxAtlasFeatures ) { throw QgsBadRequestException( QgsServiceException::QGIS_InvalidParameterValue, - QString( "%1 atlas features have been requestet, but the project configuration only allows printing %2 atlas features at a time" ) + QString( "%1 atlas features have been requested, but the project configuration only allows printing %2 atlas features at a time" ) .arg( nAtlasFeatures ).arg( maxAtlasFeatures ) ); } @@ -399,14 +400,23 @@ namespace QgsWms filterString.append( "( " ); - for ( int j = 0; j < pkIndexes.size(); ++j ) + // If the layer has no PK attributes, assume FID + if ( pkAttributeNames.isEmpty() ) { - if ( j > 0 ) + filterString.append( QStringLiteral( "$id = %1" ).arg( atlasPk.at( currentAtlasPk ) ) ); + ++currentAtlasPk; + } + else + { + for ( int j = 0; j < pkIndexes.size(); ++j ) { - filterString.append( " AND " ); + if ( j > 0 ) + { + filterString.append( " AND " ); + } + filterString.append( QStringLiteral( "\"%1\" = %2" ).arg( pkAttributeNames.at( j ), atlasPk.at( currentAtlasPk ) ) ); + ++currentAtlasPk; } - filterString.append( QString( "\"%1\" = %2" ).arg( pkAttributeNames.at( j ), atlasPk.at( currentAtlasPk ) ) ); - ++currentAtlasPk; } filterString.append( " )" ); @@ -417,7 +427,7 @@ namespace QgsWms atlas->setFilterExpression( filterString, errorString ); if ( !errorString.isEmpty() ) { - throw QgsException( QStringLiteral( "An error occurred during the Atlas print" ) ); + throw QgsException( QStringLiteral( "An error occurred during the Atlas print: %1" ).arg( errorString ) ); } } } diff --git a/tests/src/python/test_qgsserver_wms_getprint_atlas.py b/tests/src/python/test_qgsserver_wms_getprint_atlas.py index 9251982ff281..2cefd2db0aef 100644 --- a/tests/src/python/test_qgsserver_wms_getprint_atlas.py +++ b/tests/src/python/test_qgsserver_wms_getprint_atlas.py @@ -22,9 +22,11 @@ import urllib.parse from qgis.testing import unittest - +from utilities import unitTestDataPath from test_qgsserver import QgsServerTestBase +from qgis.core import QgsProject + class TestQgsServerWMSGetPrintAtlas(QgsServerTestBase): """QGIS Server WMS Tests for GetPrint atlas request""" @@ -55,6 +57,25 @@ def test_wms_getprint_atlas_getProjectSettings(self): self.assertTrue('atlasEnabled="1"' in str(r)) self.assertTrue('' in str(r)) + def test_wms_getprint_atlas_no_pk(self): + """Test issue GH #30817""" + + project = QgsProject() + self.assertTrue(project.read(os.path.join(unitTestDataPath(), 'qgis_server', 'bug_gh30817_atlas_pk.qgs'))) + qs = "?" + "&".join(["%s=%s" % i for i in list({ + "SERVICE": "WMS", + "VERSION": "1.3.0", + "REQUEST": "GetPrint", + "TEMPLATE": "layout_csv", + "TRANSPARENT": "true", + "FORMAT": "png", + "DPI": "50", + "CRS": "EPSG:2056", + "ATLAS_PK": "2", + }.items())]) + r, h = self._result(self._execute_request_project(qs, project)) + self._img_diff_error(r, h, "WMS_GetPrint_Atlas_No_Pk") + if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/qgis_server/bug_gh30817_atlas_pk.qgs b/tests/testdata/qgis_server/bug_gh30817_atlas_pk.qgs new file mode 100644 index 000000000000..ff4359e4d448 --- /dev/null +++ b/tests/testdata/qgis_server/bug_gh30817_atlas_pk.qgs @@ -0,0 +1,808 @@ + + + + + + + + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",DATUM["World Geodetic System 1984",ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + + + + + + + + + data_34a17c5e_39a1_493a_af95_b5a233b40db1 + + + + + + + + + + + meters + + -2217275.19168864423409104 + 3779713.49600001005455852 + -2217273.09938558330759406 + 3779715.24036237737163901 + + 0 + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",DATUM["World Geodetic System 1984",ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + 0 + + + + + + + + + + + + Annotations_c1e8b38e_61dd_49f2_8dc3_36f4fd4a02fd + + + + + Annotations + + + + + 0 + 0 + + + + + false + + + + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + + + 1 + 0 + + + + + + 3.97240340488328014 + 45.15886406139620135 + 5.44448585846197997 + 46.14132936036769905 + + + -19.91812149041812674 + 32.12487455193483754 + -19.91810358996271191 + 32.12488719067417264 + + data_34a17c5e_39a1_493a_af95_b5a233b40db1 + ./bug_gh30817_atlas_pk_data.csv + + + + data_csv + + + PROJCRS["CH1903+ / LV95",BASEGEOGCRS["CH1903+",DATUM["CH1903+",ELLIPSOID["Bessel 1841",6377397.155,299.1528128,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4150]],CONVERSION["Swiss Oblique Mercator 1995",METHOD["Hotine Oblique Mercator (variant B)",ID["EPSG",9815]],PARAMETER["Latitude of projection centre",46.9524055555556,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8811]],PARAMETER["Longitude of projection centre",7.43958333333333,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8812]],PARAMETER["Azimuth of initial line",90,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8813]],PARAMETER["Angle from Rectified to Skew Grid",90,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8814]],PARAMETER["Scale factor on initial line",1,SCALEUNIT["unity",1],ID["EPSG",8815]],PARAMETER["Easting at projection centre",2600000,LENGTHUNIT["metre",1],ID["EPSG",8816]],PARAMETER["Northing at projection centre",1200000,LENGTHUNIT["metre",1],ID["EPSG",8817]]],CS[Cartesian,2],AXIS["(E)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["(N)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Cadastre, engineering survey, topographic mapping (large and medium scale)."],AREA["Liechtenstein; Switzerland."],BBOX[45.82,5.96,47.81,10.49]],ID["EPSG",2056]] + +proj=somerc +lat_0=46.9524055555556 +lon_0=7.43958333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs + 47 + 2056 + EPSG:2056 + CH1903+ / LV95 + somerc + EPSG:7004 + false + + + + + + + dataset + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + false + + + + + + + + + + + + + ogr + + + + + + + + + + + 1 + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + + + + + + + "WKT" + + + + + + + + + + + + + 1 + true + + + 0 + + + 255 + 255 + 255 + 255 + 0 + 255 + 255 + + + false + + + + + + EPSG:7030 + + + m2 + meters + + + 5 + 2.5 + false + false + 1 + 0 + false + false + true + 0 + 255,0,0,255 + + + false + + + true + 2 + MU + + false + + 1 + + + + + + + + + + + None + false + + + + + + 1 + false + conditions unknown + 90 + + + + 100 + + 8 + + false + + false + + 0 + + false + + + + + + + + false + + + + + false + + 5000 + + + + false + + + + 10 + + 1024 + singleLayer + 0 + online + 0 + + + + + + + + + + + + + + + + + + + + + + + + + Olivier + 2021-10-13T14:25:13 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",DATUM["World Geodetic System 1984",ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]] + +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + EPSG:7030 + false + + + + + + + + + + diff --git a/tests/testdata/qgis_server/bug_gh30817_atlas_pk_data.csv b/tests/testdata/qgis_server/bug_gh30817_atlas_pk_data.csv new file mode 100644 index 000000000000..c0a58eb04b2e --- /dev/null +++ b/tests/testdata/qgis_server/bug_gh30817_atlas_pk_data.csv @@ -0,0 +1,4 @@ +WKT, +"POLYGON ((4.8452965180606 46.1362035978033,4.94146270849539 45.8947544654919,5.21516648127133 45.9153443716443,5.16338468642183 46.1413293603677,4.8452965180606 46.1362035978033))" +"POLYGON ((4.35706816662244 45.7916903788217,4.40145256220773 45.4865387880861,4.06856959531807 45.5280126703756,3.97240340488328 45.786532162445,4.35706816662244 45.7916903788217))" +"POLYGON ((5.08201329451547 45.4138859638244,5.01543670113754 45.2787109954903,5.43708845919777 45.1588640613962,5.44448585846198 45.3827203902239,5.08201329451547 45.4138859638244))" From ce2d58d0a78ca76776fb2c9c30f88397356a7df5 Mon Sep 17 00:00:00 2001 From: Alessandro Pasotti Date: Thu, 14 Oct 2021 12:10:22 +0200 Subject: [PATCH 2/4] Add test control files for issue GH #30817 --- src/server/services/wms/qgswmsrenderer.cpp | 2 +- .../WMS_GetPrint_Atlas_No_Pk.png | Bin 0 -> 11690 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 tests/testdata/control_images/qgis_server/WMS_GetPrint_Atlas_No_Pk/WMS_GetPrint_Atlas_No_Pk.png diff --git a/src/server/services/wms/qgswmsrenderer.cpp b/src/server/services/wms/qgswmsrenderer.cpp index 767333baca4b..96d4619430cc 100644 --- a/src/server/services/wms/qgswmsrenderer.cpp +++ b/src/server/services/wms/qgswmsrenderer.cpp @@ -363,7 +363,7 @@ namespace QgsWms { const QgsAttributeList pkIndexes = cLayer->primaryKeyAttributes(); const int pkIndexesSize {std::max( pkIndexes.size(), 1 )}; - if ( pkIndexesSize ) + if ( pkIndexesSize == 0 ) { QgsDebugMsgLevel( QStringLiteral( "Atlas print: layer %1 has no primary key attributes" ).arg( cLayer->name() ), 2 ); } diff --git a/tests/testdata/control_images/qgis_server/WMS_GetPrint_Atlas_No_Pk/WMS_GetPrint_Atlas_No_Pk.png b/tests/testdata/control_images/qgis_server/WMS_GetPrint_Atlas_No_Pk/WMS_GetPrint_Atlas_No_Pk.png new file mode 100644 index 0000000000000000000000000000000000000000..26ec5f41687fd921e4853242536bde1bb3ee76d5 GIT binary patch literal 11690 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

5LS+~<7Kq;pGpnB;w@hJE5DC*%Cs%Xh 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 Date: Fri, 29 Oct 2021 16:50:43 +0200 Subject: [PATCH 3/4] Address PR comments --- src/server/services/wms/qgswmsrenderer.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/server/services/wms/qgswmsrenderer.cpp b/src/server/services/wms/qgswmsrenderer.cpp index 96d4619430cc..520ed5d43532 100644 --- a/src/server/services/wms/qgswmsrenderer.cpp +++ b/src/server/services/wms/qgswmsrenderer.cpp @@ -362,13 +362,16 @@ namespace QgsWms else { const QgsAttributeList pkIndexes = cLayer->primaryKeyAttributes(); - const int pkIndexesSize {std::max( pkIndexes.size(), 1 )}; - if ( pkIndexesSize == 0 ) + if ( pkIndexes.size() == 0 ) { QgsDebugMsgLevel( QStringLiteral( "Atlas print: layer %1 has no primary key attributes" ).arg( cLayer->name() ), 2 ); } + + // Handles the pk-less case + const int pkIndexesSize {std::max( pkIndexes.size(), 1 )}; + QStringList pkAttributeNames; - for ( int pkIndex : pkIndexes ) + for ( int pkIndex : std::as_const( pkIndexes ) ) { pkAttributeNames.append( cLayer->fields().at( pkIndex ).name() ); } @@ -414,7 +417,7 @@ namespace QgsWms { filterString.append( " AND " ); } - filterString.append( QStringLiteral( "\"%1\" = %2" ).arg( pkAttributeNames.at( j ), atlasPk.at( currentAtlasPk ) ) ); + filterString.append( QgsExpression::createFieldEqualityExpression( pkAttributeNames.at( j ), atlasPk.at( currentAtlasPk ) ) ); ++currentAtlasPk; } } From 96187b20c562442d254d907928eb2c1d9bfc9d46 Mon Sep 17 00:00:00 2001 From: Alessandro Pasotti Date: Sat, 30 Oct 2021 12:55:51 +0200 Subject: [PATCH 4/4] Update src/server/services/wms/qgswmsrenderer.cpp Co-authored-by: David Marteau --- src/server/services/wms/qgswmsrenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/services/wms/qgswmsrenderer.cpp b/src/server/services/wms/qgswmsrenderer.cpp index 520ed5d43532..e2966dabb132 100644 --- a/src/server/services/wms/qgswmsrenderer.cpp +++ b/src/server/services/wms/qgswmsrenderer.cpp @@ -377,7 +377,7 @@ namespace QgsWms } const int nAtlasFeatures = atlasPk.size() / pkIndexesSize; - if ( nAtlasFeatures * pkIndexesSize != atlasPk.size() ) //Test is atlasPk.size() is a multiple of pkIndexesSize. Bail out if not + if ( nAtlasFeatures * pkIndexesSize != atlasPk.size() ) //Test if atlasPk.size() is a multiple of pkIndexesSize. Bail out if not { throw QgsBadRequestException( QgsServiceException::QGIS_InvalidParameterValue, QStringLiteral( "Wrong number of ATLAS_PK parameters" ) );