mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Merge pull request #2118 from jef-n/postgres-like-concat
expressions: let concat handle NULL like empty string (like in postgres; fixes #1927)
This commit is contained in:
commit
6e3a1fa057
@ -194,7 +194,14 @@ class QgsExpression
|
||||
class Function
|
||||
{
|
||||
public:
|
||||
Function( const QString& fnname, int params, const QString& group, const QString& helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList(), bool lazyEval = false );
|
||||
Function( const QString& fnname,
|
||||
int params,
|
||||
QString group,
|
||||
QString helpText = QString(),
|
||||
bool usesGeometry = false,
|
||||
QStringList referencedColumns = QStringList(),
|
||||
bool lazyEval = false,
|
||||
bool handlesNull = false );
|
||||
|
||||
virtual ~Function();
|
||||
|
||||
@ -225,11 +232,11 @@ class QgsExpression
|
||||
const QString helptext();
|
||||
|
||||
virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) = 0;
|
||||
|
||||
virtual bool handlesNull() const;
|
||||
};
|
||||
|
||||
|
||||
static const QList<QgsExpression::Function *>& Functions();
|
||||
|
||||
static const QStringList& BuiltinFunctions();
|
||||
|
||||
static bool registerFunction( Function* function );
|
||||
@ -310,6 +317,7 @@ class QgsExpression
|
||||
public:
|
||||
NodeList();
|
||||
~NodeList();
|
||||
/** Takes ownership of the provided node */
|
||||
void append( QgsExpression::Node* node /Transfer/ );
|
||||
int count();
|
||||
const QList<QgsExpression::Node*>& list();
|
||||
|
@ -1741,7 +1741,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
|
||||
<< new StaticFunction( "to_date", 1, fcnToDate, "Conversions", QString(), false, QStringList(), false, QStringList() << "todate" )
|
||||
<< new StaticFunction( "to_time", 1, fcnToTime, "Conversions", QString(), false, QStringList(), false, QStringList() << "totime" )
|
||||
<< new StaticFunction( "to_interval", 1, fcnToInterval, "Conversions", QString(), false, QStringList(), false, QStringList() << "tointerval" )
|
||||
<< new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals" )
|
||||
<< new StaticFunction( "coalesce", -1, fcnCoalesce, "Conditionals", QString(), false, QStringList(), false, QStringList(), true )
|
||||
<< new StaticFunction( "if", 3, fcnIf, "Conditionals", "", False, QStringList(), true )
|
||||
<< new StaticFunction( "regexp_match", 2, fcnRegexpMatch, "Conditionals" )
|
||||
<< new StaticFunction( "now", 0, fcnNow, "Date and Time", QString(), false, QStringList(), false, QStringList() << "$now" )
|
||||
@ -1763,7 +1763,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
|
||||
<< new StaticFunction( "regexp_replace", 3, fcnRegexpReplace, "String" )
|
||||
<< new StaticFunction( "regexp_substr", 2, fcnRegexpSubstr, "String" )
|
||||
<< new StaticFunction( "substr", 3, fcnSubstr, "String" )
|
||||
<< new StaticFunction( "concat", -1, fcnConcat, "String" )
|
||||
<< new StaticFunction( "concat", -1, fcnConcat, "String", QString(), false, QStringList(), false, QStringList(), true )
|
||||
<< new StaticFunction( "strpos", 2, fcnStrpos, "String" )
|
||||
<< new StaticFunction( "left", 2, fcnLeft, "String" )
|
||||
<< new StaticFunction( "right", 2, fcnRight, "String" )
|
||||
@ -2683,7 +2683,7 @@ QVariant QgsExpression::NodeFunction::eval( QgsExpression* parent, const QgsFeat
|
||||
{
|
||||
v = n->eval( parent, f );
|
||||
ENSURE_NO_EVAL_ERROR;
|
||||
if ( isNull( v ) && fd->name() != "coalesce" )
|
||||
if ( isNull( v ) && !fd->handlesNull() )
|
||||
return QVariant(); // all "normal" functions return NULL, when any parameter is NULL (so coalesce is abnormal)
|
||||
}
|
||||
argValues.append( v );
|
||||
|
@ -286,8 +286,23 @@ class CORE_EXPORT QgsExpression
|
||||
class CORE_EXPORT Function
|
||||
{
|
||||
public:
|
||||
Function( const QString& fnname, int params, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList(), bool lazyEval = false )
|
||||
: mName( fnname ), mParams( params ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ), mReferencedColumns( referencedColumns ), mLazyEval( lazyEval ) {}
|
||||
Function( const QString& fnname,
|
||||
int params,
|
||||
QString group,
|
||||
QString helpText = QString(),
|
||||
bool usesGeometry = false,
|
||||
QStringList referencedColumns = QStringList(),
|
||||
bool lazyEval = false,
|
||||
bool handlesNull = false )
|
||||
: mName( fnname )
|
||||
, mParams( params )
|
||||
, mUsesGeometry( usesGeometry )
|
||||
, mGroup( group )
|
||||
, mHelpText( helpText )
|
||||
, mReferencedColumns( referencedColumns )
|
||||
, mLazyEval( lazyEval )
|
||||
, mHandlesNull( handlesNull )
|
||||
{}
|
||||
|
||||
virtual ~Function() {}
|
||||
|
||||
@ -327,6 +342,8 @@ class CORE_EXPORT QgsExpression
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool handlesNull() const { return mHandlesNull; }
|
||||
|
||||
private:
|
||||
QString mName;
|
||||
int mParams;
|
||||
@ -335,13 +352,26 @@ class CORE_EXPORT QgsExpression
|
||||
QString mHelpText;
|
||||
QStringList mReferencedColumns;
|
||||
bool mLazyEval;
|
||||
bool mHandlesNull;
|
||||
};
|
||||
|
||||
class StaticFunction : public Function
|
||||
{
|
||||
public:
|
||||
StaticFunction( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList(), bool lazyEval = false, const QStringList& aliases = QStringList() )
|
||||
: Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval ), mFnc( fcn ), mAliases( aliases ) {}
|
||||
StaticFunction( QString fnname,
|
||||
int params,
|
||||
FcnEval fcn,
|
||||
QString group,
|
||||
QString helpText = QString(),
|
||||
bool usesGeometry = false,
|
||||
QStringList referencedColumns = QStringList(),
|
||||
bool lazyEval = false,
|
||||
const QStringList& aliases = QStringList(),
|
||||
bool handlesNull = false )
|
||||
: Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
|
||||
, mFnc( fcn )
|
||||
, mAliases( aliases )
|
||||
{}
|
||||
|
||||
virtual ~StaticFunction() {}
|
||||
|
||||
|
@ -387,7 +387,8 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "wordwrap" ) << "wordwrap('university of qgis\nsupports many multiline',-5,' ')" << false << QVariant( "university\nof qgis\nsupports\nmany multiline" );
|
||||
QTest::newRow( "format" ) << "format('%1 %2 %3 %1', 'One', 'Two', 'Three')" << false << QVariant( "One Two Three One" );
|
||||
QTest::newRow( "concat" ) << "concat('a', 'b', 'c', 'd')" << false << QVariant( "abcd" );
|
||||
QTest::newRow( "concat single" ) << "concat('a')" << false << QVariant( "a" );
|
||||
QTest::newRow( "concat function single" ) << "concat('a')" << false << QVariant( "a" );
|
||||
QTest::newRow( "concat function with NULL" ) << "concat(NULL,'a','b')" << false << QVariant( "ab" );
|
||||
|
||||
// implicit conversions
|
||||
QTest::newRow( "implicit int->text" ) << "length(123)" << false << QVariant( 3 );
|
||||
|
Loading…
x
Reference in New Issue
Block a user