mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Merge pull request #4848 from nyalldawson/virtual_agg
Fix aggregate calculation in virtual fields
This commit is contained in:
commit
4e5597ab72
@ -61,6 +61,7 @@ class QgsVectorLayerFeatureSource : QgsAbstractFeatureSource
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -79,6 +79,9 @@ QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource( const QgsVectorLayer *
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr< QgsExpressionContextScope > layerScope( QgsExpressionContextUtils::layerScope( layer ) );
|
||||
mLayerScope = *layerScope;
|
||||
}
|
||||
|
||||
QgsVectorLayerFeatureSource::~QgsVectorLayerFeatureSource()
|
||||
@ -614,6 +617,15 @@ void QgsVectorLayerFeatureIterator::prepareExpression( int fieldIdx )
|
||||
exp->setAreaUnits( QgsProject::instance()->areaUnits() );
|
||||
|
||||
exp->prepare( mExpressionContext.get() );
|
||||
Q_FOREACH ( const QString &col, exp->referencedColumns() )
|
||||
{
|
||||
if ( mSource->fields().lookupField( col ) == fieldIdx )
|
||||
{
|
||||
// circular reference - expression depends on column itself
|
||||
delete exp;
|
||||
return;
|
||||
}
|
||||
}
|
||||
mExpressionFieldInfo.insert( fieldIdx, exp );
|
||||
|
||||
Q_FOREACH ( const QString &col, exp->referencedColumns() )
|
||||
@ -644,7 +656,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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -1609,6 +1609,11 @@ class TestQgsVectorLayer(unittest.TestCase, FeatureSourceTestCase):
|
||||
|
||||
self.assertEqual(layer.pendingFields().count(), cnt)
|
||||
|
||||
# expression field which references itself
|
||||
idx = layer.addExpressionField('sum(test2)', QgsField('test2', QVariant.LongLong))
|
||||
fet = next(layer.getFeatures())
|
||||
self.assertEqual(fet['test2'], NULL)
|
||||
|
||||
def test_ExpressionFieldEllipsoidLengthCalculation(self):
|
||||
#create a temporary layer
|
||||
temp_layer = QgsVectorLayer("LineString?crs=epsg:3111&field=pk:int", "vl", "memory")
|
||||
@ -1829,6 +1834,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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user