Skip to content

Commit e098b9a

Browse files
committed
Fix loss of precision when converting fields to uri in memory provider
Fixes #21316 (cherry picked from commit f3cb348)
1 parent b30f51a commit e098b9a

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

src/core/providers/memory/qgsmemoryprovider.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ QgsMemoryProvider::QgsMemoryProvider( const QString &uri, const ProviderOptions
101101
QRegExp reFieldDef( "\\:"
102102
"(int|integer|long|int8|real|double|string|date|time|datetime)" // type
103103
"(?:\\((\\-?\\d+)" // length
104-
"(?:\\,(\\d+))?" // precision
104+
"(?:\\,(\\-?\\d+))?" // precision
105105
"\\))?(\\[\\])?" // array
106106
"$", Qt::CaseInsensitive );
107107
QStringList fields = url.allQueryItemValues( QStringLiteral( "field" ) );

src/core/providers/memory/qgsmemoryproviderutils.cpp

+1-9
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,7 @@ QgsVectorLayer *QgsMemoryProviderUtils::createMemoryLayer( const QString &name,
6363
}
6464
for ( const auto &field : fields )
6565
{
66-
QString lengthPrecision;
67-
if ( field.length() > 0 && field.precision() > 0 )
68-
{
69-
lengthPrecision = QStringLiteral( "(%1,%2)" ).arg( field.length() ).arg( field.precision() );
70-
}
71-
else if ( field.length() > 0 )
72-
{
73-
lengthPrecision = QStringLiteral( "(%1)" ).arg( field.length() );
74-
}
66+
const QString lengthPrecision = QStringLiteral( "(%1,%2)" ).arg( field.length() ).arg( field.precision() );
7567
parts << QStringLiteral( "field=%1:%2%3" ).arg( QString( QUrl::toPercentEncoding( field.name() ) ), memoryLayerFieldType( field.type() ), lengthPrecision );
7668
}
7769

tests/src/python/test_provider_memory.py

+33
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,21 @@ def testLengthPrecisionFromUri(self):
275275
self.assertEqual(myMemoryLayer.fields().field('size').length(), 12)
276276
self.assertEqual(myMemoryLayer.fields().field('size').precision(), 9)
277277

278+
myMemoryLayer = QgsVectorLayer(
279+
('Point?crs=epsg:4326&field=size:double(-1,-1)&index=yes'),
280+
'test',
281+
'memory')
282+
283+
self.assertEqual(myMemoryLayer.fields().field('size').length(), -1)
284+
self.assertEqual(myMemoryLayer.fields().field('size').precision(), -1)
285+
286+
myMemoryLayer = QgsVectorLayer(
287+
('Point?crs=epsg:4326&field=size:string(-1)&index=yes'),
288+
'test',
289+
'memory')
290+
291+
self.assertEqual(myMemoryLayer.fields().field('size').length(), -1)
292+
278293
def testFromUriWithEncodedField(self):
279294
"""Test we can construct the mem provider from a uri when a field name is encoded"""
280295
layer = QgsVectorLayer(
@@ -417,6 +432,8 @@ def testCreateMemoryLayer(self):
417432
for i in range(len(fields)):
418433
self.assertEqual(layer.fields()[i].name(), fields[i].name())
419434
self.assertEqual(layer.fields()[i].type(), fields[i].type())
435+
self.assertEqual(layer.fields()[i].length(), fields[i].length())
436+
self.assertEqual(layer.fields()[i].precision(), fields[i].precision(), fields[i].name())
420437

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

447+
# field precision
448+
fields = QgsFields()
449+
fields.append(QgsField("string", QVariant.String, len=10))
450+
fields.append(QgsField("long", QVariant.LongLong, len=6))
451+
fields.append(QgsField("double", QVariant.Double, len=10, prec=7))
452+
fields.append(QgsField("double2", QVariant.Double, len=-1, prec=-1))
453+
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
454+
self.assertTrue(layer.isValid())
455+
self.assertFalse(layer.fields().isEmpty())
456+
self.assertEqual(len(layer.fields()), len(fields))
457+
for i in range(len(fields)):
458+
self.assertEqual(layer.fields()[i].name(), fields[i].name())
459+
self.assertEqual(layer.fields()[i].type(), fields[i].type())
460+
self.assertEqual(layer.fields()[i].length(), fields[i].length())
461+
self.assertEqual(layer.fields()[i].precision(), fields[i].precision())
462+
430463
def testThreadSafetyWithIndex(self):
431464
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',
432465
'test', 'memory')

0 commit comments

Comments
 (0)