Skip to content

Commit f3cb348

Browse files
committed
Fix loss of precision when converting fields to uri in memory provider
Fixes #21316
1 parent ff9a65c commit f3cb348

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

src/core/providers/memory/qgsmemoryprovider.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ QgsMemoryProvider::QgsMemoryProvider( const QString &uri, const ProviderOptions
108108
QRegExp reFieldDef( "\\:"
109109
"(int|integer|long|int8|real|double|string|date|time|datetime|binary|bool|boolean)" // type
110110
"(?:\\((\\-?\\d+)" // length
111-
"(?:\\,(\\d+))?" // precision
111+
"(?:\\,(\\-?\\d+))?" // precision
112112
"\\))?(\\[\\])?" // array
113113
"$", Qt::CaseInsensitive );
114114
QStringList fields = url.allQueryItemValues( QStringLiteral( "field" ) );

src/core/providers/memory/qgsmemoryproviderutils.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,7 @@ QgsVectorLayer *QgsMemoryProviderUtils::createMemoryLayer( const QString &name,
6969
}
7070
for ( const auto &field : fields )
7171
{
72-
QString lengthPrecision;
73-
if ( field.length() > 0 && field.precision() > 0 )
74-
{
75-
lengthPrecision = QStringLiteral( "(%1,%2)" ).arg( field.length() ).arg( field.precision() );
76-
}
77-
else if ( field.length() > 0 )
78-
{
79-
lengthPrecision = QStringLiteral( "(%1)" ).arg( field.length() );
80-
}
72+
const QString lengthPrecision = QStringLiteral( "(%1,%2)" ).arg( field.length() ).arg( field.precision() );
8173
parts << QStringLiteral( "field=%1:%2%3" ).arg( QString( QUrl::toPercentEncoding( field.name() ) ), memoryLayerFieldType( field.type() ), lengthPrecision );
8274
}
8375

tests/src/python/test_provider_memory.py

Lines changed: 33 additions & 0 deletions
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(
@@ -419,6 +434,8 @@ def testCreateMemoryLayer(self):
419434
for i in range(len(fields)):
420435
self.assertEqual(layer.fields()[i].name(), fields[i].name())
421436
self.assertEqual(layer.fields()[i].type(), fields[i].type())
437+
self.assertEqual(layer.fields()[i].length(), fields[i].length())
438+
self.assertEqual(layer.fields()[i].precision(), fields[i].precision(), fields[i].name())
422439

423440
# unsupported field type
424441
fields = QgsFields()
@@ -429,6 +446,22 @@ def testCreateMemoryLayer(self):
429446
self.assertEqual(layer.fields()[0].name(), 'rect')
430447
self.assertEqual(layer.fields()[0].type(), QVariant.String) # should be mapped to string
431448

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

0 commit comments

Comments
 (0)