Skip to content

Commit bf86521

Browse files
committed
Fixes for refinement of rules.
- quoting of columns (#5536 and #5542) - quoting of string - do not quote of numbers (avoids type cast during evaluation) - use at least 4 floating point digits for doubles
1 parent 1125571 commit bf86521

File tree

4 files changed

+24
-4
lines changed

4 files changed

+24
-4
lines changed

python/core/qgsexpression.sip

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ public:
122122

123123
//! return quoted column reference (in double quotes)
124124
static QString quotedColumnRef( QString name );
125+
//! return quoted string (in single quotes)
126+
static QString quotedString( QString text );
125127

126128
//////
127129

src/core/qgsexpression.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ class CORE_EXPORT QgsExpression
209209

210210
//! return quoted column reference (in double quotes)
211211
static QString quotedColumnRef( QString name ) { return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) ); }
212+
//! return quoted string (in single quotes)
213+
static QString quotedString( QString text ) { return QString( "'%1'" ).arg( text.replace( "'", "''" ) ); }
212214

213215
//////
214216

src/core/symbology-ng/qgsrulebasedrendererv2.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,18 @@ void QgsRuleBasedRendererV2::refineRuleCategories( QgsRuleBasedRendererV2::Rule*
803803
{
804804
foreach( const QgsRendererCategoryV2& cat, r->categories() )
805805
{
806-
QString filter = QString( "%1 = '%2'" ).arg( r->classAttribute() ).arg( cat.value().toString() );
806+
QString attr = QgsExpression::quotedColumnRef( r->classAttribute() );
807+
QString value;
808+
// not quoting numbers saves a type cast
809+
if ( cat.value().type() == QVariant::Int )
810+
value = cat.value().toString();
811+
else if ( cat.value().type() == QVariant::Double )
812+
// we loose precision here - so we may miss some categories :-(
813+
// TODO: have a possibility to construct expressions directly as a parse tree to avoid loss of precision
814+
value = QString::number( cat.value().toDouble(), 'f', 4 );
815+
else
816+
value = QgsExpression::quotedString( cat.value().toString() );
817+
QString filter = QString( "%1 = %2" ).arg( attr ).arg( value );
807818
QString label = filter;
808819
initialRule->appendChild( new Rule( cat.symbol()->clone(), 0, 0, filter, label ) );
809820
}
@@ -813,7 +824,12 @@ void QgsRuleBasedRendererV2::refineRuleRanges( QgsRuleBasedRendererV2::Rule* ini
813824
{
814825
foreach( const QgsRendererRangeV2& rng, r->ranges() )
815826
{
816-
QString filter = QString( "%1 >= '%2' AND %1 <= '%3'" ).arg( r->classAttribute() ).arg( rng.lowerValue() ).arg( rng.upperValue() );
827+
// due to the loss of precision in double->string conversion we may miss out values at the limit of the range
828+
// TODO: have a possibility to construct expressions directly as a parse tree to avoid loss of precision
829+
QString attr = QgsExpression::quotedColumnRef( r->classAttribute() );
830+
QString filter = QString( "%1 >= %2 AND %1 <= %3" ).arg( attr )
831+
.arg( QString::number( rng.lowerValue(), 'f', 4 ) )
832+
.arg( QString::number( rng.upperValue(), 'f', 4 ) );
817833
QString label = filter;
818834
initialRule->appendChild( new Rule( rng.symbol()->clone(), 0, 0, filter, label ) );
819835
}

src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,8 @@ void QgsGraduatedSymbolRendererV2Widget::changeRange( int rangeIdx )
325325
QgsLUDialog dialog( this );
326326

327327
const QgsRendererRangeV2& range = mRenderer->ranges()[rangeIdx];
328-
dialog.setLowerValue( QString( "%1" ).arg( range.lowerValue() ) );
329-
dialog.setUpperValue( QString( "%1" ).arg( range.upperValue() ) );
328+
dialog.setLowerValue( QString::number( range.lowerValue(), 'f', 4 ) );
329+
dialog.setUpperValue( QString::number( range.upperValue(), 'f', 4 ) );
330330

331331
if ( dialog.exec() == QDialog::Accepted )
332332
{

0 commit comments

Comments
 (0)