Skip to content

Commit db1a192

Browse files
committed
[FEATURE][expressions] Simplified variant of "attribute" function
This adds a second variant for the existing "attribute" function. The current function requires both a target feature and attribute name to be specified, while the NEW variant just uses the current feature. E.g. NEW: attribute( 'name' ) -> returns the value stored in 'name' attribute for the current feature EXISTING: attribute( @atlas_feature, 'name' ) -> returns value stored in 'name' attribute for the current atlas feature It's just a faster shorthand version!
1 parent 3433c9c commit db1a192

File tree

3 files changed

+66
-9
lines changed

3 files changed

+66
-9
lines changed
Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
{
22
"name": "attribute",
33
"type": "function",
4-
"description": "Returns the value of a specified attribute from a feature.",
5-
"arguments": [ {"arg":"feature","description":"a feature"},
6-
{"arg":"attribute_name","description":"name of attribute to be returned"}],
7-
"examples": [ { "expression":"attribute( $currentfeature, 'name' )", "returns":"value stored in 'name' attribute for the current feature"}]
4+
"description": "Returns an attribute from a feature.",
5+
"variants": [
6+
{ "variant": "Variant 1",
7+
"variant_description": "Returns the value of an attribute from the current feature.",
8+
"arguments": [ {"arg":"attribute_name","description":"name of attribute to be returned"}],
9+
"examples": [ { "expression":"attribute( 'name' )", "returns":"value stored in 'name' attribute for the current feature"}] },
10+
{ "variant": "Variant 2",
11+
"variant_description": "Allows the target feature and attribute name to be specified.",
12+
"arguments": [ {"arg":"feature","description":"a feature"},
13+
{"arg":"attribute_name","description":"name of attribute to be returned"}],
14+
"examples": [ { "expression":"attribute( @atlas_feature, 'name' )", "returns":"value stored in 'name' attribute for the current atlas feature"}] }
15+
]
816
}

src/core/expression/qgsexpressionfunction.cpp

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,12 +1332,27 @@ static QVariant fcnFeature( const QVariantList &, const QgsExpressionContext *co
13321332

13331333
return context->feature();
13341334
}
1335-
static QVariant fcnAttribute( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
1335+
static QVariant fcnAttribute( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
13361336
{
1337-
QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1338-
QString attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1337+
QgsFeature feature;
1338+
QString attr;
1339+
if ( values.size() == 1 )
1340+
{
1341+
attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1342+
feature = context->feature();
1343+
}
1344+
else if ( values.size() == 2 )
1345+
{
1346+
feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1347+
attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1348+
}
1349+
else
1350+
{
1351+
parent->setEvalErrorString( QObject::tr( "Function `attribute` requires one or two parameters. %1 given." ).arg( values.length() ) );
1352+
return QVariant();
1353+
}
13391354

1340-
return feat.attribute( attr );
1355+
return feature.attribute( attr );
13411356
}
13421357

13431358
static QVariant fcnIsSelected( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
@@ -5319,10 +5334,30 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
53195334

53205335
sFunctions << evalFunc;
53215336

5337+
QgsStaticExpressionFunction *attributeFunc = new QgsStaticExpressionFunction( QStringLiteral( "attribute" ), -1, fcnAttribute, QStringLiteral( "Record and Attributes" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES );
5338+
attributeFunc->setIsStaticFunction(
5339+
[]( const QgsExpressionNodeFunction * node, QgsExpression * parent, const QgsExpressionContext * context )
5340+
{
5341+
const QList< QgsExpressionNode *> argList = node->args()->list();
5342+
for ( QgsExpressionNode *argNode : argList )
5343+
{
5344+
if ( !argNode->isStatic( parent, context ) )
5345+
return false;
5346+
}
5347+
5348+
if ( node->args()->count() == 1 )
5349+
{
5350+
// not static -- this is the variant which uses the current feature taken direct from the expression context
5351+
return false;
5352+
}
5353+
5354+
return true;
5355+
} );
5356+
sFunctions << attributeFunc;
5357+
53225358
sFunctions
53235359
<< new QgsStaticExpressionFunction( QStringLiteral( "env" ), 1, fcnEnvVar, QStringLiteral( "General" ), QString() )
53245360
<< new QgsWithVariableExpressionFunction()
5325-
<< new QgsStaticExpressionFunction( QStringLiteral( "attribute" ), 2, fcnAttribute, QStringLiteral( "Record and Attributes" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES )
53265361
<< new QgsStaticExpressionFunction( QStringLiteral( "raster_value" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "band" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "point" ) ), fcnRasterValue, QStringLiteral( "Rasters" ) )
53275362

53285363
// functions for arrays

tests/src/core/testqgsexpression.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,20 @@ class TestQgsExpression: public QObject
15481548
QgsExpression exp2( QStringLiteral( "attribute($currentfeature,'second'||'_column')" ) );
15491549
v = exp2.evaluate( &context );
15501550
QCOMPARE( v.toInt(), 5 );
1551+
1552+
QgsExpression exp3( QStringLiteral( "attribute()" ) );
1553+
v = exp3.evaluate( &context );
1554+
QVERIFY( v.isNull() );
1555+
QVERIFY( exp3.hasEvalError() );
1556+
1557+
QgsExpression exp4( QStringLiteral( "attribute('a','b','c')" ) );
1558+
v = exp4.evaluate( &context );
1559+
QVERIFY( v.isNull() );
1560+
QVERIFY( exp4.hasEvalError() );
1561+
1562+
QgsExpression exp5( QStringLiteral( "attribute('col1')" ) );
1563+
v = exp5.evaluate( &context );
1564+
QCOMPARE( v.toString(), QString( "test value" ) );
15511565
}
15521566

15531567
void eval_get_feature_data()

0 commit comments

Comments
 (0)