Skip to content
Permalink
Browse files

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

Fixes #21316
  • Loading branch information
nyalldawson committed Feb 20, 2019
1 parent ff9a65c commit f3cb3488ec5b1edca298833c6a982fe77b056e59
@@ -108,7 +108,7 @@ QgsMemoryProvider::QgsMemoryProvider( const QString &uri, const ProviderOptions
QRegExp reFieldDef( "\\:"
"(int|integer|long|int8|real|double|string|date|time|datetime|binary|bool|boolean)" // type
"(?:\\((\\-?\\d+)" // length
"(?:\\,(\\d+))?" // precision
"(?:\\,(\\-?\\d+))?" // precision
"\\))?(\\[\\])?" // array
"$", Qt::CaseInsensitive );
QStringList fields = url.allQueryItemValues( QStringLiteral( "field" ) );
@@ -69,15 +69,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(
@@ -419,6 +434,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()
@@ -429,6 +446,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 f3cb348

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