Skip to content
Permalink
Browse files

When creating a expression filter string for a rule based renderer,

try to create a simple "field IN (...)" expression wherever possible

This avoids some issues with complex rule based renderers that have
many similar classes, where the generated expression was previously
an extremely long and complex "(field = ...) OR (field = ...) OR ..."
type expression (which some providers have issues with)

Fixes missing features in some circumstances in rule based renderers

Sponsored by SLYR
  • Loading branch information
nyalldawson committed Jan 12, 2021
1 parent 44c2a26 commit 9e9d2478dd3e1b960c62a2bddb3d1fbae3056572
Showing with 30 additions and 22 deletions.
  1. +30 −22 src/core/symbology/qgsrulebasedrenderer.cpp
@@ -453,31 +453,39 @@ bool QgsRuleBasedRenderer::Rule::startRender( QgsRenderContext &context, const Q
{
sf = QStringLiteral( "TRUE" );
}
// If we have more than 50 rules (to stay on the safe side) make a binary tree or SQLITE will fail,
// see: https://github.com/qgis/QGIS/issues/27269
else if ( subfilters.count() > 50 )
else
{
std::function<QString( const QStringList & )>bt = [ &bt ]( const QStringList & subf )
// test for a common case -- all subfilters can be combined into a single "field in (...)" expression
if ( QgsExpression::attemptReduceToInClause( subfilters, sf ) )
{
if ( subf.count( ) == 1 )
{
return subf.at( 0 );
}
else if ( subf.count( ) == 2 )
{
return subf.join( QLatin1String( ") OR (" ) ).prepend( '(' ).append( ')' );
}
else
// success! we can use a simple "field IN (...)" list!
}
// If we have more than 50 rules (to stay on the safe side) make a binary tree or SQLITE will fail,
// see: https://github.com/qgis/QGIS/issues/27269
else if ( subfilters.count() > 50 )
{
std::function<QString( const QStringList & )>bt = [ &bt ]( const QStringList & subf )
{
int midpos = static_cast<int>( subf.length() / 2 );
return QStringLiteral( "(%1) OR (%2)" ).arg( bt( subf.mid( 0, midpos ) ) ).arg( bt( subf.mid( midpos ) ) );
}
};
sf = bt( subfilters );
}
else
{
sf = subfilters.join( QLatin1String( ") OR (" ) ).prepend( '(' ).append( ')' );
if ( subf.count( ) == 1 )
{
return subf.at( 0 );
}
else if ( subf.count( ) == 2 )
{
return subf.join( QLatin1String( ") OR (" ) ).prepend( '(' ).append( ')' );
}
else
{
int midpos = static_cast<int>( subf.length() / 2 );
return QStringLiteral( "(%1) OR (%2)" ).arg( bt( subf.mid( 0, midpos ) ), bt( subf.mid( midpos ) ) );
}
};
sf = bt( subfilters );
}
else
{
sf = subfilters.join( QLatin1String( ") OR (" ) ).prepend( '(' ).append( ')' );
}
}
}

0 comments on commit 9e9d247

Please sign in to comment.
You can’t perform that action at this time.