Skip to content

Commit

Permalink
[memory] Correctly store converted field values when adding or
Browse files Browse the repository at this point in the history
changing attributes

If testing for value compatiblity via QgsField::convertCompatibility
only resulted in true because an automatic type conversion happened
then we need to store the auto converted value, not the original.

(cherry picked from commit d5eb6b0)
(cherry picked from commit 0a8f040)
  • Loading branch information
nyalldawson committed Mar 19, 2021
1 parent ada0bc7 commit f892b3c
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 3 deletions.
10 changes: 8 additions & 2 deletions src/core/providers/memory/qgsmemoryprovider.cpp
Expand Up @@ -430,7 +430,8 @@ bool QgsMemoryProvider::addFeatures( QgsFeatureList &flist, Flags flags )
QString errorMessage;
for ( int i = 0; i < mFields.count(); ++i )
{
QVariant attrValue = it->attribute( i );
const QVariant originalValue = it->attribute( i );
QVariant attrValue = originalValue;
if ( ! attrValue.isNull() && ! mFields.at( i ).convertCompatible( attrValue, &errorMessage ) )
{
// Push first conversion error only
Expand All @@ -443,6 +444,11 @@ bool QgsMemoryProvider::addFeatures( QgsFeatureList &flist, Flags flags )
conversionError = true;
continue;
}
else if ( attrValue.type() != originalValue.type() )
{
// convertCompatible has resulted in a data type conversion
it->setAttribute( i, attrValue );
}
}

// Skip the feature if there is at least one conversion error
Expand Down Expand Up @@ -631,7 +637,7 @@ bool QgsMemoryProvider::changeAttributeValues( const QgsChangedAttributesMap &at
break;
}
rollBackAttrs.insert( it2.key(), fit->attribute( it2.key() ) );
fit->setAttribute( it2.key(), it2.value() );
fit->setAttribute( it2.key(), attrValue );
}
rollBackMap.insert( it.key(), rollBackAttrs );
}
Expand Down
2 changes: 1 addition & 1 deletion tests/src/analysis/testqgsnetworkanalysis.cpp
Expand Up @@ -520,7 +520,7 @@ void TestQgsNetworkAnalysis::testRouteFail()

void TestQgsNetworkAnalysis::testRouteFail2()
{
std::unique_ptr< QgsVectorLayer > network = qgis::make_unique< QgsVectorLayer >( QStringLiteral( "LineString?crs=epsg:4326&field=cost:int" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
std::unique_ptr< QgsVectorLayer > network = qgis::make_unique< QgsVectorLayer >( QStringLiteral( "LineString?crs=epsg:4326&field=cost:double" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );

QStringList lines = QStringList() << QStringLiteral( "LineString (11.25044997999680874 48.42605439713970128, 11.25044693759680925 48.42603339773970106, 11.25044760759680962 48.42591690773969759, 11.25052289759680946 48.42589190773969676)" )
<< QStringLiteral( "LineString (11.25052289759680946 48.42589190773969676, 11.25050350759680917 48.42586202773969717, 11.25047190759680937 48.42581754773969749, 11.2504146475968092 48.42573849773970096, 11.25038716759680923 48.42569834773969717, 11.2502920175968093 48.42557470773969897, 11.25019984759680902 48.42560406773969817, 11.25020393759680992 48.42571203773970012, 11.2502482875968095 48.42577478773969801, 11.25021922759680848 48.42578442773969982)" )
Expand Down
21 changes: 21 additions & 0 deletions tests/src/python/test_provider_memory.py
Expand Up @@ -506,6 +506,27 @@ def testCreateMemoryLayer(self):
self.assertEqual(layer.fields()[i].length(), fields[i].length())
self.assertEqual(layer.fields()[i].precision(), fields[i].precision())

def testAddChangeFeatureConvertAttribute(self):
"""
Test add features with attribute values which require conversion
"""
layer = QgsVectorLayer(
'Point?crs=epsg:4326&index=yes&field=pk:integer&field=cnt:int8&field=dt:datetime', 'test', 'memory')
provider = layer.dataProvider()
f = QgsFeature()
# string value specified for datetime field -- must be converted when adding the feature
f.setAttributes([5, -200, '2021-02-10 00:00'])
self.assertTrue(provider.addFeatures([f]))

saved_feature = next(provider.getFeatures())
# saved feature must have a QDateTime value for field, not string
self.assertEqual(saved_feature.attributes(), [5, -200, QDateTime(2021, 2, 10, 0, 0)])

self.assertTrue(provider.changeAttributeValues({saved_feature.id(): {2: '2021-02-12 00:00'}}))
saved_feature = next(provider.getFeatures())
# saved feature must have a QDateTime value for field, not string
self.assertEqual(saved_feature.attributes(), [5, -200, QDateTime(2021, 2, 12, 0, 0)])

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',
Expand Down

0 comments on commit f892b3c

Please sign in to comment.