Skip to content

Commit

Permalink
Server getprint atlas: fix pk-less layers
Browse files Browse the repository at this point in the history
Co-authored-by: David Marteau <dmarteau@3liz.com>
  • Loading branch information
2 people authored and m-kuhn committed Dec 27, 2021
1 parent 69f86a4 commit 54946c9
Show file tree
Hide file tree
Showing 5 changed files with 861 additions and 15 deletions.
41 changes: 27 additions & 14 deletions src/server/services/wms/qgswmsrenderer.cpp
Expand Up @@ -356,19 +356,23 @@ namespace QgsWms
}
else
{
QgsAttributeList pkIndexes = cLayer->primaryKeyAttributes();
if ( pkIndexes.size() < 1 )
const QgsAttributeList pkIndexes = cLayer->primaryKeyAttributes();
if ( pkIndexes.size() == 0 )
{
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 );
}

// Handles the pk-less case
const int pkIndexesSize {std::max( pkIndexes.size(), 1 )};

QStringList pkAttributeNames;
for ( int i = 0; i < pkIndexes.size(); ++i )
for ( int pkIndex : qgis::as_const( pkIndexes ) )
{
pkAttributeNames.append( cLayer->fields()[pkIndexes.at( i )].name() );
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 if atlasPk.size() is a multiple of pkIndexesSize. Bail out if not
{
throw QgsBadRequestException( QgsServiceException::QGIS_InvalidParameterValue,
QStringLiteral( "Wrong number of ATLAS_PK parameters" ) );
Expand All @@ -378,7 +382,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 ) );
}

Expand All @@ -394,14 +398,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( QgsExpression::createFieldEqualityExpression( pkAttributeNames.at( j ), atlasPk.at( currentAtlasPk ) ) );
++currentAtlasPk;
}
filterString.append( QString( "\"%1\" = %2" ).arg( pkAttributeNames.at( j ), atlasPk.at( currentAtlasPk ) ) );
++currentAtlasPk;
}

filterString.append( " )" );
Expand All @@ -412,7 +425,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 ) );
}
}
}
Expand Down
23 changes: 22 additions & 1 deletion tests/src/python/test_qgsserver_wms_getprint_atlas.py
Expand Up @@ -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"""
Expand Down Expand Up @@ -55,6 +57,25 @@ def test_wms_getprint_atlas_getProjectSettings(self):
self.assertTrue('atlasEnabled="1"' in str(r))
self.assertTrue('<PrimaryKeyAttribute>' 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()
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 54946c9

Please sign in to comment.