Fix boolean filtering in QGIS expressions with WFS layers (#60075)

PR #56369 introduced a regression for WFS layers, because stopping using
'false' and 'true' strings to compare with boolean fields in qgis
expressions, and forcing to use the keywords false and true, it
conflicted with the internal SQLite cache database of WFS layers.

This PR fixes it by storing internal boolean in SQLite cache database in
the right form compatible with QGIS internal functions (i.e. storing '0'
and '1' strings instead of 'true' and 'false' strings).
This commit is contained in:
Jacky Volpes 2025-01-07 20:20:04 +01:00 committed by GitHub
parent 8e7781d4d9
commit c45551b26e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 0 deletions

View File

@ -642,6 +642,8 @@ void QgsBackgroundCachedSharedData::serializeFeatures( QVector<QgsFeatureUniqueI
}
cachedFeature.setAttribute( idx, stringValue );
}
else if ( mFields.at( i ).type() == QMetaType::Type::Bool ) // WFS boolean fields are stored as varchar in underlying cache sqlite database
cachedFeature.setAttribute( idx, QgsSqliteUtils::quotedValue( QVariant::fromValue( v.toBool() ) ) );
else if ( QgsWFSUtils::isCompatibleType( static_cast<QMetaType::Type>( v.userType() ), fieldType ) )
cachedFeature.setAttribute( idx, v );
else

View File

@ -6277,6 +6277,7 @@ class TestPyQgsWFSProvider(QgisTestCase, ProviderTestCase):
<element type="gml:MultiPointPropertyType" name="geometry" minOccurs="0" maxOccurs="1"/>
<element type="int" name="id"/>
<element type="string" name="name"/>
<element type="boolean" name="verified"/>
<element type="int" name="type" nillable="true"/>
<element type="decimal" name="elevation" nillable="true"/>
</sequence>
@ -6313,6 +6314,7 @@ class TestPyQgsWFSProvider(QgisTestCase, ProviderTestCase):
</qgs:geometry>
<qgs:id>177</qgs:id>
<qgs:name>Xxx</qgs:name>
<qgs:verified>true</qgs:verified>
<qgs:elevation_source></qgs:elevation_source>
</qgs:points>
</gml:featureMember>
@ -6344,6 +6346,7 @@ class TestPyQgsWFSProvider(QgisTestCase, ProviderTestCase):
</qgs:geometry>
<qgs:id>177</qgs:id>
<qgs:name>Xxx</qgs:name>
<qgs:verified>true</qgs:verified>
<qgs:type xsi:nil="true"></qgs:type>
<qgs:elevation xsi:nil="true"></qgs:elevation>
</qgs:points>
@ -6367,6 +6370,7 @@ class TestPyQgsWFSProvider(QgisTestCase, ProviderTestCase):
</qgs:geometry>
<qgs:id>5</qgs:id>
<qgs:name>qgis</qgs:name>
<qgs:verified>false</qgs:verified>
<qgs:type>0</qgs:type>
<qgs:elevation xsi:nil="true"></qgs:elevation>
</qgs:points>
@ -6412,6 +6416,31 @@ class TestPyQgsWFSProvider(QgisTestCase, ProviderTestCase):
self.assertEqual(qgis_feat["name"], "qgis")
self.assertEqual(other_feat["name"], "Xxx")
qgis_feat = next(
vl.getFeatures(QgsFeatureRequest(QgsExpression('"verified" is true')))
)
other_feat = next(
vl.getFeatures(QgsFeatureRequest(QgsExpression('"verified" is false')))
)
self.assertEqual(qgis_feat["name"], "Xxx")
self.assertEqual(other_feat["name"], "qgis")
qgis_feat = next(vl.getFeatures(QgsFeatureRequest(QgsExpression('"verified"'))))
other_feat = next(
vl.getFeatures(QgsFeatureRequest(QgsExpression('not "verified"')))
)
self.assertEqual(qgis_feat["name"], "Xxx")
self.assertEqual(other_feat["name"], "qgis")
qgis_feat = next(
vl.getFeatures(QgsFeatureRequest(QgsExpression('"verified" = true')))
)
other_feat = next(
vl.getFeatures(QgsFeatureRequest(QgsExpression('"verified" = false')))
)
self.assertEqual(qgis_feat["name"], "Xxx")
self.assertEqual(other_feat["name"], "qgis")
form_scope = QgsExpressionContextUtils.formScope(qgis_feat)
form_exp = QgsExpression("current_value('name') = \"name\"")
ctx = QgsExpressionContext()