Skip to content

Commit

Permalink
[feature][expressions] Add feature_id(some feature) function
Browse files Browse the repository at this point in the history
Allows for retrieving the feature ID of a feature object. Accepts
one argument which must be a feature object. Accordingly this
function can be used with the results of any other function
which returns feature objects, such as "get_feature", "overlay_*",
etc.

Fixes #51116
  • Loading branch information
nyalldawson committed Jan 13, 2023
1 parent 0b31551 commit 390cb76
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
15 changes: 15 additions & 0 deletions resources/function_help/json/feature_id
@@ -0,0 +1,15 @@
{
"name": "feature_id",
"type": "function",
"groups": ["Record and Attributes"],
"description": "Returns a feature's unique ID.",
"arguments": [{
"arg": "feature",
"description": "a feature object"
}],
"examples": [{
"expression": "feature_id( @feature )",
"returns": "the ID of the current feature"
}],
"tags": []
}
9 changes: 9 additions & 0 deletions src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -6058,6 +6058,14 @@ static QVariant fcnGetGeometry( const QVariantList &values, const QgsExpressionC
return QVariant();
}

static QVariant fcnGetFeatureId( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
if ( !feat.isValid() )
return QVariant();
return feat.id();
}

static QVariant fcnTransformGeometry( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
Expand Down Expand Up @@ -8730,6 +8738,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
functions << uuidFunc;

functions
<< new QgsStaticExpressionFunction( QStringLiteral( "feature_id" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "feature" ) ), fcnGetFeatureId, QStringLiteral( "Record and Attributes" ), QString(), true )
<< new QgsStaticExpressionFunction( QStringLiteral( "get_feature" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "attribute" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "value" ), true ),
Expand Down
18 changes: 18 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Expand Up @@ -2342,6 +2342,7 @@ class TestQgsExpression: public QObject
void eval_feature_id()
{
QgsFeature f( 100 );
f.setValid( true );
// older form
QgsExpression exp( QStringLiteral( "$id * 2" ) );
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
Expand All @@ -2352,23 +2353,36 @@ class TestQgsExpression: public QObject
QgsExpression exp2( QStringLiteral( "@id * 2" ) );
v = exp.evaluate( &context );
QCOMPARE( v.toInt(), 200 );

QgsExpression exp3( QStringLiteral( "feature_id(@feature)" ) );
v = exp3.evaluate( &context );
QCOMPARE( v.toInt(), 100 );
}

void eval_current_feature()
{
QgsFeature f( 100 );
f.setValid( true );
// older form
QgsExpression exp( QStringLiteral( "$currentfeature" ) );
QgsExpressionContext context = QgsExpressionContextUtils::createFeatureBasedContext( f, QgsFields() );
QVariant v = exp.evaluate( &context );
QgsFeature evalFeature = v.value<QgsFeature>();
QCOMPARE( evalFeature.id(), f.id() );

QgsExpression expId( QStringLiteral( "feature_id($currentfeature)" ) );
v = expId.evaluate( &context );
QCOMPARE( v.toInt(), f.id() );

// newer form
QgsExpression exp2( QStringLiteral( "@feature" ) );
v = exp2.evaluate( &context );
evalFeature = v.value<QgsFeature>();
QCOMPARE( evalFeature.id(), f.id() );

QgsExpression exp2Id( QStringLiteral( "feature_id(@feature)" ) );
v = exp2Id.evaluate( &context );
QCOMPARE( v.toInt(), f.id() );
}

void eval_current_geometry()
Expand Down Expand Up @@ -2521,6 +2535,10 @@ class TestQgsExpression: public QObject
{
QgsFeature feat = res.value<QgsFeature>();
QCOMPARE( feat.id(), static_cast<QgsFeatureId>( featureId ) );

QgsExpression featureIdExp( QStringLiteral( "feature_id(%1)" ).arg( string ) );
const QVariant idRes = featureIdExp.evaluate();
QCOMPARE( idRes.toInt(), featureId );
}
}

Expand Down

0 comments on commit 390cb76

Please sign in to comment.