Skip to content

Commit 8385cd9

Browse files
committed
Handle arrays comparison in QgsExpression
1 parent eeb1283 commit 8385cd9

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

src/core/qgsexpression.cpp

+74
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ inline bool isNull( const QVariant &v )
175175
return v.isNull();
176176
}
177177

178+
inline bool isList( const QVariant &v )
179+
{
180+
return v.type() == QVariant::List;
181+
}
182+
178183
///////////////////////////////////////////////
179184
// evaluation error macros
180185

@@ -4813,6 +4818,75 @@ QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression *parent, const Q
48134818
{
48144819
return TVL_Unknown;
48154820
}
4821+
else if ( isList( vL ) || isList( vR ) )
4822+
{
4823+
// verify that we have two lists
4824+
if ( !isList( vL ) || !isList( vR ) )
4825+
return TVL_Unknown;
4826+
4827+
// and search for not equal respective items
4828+
QVariantList lL = vL.toList();
4829+
QVariantList lR = vR.toList();
4830+
for ( int i = 0; i < lL.length() && i < lR.length(); i++ )
4831+
{
4832+
if ( isNull( lL.at( i ) ) && isNull( lR.at( i ) ) )
4833+
continue; // same behavior as PostgreSQL
4834+
4835+
if ( isNull( lL.at( i ) ) || isNull( lR.at( i ) ) )
4836+
{
4837+
switch ( mOp )
4838+
{
4839+
case boEQ:
4840+
return false;
4841+
case boNE:
4842+
return true;
4843+
case boLT:
4844+
case boLE:
4845+
return isNull( lR.at( i ) );
4846+
case boGT:
4847+
case boGE:
4848+
return isNull( lL.at( i ) );
4849+
default:
4850+
Q_ASSERT( false );
4851+
return TVL_Unknown;
4852+
}
4853+
}
4854+
4855+
QgsExpression::NodeLiteral nL( lL.at( i ) );
4856+
QgsExpression::NodeLiteral nR( lR.at( i ) );
4857+
QgsExpression::NodeBinaryOperator eqNode( boEQ, nL.clone(), nR.clone() );
4858+
QVariant eq = eqNode.eval( parent, context );
4859+
ENSURE_NO_EVAL_ERROR;
4860+
if ( eq == TVL_False )
4861+
{
4862+
// return the two items comparison
4863+
QgsExpression::NodeBinaryOperator node( mOp, nL.clone(), nR.clone() );
4864+
QVariant v = node.eval( parent, context );
4865+
ENSURE_NO_EVAL_ERROR;
4866+
return v;
4867+
}
4868+
}
4869+
4870+
// default to length comparison
4871+
switch ( mOp )
4872+
{
4873+
case boEQ:
4874+
return lL.length() == lR.length();
4875+
case boNE:
4876+
return lL.length() != lR.length();
4877+
case boLT:
4878+
return lL.length() < lR.length();
4879+
case boGT:
4880+
return lL.length() > lR.length();
4881+
case boLE:
4882+
return lL.length() <= lR.length();
4883+
case boGE:
4884+
return lL.length() >= lR.length();
4885+
default:
4886+
Q_ASSERT( false );
4887+
return TVL_Unknown;
4888+
}
4889+
}
48164890
else if ( isDoubleSafe( vL ) && isDoubleSafe( vR ) &&
48174891
( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
48184892
{

tests/src/core/testqgsexpression.cpp

+42
Original file line numberDiff line numberDiff line change
@@ -2443,6 +2443,48 @@ class TestQgsExpression: public QObject
24432443
QCOMPARE( badArray.evalErrorString(), QString( "Cannot convert 'not an array' to array" ) );
24442444
}
24452445

2446+
void compare_arrays()
2447+
{
2448+
QCOMPARE( QgsExpression( "array() = array()" ).evaluate(), QVariant( true ) );
2449+
QCOMPARE( QgsExpression( "array(NULL) = array(NULL)" ).evaluate(), QVariant( true ) );
2450+
QCOMPARE( QgsExpression( "array() = array(NULL)" ).evaluate(), QVariant( false ) );
2451+
QCOMPARE( QgsExpression( "array(1, NULL) = array(NULL, 1)" ).evaluate(), QVariant( false ) );
2452+
2453+
QCOMPARE( QgsExpression( "array('hello') = array('hello')" ).evaluate(), QVariant( true ) );
2454+
QCOMPARE( QgsExpression( "array('hello') = array('hello2')" ).evaluate(), QVariant( false ) );
2455+
QCOMPARE( QgsExpression( "array('h', 'e', 'l', 'l', 'o') = array('h', 'e', 'l', 'l', 'o')" ).evaluate(), QVariant( true ) );
2456+
QCOMPARE( QgsExpression( "array('h', 'e', 'l', 'l', 'o') = array('h', 'e', 'l', 'l')" ).evaluate(), QVariant( false ) );
2457+
2458+
QCOMPARE( QgsExpression( "array('1') = array(1)" ).evaluate(), QVariant( true ) );
2459+
QCOMPARE( QgsExpression( "array('1.2') = array(1.2)" ).evaluate(), QVariant( true ) );
2460+
2461+
QCOMPARE( QgsExpression( "array() != array()" ).evaluate(), QVariant( false ) );
2462+
QCOMPARE( QgsExpression( "array(NULL) != array(NULL)" ).evaluate(), QVariant( false ) );
2463+
QCOMPARE( QgsExpression( "array() != array(NULL)" ).evaluate(), QVariant( true ) );
2464+
QCOMPARE( QgsExpression( "array('hello') != array('hello')" ).evaluate(), QVariant( false ) );
2465+
QCOMPARE( QgsExpression( "array('hello') != array('hello2')" ).evaluate(), QVariant( true ) );
2466+
2467+
QCOMPARE( QgsExpression( "array() < array(1)" ).evaluate(), QVariant( true ) );
2468+
QCOMPARE( QgsExpression( "array(1) < array(NULL)" ).evaluate(), QVariant( true ) );
2469+
QCOMPARE( QgsExpression( "array(1) < array(1)" ).evaluate(), QVariant( false ) );
2470+
QCOMPARE( QgsExpression( "array(1) < array(2)" ).evaluate(), QVariant( true ) );
2471+
QCOMPARE( QgsExpression( "array(2) < array(1)" ).evaluate(), QVariant( false ) );
2472+
QCOMPARE( QgsExpression( "array(1) < array(1, 2)" ).evaluate(), QVariant( true ) );
2473+
QCOMPARE( QgsExpression( "array(1, 2) < array(1)" ).evaluate(), QVariant( false ) );
2474+
QCOMPARE( QgsExpression( "array('h', 'e', 'l', 'l', 'o') < array('h', 'e', 'l', 'l')" ).evaluate(), QVariant( false ) );
2475+
QCOMPARE( QgsExpression( "array('h', 'e', 'l', 'l', 'o') > array('h', 'e', 'l', 'l')" ).evaluate(), QVariant( true ) );
2476+
2477+
QCOMPARE( QgsExpression( "array() <= array(1)" ).evaluate(), QVariant( true ) );
2478+
QCOMPARE( QgsExpression( "array(1) <= array(NULL)" ).evaluate(), QVariant( true ) );
2479+
QCOMPARE( QgsExpression( "array(1) <= array(1)" ).evaluate(), QVariant( true ) );
2480+
QCOMPARE( QgsExpression( "array(1) <= array(2)" ).evaluate(), QVariant( true ) );
2481+
QCOMPARE( QgsExpression( "array(2) <= array(1)" ).evaluate(), QVariant( false ) );
2482+
QCOMPARE( QgsExpression( "array(1) <= array(1, 2)" ).evaluate(), QVariant( true ) );
2483+
QCOMPARE( QgsExpression( "array(1, 2) <= array(1)" ).evaluate(), QVariant( false ) );
2484+
QCOMPARE( QgsExpression( "array('h', 'e', 'l', 'l', 'o') <= array('h', 'e', 'l', 'l')" ).evaluate(), QVariant( false ) );
2485+
QCOMPARE( QgsExpression( "array('h', 'e', 'l', 'l', 'o') >= array('h', 'e', 'l', 'l')" ).evaluate(), QVariant( true ) );
2486+
}
2487+
24462488
void eval_map()
24472489
{
24482490
QgsFeature f( 100 );

0 commit comments

Comments
 (0)