diff --git a/resources/function_help/json/nullif b/resources/function_help/json/nullif new file mode 100644 index 000000000000..bf50901401bd --- /dev/null +++ b/resources/function_help/json/nullif @@ -0,0 +1,11 @@ +{ + "name": "nullif", + "type": "function", + "description": "Returns a null value if value1 equals value2; otherwise it returns value1. This can be used to conditionally substitute values with NULL.", + "arguments": [ {"arg":"value1", "description": "The value that should either be used or substituted with NULL."}, + {"arg":"value2", "description": "The control value that will trigger the NULL substitution."}], + "examples": [ { "expression":"nullif('(none)', '(none)')", "returns":"NULL"}, + { "expression":"nullif('text', '(none)')", "returns":"'text'"}, + { "expression":"nullif(\"name\", ''), "returns":"NULL, if name is an empty string (or already NULL), the name in any other case."} ] +} + diff --git a/src/core/expression/qgsexpressionfunction.cpp b/src/core/expression/qgsexpressionfunction.cpp index 212a856ad3ab..b09cd9b8a278 100644 --- a/src/core/expression/qgsexpressionfunction.cpp +++ b/src/core/expression/qgsexpressionfunction.cpp @@ -947,6 +947,18 @@ static QVariant fcnCoalesce( const QVariantList &values, const QgsExpressionCont } return QVariant(); } + +static QVariant fcnNullIf( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * ) +{ + const QVariant val1 = values.at( 0 ); + const QVariant val2 = values.at( 1 ); + + if ( val1 == val2 ) + return QVariant(); + else + return val1; +} + static QVariant fcnLower( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * ) { QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent ); @@ -4575,6 +4587,7 @@ const QList &QgsExpression::Functions() << new QgsStaticExpressionFunction( QStringLiteral( "to_dm" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "value" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "axis" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "precision" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "formatting" ), true ), fcnToDegreeMinute, QStringLiteral( "Conversions" ), QString(), false, QSet(), false, QStringList() << QStringLiteral( "todm" ) ) << 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(), false, QStringList() << QStringLiteral( "todms" ) ) << new QgsStaticExpressionFunction( QStringLiteral( "coalesce" ), -1, fcnCoalesce, QStringLiteral( "Conditionals" ), QString(), false, QSet(), false, QStringList(), true ) + << new QgsStaticExpressionFunction( QStringLiteral( "nullif" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "value1" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "value2" ) ), fcnNullIf, QStringLiteral( "Conditionals" ) ) << new QgsStaticExpressionFunction( QStringLiteral( "if" ), 3, fcnIf, QStringLiteral( "Conditionals" ), QString(), false, QSet(), true ) << new QgsStaticExpressionFunction( QStringLiteral( "aggregate" ), diff --git a/tests/src/core/testqgsexpression.cpp b/tests/src/core/testqgsexpression.cpp index 5403b3de2de4..91a08e578260 100644 --- a/tests/src/core/testqgsexpression.cpp +++ b/tests/src/core/testqgsexpression.cpp @@ -1129,6 +1129,11 @@ class TestQgsExpression: public QObject QTest::newRow( "coalesce null" ) << "coalesce(NULL)" << false << QVariant(); QTest::newRow( "coalesce mid-null" ) << "coalesce(1, NULL, 3)" << false << QVariant( 1 ); QTest::newRow( "coalesce exp" ) << "coalesce(NULL, 1+1)" << false << QVariant( 2 ); + QTest::newRow( "nullif no substitution" ) << "nullif(3, '(none)')" << false << QVariant( 3 ); + QTest::newRow( "nullif NULL" ) << "nullif(NULL, '(none)')" << false << QVariant(); + QTest::newRow( "nullif substitute string" ) << "nullif('(none)', '(none)')" << false << QVariant(); + QTest::newRow( "nullif substitute double" ) << "nullif(3.3, 3.3)" << false << QVariant(); + QTest::newRow( "nullif substitute int" ) << "nullif(0, 0)" << false << QVariant(); QTest::newRow( "regexp match" ) << "regexp_match('abc','.b.')" << false << QVariant( 1 ); QTest::newRow( "regexp match invalid" ) << "regexp_match('abc DEF','[[[')" << true << QVariant(); QTest::newRow( "regexp match escaped" ) << "regexp_match('abc DEF','\\\\s[A-Z]+')" << false << QVariant( 4 ); @@ -1552,7 +1557,7 @@ class TestQgsExpression: public QObject if ( featureMatched ) { QgsFeature feat = res.value(); - QCOMPARE( feat.id(), ( long long )featureId ); + QCOMPARE( feat.id(), static_cast( featureId ) ); } }