Skip to content

Commit abc96ce

Browse files
committed
[bugfix] Vector file writer: also check for layername before giving up
while (over)writing gpkg &C from vector file writer With tests Fixes #19611 - Cannot save selected features back to the same GeoPackage
1 parent b6251d2 commit abc96ce

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

src/core/qgsvectorfilewriter.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,16 +2550,35 @@ QgsVectorFileWriter::WriterError QgsVectorFileWriter::writeAsVectorFormat( Prepa
25502550
int lastProgressReport = 0;
25512551
long total = details.featureCount;
25522552

2553+
// Special rules for OGR layers
25532554
if ( details.providerType == QLatin1String( "ogr" ) && !details.dataSourceUri.isEmpty() )
25542555
{
25552556
QStringList theURIParts = details.dataSourceUri.split( '|' );
25562557
QString srcFileName = theURIParts[0];
2558+
QgsStringMap srcUriParams;
2559+
if ( theURIParts.length() > 0 )
2560+
{
2561+
for ( int i = 1; i < theURIParts.length(); ++i )
2562+
{
2563+
QStringList parts( theURIParts[i].split( '=' ) );
2564+
if ( parts.length() == 2 )
2565+
srcUriParams[parts[0]] = parts[1];
2566+
}
2567+
}
25572568

25582569
if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
25592570
{
2560-
if ( errorMessage )
2561-
*errorMessage = QObject::tr( "Cannot overwrite a OGR layer in place" );
2562-
return ErrCreateDataSource;
2571+
// Check the layer name too if it's a GPKG/SpatiaLite/SQLite OGR driver
2572+
QgsDataSourceUri uri( details.dataSourceUri );
2573+
if ( !( ( options.driverName == QLatin1String( "GPKG" ) ||
2574+
options.driverName == QLatin1String( "SpatiaLite" ) ||
2575+
options.driverName == QLatin1String( "SQLite" ) ) &&
2576+
options.layerName != srcUriParams["layername"] ) )
2577+
{
2578+
if ( errorMessage )
2579+
*errorMessage = QObject::tr( "Cannot overwrite a OGR layer in place" );
2580+
return ErrCreateDataSource;
2581+
}
25632582
}
25642583

25652584
// Shapefiles might contain multi types although wkbType() only reports singles

tests/src/python/test_qgsvectorfilewriter.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
)
3333
from qgis.PyQt.QtCore import QDate, QTime, QDateTime, QVariant, QDir
3434
import os
35+
import tempfile
3536
import osgeo.gdal # NOQA
3637
from osgeo import gdal, ogr
3738
from qgis.testing import start_app, unittest
@@ -898,6 +899,46 @@ def testSupportsFeatureStyles(self):
898899
self.assertTrue(QgsVectorFileWriter.supportsFeatureStyles('MapInfo File'))
899900
self.assertTrue(QgsVectorFileWriter.supportsFeatureStyles('MapInfo MIF'))
900901

902+
def testOverwriteGPKG(self):
903+
"""Test that overwriting the same origin GPKG file works only if the layername is different"""
904+
905+
# Prepare test data
906+
ml = QgsVectorLayer('Point?field=firstfield:int&field=secondfield:int', 'test', 'memory')
907+
provider = ml.dataProvider()
908+
ft = QgsFeature()
909+
ft.setAttributes([4, -10])
910+
provider.addFeatures([ft])
911+
filehandle, filename = tempfile.mkstemp('.gpkg')
912+
913+
options = QgsVectorFileWriter.SaveVectorOptions()
914+
options.driverName = 'GPKG'
915+
options.layerName = 'test'
916+
write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
917+
ml,
918+
filename,
919+
options)
920+
self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)
921+
922+
# Real test
923+
vl = QgsVectorLayer("%s|layername=test" % filename, 'src_test', 'ogr')
924+
self.assertTrue(vl.isValid())
925+
self.assertEqual(vl.featureCount(), 1)
926+
927+
# This must fail
928+
write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
929+
vl,
930+
filename,
931+
options)
932+
self.assertEqual(write_result, QgsVectorFileWriter.ErrCreateDataSource)
933+
self.assertEqual(error_message, 'Cannot overwrite a OGR layer in place')
934+
935+
options.layerName = 'test2'
936+
write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
937+
vl,
938+
filename,
939+
options)
940+
self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)
941+
901942

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

0 commit comments

Comments
 (0)