Fix aggregate expression calculation when used with virtual fields

The layer expression context (which is required for aggregate
calculation to work) was not being added to the context used
by vector layer feature iterators.

Fix #15930
This commit is contained in:
Nyall Dawson 2017-07-13 10:58:04 +10:00
parent 0639264a4a
commit 3f4d6de54b
4 changed files with 28 additions and 1 deletions

View File

@ -61,6 +61,7 @@ class QgsVectorLayerFeatureSource : QgsAbstractFeatureSource
};

View File

@ -79,6 +79,9 @@ QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource( const QgsVectorLayer *
}
#endif
}
std::unique_ptr< QgsExpressionContextScope > layerScope( QgsExpressionContextUtils::layerScope( layer ) );
mLayerScope = *layerScope;
}
QgsVectorLayerFeatureSource::~QgsVectorLayerFeatureSource()
@ -644,7 +647,7 @@ void QgsVectorLayerFeatureIterator::prepareFields()
mExpressionContext.reset( new QgsExpressionContext() );
mExpressionContext->appendScope( QgsExpressionContextUtils::globalScope() );
mExpressionContext->appendScope( QgsExpressionContextUtils::projectScope( QgsProject::instance() ) );
mExpressionContext->setFields( mSource->mFields );
mExpressionContext->appendScope( new QgsExpressionContextScope( mSource->mLayerScope ) );
mFieldsToPrepare = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) ? mRequest.subsetOfAttributes() : mSource->mFields.allAttributesList();

View File

@ -84,6 +84,8 @@ class CORE_EXPORT QgsVectorLayerFeatureSource : public QgsAbstractFeatureSource
QgsFields mFields;
QgsExpressionContextScope mLayerScope;
bool mHasEditBuffer;
// A deep-copy is only performed, if the original maps change

View File

@ -1829,6 +1829,27 @@ class TestQgsVectorLayer(unittest.TestCase, FeatureSourceTestCase):
self.assertTrue(ok)
self.assertEqual(val, 'this is a test')
def testAggregateInVirtualField(self):
"""
Test aggregates in a virtual field
"""
layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory")
pr = layer.dataProvider()
int_values = [4, 2, 3, 2, 5, None, 8]
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.Double)
layer.addExpressionField('sum(fldint*2)', field)
vals = [f['virtual'] for f in layer.getFeatures()]
self.assertEqual(vals, [48, 48, 48, 48, 48, 48, 48])
def onLayerOpacityChanged(self, tr):
self.opacityTest = tr