Skip to content

Commit ec55161

Browse files
committed
Avoid lazy evaluation for substr expression function
Better solution is to set handlesNull to true to avoid the default null parameter = null result behaviour, and handle null values in params 1 and 2 manually
1 parent 0fbcc4b commit ec55161

File tree

2 files changed

+12
-20
lines changed

2 files changed

+12
-20
lines changed

src/core/qgsexpression.cpp

+10-20
Original file line numberDiff line numberDiff line change
@@ -1398,30 +1398,19 @@ static QVariant fcnUuid( const QVariantList&, const QgsExpressionContext*, QgsEx
13981398
return QUuid::createUuid().toString();
13991399
}
14001400

1401-
static QVariant fcnSubstr( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent )
1401+
static QVariant fcnSubstr( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
14021402
{
1403+
if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1404+
return QVariant();
14031405

1404-
QgsExpression::Node* node;
1405-
1406-
node = getNode( values.at( 0 ), parent );
1407-
ENSURE_NO_EVAL_ERROR;
1408-
QString str = node->eval( parent, context ).toString();
1409-
1410-
node = getNode( values.at( 1 ), parent );
1411-
ENSURE_NO_EVAL_ERROR;
1412-
int from = node->eval( parent, context ).toInt();
1406+
QString str = getStringValue( values.at( 0 ), parent );
1407+
int from = getIntValue( values.at( 1 ), parent );
14131408

1414-
node = getNode( values.at( 2 ), parent );
1415-
QVariant value = node->eval( parent, context );
1416-
int len;
1417-
if ( value.isValid() )
1418-
{
1419-
len = value.toInt();
1420-
}
1409+
int len = 0;
1410+
if ( values.at( 2 ).isValid() )
1411+
len = getIntValue( values.at( 2 ), parent );
14211412
else
1422-
{
14231413
len = str.size();
1424-
}
14251414

14261415
if ( from < 0 )
14271416
{
@@ -3847,7 +3836,8 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
38473836
<< new StaticFunction( QStringLiteral( "replace" ), -1, fcnReplace, QStringLiteral( "String" ) )
38483837
<< new StaticFunction( QStringLiteral( "regexp_replace" ), 3, fcnRegexpReplace, QStringLiteral( "String" ) )
38493838
<< new StaticFunction( QStringLiteral( "regexp_substr" ), 2, fcnRegexpSubstr, QStringLiteral( "String" ) )
3850-
<< new StaticFunction( QStringLiteral( "substr" ), ParameterList() << Parameter( QStringLiteral( "string" ) ) << Parameter( QStringLiteral( "start " ) ) << Parameter( QStringLiteral( "length" ), true ), fcnSubstr, QStringLiteral( "String" ), QString(), False, QSet<QString>(), true )
3839+
<< new StaticFunction( QStringLiteral( "substr" ), ParameterList() << Parameter( QStringLiteral( "string" ) ) << Parameter( QStringLiteral( "start " ) ) << Parameter( QStringLiteral( "length" ), true ), fcnSubstr, QStringLiteral( "String" ), QString(),
3840+
false, QSet< QString >(), false, QStringList(), true )
38513841
<< new StaticFunction( QStringLiteral( "concat" ), -1, fcnConcat, QStringLiteral( "String" ), QString(), false, QSet<QString>(), false, QStringList(), true )
38523842
<< new StaticFunction( QStringLiteral( "strpos" ), 2, fcnStrpos, QStringLiteral( "String" ) )
38533843
<< new StaticFunction( QStringLiteral( "left" ), 2, fcnLeft, QStringLiteral( "String" ) )

tests/src/core/testqgsexpression.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,8 @@ class TestQgsExpression: public QObject
840840
QTest::newRow( "substr negative length" ) << "substr('HeLLo', 1,-3)" << false << QVariant( "He" );
841841
QTest::newRow( "substr positive start and negative length" ) << "substr('HeLLo', 3,-1)" << false << QVariant( "LL" );
842842
QTest::newRow( "substr start only" ) << "substr('HeLLo', 3)" << false << QVariant( "LLo" );
843+
QTest::newRow( "substr null value" ) << "substr(NULL, 3,2)" << false << QVariant();
844+
QTest::newRow( "substr null start" ) << "substr('Hello',NULL,2)" << false << QVariant();
843845
QTest::newRow( "regexp_substr" ) << "regexp_substr('abc123','(\\\\d+)')" << false << QVariant( "123" );
844846
QTest::newRow( "regexp_substr non-greedy" ) << "regexp_substr('abc123','(\\\\d+?)')" << false << QVariant( "1" );
845847
QTest::newRow( "regexp_substr no hit" ) << "regexp_substr('abcdef','(\\\\d+)')" << false << QVariant( "" );

0 commit comments

Comments
 (0)