Skip to content
Permalink
Browse files

Fix loss of precision when converting fields to uri in memory provider

Fixes #21316

(cherry picked from commit f3cb348)
  • Loading branch information
nyalldawson committed Feb 20, 2019
1 parent b30f51a commit e098b9a37d3ddd9681a9b5d7eb2fd2c92ffff852
@@ -101,7 +101,7 @@ QgsMemoryProvider::QgsMemoryProvider( const QString &uri, const ProviderOptions
QRegExp reFieldDef( "\\:"
"(int|integer|long|int8|real|double|string|date|time|datetime)" // type
"(?:\\((\\-?\\d+)" // length
"(?:\\,(\\d+))?" // precision
"(?:\\,(\\-?\\d+))?" // precision
"\\))?(\\[\\])?" // array
"$", Qt::CaseInsensitive );
QStringList fields = url.allQueryItemValues( QStringLiteral( "field" ) );
@@ -63,15 +63,7 @@ QgsVectorLayer *QgsMemoryProviderUtils::createMemoryLayer( const QString &name,
}
for ( const auto &field : fields )
{
QString lengthPrecision;
if ( field.length() > 0 && field.precision() > 0 )
{
lengthPrecision = QStringLiteral( "(%1,%2)" ).arg( field.length() ).arg( field.precision() );
}
else if ( field.length() > 0 )
{
lengthPrecision = QStringLiteral( "(%1)" ).arg( field.length() );
}
const QString lengthPrecision = QStringLiteral( "(%1,%2)" ).arg( field.length() ).arg( field.precision() );
parts << QStringLiteral( "field=%1:%2%3" ).arg( QString( QUrl::toPercentEncoding( field.name() ) ), memoryLayerFieldType( field.type() ), lengthPrecision );
}

@@ -275,6 +275,21 @@ def testLengthPrecisionFromUri(self):
self.assertEqual(myMemoryLayer.fields().field('size').length(), 12)
self.assertEqual(myMemoryLayer.fields().field('size').precision(), 9)

myMemoryLayer = QgsVectorLayer(
('Point?crs=epsg:4326&field=size:double(-1,-1)&index=yes'),
'test',
'memory')

self.assertEqual(myMemoryLayer.fields().field('size').length(), -1)
self.assertEqual(myMemoryLayer.fields().field('size').precision(), -1)

myMemoryLayer = QgsVectorLayer(
('Point?crs=epsg:4326&field=size:string(-1)&index=yes'),
'test',
'memory')

self.assertEqual(myMemoryLayer.fields().field('size').length(), -1)

def testFromUriWithEncodedField(self):
"""Test we can construct the mem provider from a uri when a field name is encoded"""
layer = QgsVectorLayer(
@@ -417,6 +432,8 @@ def testCreateMemoryLayer(self):
for i in range(len(fields)):
self.assertEqual(layer.fields()[i].name(), fields[i].name())
self.assertEqual(layer.fields()[i].type(), fields[i].type())
self.assertEqual(layer.fields()[i].length(), fields[i].length())
self.assertEqual(layer.fields()[i].precision(), fields[i].precision(), fields[i].name())

# unsupported field type
fields = QgsFields()
@@ -427,6 +444,22 @@ def testCreateMemoryLayer(self):
self.assertEqual(layer.fields()[0].name(), 'rect')
self.assertEqual(layer.fields()[0].type(), QVariant.String) # should be mapped to string

# field precision
fields = QgsFields()
fields.append(QgsField("string", QVariant.String, len=10))
fields.append(QgsField("long", QVariant.LongLong, len=6))
fields.append(QgsField("double", QVariant.Double, len=10, prec=7))
fields.append(QgsField("double2", QVariant.Double, len=-1, prec=-1))
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
self.assertTrue(layer.isValid())
self.assertFalse(layer.fields().isEmpty())
self.assertEqual(len(layer.fields()), len(fields))
for i in range(len(fields)):
self.assertEqual(layer.fields()[i].name(), fields[i].name())
self.assertEqual(layer.fields()[i].type(), fields[i].type())
self.assertEqual(layer.fields()[i].length(), fields[i].length())
self.assertEqual(layer.fields()[i].precision(), fields[i].precision())

def testThreadSafetyWithIndex(self):
layer = QgsVectorLayer('Point?crs=epsg:4326&index=yes&field=pk:integer&field=cnt:int8&field=name:string(0)&field=name2:string(0)&field=num_char:string&key=pk',
'test', 'memory')

0 comments on commit e098b9a

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