Skip to content

Commit

Permalink
[OGR provider] Make changeGeometryValues() accept null geometry
Browse files Browse the repository at this point in the history
Fixes #15081
  • Loading branch information
rouault committed Jun 20, 2016
1 parent 7b0bec7 commit 72d75ff
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 22 deletions.
50 changes: 28 additions & 22 deletions src/providers/ogr/qgsogrprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1323,9 +1323,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 )
Expand All @@ -1336,46 +1333,55 @@ 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;
}
}

//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;
Expand Down
18 changes: 18 additions & 0 deletions tests/src/python/test_provider_shapefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,5 +244,23 @@ def testreloadData(self):
# And now check that fields are up-to-date
self.assertEquals(len(vl1.fields()), len(vl2.fields()))

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 72d75ff

Please sign in to comment.