Skip to content

Commit

Permalink
Fix storing string representations of doubles in an int field
Browse files Browse the repository at this point in the history
results in NULL rather than converting value to int
  • Loading branch information
nyalldawson committed Oct 20, 2015
1 parent cac6201 commit 1c76b93
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 1 deletion.
25 changes: 25 additions & 0 deletions src/core/qgsfield.cpp
Expand Up @@ -16,6 +16,7 @@

#include "qgsfield.h"
#include "qgsfield_p.h"
#include "qgis.h"

#include <QSettings>
#include <QDataStream>
Expand Down Expand Up @@ -155,6 +156,30 @@ bool QgsField::convertCompatible( QVariant& v ) const
return false;
}

//String representations of doubles in QVariant will return false to convert( QVariant::Int )
//work around this by first converting to double, and then checking whether the double is convertible to int
if ( d->type == QVariant::Int && v.canConvert( QVariant::Double ) )
{
bool ok = false;
double dbl = v.toDouble( &ok );
if ( !ok )
{
//couldn't convert to number
v = QVariant( d->type );
return false;
}

double round = qgsRound( dbl );
if ( round > INT_MAX || round < -INT_MAX )
{
//double too large to fit in int
v = QVariant( d->type );
return false;
}
v = QVariant( qRound( dbl ) );
return true;
}

if ( !v.convert( d->type ) )
{
v = QVariant( d->type );
Expand Down
42 changes: 41 additions & 1 deletion tests/src/core/testqgsfield.cpp
Expand Up @@ -256,12 +256,52 @@ void TestQgsField::convertCompatible()

//test special rules

//conversion of longlong to int
//conversion of double to int
QgsField intField( "int", QVariant::Int, "int" );
//small double, should be rounded
QVariant smallDouble( 45.7 );
QVERIFY( intField.convertCompatible( smallDouble ) );
QCOMPARE( smallDouble.type(), QVariant::Int );
QCOMPARE( smallDouble, QVariant( 46 ) );
QVariant negativeSmallDouble( -9345.754534525235235 );
QVERIFY( intField.convertCompatible( negativeSmallDouble ) );
QCOMPARE( negativeSmallDouble.type(), QVariant::Int );
QCOMPARE( negativeSmallDouble, QVariant( -9346 ) );
//large double, cannot be converted
QVariant largeDouble( 9999999999.99 );
QVERIFY( !intField.convertCompatible( largeDouble ) );
QCOMPARE( largeDouble.type(), QVariant::Int );
QVERIFY( largeDouble.isNull( ) );

//conversion of string double value to int
QVariant notNumberString( "notanumber" );
QVERIFY( !intField.convertCompatible( notNumberString ) );
QCOMPARE( notNumberString.type(), QVariant::Int );
QVERIFY( notNumberString.isNull( ) );
//small double, should be rounded
QVariant smallDoubleString( "45.7" );
QVERIFY( intField.convertCompatible( smallDoubleString ) );
QCOMPARE( smallDoubleString.type(), QVariant::Int );
QCOMPARE( smallDoubleString, QVariant( 46 ) );
QVariant negativeSmallDoubleString( "-9345.754534525235235" );
QVERIFY( intField.convertCompatible( negativeSmallDoubleString ) );
QCOMPARE( negativeSmallDoubleString.type(), QVariant::Int );
QCOMPARE( negativeSmallDoubleString, QVariant( -9346 ) );
//large double, cannot be converted
QVariant largeDoubleString( "9999999999.99" );
QVERIFY( !intField.convertCompatible( largeDoubleString ) );
QCOMPARE( largeDoubleString.type(), QVariant::Int );
QVERIFY( largeDoubleString.isNull( ) );

//conversion of longlong to int
QVariant longlong( 99999999999999999LL );
QVERIFY( !intField.convertCompatible( longlong ) );
QCOMPARE( longlong.type(), QVariant::Int );
QVERIFY( longlong.isNull( ) );
QVariant smallLonglong( 99LL );
QVERIFY( intField.convertCompatible( smallLonglong ) );
QCOMPARE( smallLonglong.type(), QVariant::Int );
QCOMPARE( smallLonglong, QVariant( 99 ) );
//conversion of longlong to longlong field
QgsField longlongField( "long", QVariant::LongLong, "longlong" );
longlong = QVariant( 99999999999999999LL );
Expand Down

0 comments on commit 1c76b93

Please sign in to comment.