diff --git a/src/core/qgsexpression.cpp b/src/core/qgsexpression.cpp index 8c20361b567a..f625c6f0074a 100644 --- a/src/core/qgsexpression.cpp +++ b/src/core/qgsexpression.cpp @@ -4283,11 +4283,23 @@ QgsExpression::Node*QgsExpression::NodeLiteral::clone() const QVariant QgsExpression::NodeColumnRef::eval( QgsExpression *parent, const QgsExpressionContext *context ) { Q_UNUSED( parent ); + int index = mIndex; + + if ( index < 0 ) + { + // have not yet found field index - first check explicitly set fields collection + if ( context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) ) + { + QgsFields fields = qvariant_cast( context->variable( QgsExpressionContext::EXPR_FIELDS ) ); + index = fields.fieldNameIndex( mName ); + } + } + if ( context && context->hasVariable( QgsExpressionContext::EXPR_FEATURE ) ) { QgsFeature feature = qvariant_cast( context->variable( QgsExpressionContext::EXPR_FEATURE ) ); - if ( mIndex >= 0 ) - return feature.attribute( mIndex ); + if ( index >= 0 ) + return feature.attribute( index ); else return feature.attribute( mName ); } diff --git a/tests/src/core/testqgsexpression.cpp b/tests/src/core/testqgsexpression.cpp index f0f5e01f45fa..a4de62dec027 100644 --- a/tests/src/core/testqgsexpression.cpp +++ b/tests/src/core/testqgsexpression.cpp @@ -2101,6 +2101,47 @@ class TestQgsExpression: public QObject QgsExpression nodeExpression( "1 IN (1, 2, 3, 4)" ); QgsExpression nodeExpression2( nodeExpression ); } + + void test_columnRefUnprepared() + { + //test retrieving fields from feature when expression is unprepared - explicitly specified fields collection + //should take precedence over feature's field collection + + QgsFields fields; + fields.append( QgsField( "f1", QVariant::String ) ); + + QgsFeature f( 1 ); + f.setFields( fields ); + + //also add a joined field - this will not be available in feature's field collection + fields.append( QgsField( "j1", QVariant::String ), QgsFields::OriginJoin, 1 ); + + f.setAttributes( QgsAttributes() << QVariant( "f1" ) << QVariant( "j1" ) ); + f.setValid( true ); + + QgsExpression e( "\"f1\"" ); + QgsExpressionContext context; + context.setFeature( f ); + context.setFields( fields ); + QVariant result = e.evaluate( &context ); + QCOMPARE( result.toString(), QString( "f1" ) ); + + //test joined field + QgsExpression e2( "\"j1\"" ); + result = e2.evaluate( &context ); + QCOMPARE( result.toString(), QString( "j1" ) ); + + // final test - check that feature's field collection is also used when corresponding field NOT found + // in explicitly passed field collection + fields.append( QgsField( "f2", QVariant::String ) ); + f.setFields( fields ); + f.setAttributes( QgsAttributes() << QVariant( "f1" ) << QVariant( "j1" ) << QVariant( "f2" ) ); + context.setFeature( f ); + QgsExpression e3( "\"f2\"" ); + result = e3.evaluate( &context ); + QCOMPARE( result.toString(), QString( "f2" ) ); + } + }; QTEST_MAIN( TestQgsExpression )