Skip to content
Permalink
Browse files

correctly determine if variables are static in aggregate expression a…

…nd filter

fixes #33382
  • Loading branch information
3nids authored and nyalldawson committed Oct 16, 2020
1 parent 212085e commit d1f3f9d4f14784b98fc041f9eb488dc277e31f62
Showing with 41 additions and 1 deletion.
  1. +22 −1 src/core/expression/qgsexpressionfunction.cpp
  2. +19 −0 tests/src/core/testqgsexpression.cpp
@@ -637,10 +637,30 @@ static QVariant fcnAggregate( const QVariantList &values, const QgsExpressionCon
QString cacheKey;
QgsExpression subExp( subExpression );
QgsExpression filterExp( parameters.filter );

bool isStatic = true;
if ( filterExp.referencedVariables().contains( QStringLiteral( "parent" ) )
|| filterExp.referencedVariables().contains( QString() )
|| subExp.referencedVariables().contains( QStringLiteral( "parent" ) )
|| subExp.referencedVariables().contains( QString() ) )
{
isStatic = false;
}
else
{
const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
for ( const QString &varName : refVars )
{
const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
if ( scope && !scope->isStatic( varName ) )
{
isStatic = false;
break;
}
}
}

if ( !isStatic )
{
cacheKey = QStringLiteral( "aggfcn:%1:%2:%3:%4:%5%6:%7" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.filter,
QString::number( context->feature().id() ), QString( qHash( context->feature() ) ), orderBy );
@@ -651,8 +671,9 @@ static QVariant fcnAggregate( const QVariantList &values, const QgsExpressionCon
}

if ( context && context->hasCachedValue( cacheKey ) )
{
return context->cachedValue( cacheKey );

}
QgsExpressionContext subContext( *context );
QgsExpressionContextScope *subScope = new QgsExpressionContextScope();
subScope->setVariable( QStringLiteral( "parent" ), context->feature() );
@@ -2029,6 +2029,25 @@ class TestQgsExpression: public QObject
QCOMPARE( res.toInt(), 1 );
}

void test_aggregate_with_variable()
{
// this checks that a variable can be non static in a aggregate, i.e. the result will change across the fetched features
// see https://github.com/qgis/QGIS/issues/33382
QgsExpressionContext context;
context.appendScope( QgsExpressionContextUtils::layerScope( mAggregatesLayer ) );
QgsFeature f;

QgsFeatureIterator it = mAggregatesLayer->getFeatures();

while ( it.nextFeature( f ) )
{
context.setFeature( f );
QgsExpression exp( QString( "with_variable('my_var',\"col1\", aggregate(layer:='aggregate_layer', aggregate:='concatenate_unique', expression:=\"col2\", filter:=\"col1\"=@my_var))" ) );
QString res = exp.evaluate( &context ).toString();
QCOMPARE( res, f.attribute( "col2" ) );
}
}

void aggregate_data()
{
QTest::addColumn<QString>( "string" );

0 comments on commit d1f3f9d

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