@@ -622,7 +622,7 @@ static QVariant fcnMin( const QVariantList& values, const QgsExpressionContext*,
622
622
return QVariant ( minVal );
623
623
}
624
624
625
- static QVariant fcnAggregate ( const QVariantList& values, const QgsExpressionContext* context, QgsExpression * parent )
625
+ static QVariant fcnAggregate ( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent )
626
626
{
627
627
// lazy eval, so we need to evaluate nodes now
628
628
@@ -677,15 +677,28 @@ static QVariant fcnAggregate( const QVariantList& values, const QgsExpressionCon
677
677
parameters.delimiter = value.toString ();
678
678
}
679
679
680
- QString cacheKey = QStringLiteral ( " aggfcn:%1:%2:%3:%4" ).arg ( vl->id (), QString::number ( static_cast < int >( aggregate ) ), subExpression, parameters.filter );
681
- if ( context && context->hasCachedValue ( cacheKey ) )
682
- return context->cachedValue ( cacheKey );
683
-
684
680
QVariant result;
685
681
if ( context )
686
682
{
683
+ QString cacheKey = QStringLiteral ( " aggfcn:%1:%2:%3:%4" ).arg ( vl->id (), QString::number ( aggregate ), subExpression, parameters.filter );
684
+
685
+ QgsExpression subExp ( subExpression );
686
+ if ( subExp.referencedVariables ().contains ( " parent" ) || subExp.referencedVariables ().contains ( QString () ) )
687
+ {
688
+ cacheKey += ' :' + qHash ( context->feature () );
689
+ }
690
+
691
+ if ( context && context->hasCachedValue ( cacheKey ) )
692
+ return context->cachedValue ( cacheKey );
693
+
687
694
QgsExpressionContext subContext ( *context );
695
+ QgsExpressionContextScope* subScope = new QgsExpressionContextScope ();
696
+ subScope->setVariable ( " parent" , context->feature () );
697
+ subContext.appendScope ( subScope );
688
698
result = vl->aggregate ( aggregate, subExpression, parameters, &subContext, &ok );
699
+
700
+ if ( ok )
701
+ context->setCachedValue ( cacheKey, result );
689
702
}
690
703
else
691
704
{
@@ -697,9 +710,6 @@ static QVariant fcnAggregate( const QVariantList& values, const QgsExpressionCon
697
710
return QVariant ();
698
711
}
699
712
700
- // cache value
701
- if ( context )
702
- context->setCachedValue ( cacheKey, result );
703
713
return result;
704
714
}
705
715
@@ -3991,6 +4001,14 @@ QSet<QString> QgsExpression::referencedColumns() const
3991
4001
return d->mRootNode ->referencedColumns ();
3992
4002
}
3993
4003
4004
+ QSet<QString> QgsExpression::referencedVariables () const
4005
+ {
4006
+ if ( !d->mRootNode )
4007
+ return QSet<QString>();
4008
+
4009
+ return d->mRootNode ->referencedVariables ();
4010
+ }
4011
+
3994
4012
bool QgsExpression::NodeInOperator::needsGeometry () const
3995
4013
{
3996
4014
bool needs = false ;
@@ -4303,6 +4321,16 @@ QString QgsExpression::NodeUnaryOperator::dump() const
4303
4321
return QStringLiteral ( " %1 %2" ).arg ( UnaryOperatorText[mOp ], mOperand ->dump () );
4304
4322
}
4305
4323
4324
+ QSet<QString> QgsExpression::NodeUnaryOperator::referencedColumns () const
4325
+ {
4326
+ return mOperand ->referencedColumns ();
4327
+ }
4328
+
4329
+ QSet<QString> QgsExpression::NodeUnaryOperator::referencedVariables () const
4330
+ {
4331
+ return mOperand ->referencedVariables ();
4332
+ }
4333
+
4306
4334
QgsExpression::Node*QgsExpression::NodeUnaryOperator::clone () const
4307
4335
{
4308
4336
return new NodeUnaryOperator ( mOp , mOperand ->clone () );
@@ -4790,6 +4818,11 @@ QSet<QString> QgsExpression::NodeBinaryOperator::referencedColumns() const
4790
4818
return mOpLeft ->referencedColumns () + mOpRight ->referencedColumns ();
4791
4819
}
4792
4820
4821
+ QSet<QString> QgsExpression::NodeBinaryOperator::referencedVariables () const
4822
+ {
4823
+ return mOpLeft ->referencedVariables () + mOpRight ->referencedVariables ();
4824
+ }
4825
+
4793
4826
bool QgsExpression::NodeBinaryOperator::needsGeometry () const
4794
4827
{
4795
4828
return mOpLeft ->needsGeometry () || mOpRight ->needsGeometry ();
@@ -4993,6 +5026,23 @@ QSet<QString> QgsExpression::NodeFunction::referencedColumns() const
4993
5026
return functionColumns;
4994
5027
}
4995
5028
5029
+ QSet<QString> QgsExpression::NodeFunction::referencedVariables () const
5030
+ {
5031
+ Function* fd = Functions ()[mFnIndex ];
5032
+ if ( fd->name () == " var" )
5033
+ {
5034
+ if ( !mArgs ->list ().isEmpty () )
5035
+ {
5036
+ QgsExpression::NodeLiteral* var = dynamic_cast <QgsExpression::NodeLiteral*>( mArgs ->list ().first () );
5037
+ if ( var )
5038
+ return QSet<QString>() << var->value ().toString ();
5039
+ }
5040
+ return QSet<QString>() << QString ();
5041
+ }
5042
+ else
5043
+ return QSet<QString>();
5044
+ }
5045
+
4996
5046
bool QgsExpression::NodeFunction::needsGeometry () const
4997
5047
{
4998
5048
bool needs = Functions ()[mFnIndex ]->usesGeometry ();
@@ -5119,6 +5169,16 @@ QString QgsExpression::NodeLiteral::dump() const
5119
5169
}
5120
5170
}
5121
5171
5172
+ QSet<QString> QgsExpression::NodeLiteral::referencedColumns () const
5173
+ {
5174
+ return QSet<QString>();
5175
+ }
5176
+
5177
+ QSet<QString> QgsExpression::NodeLiteral::referencedVariables () const
5178
+ {
5179
+ return QSet<QString>();
5180
+ }
5181
+
5122
5182
QgsExpression::Node*QgsExpression::NodeLiteral::clone () const
5123
5183
{
5124
5184
return new NodeLiteral ( mValue );
@@ -5177,6 +5237,16 @@ QString QgsExpression::NodeColumnRef::dump() const
5177
5237
return QRegExp ( " ^[A-Za-z_\x80 -\xff ][A-Za-z0-9_\x80 -\xff ]*$" ).exactMatch ( mName ) ? mName : quotedColumnRef ( mName );
5178
5238
}
5179
5239
5240
+ QSet<QString> QgsExpression::NodeColumnRef::referencedColumns () const
5241
+ {
5242
+ return QSet<QString>() << mName ;
5243
+ }
5244
+
5245
+ QSet<QString> QgsExpression::NodeColumnRef::referencedVariables () const
5246
+ {
5247
+ return QSet<QString>();
5248
+ }
5249
+
5180
5250
QgsExpression::Node*QgsExpression::NodeColumnRef::clone () const
5181
5251
{
5182
5252
return new NodeColumnRef ( mName );
@@ -5253,6 +5323,20 @@ QSet<QString> QgsExpression::NodeCondition::referencedColumns() const
5253
5323
return lst;
5254
5324
}
5255
5325
5326
+ QSet<QString> QgsExpression::NodeCondition::referencedVariables () const
5327
+ {
5328
+ QSet<QString> lst;
5329
+ Q_FOREACH ( WhenThen* cond, mConditions )
5330
+ {
5331
+ lst += cond->mWhenExp ->referencedVariables () + cond->mThenExp ->referencedVariables ();
5332
+ }
5333
+
5334
+ if ( mElseExp )
5335
+ lst += mElseExp ->referencedVariables ();
5336
+
5337
+ return lst;
5338
+ }
5339
+
5256
5340
bool QgsExpression::NodeCondition::needsGeometry () const
5257
5341
{
5258
5342
Q_FOREACH ( WhenThen* cond, mConditions )
@@ -5619,6 +5703,14 @@ QSet<QString> QgsExpression::NodeInOperator::referencedColumns() const
5619
5703
return lst;
5620
5704
}
5621
5705
5706
+ QSet<QString> QgsExpression::NodeInOperator::referencedVariables () const
5707
+ {
5708
+ QSet<QString> lst ( mNode ->referencedVariables () );
5709
+ Q_FOREACH ( const Node* n, mList ->list () )
5710
+ lst.unite ( n->referencedVariables () );
5711
+ return lst;
5712
+ }
5713
+
5622
5714
bool QgsExpression::Function::operator ==( const QgsExpression::Function& other ) const
5623
5715
{
5624
5716
if ( QString::compare ( mName , other.mName , Qt::CaseInsensitive ) == 0 )
1 commit comments
andreasneumann commentedon Oct 28, 2016
Nice! The expressions are more and more powerful! Thanks for the improvement.