diff --git a/src/core/expression/qgsexpressionfunction.cpp b/src/core/expression/qgsexpressionfunction.cpp index f4ac989f3b8..2a592facd63 100644 --- a/src/core/expression/qgsexpressionfunction.cpp +++ b/src/core/expression/qgsexpressionfunction.cpp @@ -4302,20 +4302,17 @@ bool QgsWithVariableExpressionFunction::isStatic( const QgsExpressionNodeFunctio if ( args->count() < 3 ) return false; + // We only need to check if the node evaluation is static, if both - name and value - are static. if ( args->at( 0 )->isStatic( parent, context ) && args->at( 1 )->isStatic( parent, context ) ) { QVariant name = args->at( 0 )->eval( parent, context ); QVariant value = args->at( 1 )->eval( parent, context ); - QgsExpressionContextScope *scope = new QgsExpressionContextScope(); - scope->setVariable( name.toString(), value ); - - QgsExpressionContext *updatedContext = const_cast<QgsExpressionContext *>( context ); - updatedContext->appendScope( scope ); - - if ( args->at( 2 )->isStatic( parent, updatedContext ) ) + // Temporarily append a new scope to provide the variable + appendTemporaryVariable( context, name.toString(), value ); + if ( args->at( 2 )->isStatic( parent, context ) ) isStatic = true; - delete updatedContext->popScope(); + popTemporaryVariable( context ); } return false; @@ -4332,15 +4329,13 @@ QVariant QgsWithVariableExpressionFunction::run( QgsExpressionNode::NodeList *ar QVariant name = args->at( 0 )->eval( parent, context ); QVariant value = args->at( 1 )->eval( parent, context ); - QgsExpressionContextScope *scope = new QgsExpressionContextScope(); - scope->setVariable( name.toString(), value ); - QgsExpressionContext *updatedContext = const_cast<QgsExpressionContext *>( context ); if ( !context ) updatedContext = new QgsExpressionContext(); - updatedContext->appendScope( scope ); + + appendTemporaryVariable( updatedContext, name.toString(), value ); result = args->at( 2 )->eval( parent, updatedContext ); - delete updatedContext->popScope(); + popTemporaryVariable( updatedContext ); if ( !context ) delete updatedContext; @@ -4369,13 +4364,24 @@ bool QgsWithVariableExpressionFunction::prepare( const QgsExpressionNodeFunction QVariant name = args->at( 0 )->prepare( parent, context ); QVariant value = args->at( 1 )->prepare( parent, context ); - QgsExpressionContextScope *scope = new QgsExpressionContextScope(); - scope->setVariable( name.toString(), value ); - - QgsExpressionContext *updatedContext = const_cast<QgsExpressionContext *>( context ); - updatedContext->appendScope( scope ); - args->at( 2 )->prepare( parent, updatedContext ); - delete updatedContext->popScope(); + appendTemporaryVariable( context, name.toString(), value ); + args->at( 2 )->prepare( parent, context ); + popTemporaryVariable( context ); return true; } + +void QgsWithVariableExpressionFunction::popTemporaryVariable( const QgsExpressionContext *context ) const +{ + QgsExpressionContext *updatedContext = const_cast<QgsExpressionContext *>( context ); + delete updatedContext->popScope(); +} + +void QgsWithVariableExpressionFunction::appendTemporaryVariable( const QgsExpressionContext *context, const QString &name, const QVariant &value ) const +{ + QgsExpressionContextScope *scope = new QgsExpressionContextScope(); + scope->setVariable( name, value ); + + QgsExpressionContext *updatedContext = const_cast<QgsExpressionContext *>( context ); + updatedContext->appendScope( scope ); +} diff --git a/src/core/expression/qgsexpressionfunction.h b/src/core/expression/qgsexpressionfunction.h index fc6b8f80876..4734cad60de 100644 --- a/src/core/expression/qgsexpressionfunction.h +++ b/src/core/expression/qgsexpressionfunction.h @@ -29,6 +29,7 @@ class QgsExpressionNodeFunction; class QgsExpression; class QgsExpressionContext; +class QgsExpressionContextScope; /** \ingroup core * A abstract base class for defining QgsExpression functions. @@ -475,6 +476,18 @@ class QgsWithVariableExpressionFunction : public QgsExpressionFunction QVariant func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent ) override; bool prepare( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const override; + + private: + + /** + * Append a scope with a single variable definition (``name``=``value``) + */ + void appendTemporaryVariable( const QgsExpressionContext *context, const QString &name, const QVariant &value ) const; + + /** + * Pop the temporary scope again + */ + void popTemporaryVariable( const QgsExpressionContext *context ) const; }; #endif