From 79cc9be200499ec8401a8e5b241225ea14cddf99 Mon Sep 17 00:00:00 2001 From: Yohan Cabion Date: Wed, 20 Mar 2024 16:41:05 +0000 Subject: [PATCH] Handle setting geometry column name for GDAL 3.6+ --- errors.go | 4 ++++ godal.cpp | 14 ++++++++++++++ godal.go | 14 ++++++++++++++ godal.h | 1 + godal_test.go | 14 ++++++++++++++ options.go | 13 +++++++++++++ 6 files changed, 60 insertions(+) diff --git a/errors.go b/errors.go index d90775b..093ac34 100644 --- a/errors.go +++ b/errors.go @@ -134,6 +134,7 @@ func ErrLogger(fn ErrorHandler) interface { SetNoDataOption SetScaleOffsetOption SetGeoTransformOption + SetGeometryColumnNameOption SetProjectionOption SetSpatialRefOption SieveFilterOption @@ -241,6 +242,9 @@ func (ec errorCallback) setFillnodataOpt(o *fillnodataOpts) { func (ec errorCallback) setGeojsonOpt(o *geojsonOpts) { o.errorHandler = ec.fn } +func (ec errorCallback) setGeometryColumnNameOpt(o *setGeometryColumnNameOpts) { + o.errorHandler = ec.fn +} func (ec errorCallback) setGeometryTransformOpt(o *geometryTransformOpts) { o.errorHandler = ec.fn } diff --git a/godal.cpp b/godal.cpp index d1f7951..c5135cb 100644 --- a/godal.cpp +++ b/godal.cpp @@ -816,6 +816,20 @@ void godalLayerSetFeature(cctx *ctx, OGRLayerH layer, OGRFeatureH feat) { godalUnwrap(); } +void godalLayerSetGeometryColumnName(cctx *ctx, OGRLayerH layer, char *name) { + godalWrap(ctx); +#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3, 6, 0) + OGRGeomFieldDefnH fieldWithNewName = OGR_GFld_Create(name, OGRwkbGeometryType(0)); + OGRErr gret = OGR_L_AlterGeomFieldDefn(layer, 0, fieldWithNewName, ALTER_GEOM_FIELD_DEFN_NAME_FLAG); + if(gret!=0){ + forceOGRError(ctx,gret); + } +#else + CPLError(CE_Failure, CPLE_NotSupported, "OGR_L_AlterGeomFieldDefn is only supported in GDAL version >= 3.6"); +#endif + godalUnwrap(); +} + void godalFeatureSetGeometry(cctx *ctx, OGRFeatureH feat, OGRGeometryH geom) { godalWrap(ctx); OGRErr gret = OGR_F_SetGeometry(feat,geom); diff --git a/godal.go b/godal.go index c0c9f93..0a05be6 100644 --- a/godal.go +++ b/godal.go @@ -2861,6 +2861,7 @@ func (f *Feature) SetGeometry(geom *Geometry, opts ...SetGeometryOption) error { return cgc.close() } +// Deprecated: when running with GDAL 3.6+, you may use SetGeometryColumnName on Layer // SetGeometryColumnName set the name of feature first geometry field. func (f *Feature) SetGeometryColumnName(name string) { cname := C.CString(name) @@ -3271,6 +3272,19 @@ func (layer Layer) DeleteFeature(feat *Feature, opts ...DeleteFeatureOption) err return cgc.close() } +// SetGeometryColumnName set the name of feature first geometry field. +func (layer Layer) SetGeometryColumnName(name string, opts ...SetGeometryColumnNameOption) error { + so := &setGeometryColumnNameOpts{} + for _, o := range opts { + o.setGeometryColumnNameOpt(so) + } + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + cgc := createCGOContext(nil, so.errorHandler) + C.godalLayerSetGeometryColumnName(cgc.cPointer(), layer.handle(), (*C.char)(cname)) + return cgc.close() +} + // CreateLayer creates a new vector layer // // Available CreateLayerOptions are diff --git a/godal.h b/godal.h index 6c4bc78..6cf88ba 100644 --- a/godal.h +++ b/godal.h @@ -104,6 +104,7 @@ extern "C" { void godalLayerCreateFeature(cctx *ctx, OGRLayerH layer, OGRFeatureH feat); OGRFeatureH godalLayerNewFeature(cctx *ctx, OGRLayerH layer, OGRGeometryH geom); void godalLayerDeleteFeature(cctx *ctx, OGRLayerH layer, OGRFeatureH feat); + void godalLayerSetGeometryColumnName(cctx *ctx, OGRLayerH layer, char *name); void godalFeatureSetGeometry(cctx *ctx, OGRFeatureH feat, OGRGeometryH geom); void godalFeatureSetFieldInteger(cctx *ctx, OGRFeatureH feat, int fieldIndex, int value); void godalFeatureSetFieldInteger64(cctx *ctx, OGRFeatureH feat, int fieldIndex, long long value); diff --git a/godal_test.go b/godal_test.go index 170e624..7d7f1d0 100644 --- a/godal_test.go +++ b/godal_test.go @@ -2677,6 +2677,11 @@ func TestLayerModifyFeatures(t *testing.T) { ds, _ := Open("testdata/test.geojson") //read-only defer ds.Close() l := ds.Layers()[0] + + ehc := eh() + err := l.SetGeometryColumnName("error", ErrLogger(ehc.ErrorHandler)) // can't set geometry colum name on geojson + assert.Error(t, err) + for { ff := l.NextFeature() if ff == nil { @@ -2696,6 +2701,15 @@ func TestLayerModifyFeatures(t *testing.T) { dsm, _ := ds.VectorTranslate("", []string{"-of", "Memory"}) defer dsm.Close() l = dsm.Layers()[0] + + err = l.SetGeometryColumnName("no_error_after_3.6") + runtimeVersion := Version() + if runtimeVersion.Major() <= 3 && runtimeVersion.Minor() < 6 { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + for { ff := l.NextFeature() if ff == nil { diff --git a/options.go b/options.go index 3beb34b..056cfc7 100644 --- a/options.go +++ b/options.go @@ -578,6 +578,7 @@ type updateFeatureOpts struct { type UpdateFeatureOption interface { setUpdateFeatureOpt(o *updateFeatureOpts) } + type deleteFeatureOpts struct { errorHandler ErrorHandler } @@ -590,6 +591,18 @@ type DeleteFeatureOption interface { setDeleteFeatureOpt(o *deleteFeatureOpts) } +type setGeometryColumnNameOpts struct { + errorHandler ErrorHandler +} + +// SetGeometryColumnNameOption is an option passed to Layer.SetGeometryColumnName() +// +// Available options are: +// - ErrLogger +type SetGeometryColumnNameOption interface { + setGeometryColumnNameOpt(o *setGeometryColumnNameOpts) +} + type geometryTransformOpts struct { errorHandler ErrorHandler }