Skip to content

Commit 506aaa0

Browse files
committed
[expression] Add try() function to provide a way to detect and handle
expressions which can intermittently fail.
1 parent 8f46862 commit 506aaa0

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

resources/function_help/json/try

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "try",
3+
"type": "function",
4+
"description": "Tries an expression and returns its value if error-free. If the expression returns an error, an alternative value will be returned when provided otherwise the function will return null.",
5+
"arguments": [
6+
{"arg":"expression","description":"the expression which should be run"},
7+
{"arg":"alternative","optional":true,"description":"the result which will be returned if the expression returns an error."}
8+
],
9+
"examples": [
10+
{ "expression":"try( to_int( '1' ), 0 )", "returns":"1"},
11+
{ "expression":"try( to_int( 'a' ), 0 )", "returns":"0"},
12+
{ "expression":"try( to_date( 'invalid_date' ) )", "returns":"NULL"}
13+
]
14+
}

src/core/expression/qgsexpressionfunction.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -3445,6 +3445,21 @@ static QVariant fcnColorRgb( const QVariantList &values, const QgsExpressionCont
34453445
return QStringLiteral( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
34463446
}
34473447

3448+
static QVariant fcnTry( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
3449+
{
3450+
QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
3451+
QVariant value = node->eval( parent, context );
3452+
if ( parent->hasEvalError() )
3453+
{
3454+
parent->setEvalErrorString( QString() );
3455+
node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
3456+
ENSURE_NO_EVAL_ERROR;
3457+
value = node->eval( parent, context );
3458+
ENSURE_NO_EVAL_ERROR;
3459+
}
3460+
return value;
3461+
}
3462+
34483463
static QVariant fcnIf( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
34493464
{
34503465
QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
@@ -4462,6 +4477,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
44624477
<< new QgsStaticExpressionFunction( QStringLiteral( "to_dms" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "value" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "axis" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "precision" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "formatting" ), true ), fcnToDegreeMinuteSecond, QStringLiteral( "Conversions" ), QString(), false, QSet<QString>(), false, QStringList() << QStringLiteral( "todms" ) )
44634478
<< new QgsStaticExpressionFunction( QStringLiteral( "coalesce" ), -1, fcnCoalesce, QStringLiteral( "Conditionals" ), QString(), false, QSet<QString>(), false, QStringList(), true )
44644479
<< new QgsStaticExpressionFunction( QStringLiteral( "if" ), 3, fcnIf, QStringLiteral( "Conditionals" ), QString(), false, QSet<QString>(), true )
4480+
<< new QgsStaticExpressionFunction( QStringLiteral( "try" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "expression" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "alternative" ), true, QVariant() ), fcnTry, QStringLiteral( "Conditionals" ), QString(), false, QSet<QString>(), true )
44654481

44664482
<< new QgsStaticExpressionFunction( QStringLiteral( "aggregate" ),
44674483
QgsExpressionFunction::ParameterList()

tests/src/core/testqgsexpression.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,9 @@ class TestQgsExpression: public QObject
11291129
QTest::newRow( "regexp match false" ) << "regexp_match('abc DEF','\\\\s[a-z]+')" << false << QVariant( 0 );
11301130
QTest::newRow( "if true" ) << "if(1=1, 1, 0)" << false << QVariant( 1 );
11311131
QTest::newRow( "if false" ) << "if(1=2, 1, 0)" << false << QVariant( 0 );
1132+
QTest::newRow( "try valid" ) << "try(to_int('1'),0)" << false << QVariant( 1 );
1133+
QTest::newRow( "try invalid with alternative" ) << "try(to_int('a'),0)" << false << QVariant( 0 );
1134+
QTest::newRow( "try invalid without alternative" ) << "try(to_int('a'))" << false << QVariant();
11321135

11331136
// Datetime functions
11341137
QTest::newRow( "to date" ) << "todate('2012-06-28')" << false << QVariant( QDate( 2012, 6, 28 ) );

0 commit comments

Comments
 (0)