@@ -270,6 +270,16 @@ static QVariant fcnToString( const QVariantList& values, QgsFeature* , QgsExpres
270
270
{
271
271
return QVariant ( getStringValue ( values.at ( 0 ), parent ) );
272
272
}
273
+ static QVariant fcnCoalesce ( const QVariantList& values, QgsFeature* , QgsExpression* )
274
+ {
275
+ foreach ( const QVariant &value, values )
276
+ {
277
+ if ( value.isNull () )
278
+ continue ;
279
+ return value;
280
+ }
281
+ return QVariant ();
282
+ }
273
283
static QVariant fcnLower ( const QVariantList& values, QgsFeature* , QgsExpression* parent )
274
284
{
275
285
QString str = getStringValue ( values.at ( 0 ), parent );
@@ -324,6 +334,15 @@ static QVariant fcnFeatureId( const QVariantList& , QgsFeature* f, QgsExpression
324
334
// TODO: handling of 64-bit feature ids?
325
335
return f ? QVariant (( int )f->id () ) : QVariant ();
326
336
}
337
+ static QVariant fcnConcat ( const QVariantList& values, QgsFeature* , QgsExpression *parent )
338
+ {
339
+ QString concat;
340
+ foreach ( const QVariant &value, values )
341
+ {
342
+ concat += getStringValue ( value, parent );
343
+ }
344
+ return concat;
345
+ }
327
346
328
347
#define ENSURE_GEOM_TYPE (f, g, geomtype ) if (!f) return QVariant(); \
329
348
QgsGeometry* g = f->geometry (); \
@@ -431,13 +450,15 @@ const QList<QgsExpression::FunctionDef> &QgsExpression::BuiltinFunctions()
431
450
<< FunctionDef ( " toint" , 1 , fcnToInt, QObject::tr ( " Conversions" ) )
432
451
<< FunctionDef ( " toreal" , 1 , fcnToReal, QObject::tr ( " Conversions" ) )
433
452
<< FunctionDef ( " tostring" , 1 , fcnToString, QObject::tr ( " Conversions" ) )
453
+ << FunctionDef ( " coalesce" , -1 , fcnCoalesce, QObject::tr ( " Conversions" ) )
434
454
// string manipulation
435
455
<< FunctionDef ( " lower" , 1 , fcnLower, QObject::tr ( " String" ) )
436
456
<< FunctionDef ( " upper" , 1 , fcnUpper, QObject::tr ( " String" ) )
437
457
<< FunctionDef ( " length" , 1 , fcnLength, QObject::tr ( " String" ) )
438
458
<< FunctionDef ( " replace" , 3 , fcnReplace, QObject::tr ( " String" ) )
439
459
<< FunctionDef ( " regexp_replace" , 3 , fcnRegexpReplace, QObject::tr ( " String" ) )
440
460
<< FunctionDef ( " substr" , 3 , fcnSubstr, QObject::tr ( " String" ) )
461
+ << FunctionDef ( " concat" , -1 , fcnConcat, QObject::tr ( " String" ) )
441
462
// geometry accessors
442
463
<< FunctionDef ( " xat" , 1 , fcnXat, QObject::tr ( " Geometry" ), " " , true )
443
464
<< FunctionDef ( " yat" , 1 , fcnYat, QObject::tr ( " Geometry" ), " " , true )
@@ -693,7 +714,7 @@ QgsExpression::Node* QgsExpression::Node::createFromOgcFilter( QDomElement &elem
693
714
QgsExpression::Node *operand2 = 0 , *upperBound = 0 ;
694
715
695
716
QDomElement operandElem = element.firstChildElement ();
696
- while ( !operandElem.isNull () )
717
+ while ( !operandElem.isNull () )
697
718
{
698
719
if ( operandElem.localName () == " LowerBoundary" )
699
720
{
@@ -1340,8 +1361,8 @@ QVariant QgsExpression::NodeFunction::eval( QgsExpression* parent, QgsFeature* f
1340
1361
{
1341
1362
QVariant v = n->eval ( parent, f );
1342
1363
ENSURE_NO_EVAL_ERROR;
1343
- if ( isNull ( v ) )
1344
- return QVariant (); // all "normal" functions return NULL when any parameter is NULL
1364
+ if ( isNull ( v ) && fd. mFcn != fcnCoalesce )
1365
+ return QVariant (); // all "normal" functions return NULL, when any parameter is NULL (so coalesce is abnormal)
1345
1366
argValues.append ( v );
1346
1367
}
1347
1368
}
0 commit comments