Skip to content

Commit

Permalink
Cast left node to text on string comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
m-kuhn committed May 30, 2018
1 parent ad1fef9 commit 6a88bfc
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/core/qgssqlexpressioncompiler.cpp
Expand Up @@ -38,6 +38,18 @@ QString QgsSqlExpressionCompiler::result()
return mResult;
}

bool QgsSqlExpressionCompiler::opIsStringComparison( QgsExpressionNodeBinaryOperator::BinaryOperator op )
{
if ( op == QgsExpressionNodeBinaryOperator::BinaryOperator::boILike ||
op == QgsExpressionNodeBinaryOperator::BinaryOperator::boLike ||
op == QgsExpressionNodeBinaryOperator::BinaryOperator::boNotILike ||
op == QgsExpressionNodeBinaryOperator::BinaryOperator::boNotLike ||
op == QgsExpressionNodeBinaryOperator::BinaryOperator::boRegexp )
return true;
else
return false;
}

QString QgsSqlExpressionCompiler::quotedIdentifier( const QString &identifier )
{
QString quoted = identifier;
Expand Down Expand Up @@ -253,6 +265,9 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
QString left;
Result lr( compileNode( n->opLeft(), left ) );

if ( opIsStringComparison( n ->op() ) )
left = castToText( left );

QString right;
Result rr( compileNode( n->opRight(), right ) );

Expand Down Expand Up @@ -409,6 +424,11 @@ QString QgsSqlExpressionCompiler::castToReal( const QString &value ) const
return QString();
}

QString QgsSqlExpressionCompiler::castToText( const QString &value ) const
{
return value;
}

QString QgsSqlExpressionCompiler::castToInt( const QString &value ) const
{
Q_UNUSED( value );
Expand Down
34 changes: 34 additions & 0 deletions src/core/qgssqlexpressioncompiler.h
Expand Up @@ -20,6 +20,7 @@

#include "qgis_core.h"
#include "qgsfields.h"
#include "qgsexpressionnodeimpl.h"

class QgsExpression;
class QgsExpressionNode;
Expand Down Expand Up @@ -80,6 +81,22 @@ class CORE_EXPORT QgsSqlExpressionCompiler
*/
virtual QString result();

/**
* Returns true if \a op is one of
*
* - LIKE
* - ILIKE
* - NOT LIKE
* - NOT ILIKE
* - ~ (regexp)
*
* In such cases the left operator will be cast to string to behave equal to
* QGIS own expression engine.
*
* \since QGIS 3.2
*/
bool opIsStringComparison( QgsExpressionNodeBinaryOperator::BinaryOperator op );

protected:

/**
Expand Down Expand Up @@ -132,6 +149,23 @@ class CORE_EXPORT QgsSqlExpressionCompiler
*/
virtual QString castToReal( const QString &value ) const;

/**
* Casts a value to a text result. Subclasses that support casting to text may implement this function
* to get equal behavior to the QGIS expression engine when string comparison operators are applied
* on non-string data.
*
* Example:
*
* 579 LIKE '5%'
*
* which on a postgres database needs to be
*
* 579::text LIKE '5%'
*
* \since QGIS 3.2
*/
virtual QString castToText( const QString &value ) const;

/**
* Casts a value to a integer result. Subclasses must reimplement this to cast a numeric value to a integer
* type value so that integer division results in a integer value result instead of real.
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgssqliteexpressioncompiler.cpp
Expand Up @@ -111,4 +111,9 @@ QString QgsSQLiteExpressionCompiler::castToInt( const QString &value ) const
return QStringLiteral( "CAST((%1) AS INTEGER)" ).arg( value );
}

QString QgsSQLiteExpressionCompiler::castToText( const QString &value ) const
{
return QStringLiteral( "CAST((%1) AS TEXT)" ).arg( value );
}

///@endcond
1 change: 1 addition & 0 deletions src/core/qgssqliteexpressioncompiler.h
Expand Up @@ -52,6 +52,7 @@ class CORE_EXPORT QgsSQLiteExpressionCompiler : public QgsSqlExpressionCompiler
QString sqlFunctionFromFunctionName( const QString &fnName ) const override;
QString castToReal( const QString &value ) const override;
QString castToInt( const QString &value ) const override;
QString castToText( const QString &value ) const override;

};

Expand Down
5 changes: 5 additions & 0 deletions src/providers/postgres/qgspostgresexpressioncompiler.cpp
Expand Up @@ -144,6 +144,11 @@ QString QgsPostgresExpressionCompiler::castToInt( const QString &value ) const
return QStringLiteral( "((%1)::int)" ).arg( value );
}

QString QgsPostgresExpressionCompiler::castToText( const QString &value ) const
{
return QStringLiteral( "((%1)::text)" ).arg( value );
}

QgsSqlExpressionCompiler::Result QgsPostgresExpressionCompiler::compileNode( const QgsExpressionNode *node, QString &result )
{
switch ( node->nodeType() )
Expand Down
1 change: 1 addition & 0 deletions src/providers/postgres/qgspostgresexpressioncompiler.h
Expand Up @@ -36,6 +36,7 @@ class QgsPostgresExpressionCompiler : public QgsSqlExpressionCompiler
QStringList sqlArgumentsFromFunctionName( const QString &fnName, const QStringList &fnArgs ) const override;
QString castToReal( const QString &value ) const override;
QString castToInt( const QString &value ) const override;
QString castToText( const QString &value ) const override;

QString mGeometryColumn;
QgsPostgresGeometryColumnType mSpatialColType;
Expand Down

0 comments on commit 6a88bfc

Please sign in to comment.