Skip to content
Permalink
Browse files

[vector layer] Fix minimumValue/maximumValue for joined and virtual f…

…ields
  • Loading branch information
github-actions authored and nyalldawson committed May 11, 2020
1 parent 6f0c0e2 commit f9b067e12d71c345cc1bc4ed3a5b695a4bbc7f5b
@@ -3991,21 +3991,32 @@ QVariant QgsVectorLayer::minimumOrMaximumValue( int index, bool minimum ) const
.setSubsetOfAttributes( attList ) );

QgsFeature f;
double value = minimum ? std::numeric_limits<double>::max() : -std::numeric_limits<double>::max();
double currentValue = 0;
QVariant value;
QVariant currentValue;
bool firstValue = true;
while ( fit.nextFeature( f ) )
{
currentValue = f.attribute( index ).toDouble();
if ( ( minimum && currentValue < value ) || ( !minimum && currentValue > value ) )
currentValue = f.attribute( index );
if ( currentValue.isNull() )
continue;
if ( firstValue )
{
value = currentValue;
firstValue = false;
}
else
{
if ( ( minimum && qgsVariantLessThan( currentValue, value ) ) || ( !minimum && qgsVariantGreaterThan( currentValue, value ) ) )
{
value = currentValue;
}
}
}
return QVariant( value );
return value;
}
}

Q_ASSERT_X( false, "QgsVectorLayer::minOrMax()", "Unknown source of the field!" );
Q_ASSERT_X( false, "QgsVectorLayer::minimumOrMaximum()", "Unknown source of the field!" );
return QVariant();
}

@@ -16,7 +16,7 @@
import tempfile
import shutil

from qgis.PyQt.QtCore import QVariant, Qt
from qgis.PyQt.QtCore import QDate, QDateTime, QVariant, Qt
from qgis.PyQt.QtGui import QPainter, QColor
from qgis.PyQt.QtXml import QDomDocument

@@ -137,20 +137,20 @@ def createLayerWithFivePoints():

def createJoinLayer():
joinLayer = QgsVectorLayer(
"Point?field=x:string&field=y:integer&field=z:integer",
"Point?field=x:string&field=y:integer&field=z:integer&field=date:datetime",
"joinlayer", "memory")
pr = joinLayer.dataProvider()
f1 = QgsFeature()
f1.setAttributes(["foo", 123, 321])
f1.setAttributes(["foo", 123, 321, QDateTime(QDate(2010, 1, 1))])
f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 1)))
f2 = QgsFeature()
f2.setAttributes(["bar", 456, 654])
f2.setAttributes(["bar", 456, 654, QDateTime(QDate(2020, 1, 1))])
f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 2)))
f3 = QgsFeature()
f3.setAttributes(["qar", 457, 111])
f3.setAttributes(["qar", 457, 111, None])
f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 2)))
f4 = QgsFeature()
f4.setAttributes(["a", 458, 19])
f4.setAttributes(["a", 458, 19, QDateTime(QDate(2012, 1, 1))])
f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 2)))
assert pr.addFeatures([f1, f2, f3, f4])
assert joinLayer.featureCount() == 4
@@ -1611,11 +1611,11 @@ def test_join(self):
layer.addJoin(join2)

flds = layer.fields()
self.assertEqual(len(flds), 6)
self.assertEqual(len(flds), 8)
self.assertEqual(flds[2].name(), "joinlayer_x")
self.assertEqual(flds[3].name(), "joinlayer_z")
self.assertEqual(flds[4].name(), "custom-prefix_x")
self.assertEqual(flds[5].name(), "custom-prefix_z")
self.assertEqual(flds[5].name(), "custom-prefix_x")
self.assertEqual(flds[6].name(), "custom-prefix_z")
self.assertEqual(flds.fieldOrigin(0), QgsFields.OriginProvider)
self.assertEqual(flds.fieldOrigin(2), QgsFields.OriginJoin)
self.assertEqual(flds.fieldOrigin(3), QgsFields.OriginJoin)
@@ -1627,15 +1627,15 @@ def test_join(self):
fi = layer.getFeatures()
self.assertTrue(fi.nextFeature(f))
attrs = f.attributes()
self.assertEqual(len(attrs), 6)
self.assertEqual(len(attrs), 8)
self.assertEqual(attrs[0], "test")
self.assertEqual(attrs[1], 123)
self.assertEqual(attrs[2], "foo")
self.assertEqual(attrs[3], 321)
self.assertFalse(fi.nextFeature(f))

f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
self.assertEqual(len(f2.attributes()), 6)
self.assertEqual(len(f2.attributes()), 8)
self.assertEqual(f2[2], "foo")
self.assertEqual(f2[3], 321)

@@ -1653,8 +1653,19 @@ def test_JoinStats(self):
layer.addJoin(join)

# stats on joined fields should only include values present by join

# strings
self.assertEqual(layer.minimumValue(2), "foo")
self.assertEqual(layer.maximumValue(2), "qar")

# numbers
self.assertEqual(layer.minimumValue(3), 111)
self.assertEqual(layer.maximumValue(3), 321)

# dates (maximumValue also tests we properly handle null values by skipping those)
self.assertEqual(layer.minimumValue(4), QDateTime(QDate(2010, 1, 1)))
self.assertEqual(layer.maximumValue(4), QDateTime(QDate(2010, 1, 1)))

self.assertEqual(set(layer.uniqueValues(3)), set([111, 321]))

def test_valid_join_when_opening_project(self):
@@ -1872,6 +1883,28 @@ def testMaxValue(self):
self.assertTrue(layer.changeAttributeValue(f1_id, 1, 1001))
self.assertEqual(layer.maximumValue(1), 1001)

def testMinMaxInVirtualField(self):
"""
Test minimum and maximum values in a virtual field
"""
layer = QgsVectorLayer("Point?field=fldstr:string", "layer", "memory")
pr = layer.dataProvider()

int_values = ['2010-01-01', None, '2020-01-01']
features = []
for i in int_values:
f = QgsFeature()
f.setFields(layer.fields())
f.setAttributes([i])
features.append(f)
assert pr.addFeatures(features)

field = QgsField('virtual', QVariant.Date)
layer.addExpressionField('to_date("fldstr")', field)
self.assertEqual(len(layer.getFeature(1).attributes()), 2)
self.assertEqual(layer.minimumValue(1), QDate(2010, 1, 1))
self.assertEqual(layer.maximumValue(1), QDate(2020, 1, 1))

def test_InvalidOperations(self):
layer = createLayerWithOnePoint()

Binary file not shown.

0 comments on commit f9b067e

Please sign in to comment.
You can’t perform that action at this time.