Skip to content

Commit 4c56fa6

Browse files
committed
[OGR provider] Make changeGeometryValues() accept null geometry
Fixes #15081
1 parent 0ba1286 commit 4c56fa6

File tree

2 files changed

+48
-24
lines changed

2 files changed

+48
-24
lines changed

src/providers/ogr/qgsogrprovider.cpp

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,9 +1560,6 @@ bool QgsOgrProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
15601560
if ( !doInitialActionsForEdition() )
15611561
return false;
15621562

1563-
OGRFeatureH theOGRFeature = nullptr;
1564-
OGRGeometryH theNewGeometry = nullptr;
1565-
15661563
setRelevantFields( ogrLayer, true, attributeIndexes() );
15671564

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

1576-
theOGRFeature = OGR_L_GetFeature( ogrLayer, static_cast<long>( FID_TO_NUMBER( it.key() ) ) );
1573+
OGRFeatureH theOGRFeature = OGR_L_GetFeature( ogrLayer, static_cast<long>( FID_TO_NUMBER( it.key() ) ) );
15771574
if ( !theOGRFeature )
15781575
{
15791576
pushError( tr( "OGR error changing geometry: feature %1 not found" ).arg( it.key() ) );
15801577
continue;
15811578
}
15821579

1583-
//create an OGRGeometry
1584-
if ( OGR_G_CreateFromWkb( const_cast<unsigned char*>( it->asWkb() ),
1585-
OGR_L_GetSpatialRef( ogrLayer ),
1586-
&theNewGeometry,
1587-
it->wkbSize() ) != OGRERR_NONE )
1580+
OGRGeometryH theNewGeometry = nullptr;
1581+
// We might receive null geometries. It is ok, but don't go through the
1582+
// OGR_G_CreateFromWkb() route then
1583+
if ( it->wkbSize() != 0 )
15881584
{
1589-
pushError( tr( "OGR error creating geometry for feature %1: %2" ).arg( it.key() ).arg( CPLGetLastErrorMsg() ) );
1590-
OGR_G_DestroyGeometry( theNewGeometry );
1591-
theNewGeometry = nullptr;
1592-
continue;
1593-
}
1585+
//create an OGRGeometry
1586+
if ( OGR_G_CreateFromWkb( const_cast<unsigned char*>( it->asWkb() ),
1587+
OGR_L_GetSpatialRef( ogrLayer ),
1588+
&theNewGeometry,
1589+
it->wkbSize() ) != OGRERR_NONE )
1590+
{
1591+
pushError( tr( "OGR error creating geometry for feature %1: %2" ).arg( it.key() ).arg( CPLGetLastErrorMsg() ) );
1592+
OGR_G_DestroyGeometry( theNewGeometry );
1593+
theNewGeometry = nullptr;
1594+
OGR_F_Destroy( theOGRFeature );
1595+
continue;
1596+
}
15941597

1595-
if ( !theNewGeometry )
1596-
{
1597-
pushError( tr( "OGR error in feature %1: geometry is null" ).arg( it.key() ) );
1598-
continue;
1599-
}
1598+
if ( !theNewGeometry )
1599+
{
1600+
pushError( tr( "OGR error in feature %1: geometry is null" ).arg( it.key() ) );
1601+
OGR_F_Destroy( theOGRFeature );
1602+
continue;
1603+
}
16001604

1601-
theNewGeometry = ConvertGeometryIfNecessary( theNewGeometry );
1605+
theNewGeometry = ConvertGeometryIfNecessary( theNewGeometry );
1606+
}
16021607

16031608
//set the new geometry
16041609
if ( OGR_F_SetGeometryDirectly( theOGRFeature, theNewGeometry ) != OGRERR_NONE )
16051610
{
16061611
pushError( tr( "OGR error setting geometry of feature %1: %2" ).arg( it.key() ).arg( CPLGetLastErrorMsg() ) );
1607-
OGR_G_DestroyGeometry( theNewGeometry );
1608-
theNewGeometry = nullptr;
1612+
// Shouldn't happen normally. If it happens, ownership of the geometry
1613+
// may be not really well defined, so better not destroy it, but just
1614+
// the feature.
1615+
OGR_F_Destroy( theOGRFeature );
16091616
continue;
16101617
}
16111618

16121619

16131620
if ( OGR_L_SetFeature( ogrLayer, theOGRFeature ) != OGRERR_NONE )
16141621
{
16151622
pushError( tr( "OGR error setting feature %1: %2" ).arg( it.key() ).arg( CPLGetLastErrorMsg() ) );
1616-
OGR_G_DestroyGeometry( theNewGeometry );
1617-
theNewGeometry = nullptr;
1623+
OGR_F_Destroy( theOGRFeature );
16181624
continue;
16191625
}
16201626
mShapefileMayBeCorrupted = true;

tests/src/python/test_provider_shapefile.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,5 +340,23 @@ def testRenameAttributes(self):
340340
self.assertEqual(fet.fields()[2].name(), 'newname2')
341341
self.assertEqual(fet.fields()[3].name(), 'another')
342342

343+
def testDeleteGeometry(self):
344+
''' Test changeGeometryValues() with a null geometry '''
345+
346+
tmpdir = tempfile.mkdtemp()
347+
self.dirs_to_cleanup.append(tmpdir)
348+
srcpath = os.path.join(TEST_DATA_DIR, 'provider')
349+
for file in glob.glob(os.path.join(srcpath, 'shapefile.*')):
350+
shutil.copy(os.path.join(srcpath, file), tmpdir)
351+
datasource = os.path.join(tmpdir, 'shapefile.shp')
352+
353+
vl = QgsVectorLayer(u'{}|layerid=0'.format(datasource), u'test', u'ogr')
354+
self.assertTrue(vl.dataProvider().changeGeometryValues({0: QgsGeometry()}))
355+
vl = None
356+
357+
vl = QgsVectorLayer(u'{}|layerid=0'.format(datasource), u'test', u'ogr')
358+
fet = next(vl.getFeatures())
359+
self.assertIsNone(fet.geometry())
360+
343361
if __name__ == '__main__':
344362
unittest.main()

0 commit comments

Comments
 (0)