Skip to content
Permalink
Browse files

Fix crash when a geopackage layer is open in QGIS, and then is overwr…

…itten

with another layer with different field definitions
  • Loading branch information
nyalldawson committed Nov 25, 2017
1 parent 5c22e31 commit 96857ebdd443d0fed7fb334ce0a03ab24ee22abe
Showing with 41 additions and 3 deletions.
  1. +6 −3 src/providers/ogr/qgsogrprovider.cpp
  2. +35 −0 tests/src/python/test_provider_ogr_gpkg.py
@@ -1082,10 +1082,13 @@ void QgsOgrProviderUtils::setRelevantFields( OGRLayerH ogrLayer, int fieldCount,
if ( !fetchAttributes.contains( i ) )
{
// add to ignored fields
const char *fieldName = OGR_Fld_GetNameRef( OGR_FD_GetFieldDefn( featDefn, firstAttrIsFid ? i - 1 : i ) );
if ( qstrcmp( fieldName, ORIG_OGC_FID ) != 0 )
if ( OGRFieldDefnH field = OGR_FD_GetFieldDefn( featDefn, firstAttrIsFid ? i - 1 : i ) )
{
ignoredFields.append( fieldName );
const char *fieldName = OGR_Fld_GetNameRef( field );
if ( qstrcmp( fieldName, ORIG_OGC_FID ) != 0 )
{
ignoredFields.append( fieldName );
}
}
}
}
@@ -22,6 +22,7 @@
from osgeo import gdal, ogr
from qgis.core import (QgsFeature,
QgsCoordinateReferenceSystem,
QgsFeatureRequest,
QgsFields,
QgsField,
QgsFieldConstraints,
@@ -31,6 +32,7 @@
QgsVectorLayer,
QgsVectorLayerExporter,
QgsPointXY,
QgsProject,
QgsWkbTypes)
from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.testing import start_app, unittest
@@ -566,6 +568,39 @@ def testGeopackageTwoLayerEdition(self):
reference = QgsGeometry.fromWkt('Point (5 5)')
self.assertEqual(got_geom.asWkb(), reference.asWkb(), 'Expected {}, got {}'.format(reference.asWkt(), got_geom.asWkt()))

def testReplaceLayerWhileOpen(self):
''' Replace an existing geopackage layer whilst it's open in the project'''
tmpfile = os.path.join(self.basetestpath, 'testGeopackageReplaceOpenLayer.gpkg')
ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
lyr = ds.CreateLayer('layer1', geom_type=ogr.wkbPoint)
lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger))
lyr.CreateField(ogr.FieldDefn('attr2', ogr.OFTInteger))
f = ogr.Feature(lyr.GetLayerDefn())
f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 0)'))
lyr.CreateFeature(f)
f = None

vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer1', u'ogr')
p = QgsProject()
p.addMapLayer(vl1)
request = QgsFeatureRequest().setSubsetOfAttributes([0])
features = [f for f in vl1.getFeatures(request)]
self.assertEqual(len(features), 1)

# now, overwrite the layer with a different geometry type and fields
ds.DeleteLayer('layer1')
lyr = ds.CreateLayer('layer1', geom_type=ogr.wkbLineString)
lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTString))
f = ogr.Feature(lyr.GetLayerDefn())
f.SetGeometry(ogr.CreateGeometryFromWkt('LineString(0 0, 1 1)'))
lyr.CreateFeature(f)
f = None
vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer2', u'ogr')
p.addMapLayer(vl2)

features = [f for f in vl1.getFeatures(request)]
self.assertEqual(len(features), 1)

def testGeopackageManyLayers(self):
''' test opening more than 64 layers without running out of Spatialite connections '''

0 comments on commit 96857eb

Please sign in to comment.
You can’t perform that action at this time.