Skip to content

Commit

Permalink
[bugfix] Vector file writer: also check for layername before giving up
Browse files Browse the repository at this point in the history
while (over)writing gpkg &C from vector file writer

With tests

Fixes #19611 - Cannot save selected features back to the same GeoPackage
  • Loading branch information
elpaso committed Aug 21, 2018
1 parent b6251d2 commit abc96ce
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
25 changes: 22 additions & 3 deletions src/core/qgsvectorfilewriter.cpp
Expand Up @@ -2550,16 +2550,35 @@ QgsVectorFileWriter::WriterError QgsVectorFileWriter::writeAsVectorFormat( Prepa
int lastProgressReport = 0;
long total = details.featureCount;

// Special rules for OGR layers
if ( details.providerType == QLatin1String( "ogr" ) && !details.dataSourceUri.isEmpty() )
{
QStringList theURIParts = details.dataSourceUri.split( '|' );
QString srcFileName = theURIParts[0];
QgsStringMap srcUriParams;
if ( theURIParts.length() > 0 )
{
for ( int i = 1; i < theURIParts.length(); ++i )
{
QStringList parts( theURIParts[i].split( '=' ) );
if ( parts.length() == 2 )
srcUriParams[parts[0]] = parts[1];
}
}

if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
{
if ( errorMessage )
*errorMessage = QObject::tr( "Cannot overwrite a OGR layer in place" );
return ErrCreateDataSource;
// Check the layer name too if it's a GPKG/SpatiaLite/SQLite OGR driver
QgsDataSourceUri uri( details.dataSourceUri );
if ( !( ( options.driverName == QLatin1String( "GPKG" ) ||
options.driverName == QLatin1String( "SpatiaLite" ) ||
options.driverName == QLatin1String( "SQLite" ) ) &&
options.layerName != srcUriParams["layername"] ) )
{
if ( errorMessage )
*errorMessage = QObject::tr( "Cannot overwrite a OGR layer in place" );
return ErrCreateDataSource;
}
}

// Shapefiles might contain multi types although wkbType() only reports singles
Expand Down
41 changes: 41 additions & 0 deletions tests/src/python/test_qgsvectorfilewriter.py
Expand Up @@ -32,6 +32,7 @@
)
from qgis.PyQt.QtCore import QDate, QTime, QDateTime, QVariant, QDir
import os
import tempfile
import osgeo.gdal # NOQA
from osgeo import gdal, ogr
from qgis.testing import start_app, unittest
Expand Down Expand Up @@ -898,6 +899,46 @@ def testSupportsFeatureStyles(self):
self.assertTrue(QgsVectorFileWriter.supportsFeatureStyles('MapInfo File'))
self.assertTrue(QgsVectorFileWriter.supportsFeatureStyles('MapInfo MIF'))

def testOverwriteGPKG(self):
"""Test that overwriting the same origin GPKG file works only if the layername is different"""

# Prepare test data
ml = QgsVectorLayer('Point?field=firstfield:int&field=secondfield:int', 'test', 'memory')
provider = ml.dataProvider()
ft = QgsFeature()
ft.setAttributes([4, -10])
provider.addFeatures([ft])
filehandle, filename = tempfile.mkstemp('.gpkg')

options = QgsVectorFileWriter.SaveVectorOptions()
options.driverName = 'GPKG'
options.layerName = 'test'
write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
ml,
filename,
options)
self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)

# Real test
vl = QgsVectorLayer("%s|layername=test" % filename, 'src_test', 'ogr')
self.assertTrue(vl.isValid())
self.assertEqual(vl.featureCount(), 1)

# This must fail
write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
vl,
filename,
options)
self.assertEqual(write_result, QgsVectorFileWriter.ErrCreateDataSource)
self.assertEqual(error_message, 'Cannot overwrite a OGR layer in place')

options.layerName = 'test2'
write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
vl,
filename,
options)
self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)


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

0 comments on commit abc96ce

Please sign in to comment.