Skip to content
Permalink
Browse files

[OGR provider] Make changeGeometryValues() accept null geometry

Fixes #15081
  • Loading branch information
rouault committed Jun 20, 2016
1 parent 0ba1286 commit 4c56fa6e8ebcbcfc732d39e7bbe31d9f8376dee6
Showing with 48 additions and 24 deletions.
  1. +30 −24 src/providers/ogr/qgsogrprovider.cpp
  2. +18 −0 tests/src/python/test_provider_shapefile.py
@@ -1560,9 +1560,6 @@ bool QgsOgrProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
if ( !doInitialActionsForEdition() )
return false;

OGRFeatureH theOGRFeature = nullptr;
OGRGeometryH theNewGeometry = nullptr;

setRelevantFields( ogrLayer, true, attributeIndexes() );

for ( QgsGeometryMap::const_iterator it = geometry_map.constBegin(); it != geometry_map.constEnd(); ++it )
@@ -1573,48 +1570,57 @@ bool QgsOgrProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
continue;
}

theOGRFeature = OGR_L_GetFeature( ogrLayer, static_cast<long>( FID_TO_NUMBER( it.key() ) ) );
OGRFeatureH theOGRFeature = OGR_L_GetFeature( ogrLayer, static_cast<long>( FID_TO_NUMBER( it.key() ) ) );
if ( !theOGRFeature )
{
pushError( tr( "OGR error changing geometry: feature %1 not found" ).arg( it.key() ) );
continue;
}

//create an OGRGeometry
if ( OGR_G_CreateFromWkb( const_cast<unsigned char*>( it->asWkb() ),
OGR_L_GetSpatialRef( ogrLayer ),
&theNewGeometry,
it->wkbSize() ) != OGRERR_NONE )
OGRGeometryH theNewGeometry = nullptr;
// We might receive null geometries. It is ok, but don't go through the
// OGR_G_CreateFromWkb() route then
if ( it->wkbSize() != 0 )
{
pushError( tr( "OGR error creating geometry for feature %1: %2" ).arg( it.key() ).arg( CPLGetLastErrorMsg() ) );
OGR_G_DestroyGeometry( theNewGeometry );
theNewGeometry = nullptr;
continue;
}
//create an OGRGeometry
if ( OGR_G_CreateFromWkb( const_cast<unsigned char*>( it->asWkb() ),
OGR_L_GetSpatialRef( ogrLayer ),
&theNewGeometry,
it->wkbSize() ) != OGRERR_NONE )
{
pushError( tr( "OGR error creating geometry for feature %1: %2" ).arg( it.key() ).arg( CPLGetLastErrorMsg() ) );
OGR_G_DestroyGeometry( theNewGeometry );
theNewGeometry = nullptr;
OGR_F_Destroy( theOGRFeature );
continue;
}

if ( !theNewGeometry )
{
pushError( tr( "OGR error in feature %1: geometry is null" ).arg( it.key() ) );
continue;
}
if ( !theNewGeometry )
{
pushError( tr( "OGR error in feature %1: geometry is null" ).arg( it.key() ) );
OGR_F_Destroy( theOGRFeature );
continue;
}

theNewGeometry = ConvertGeometryIfNecessary( theNewGeometry );
theNewGeometry = ConvertGeometryIfNecessary( theNewGeometry );
}

//set the new geometry
if ( OGR_F_SetGeometryDirectly( theOGRFeature, theNewGeometry ) != OGRERR_NONE )
{
pushError( tr( "OGR error setting geometry of feature %1: %2" ).arg( it.key() ).arg( CPLGetLastErrorMsg() ) );
OGR_G_DestroyGeometry( theNewGeometry );
theNewGeometry = nullptr;
// Shouldn't happen normally. If it happens, ownership of the geometry
// may be not really well defined, so better not destroy it, but just
// the feature.
OGR_F_Destroy( theOGRFeature );
continue;
}


if ( OGR_L_SetFeature( ogrLayer, theOGRFeature ) != OGRERR_NONE )
{
pushError( tr( "OGR error setting feature %1: %2" ).arg( it.key() ).arg( CPLGetLastErrorMsg() ) );
OGR_G_DestroyGeometry( theNewGeometry );
theNewGeometry = nullptr;
OGR_F_Destroy( theOGRFeature );
continue;
}
mShapefileMayBeCorrupted = true;
@@ -340,5 +340,23 @@ def testRenameAttributes(self):
self.assertEqual(fet.fields()[2].name(), 'newname2')
self.assertEqual(fet.fields()[3].name(), 'another')

def testDeleteGeometry(self):
''' Test changeGeometryValues() with a null geometry '''

tmpdir = tempfile.mkdtemp()
self.dirs_to_cleanup.append(tmpdir)
srcpath = os.path.join(TEST_DATA_DIR, 'provider')
for file in glob.glob(os.path.join(srcpath, 'shapefile.*')):
shutil.copy(os.path.join(srcpath, file), tmpdir)
datasource = os.path.join(tmpdir, 'shapefile.shp')

vl = QgsVectorLayer(u'{}|layerid=0'.format(datasource), u'test', u'ogr')
self.assertTrue(vl.dataProvider().changeGeometryValues({0: QgsGeometry()}))
vl = None

vl = QgsVectorLayer(u'{}|layerid=0'.format(datasource), u'test', u'ogr')
fet = next(vl.getFeatures())
self.assertIsNone(fet.geometry())

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

0 comments on commit 4c56fa6

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