Skip to content
Permalink
Browse files

Fix storing string representations of doubles in an int field

results in NULL rather than converting value to int
  • Loading branch information
nyalldawson committed Oct 20, 2015
1 parent cac6201 commit 1c76b93d89e9edf3a3abb153402c541e66756add
Showing with 66 additions and 1 deletion.
  1. +25 −0 src/core/qgsfield.cpp
  2. +41 −1 tests/src/core/testqgsfield.cpp
@@ -16,6 +16,7 @@

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

#include <QSettings>
#include <QDataStream>
@@ -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 );
@@ -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 );

0 comments on commit 1c76b93

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