Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle setting geometry column name for GDAL 3.6+ #123

Merged
merged 1 commit into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading