Skip to content

Commit 872d86e

Browse files
committedOct 7, 2016
[OGR provider] Force REPACK at the first edit action.
In the case where we deal with a shapefile, it is possible that it has pre-existing holes in the DBF (see #15407), so if using a GDAL version recent enough (>=2.1.2) to have reliable packing, do a packing at the first edit action. Fixes #15407 Conflicts: src/providers/ogr/qgsogrprovider.cpp
1 parent 35ddf1f commit 872d86e

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed
 

‎src/providers/ogr/qgsogrprovider.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3109,6 +3109,18 @@ void QgsOgrProvider::open( OpenMode mode )
31093109
ogrLayer = ogrOrigLayer = nullptr;
31103110
mValid = false;
31113111

3112+
#if defined(GDAL_COMPUTE_VERSION)
3113+
// In the case where we deal with a shapefile, it is possible that it has
3114+
// pre-existing holes in the DBF (see #15407), so if using a GDAL version
3115+
// recent enough to have reliable packing, do a packing at the first edit
3116+
// action.
3117+
if ( ogrDriverName == "ESRI Shapefile" &&
3118+
atoi( GDALVersionInfo( "VERSION_NUM" ) ) >= GDAL_COMPUTE_VERSION( 2, 1, 2 ) )
3119+
{
3120+
mShapefileMayBeCorrupted = true;
3121+
}
3122+
#endif
3123+
31123124
ogrDataSource = OGROpen( TO8F( mFilePath ), false, &ogrDriver );
31133125

31143126
mWriteAccess = false;

‎tests/src/python/test_provider_shapefile.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,5 +319,49 @@ def testRepackUnderFileLocks(self):
319319
self.assertTrue(ds.GetLayer(0).GetFeatureCount(), feature_count - 1)
320320
ds = None
321321

322+
def testRepackAtFirstSave(self):
323+
''' Test fix for #15407 '''
324+
325+
# This requires a GDAL fix done per https://trac.osgeo.org/gdal/ticket/6672
326+
# but on non-Windows version the test would succeed
327+
if int(osgeo.gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(2, 1, 2):
328+
return
329+
330+
tmpdir = tempfile.mkdtemp()
331+
self.dirs_to_cleanup.append(tmpdir)
332+
srcpath = os.path.join(TEST_DATA_DIR, 'provider')
333+
for file in glob.glob(os.path.join(srcpath, 'shapefile.*')):
334+
shutil.copy(os.path.join(srcpath, file), tmpdir)
335+
datasource = os.path.join(tmpdir, 'shapefile.shp')
336+
337+
ds = osgeo.ogr.Open(datasource)
338+
lyr = ds.GetLayer(0)
339+
original_feature_count = lyr.GetFeatureCount()
340+
lyr.DeleteFeature(2)
341+
ds = None
342+
343+
vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
344+
345+
self.assertTrue(vl.featureCount(), original_feature_count)
346+
347+
# Edit a feature (attribute change only)
348+
self.assertTrue(vl.startEditing())
349+
self.assertTrue(vl.dataProvider().changeAttributeValues({0: {0: 100}}))
350+
351+
# Commit changes and check no error is emitted
352+
cbk = ErrorReceiver()
353+
vl.dataProvider().raiseError.connect(cbk.receiveError)
354+
self.assertTrue(vl.commitChanges())
355+
self.assertIsNone(cbk.msg)
356+
357+
self.assertTrue(vl.featureCount(), original_feature_count - 1)
358+
359+
vl = None
360+
361+
# Test repacking has been done
362+
ds = osgeo.ogr.Open(datasource)
363+
self.assertTrue(ds.GetLayer(0).GetFeatureCount(), original_feature_count - 1)
364+
ds = None
365+
322366
if __name__ == '__main__':
323367
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.