Skip to content

Commit

Permalink
Fix OGR expression compiler with GDAL >= 2.0
Browse files Browse the repository at this point in the history
Some extreme corner cases (eg "NULL OR TRUE") tested by the provider
tests were failing with GDAL 2.0. In GDAL<2.0 these expressions would
be rejected by OGR, but it seems GDAL>=2.0 has partial support for
these so the expression compiler needs to handle them before handing
off to GDAL.
  • Loading branch information
nyalldawson committed Mar 3, 2016
1 parent 4dbd884 commit 81be559
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 1 deletion.
21 changes: 21 additions & 0 deletions src/core/qgssqlexpressioncompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,22 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
break;

case QgsExpression::boOr:
if ( mFlags.testFlag( NoNullInBooleanLogic ) )
{
if ( nodeIsNullLiteral( n->opLeft() ) || nodeIsNullLiteral( n->opRight() ) )
return Fail;
}

op = "OR";
break;

case QgsExpression::boAnd:
if ( mFlags.testFlag( NoNullInBooleanLogic ) )
{
if ( nodeIsNullLiteral( n->opLeft() ) || nodeIsNullLiteral( n->opRight() ) )
return Fail;
}

op = "AND";
break;

Expand Down Expand Up @@ -297,3 +309,12 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg

return Fail;
}

bool QgsSqlExpressionCompiler::nodeIsNullLiteral( const QgsExpression::Node* node ) const
{
if ( node->nodeType() != QgsExpression::ntLiteral )
return false;

const QgsExpression::NodeLiteral* nLit = static_cast<const QgsExpression::NodeLiteral*>( node );
return nLit->value().isNull();
}
3 changes: 3 additions & 0 deletions src/core/qgssqlexpressioncompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class CORE_EXPORT QgsSqlExpressionCompiler
{
CaseInsensitiveStringMatch = 0x01, //!< Provider performs case-insensitive string matching for all strings
LikeIsCaseInsensitive = 0x02, //!< Provider treats LIKE as case-insensitive
NoNullInBooleanLogic = 0x04, //!< Provider does not support using NULL with boolean logic, eg "(...) OR NULL"
};
Q_DECLARE_FLAGS( Flags, Flag )

Expand Down Expand Up @@ -98,6 +99,8 @@ class CORE_EXPORT QgsSqlExpressionCompiler

Flags mFlags;

bool nodeIsNullLiteral( const QgsExpression::Node* node ) const;

};

Q_DECLARE_OPERATORS_FOR_FLAGS( QgsSqlExpressionCompiler::Flags )
Expand Down
9 changes: 8 additions & 1 deletion src/providers/ogr/qgsogrexpressioncompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "qgsogrprovider.h"

QgsOgrExpressionCompiler::QgsOgrExpressionCompiler( QgsOgrFeatureSource* source )
: QgsSqlExpressionCompiler( source->mFields, QgsSqlExpressionCompiler::CaseInsensitiveStringMatch )
: QgsSqlExpressionCompiler( source->mFields, QgsSqlExpressionCompiler::CaseInsensitiveStringMatch | QgsSqlExpressionCompiler::NoNullInBooleanLogic )
, mSource( source )
{
}
Expand Down Expand Up @@ -95,5 +95,12 @@ QString QgsOgrExpressionCompiler::quotedIdentifier( const QString& identifier )
QString QgsOgrExpressionCompiler::quotedValue( const QVariant& value, bool& ok )
{
ok = true;

if ( value.type() == QVariant::Bool )
{
// No support for boolean literals, so fake them
return value.toBool() ? "(1=1)" : "(1=0)";
}

return QgsOgrProviderUtils::quotedValue( value );
}

0 comments on commit 81be559

Please sign in to comment.