Skip to content

Commit

Permalink
Handle setting geometry column name for GDAL 3.6+ (#123)
Browse files Browse the repository at this point in the history
Co-authored-by: Yohan Cabion <[email protected]>
  • Loading branch information
yohancabion and Yohan Cabion authored Mar 22, 2024
1 parent 41946e3 commit cf193d9
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 6 deletions.
4 changes: 4 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ func ErrLogger(fn ErrorHandler) interface {
SetNoDataOption
SetScaleOffsetOption
SetGeoTransformOption
SetGeometryColumnNameOption
SetProjectionOption
SetSpatialRefOption
SieveFilterOption
Expand Down Expand Up @@ -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
}
Expand Down
23 changes: 23 additions & 0 deletions godal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,29 @@ 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 godalFeatureSetGeometryColumnName(cctx *ctx, OGRFeatureH feat, char *name) {
godalWrap(ctx);
OGRGeomFieldDefnH gfdef = OGR_F_GetGeomFieldDefnRef(feat, 0);
if(gfdef != nullptr){
OGR_GFld_SetName(gfdef, name);
}
godalUnwrap();
}

void godalFeatureSetGeometry(cctx *ctx, OGRFeatureH feat, OGRGeometryH geom) {
godalWrap(ctx);
OGRErr gret = OGR_F_SetGeometry(feat,geom);
Expand Down
29 changes: 24 additions & 5 deletions godal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2862,13 +2862,18 @@ func (f *Feature) SetGeometry(geom *Geometry, opts ...SetGeometryOption) error {
}

// SetGeometryColumnName set the name of feature first geometry field.
func (f *Feature) SetGeometryColumnName(name string) {
// Deprecated when running with GDAL 3.6+, use SetGeometryColumnName on Layer instead.
// No more supported when running with GDAL 3.9+.
func (f *Feature) 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))
gfdef := C.OGR_F_GetGeomFieldDefnRef(f.handle, C.int(0))
if gfdef != nil {
C.OGR_GFld_SetName(gfdef, (*C.char)(unsafe.Pointer(cname)))
}
cgc := createCGOContext(nil, so.errorHandler)
C.godalFeatureSetGeometryColumnName(cgc.cPointer(), f.handle, (*C.char)(cname))
return cgc.close()
}

// SetFID set feature identifier
Expand Down Expand Up @@ -3271,6 +3276,20 @@ func (layer Layer) DeleteFeature(feat *Feature, opts ...DeleteFeatureOption) err
return cgc.close()
}

// SetGeometryColumnName set the name of feature first geometry field.
// Only supported when running with GDAL 3.6+.
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
Expand Down
2 changes: 2 additions & 0 deletions godal.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ 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 godalFeatureSetGeometryColumnName(cctx *ctx, OGRFeatureH feat, 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);
Expand Down
25 changes: 24 additions & 1 deletion godal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -3066,7 +3080,16 @@ func TestFeatureAttributes(t *testing.T) {
assert.NoError(t, err)
fc, _ := lyr.FeatureCount()
assert.Equal(t, fc, 1)
nf.SetGeometryColumnName("no_error")

ehc = eh()
err = nf.SetGeometryColumnName("no_error_before_3_9", ErrLogger(ehc.ErrorHandler))
runtimeVersion := Version()
if runtimeVersion.Major() <= 3 && runtimeVersion.Minor() < 9 {
assert.NoError(t, err)
} else {
assert.Error(t, err)
}

nf.SetFID(99999999999)
attrs := nf.Fields()
intCol := attrs["intCol"]
Expand Down
13 changes: 13 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ type updateFeatureOpts struct {
type UpdateFeatureOption interface {
setUpdateFeatureOpt(o *updateFeatureOpts)
}

type deleteFeatureOpts struct {
errorHandler ErrorHandler
}
Expand All @@ -590,6 +591,18 @@ type DeleteFeatureOption interface {
setDeleteFeatureOpt(o *deleteFeatureOpts)
}

type setGeometryColumnNameOpts struct {
errorHandler ErrorHandler
}

// SetGeometryColumnNameOption is an option passed to Layer.SetGeometryColumnName() or Feature.SetGeometryColumnName()
//
// Available options are:
// - ErrLogger
type SetGeometryColumnNameOption interface {
setGeometryColumnNameOpt(o *setGeometryColumnNameOpts)
}

type geometryTransformOpts struct {
errorHandler ErrorHandler
}
Expand Down

0 comments on commit cf193d9

Please sign in to comment.