Skip to content

Commit

Permalink
Rework handling of 'not null' filter expression in HANA
Browse files Browse the repository at this point in the history
  • Loading branch information
Maksim Rylov authored and mrylov committed Dec 7, 2020
1 parent a9fb9df commit 00b7554
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 18 deletions.
30 changes: 30 additions & 0 deletions src/providers/hana/qgshanaexpressioncompiler.cpp
Expand Up @@ -132,6 +132,28 @@ QgsSqlExpressionCompiler::Result QgsHanaExpressionCompiler::compileNode(
}
}
break;
case QgsExpressionNode::ntUnaryOperator:
{
const QgsExpressionNodeUnaryOperator *unaryOp = static_cast<const QgsExpressionNodeUnaryOperator *>( node );
switch ( unaryOp->op() )
{
case QgsExpressionNodeUnaryOperator::uoNot:
{
Result resRight = compileNode( unaryOp->operand(), result );
if ( "NULL" == result.toUpper() )
{
result.clear();
return Fail;
}
result = "NOT " + result;

return resRight;
}
case QgsExpressionNodeUnaryOperator::uoMinus:
break;
}
}
break;
case QgsExpressionNode::ntBinaryOperator:
{
const QgsExpressionNodeBinaryOperator *binOp( static_cast<const QgsExpressionNodeBinaryOperator *>( node ) );
Expand All @@ -144,6 +166,14 @@ QgsSqlExpressionCompiler::Result QgsHanaExpressionCompiler::compileNode(
if ( resLeft == Fail || resRight == Fail )
return Fail;

// NULL can not appear on the left, only as part of IS NULL or IS NOT NULL
if ( "NULL" == opLeft.toUpper() )
return Fail;
// NULL can only be on the right for IS and IS NOT
if ( "NULL" == opRight.toUpper() &&
( binOp->op() != QgsExpressionNodeBinaryOperator::boIs && binOp->op() != QgsExpressionNodeBinaryOperator::boIsNot ) )
return Fail;

switch ( binOp->op() )
{
case QgsExpressionNodeBinaryOperator::boMod:
Expand Down
43 changes: 25 additions & 18 deletions src/providers/hana/qgshanafeatureiterator.cpp
Expand Up @@ -339,9 +339,10 @@ QString QgsHanaFeatureIterator::buildSqlQuery( const QgsFeatureRequest &request
QString sqlFilter;
// Set spatial filter
if ( !( filterRect.isNull() || filterRect.isEmpty() ) && mSource->isSpatial() && mHasGeometryColumn )
{
sqlFilter = getBBOXFilter( filterRect, QgsHanaUtils::toHANAVersion( mConnRef->getDatabaseVersion() ) );
}

if ( !mSource->mQueryWhereClause.isEmpty() )
sqlFilter = andWhereClauses( sqlFilter, mSource->mQueryWhereClause );

// Set fid filter
if ( !mFidColumn.isEmpty() )
Expand Down Expand Up @@ -375,22 +376,31 @@ QString QgsHanaFeatureIterator::buildSqlQuery( const QgsFeatureRequest &request
if ( QgsSettings().value( QStringLiteral( "qgis/compileExpressions" ), true ).toBool() )
{
QgsHanaExpressionCompiler compiler = QgsHanaExpressionCompiler( mSource );

QgsSqlExpressionCompiler::Result result = compiler.compile( request.filterExpression() );

if ( result == QgsSqlExpressionCompiler::Complete || result == QgsSqlExpressionCompiler::Partial )
switch(result)
{
case QgsSqlExpressionCompiler::Result::Complete:
case QgsSqlExpressionCompiler::Result::Partial:
{
QString filterExpr = compiler.result();
if ( !filterExpr.isEmpty() )
{
sqlFilter = andWhereClauses( sqlFilter, filterExpr );
//if only partial success when compiling expression, we need to double-check results
//using QGIS' expressions
mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Complete );
mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled );
}
QString filterExpr = compiler.result();
if ( !filterExpr.isEmpty() )
{
sqlFilter = andWhereClauses( sqlFilter, filterExpr );
//if only partial success when compiling expression, we need to double-check results
//using QGIS' expressions
mExpressionCompiled = ( result == QgsSqlExpressionCompiler::Result::Complete );
mCompileStatus = ( mExpressionCompiled ? Compiled : PartiallyCompiled );
}
}
break;
case QgsSqlExpressionCompiler::Result::Fail:
QgsDebugMsg(QStringLiteral("Unable to compile filter expression: '%1'")
.arg(request.filterExpression()->expression()).toStdString().c_str());
break;
case QgsSqlExpressionCompiler::Result::None:
break;
}
if ( result != QgsSqlExpressionCompiler::Complete )
if ( result != QgsSqlExpressionCompiler::Result::Complete )
{
//can't apply limit at provider side as we need to check all results using QGIS expressions
limitAtProvider = false;
Expand All @@ -402,9 +412,6 @@ QString QgsHanaFeatureIterator::buildSqlQuery( const QgsFeatureRequest &request
}
}

if ( !mSource->mQueryWhereClause.isEmpty() )
sqlFilter = andWhereClauses( sqlFilter, mSource->mQueryWhereClause );

if ( !sqlFilter.isEmpty() )
sql += QStringLiteral( " WHERE " ) + sqlFilter;

Expand Down
1 change: 1 addition & 0 deletions tests/src/python/test_provider_hana.py
Expand Up @@ -128,6 +128,7 @@ def uncompiledFilters(self):
'NULL or false',
'NULL or true',
'NULL or NULL',
'not null',
'\'x\' || "name" IS NOT NULL',
'\'x\' || "name" IS NULL',
'radians(cnt) < 2',
Expand Down

0 comments on commit 00b7554

Please sign in to comment.