Skip to content

Commit

Permalink
[OGR provider] Support 64bit FID (fixes #16404)
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Nov 13, 2017
1 parent 7d8f3f7 commit 86247cf
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -1656,17 +1656,19 @@ bool QgsOgrProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_
{
QgsFeatureId fid = it.key();

#if !(defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(2,0,0))
if ( FID_TO_NUMBER( fid ) > std::numeric_limits<long>::max() )
{
pushError( tr( "OGR error on feature %1: id too large" ).arg( fid ) );
continue;
}
#endif

const QgsAttributeMap &attr = it.value();
if ( attr.isEmpty() )
continue;

OGRFeatureH of = OGR_L_GetFeature( ogrLayer, static_cast<long>( FID_TO_NUMBER( fid ) ) );
OGRFeatureH of = OGR_L_GetFeature( ogrLayer, FID_TO_NUMBER( fid ) );
if ( !of )
{
pushError( tr( "Feature %1 for attribute update not found." ).arg( fid ) );
Expand Down Expand Up @@ -1803,13 +1805,15 @@ bool QgsOgrProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )

for ( QgsGeometryMap::const_iterator it = geometry_map.constBegin(); it != geometry_map.constEnd(); ++it )
{
#if !(defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(2,0,0))
if ( FID_TO_NUMBER( it.key() ) > std::numeric_limits<long>::max() )
{
pushError( tr( "OGR error on feature %1: id too large" ).arg( it.key() ) );
continue;
}
#endif

OGRFeatureH theOGRFeature = OGR_L_GetFeature( ogrLayer, static_cast<long>( FID_TO_NUMBER( it.key() ) ) );
OGRFeatureH theOGRFeature = OGR_L_GetFeature( ogrLayer, FID_TO_NUMBER( it.key() ) );
if ( !theOGRFeature )
{
pushError( tr( "OGR error changing geometry: feature %1 not found" ).arg( it.key() ) );
Expand Down Expand Up @@ -1959,11 +1963,13 @@ bool QgsOgrProvider::deleteFeature( QgsFeatureId id )
if ( !doInitialActionsForEdition() )
return false;

#if !(defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(2,0,0))
if ( FID_TO_NUMBER( id ) > std::numeric_limits<long>::max() )
{
pushError( tr( "OGR error on feature %1: id too large" ).arg( id ) );
return false;
}
#endif

if ( OGR_L_DeleteFeature( ogrLayer, FID_TO_NUMBER( id ) ) != OGRERR_NONE )
{
Expand Down
33 changes: 33 additions & 0 deletions tests/src/python/test_provider_ogr_gpkg.py
Expand Up @@ -386,6 +386,39 @@ def testGeopackageTwoLayerEdition(self):
reference = QgsGeometry.fromWkt('Point (5 5)')
self.assertEqual(got_geom.asWkb(), reference.asWkb(), 'Expected {}, got {}'.format(reference.exportToWkt(), got_geom.exportToWkt()))

@unittest.expectedFailure(int(gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(2, 0, 0))
def testGeopackageLargeFID(self):

tmpfile = os.path.join(self.basetestpath, 'testGeopackageLargeFID.gpkg')
ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint)
lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString))
ds = None

vl = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr')
f = QgsFeature()
f.setAttributes([1234567890123, None])
self.assertTrue(vl.startEditing())
self.assertTrue(vl.dataProvider().addFeatures([f]))
self.assertTrue(vl.commitChanges())

got = [feat for feat in vl.getFeatures()][0]
self.assertEqual(got['fid'], 1234567890123)

self.assertTrue(vl.startEditing())
self.assertTrue(vl.changeGeometry(1234567890123, QgsGeometry.fromWkt('Point (3 50)')))
self.assertTrue(vl.changeAttributeValue(1234567890123, 1, 'foo'))
self.assertTrue(vl.commitChanges())

got = [feat for feat in vl.getFeatures()][0]
self.assertEqual(got['str_field'], 'foo')
got_geom = got.geometry()
self.assertIsNotNone(got_geom)

self.assertTrue(vl.startEditing())
self.assertTrue(vl.deleteFeature(1234567890123))
self.assertTrue(vl.commitChanges())


if __name__ == '__main__':
unittest.main()

0 comments on commit 86247cf

Please sign in to comment.