From 3599700d867dba22fa3ac3ef10b574d1c0774c13 Mon Sep 17 00:00:00 2001 From: "Juergen E. Fischer" Date: Fri, 22 Jun 2012 20:16:07 +0200 Subject: [PATCH] [FEATURE] implement coalesce and concat function expressions (implements #4551) --- src/core/qgsexpression.cpp | 27 ++++++++++++++++++++++++--- src/core/qgsexpressionparser.yy | 2 +- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/core/qgsexpression.cpp b/src/core/qgsexpression.cpp index 7c8fd3344aec..449d526b4112 100644 --- a/src/core/qgsexpression.cpp +++ b/src/core/qgsexpression.cpp @@ -270,6 +270,16 @@ static QVariant fcnToString( const QVariantList& values, QgsFeature* , QgsExpres { return QVariant( getStringValue( values.at( 0 ), parent ) ); } +static QVariant fcnCoalesce( const QVariantList& values, QgsFeature* , QgsExpression* ) +{ + foreach( const QVariant &value, values ) + { + if ( value.isNull() ) + continue; + return value; + } + return QVariant(); +} static QVariant fcnLower( const QVariantList& values, QgsFeature* , QgsExpression* parent ) { QString str = getStringValue( values.at( 0 ), parent ); @@ -324,6 +334,15 @@ static QVariant fcnFeatureId( const QVariantList& , QgsFeature* f, QgsExpression // TODO: handling of 64-bit feature ids? return f ? QVariant(( int )f->id() ) : QVariant(); } +static QVariant fcnConcat( const QVariantList& values, QgsFeature* , QgsExpression *parent ) +{ + QString concat; + foreach( const QVariant &value, values ) + { + concat += getStringValue( value, parent ); + } + return concat; +} #define ENSURE_GEOM_TYPE(f, g, geomtype) if (!f) return QVariant(); \ QgsGeometry* g = f->geometry(); \ @@ -431,6 +450,7 @@ const QList &QgsExpression::BuiltinFunctions() << FunctionDef( "toint", 1, fcnToInt, QObject::tr( "Conversions" ) ) << FunctionDef( "toreal", 1, fcnToReal, QObject::tr( "Conversions" ) ) << FunctionDef( "tostring", 1, fcnToString, QObject::tr( "Conversions" ) ) + << FunctionDef( "coalesce", -1, fcnCoalesce, QObject::tr( "Conversions" ) ) // string manipulation << FunctionDef( "lower", 1, fcnLower, QObject::tr( "String" ) ) << FunctionDef( "upper", 1, fcnUpper, QObject::tr( "String" ) ) @@ -438,6 +458,7 @@ const QList &QgsExpression::BuiltinFunctions() << FunctionDef( "replace", 3, fcnReplace, QObject::tr( "String" ) ) << FunctionDef( "regexp_replace", 3, fcnRegexpReplace, QObject::tr( "String" ) ) << FunctionDef( "substr", 3, fcnSubstr, QObject::tr( "String" ) ) + << FunctionDef( "concat", -1, fcnConcat, QObject::tr( "String" ) ) // geometry accessors << FunctionDef( "xat", 1, fcnXat, QObject::tr( "Geometry" ), "", true ) << FunctionDef( "yat", 1, fcnYat, QObject::tr( "Geometry" ), "", true ) @@ -693,7 +714,7 @@ QgsExpression::Node* QgsExpression::Node::createFromOgcFilter( QDomElement &elem QgsExpression::Node *operand2 = 0, *upperBound = 0; QDomElement operandElem = element.firstChildElement(); - while( !operandElem.isNull() ) + while ( !operandElem.isNull() ) { if ( operandElem.localName() == "LowerBoundary" ) { @@ -1340,8 +1361,8 @@ QVariant QgsExpression::NodeFunction::eval( QgsExpression* parent, QgsFeature* f { QVariant v = n->eval( parent, f ); ENSURE_NO_EVAL_ERROR; - if ( isNull( v ) ) - return QVariant(); // all "normal" functions return NULL when any parameter is NULL + if ( isNull( v ) && fd.mFcn != fcnCoalesce ) + return QVariant(); // all "normal" functions return NULL, when any parameter is NULL (so coalesce is abnormal) argValues.append( v ); } } diff --git a/src/core/qgsexpressionparser.yy b/src/core/qgsexpressionparser.yy index f96810e640e2..e93c5f1ce520 100644 --- a/src/core/qgsexpressionparser.yy +++ b/src/core/qgsexpressionparser.yy @@ -165,7 +165,7 @@ expression: exp_error("Function is not known"); YYERROR; } - if (QgsExpression::BuiltinFunctions()[fnIndex].mParams != $3->count()) + if ( QgsExpression::BuiltinFunctions()[fnIndex].mParams != -1 && QgsExpression::BuiltinFunctions()[fnIndex].mParams != $3->count() ) { exp_error("Function is called with wrong number of arguments"); YYERROR;