Skip to content
Permalink
Browse files
[OGR provider] Fix wrong gpkg_metadata_reference_column_name_update t…
…rigger

Fixes #42768

Proper GDAL fix in OSGeo/gdal#3863
  • Loading branch information
rouault committed May 21, 2021
1 parent ce77528 commit aa1a9d62e814d6739d084773f378dbedbcb3d911
Showing with 78 additions and 0 deletions.
  1. +36 −0 src/core/providers/ogr/qgsogrprovider.cpp
  2. +42 −0 tests/src/python/test_provider_ogr_gpkg.py
@@ -4749,6 +4749,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;
}

@@ -2155,6 +2155,48 @@ def testRollback(self):
self.assertEqual(features[0].attributes(), [1, -1, 123])
self.assertEqual(features[1].attributes(), [2, -4, 125])

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)
self.assertNotIn('column_nameIS', sql)


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

0 comments on commit aa1a9d6

Please sign in to comment.