diff --git a/src/core/providers/ogr/qgsogrfeatureiterator.cpp b/src/core/providers/ogr/qgsogrfeatureiterator.cpp index 8b7abd111363..ef229ee8fd5e 100644 --- a/src/core/providers/ogr/qgsogrfeatureiterator.cpp +++ b/src/core/providers/ogr/qgsogrfeatureiterator.cpp @@ -207,6 +207,11 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrFeatureSource *source, bool mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete ); mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled ); } + else if ( !mSource->mSubsetString.isEmpty() ) + { + // OGR rejected the compiled expression. Make sure we restore the original subset string if set (and do the filtering on QGIS' side) + OGR_L_SetAttributeFilter( mOgrLayer, mSource->mEncoding->fromUnicode( mSource->mSubsetString ).constData() ); + } } else if ( mSource->mSubsetString.isEmpty() ) { diff --git a/tests/src/python/test_provider_ogr.py b/tests/src/python/test_provider_ogr.py index fe5a0715547b..3bef0bc057cd 100644 --- a/tests/src/python/test_provider_ogr.py +++ b/tests/src/python/test_provider_ogr.py @@ -687,6 +687,31 @@ def testSpatialiteDefaultValues(self): self.assertEqual(feature.attribute(4), 123) self.assertEqual(feature.attribute(5), 'My default') + def testMixOfFilterExpressionAndSubsetStringWhenFilterExpressionCompilationFails(self): + datasource = os.path.join(unitTestDataPath(), 'filter_test.shp') + vl = QgsVectorLayer(datasource, 'test', 'ogr') + self.assertTrue(vl.isValid()) + + self.assertCountEqual([f.attributes() for f in vl.getFeatures()], [['circle', '1'], + ['circle', '2'], + ['rectangle', '1'], + ['rectangle', '2']]) + + # note - request uses wrong type for match (string vs int). This is OK for QGIS expressions, + # but will be rejected after we try to compile the expression for OGR to use. + request = QgsFeatureRequest().setFilterExpression('"color" = 1') + self.assertCountEqual([f.attributes() for f in vl.getFeatures(request)], [['circle', '1'], + ['rectangle', '1']]) + request = QgsFeatureRequest().setFilterExpression('"color" = 1') + self.assertCountEqual([f.attributes() for f in vl.getFeatures(request)], [['circle', '1'], + ['rectangle', '1']]) + + vl.setSubsetString("\"shape\" = 'rectangle'") + self.assertCountEqual([f.attributes() for f in vl.getFeatures()], [['rectangle', '1'], + ['rectangle', '2']]) + + self.assertCountEqual([f.attributes() for f in vl.getFeatures(request)], [['rectangle', '1']]) + if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/filter_test.cpg b/tests/testdata/filter_test.cpg new file mode 100644 index 000000000000..3ad133c048f2 --- /dev/null +++ b/tests/testdata/filter_test.cpg @@ -0,0 +1 @@ +UTF-8 \ No newline at end of file diff --git a/tests/testdata/filter_test.dbf b/tests/testdata/filter_test.dbf new file mode 100644 index 000000000000..031ac0e62ee5 Binary files /dev/null and b/tests/testdata/filter_test.dbf differ diff --git a/tests/testdata/filter_test.prj b/tests/testdata/filter_test.prj new file mode 100644 index 000000000000..f45cbadf0074 --- /dev/null +++ b/tests/testdata/filter_test.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] \ No newline at end of file diff --git a/tests/testdata/filter_test.shp b/tests/testdata/filter_test.shp new file mode 100644 index 000000000000..c3b024ee141f Binary files /dev/null and b/tests/testdata/filter_test.shp differ diff --git a/tests/testdata/filter_test.shx b/tests/testdata/filter_test.shx new file mode 100644 index 000000000000..f71718e2a1fb Binary files /dev/null and b/tests/testdata/filter_test.shx differ