Skip to content

Commit

Permalink
[OGR provider] Fix wrong gpkg_metadata_reference_column_name_update t…
Browse files Browse the repository at this point in the history
…rigger

Fixes #42768

Proper GDAL fix in OSGeo/gdal#3863
  • Loading branch information
rouault authored and nyalldawson committed May 25, 2021
1 parent 3dca51d commit 0999a96
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/core/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -4353,6 +4353,42 @@ GDALDatasetH QgsOgrProviderUtils::GDALOpenWrapper( const char *pszPath, bool bUp
if ( phDriver )
*phDriver = hDrv;

#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3, 3, 1)
if ( bUpdate && bIsGpkg && strcmp( GDALGetDriverShortName( hDrv ), "GPKG" ) == 0 )
{
// Fix wrong gpkg_metadata_reference_column_name_update trigger that was
// generated by GDAL < 2.4.0
OGRLayerH hSqlLyr = GDALDatasetExecuteSQL(
hDS,
"SELECT sql FROM sqlite_master WHERE type = 'trigger' AND "
"NAME ='gpkg_metadata_reference_column_name_update' AND "
"sql LIKE '%column_nameIS%'",
nullptr, nullptr );
if ( hSqlLyr )
{
QString triggerSql;
gdal::ogr_feature_unique_ptr hFeat( OGR_L_GetNextFeature( hSqlLyr ) );
if ( hFeat )
{
triggerSql = OGR_F_GetFieldAsString( hFeat.get(), 0 );
}
GDALDatasetReleaseResultSet( hDS, hSqlLyr );

if ( !triggerSql.isEmpty() )
{
GDALDatasetExecuteSQL(
hDS, "DROP TRIGGER gpkg_metadata_reference_column_name_update",
nullptr, nullptr );
GDALDatasetExecuteSQL(
hDS,
triggerSql.replace( QLatin1String( "column_nameIS" ),
QLatin1String( "column_name IS" ) ).toUtf8().toStdString().c_str(),
nullptr, nullptr );
}
}
}
#endif

return hDS;
}

Expand Down
42 changes: 42 additions & 0 deletions tests/src/python/test_provider_ogr_gpkg.py
Expand Up @@ -2086,6 +2086,48 @@ def testRejectedGeometryUpdate(self):
g = [f.geometry() for f in vl.getFeatures()][0]
self.assertEqual(g.asWkt(), 'Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))')

def testFixWrongMetadataReferenceColumnNameUpdate(self):
""" Test that we (or GDAL) fixes wrong gpkg_metadata_reference_column_name_update trigger """
tmpfile = os.path.join(self.basetestpath, 'testFixWrongMetadataReferenceColumnNameUpdate.gpkg')

ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
ds.CreateLayer('test', geom_type=ogr.wkbPoint)
ds.SetMetadata('FOO', 'BAR')
ds = None

ds = ogr.Open(tmpfile, update=1)
gdal.PushErrorHandler()
ds.ExecuteSQL('DROP TRIGGER gpkg_metadata_reference_column_name_update')
gdal.PopErrorHandler()
# inject wrong trigger on purpose
wrong_trigger = "CREATE TRIGGER 'gpkg_metadata_reference_column_name_update' " + \
"BEFORE UPDATE OF column_name ON 'gpkg_metadata_reference' " + \
"FOR EACH ROW BEGIN " + \
"SELECT RAISE(ABORT, 'update on table gpkg_metadata_reference " + \
"violates constraint: column name must be NULL when reference_scope " + \
"is \"geopackage\", \"table\" or \"row\"') " + \
"WHERE (NEW.reference_scope IN ('geopackage','table','row') " + \
"AND NEW.column_nameIS NOT NULL); END;"
ds.ExecuteSQL(wrong_trigger)
ds = None

vl = QgsVectorLayer(u'{}'.format(tmpfile), 'test', u'ogr')
self.assertTrue(vl.isValid())
del vl

# Check trigger afterwards
ds = ogr.Open(tmpfile)
sql_lyr = ds.ExecuteSQL(
"SELECT sql FROM sqlite_master WHERE type = 'trigger' " +
"AND name = 'gpkg_metadata_reference_column_name_update'")
f = sql_lyr.GetNextFeature()
sql = f['sql']
ds.ReleaseResultSet(sql_lyr)
ds = None

gdal.Unlink(tmpfile)
assert 'column_nameIS' not in sql


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

0 comments on commit 0999a96

Please sign in to comment.