Skip to content

Commit 7599d4f

Browse files
authored
[expression] Add try() function to provide a way to detect and handle
expressions which can intermittently fail.
1 parent 1d8bd00 commit 7599d4f

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
@@ -3688,6 +3688,21 @@ static QVariant fcnColorRgb( const QVariantList &values, const QgsExpressionCont
36883688
return QStringLiteral( "%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
36893689
}
36903690

3691+
static QVariant fcnTry( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
3692+
{
3693+
QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
3694+
QVariant value = node->eval( parent, context );
3695+
if ( parent->hasEvalError() )
3696+
{
3697+
parent->setEvalErrorString( QString() );
3698+
node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
3699+
ENSURE_NO_EVAL_ERROR;
3700+
value = node->eval( parent, context );
3701+
ENSURE_NO_EVAL_ERROR;
3702+
}
3703+
return value;
3704+
}
3705+
36913706
static QVariant fcnIf( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
36923707
{
36933708
QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
@@ -4763,6 +4778,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
47634778
<< new QgsStaticExpressionFunction( QStringLiteral( "coalesce" ), -1, fcnCoalesce, QStringLiteral( "Conditionals" ), QString(), false, QSet<QString>(), false, QStringList(), true )
47644779
<< new QgsStaticExpressionFunction( QStringLiteral( "nullif" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "value1" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "value2" ) ), fcnNullIf, QStringLiteral( "Conditionals" ) )
47654780
<< new QgsStaticExpressionFunction( QStringLiteral( "if" ), 3, fcnIf, QStringLiteral( "Conditionals" ), QString(), false, QSet<QString>(), true )
4781+
<< new QgsStaticExpressionFunction( QStringLiteral( "try" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "expression" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "alternative" ), true, QVariant() ), fcnTry, QStringLiteral( "Conditionals" ), QString(), false, QSet<QString>(), true )
47664782

47674783
<< new QgsStaticExpressionFunction( QStringLiteral( "aggregate" ),
47684784
QgsExpressionFunction::ParameterList()

tests/src/core/testqgsexpression.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,9 @@ class TestQgsExpression: public QObject
11771177
QTest::newRow( "regexp match false" ) << "regexp_match('abc DEF','\\\\s[a-z]+')" << false << QVariant( 0 );
11781178
QTest::newRow( "if true" ) << "if(1=1, 1, 0)" << false << QVariant( 1 );
11791179
QTest::newRow( "if false" ) << "if(1=2, 1, 0)" << false << QVariant( 0 );
1180+
QTest::newRow( "try valid" ) << "try(to_int('1'),0)" << false << QVariant( 1 );
1181+
QTest::newRow( "try invalid with alternative" ) << "try(to_int('a'),0)" << false << QVariant( 0 );
1182+
QTest::newRow( "try invalid without alternative" ) << "try(to_int('a'))" << false << QVariant();
11801183

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

0 commit comments

Comments
 (0)