Skip to content

Commit d4317a7

Browse files
committed
[OGR provider] Check if REPACK has emitted errors
Refs #15393 and #15570 Real fix for the REPACK issues has been committed per GDAL ticket https://trac.osgeo.org/gdal/ticket/6672 (GDAL 2.1.2 or above) Add test to simulate the situations that caused problems.
1 parent 446493d commit d4317a7

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

src/providers/ogr/qgsogrprovider.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,12 @@ void QgsOgrProvider::repack()
154154
// run REPACK on shape files
155155
QByteArray sql = QByteArray( "REPACK " ) + layerName; // don't quote the layer name as it works with spaces in the name and won't work if the name is quoted
156156
QgsDebugMsg( QString( "SQL: %1" ).arg( FROM8( sql ) ) );
157+
CPLErrorReset();
157158
OGR_DS_ExecuteSQL( ogrDataSource, sql.constData(), nullptr, nullptr );
159+
if ( CPLGetLastErrorType() != CE_None )
160+
{
161+
pushError( tr( "OGR[%1] error %2: %3" ).arg( CPLGetLastErrorType() ).arg( CPLGetLastErrorNo() ).arg( CPLGetLastErrorMsg() ) );
162+
}
158163
159164
if ( mFilePath.endsWith( ".shp", Qt::CaseInsensitive ) || mFilePath.endsWith( ".dbf", Qt::CaseInsensitive ) )
160165
{

tests/src/python/test_provider_shapefile.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@
3535
TEST_DATA_DIR = unitTestDataPath()
3636

3737

38+
def GDAL_COMPUTE_VERSION(maj, min, rev):
39+
return ((maj) * 1000000 + (min) * 10000 + (rev) * 100)
40+
41+
42+
class ErrorReceiver():
43+
44+
def __init__(self):
45+
self.msg = None
46+
47+
def receiveError(self, msg):
48+
self.msg = msg
49+
50+
3851
class TestPyQgsShapefileProvider(unittest.TestCase, ProviderTestCase):
3952

4053
@classmethod
@@ -262,5 +275,49 @@ def testDeleteGeometry(self):
262275
fet = next(vl.getFeatures())
263276
self.assertIsNone(fet.geometry())
264277

278+
def testRepackUnderFileLocks(self):
279+
''' Test fix for #15570 and #15393 '''
280+
281+
# This requires a GDAL fix done per https://trac.osgeo.org/gdal/ticket/6672
282+
# but on non-Windows version the test would succeed
283+
if int(osgeo.gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(2, 1, 2):
284+
return
285+
286+
tmpdir = tempfile.mkdtemp()
287+
self.dirs_to_cleanup.append(tmpdir)
288+
srcpath = os.path.join(TEST_DATA_DIR, 'provider')
289+
for file in glob.glob(os.path.join(srcpath, 'shapefile.*')):
290+
shutil.copy(os.path.join(srcpath, file), tmpdir)
291+
datasource = os.path.join(tmpdir, 'shapefile.shp')
292+
293+
vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
294+
feature_count = vl.featureCount()
295+
296+
# Keep a file descriptor opened on the .dbf, .shp and .shx
297+
f_shp = open(os.path.join(tmpdir, 'shapefile.shp'), 'rb')
298+
f_shx = open(os.path.join(tmpdir, 'shapefile.shx'), 'rb')
299+
f_dbf = open(os.path.join(tmpdir, 'shapefile.dbf'), 'rb')
300+
301+
# Delete a feature
302+
self.assertTrue(vl.startEditing())
303+
self.assertTrue(vl.deleteFeature(1))
304+
305+
# Commit changes and check no error is emitted
306+
cbk = ErrorReceiver()
307+
vl.dataProvider().raiseError.connect(cbk.receiveError)
308+
self.assertTrue(vl.commitChanges())
309+
self.assertIsNone(cbk.msg)
310+
311+
vl = None
312+
313+
del f_shp
314+
del f_shx
315+
del f_dbf
316+
317+
# Test repacking has been done
318+
ds = osgeo.ogr.Open(datasource)
319+
self.assertTrue(ds.GetLayer(0).GetFeatureCount(), feature_count - 1)
320+
ds = None
321+
265322
if __name__ == '__main__':
266323
unittest.main()

0 commit comments

Comments
 (0)