Skip to content

Commit

Permalink
Fix some providers did not respect layer's subset when calculating
Browse files Browse the repository at this point in the history
min/max/uniqueValues

Providers included delimited text, memory, virtual layer, and WFS

Add unit test to provider test
  • Loading branch information
nyalldawson committed Apr 11, 2016
1 parent 483eb86 commit 16d8da3
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/providers/delimitedtext/qgsdelimitedtextprovider.cpp
Expand Up @@ -1078,6 +1078,7 @@ bool QgsDelimitedTextProvider::setSubsetString( const QString& subset, bool upda
}
}

mCacheMinMaxDirty = true;
emit dataChanged();
return valid;
}
Expand Down
1 change: 1 addition & 0 deletions src/providers/memory/qgsmemoryprovider.cpp
Expand Up @@ -481,6 +481,7 @@ bool QgsMemoryProvider::setSubsetString( const QString& theSQL, bool updateFeatu
}

mSubsetString = theSQL;
mCacheMinMaxDirty = true;

emit dataChanged();
return true;
Expand Down
1 change: 1 addition & 0 deletions src/providers/virtual/qgsvirtuallayerprovider.cpp
Expand Up @@ -493,6 +493,7 @@ QString QgsVirtualLayerProvider::subsetString()
bool QgsVirtualLayerProvider::setSubsetString( const QString& subset, bool updateFeatureCount )
{
mSubset = subset;
mCacheMinMaxDirty = true;
if ( updateFeatureCount )
updateStatistics();
return true;
Expand Down
1 change: 1 addition & 0 deletions src/providers/wfs/qgswfsprovider.cpp
Expand Up @@ -130,6 +130,7 @@ QString QgsWFSProvider::subsetString()
bool QgsWFSProvider::setSubsetString( const QString& theSQL, bool updateFeatureCount )
{
mSubsetString = theSQL;
mCacheMinMaxDirty = true;

// update URI
mShared->mURI.setFilter( theSQL );
Expand Down
22 changes: 22 additions & 0 deletions tests/src/python/providertestbase.py
Expand Up @@ -165,6 +165,10 @@ def getSubsetString(self):
"""Individual providers may need to override this depending on their subset string formats"""
return '"cnt" > 100 and "cnt" < 410'

def getSubsetString2(self):
"""Individual providers may need to override this depending on their subset string formats"""
return '"cnt" > 100 and "cnt" < 400'

def testOrderByUncompiled(self):
try:
self.disableCompiler()
Expand Down Expand Up @@ -359,10 +363,22 @@ def testMinValue(self):
self.assertEqual(self.provider.minimumValue(1), -200)
self.assertEqual(self.provider.minimumValue(2), 'Apple')

subset = self.getSubsetString()
self.provider.setSubsetString(subset)
min_value = self.provider.minimumValue(1)
self.provider.setSubsetString(None)
self.assertEqual(min_value, 200)

def testMaxValue(self):
self.assertEqual(self.provider.maximumValue(1), 400)
self.assertEqual(self.provider.maximumValue(2), 'Pear')

subset = self.getSubsetString2()
self.provider.setSubsetString(subset)
max_value = self.provider.maximumValue(1)
self.provider.setSubsetString(None)
self.assertEqual(max_value, 300)

def testExtent(self):
reference = QgsGeometry.fromRect(
QgsRectangle(-71.123, 66.33, -65.32, 78.3))
Expand All @@ -374,6 +390,12 @@ def testUnique(self):
self.assertEqual(set(self.provider.uniqueValues(1)), set([-200, 100, 200, 300, 400]))
assert set([u'Apple', u'Honey', u'Orange', u'Pear', NULL]) == set(self.provider.uniqueValues(2)), 'Got {}'.format(set(self.provider.uniqueValues(2)))

subset = self.getSubsetString2()
self.provider.setSubsetString(subset)
values = self.provider.uniqueValues(1)
self.provider.setSubsetString(None)
self.assertEqual(set(values), set([200, 300]))

def testFeatureCount(self):
assert self.provider.featureCount() == 5, 'Got {}'.format(self.provider.featureCount())

Expand Down
61 changes: 61 additions & 0 deletions tests/src/python/test_provider_wfs.py
Expand Up @@ -228,6 +228,67 @@ def setUpClass(cls):
</wfs:member>
</wfs:FeatureCollection>""")

with open(sanitize(endpoint, """?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&FILTER=<fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0">
<fes:And>
<fes:PropertyIsGreaterThan>
<fes:ValueReference>cnt</fes:ValueReference>
<fes:Literal>100</fes:Literal>
</fes:PropertyIsGreaterThan>
<fes:PropertyIsLessThan>
<fes:ValueReference>cnt</fes:ValueReference>
<fes:Literal>400</fes:Literal>
</fes:PropertyIsLessThan>
</fes:And>
</fes:Filter>
&RESULTTYPE=hits"""), 'wb') as f:
f.write("""
<wfs:FeatureCollection
xmlns:wfs="http://www.opengis.net/wfs/2.0"
xmlns:gml="http://www.opengis.net/gml/3.2"
numberMatched="2" numberReturned="0" timeStamp="2016-03-25T14:51:48.998Z">
</wfs:FeatureCollection>""")

with open(sanitize(endpoint, """?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&SRSNAME=urn:ogc:def:crs:EPSG::4326&FILTER=<fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0">
<fes:And>
<fes:PropertyIsGreaterThan>
<fes:ValueReference>cnt</fes:ValueReference>
<fes:Literal>100</fes:Literal>
</fes:PropertyIsGreaterThan>
<fes:PropertyIsLessThan>
<fes:ValueReference>cnt</fes:ValueReference>
<fes:Literal>400</fes:Literal>
</fes:PropertyIsLessThan>
</fes:And>
</fes:Filter>
"""), 'wb') as f:
f.write("""
<wfs:FeatureCollection
xmlns:wfs="http://www.opengis.net/wfs/2.0"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:my="http://my"
numberMatched="2" numberReturned="2" timeStamp="2016-03-25T14:51:48.998Z">
<wfs:member>
<my:typename gml:id="typename.1">
<gml:boundedBy><gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"><gml:lowerCorner>70.8 -68.2</gml:lowerCorner><gml:upperCorner>70.8 -68.2</gml:upperCorner></gml:Envelope></gml:boundedBy>
<my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326" gml:id="typename.geom.1"><gml:pos>70.8 -68.2</gml:pos></gml:Point></my:geometryProperty>
<my:pk>2</my:pk>
<my:cnt>200</my:cnt>
<my:name>Apple</my:name>
<my:name2>Apple</my:name2>
<my:num_char>2</my:num_char>
</my:typename>
</wfs:member>
<wfs:member>
<my:typename gml:id="typename.3">
<my:pk>3</my:pk>
<my:cnt>300</my:cnt>
<my:name>Pear</my:name>
<my:name2>PEaR</my:name2>
<my:num_char>3</my:num_char>
</my:typename>
</wfs:member>
</wfs:FeatureCollection>""")

@classmethod
def tearDownClass(cls):
"""Run after all tests"""
Expand Down

0 comments on commit 16d8da3

Please sign in to comment.