From 7d0dafa2d6c41e594217b784e19c0e463c062bce Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Thu, 14 Aug 2025 17:33:21 +0200 Subject: Add a NOT NULL contraint on geometry columns when creating the output layer. When the output driver supports altering GeomFieldDefn's nullable flag after the fact. PostgreSQL supports that. GPKG doesn't, but one can use GEOMETRY_NULLABLE=NO in layer creation options instead. See https://gdal.org/en/stable/development/rfc/rfc53_ogr_notnull_default.html This commit partially reverts 2c3ee79cb434fc4cf315ee3a6a526156053d76c4. --- import_source.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'import_source.py') diff --git a/import_source.py b/import_source.py index 1948f7b..f40cd38 100644 --- a/import_source.py +++ b/import_source.py @@ -117,7 +117,7 @@ def createOutputLayer(ds : gdal.Dataset, logging.info('Creating new destination layer "%s"', layername) geom_type = options['geometry-type'] - lco = options.get('options', []) + lco = options.get('options', None) drv = ds.GetDriver() if geom_type != ogr.wkbNone and drv.ShortName == 'PostgreSQL': @@ -137,16 +137,16 @@ def createOutputLayer(ds : gdal.Dataset, lco = [] lco = ['dim=' + dim] + lco # prepend dim= - geom_field = ogr.GeomFieldDefn() - geom_field.SetType(geom_type) - geom_field.SetNullable(False) # XXX doesn't do anything?? + kwargs = { 'geom_type': geom_type } if srs is not None: - geom_field.SetSpatialRef(srs) - logging.debug('CreateLayer("%s", geom_type="%s"%s%s)', - layername, ogr.GeometryTypeToName(geom_type), - ', srs="' + geom_field.GetSpatialRef().GetName() + '"' if srs is not None else '', - ', options=' + str(lco) if lco is not None else '') - lyr = ds.CreateLayerFromGeomFieldDefn(layername, geom_field, lco if lco is not None else []) + kwargs['srs'] = srs + if lco is not None: + kwargs['options'] = lco + logging.debug('CreateLayer(%s, geom_type="%s"%s%s)', layername, + ogr.GeometryTypeToName(geom_type), + ', srs="' + kwargs['srs'].GetName() + '"' if 'srs' in kwargs else '', + ', options=' + str(kwargs['options']) if 'options' in kwargs else '') + lyr = ds.CreateLayer(layername, **kwargs) if lyr is None: raise RuntimeError(f'Could not create destination layer "{layername}"') @@ -217,6 +217,17 @@ def createOutputLayer(ds : gdal.Dataset, raise RuntimeError(f'Could not create field "{fldName}"') logging.debug('Added field "%s" to output layer "%s"', fldName, layername) + if lyr.TestCapability(ogr.OLCAlterGeomFieldDefn): + # it appears using .CreateLayerFromGeomFieldDefn() on a a non-nullable + # GeomFieldDefn doesn't do anything, so we alter it after the fact instead + # (GPKG doesn't support this, use GEOMETRY_NULLABLE=NO in layer creation + # options instead) + flags = drv.GetMetadataItem(gdal.DMD_ALTER_GEOM_FIELD_DEFN_FLAGS) + if flags is not None and 'nullable' in flags.lower().split(' '): + geom_field = ogr.GeomFieldDefn(None, geom_type) + geom_field.SetNullable(False) + lyr.AlterGeomFieldDefn(0, geom_field, ogr.ALTER_GEOM_FIELD_DEFN_NULLABLE_FLAG) + # sync before calling StartTransaction() so we're not trying to rollback changes # on a non-existing table lyr.SyncToDisk() -- cgit v1.2.3