RFC 35:删除、重新排序和更改OGR层的字段定义

作者:连鲁奥

联系人:spatialys.com上的even dot rouault

状态:通过

总结

本文档建议对OGR进行更改,以便在OGR层定义中添加删除字段、重新排序字段和更改字段定义的功能。

理论基础

当前,只能更改OGR层定义以使用OGR layer::CreateField()添加新的字段定义。

希望扩展OGR功能,以便能够删除、重新排序和更改现有层的字段定义。这种愿望已在2671号机票上表达,并定期出现在QGIS邮件列表中(例如。 http://lists.osgeo.org/pipermail/qgis-user/2011-May/011935.html ). QGIS目前有一个“表管理器”扩展来解决DeleteField()的不足,因此显然需要一个适当的解决方案。

计划变更

OGRLayer类将使用以下方法进行扩展:

virtual OGRErr      DeleteField( int iField );
virtual OGRErr      ReorderFields( int* panMap );
virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );

/* non virtual : conveniency wrapper for ReorderFields() */
OGRErr              ReorderField( int iOldFieldPos, int iNewFieldPos );

这些新方法的文件如下:

/**
\fn OGRErr OGRLayer::DeleteField( int iField );

\brief Delete an existing field on a layer.

You must use this to delete existing fields
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
to reflect the deleted field.  Applications should never modify the OGRFeatureDefn
used by a layer directly.

This method should not be called while there are feature objects in existence that
were obtained or created with the previous layer definition.

Not all drivers support this method. You can query a layer to check if it supports it
with the OLCDeleteField capability. Some drivers may only support this method while
there are still no features in the layer. When it is supported, the existings features of the
backing file/database should be updated accordingly.

This function is the same as the C function OGR_L_DeleteField().

@param iField index of the field to delete.

@return OGRERR_NONE on success.

@since OGR 1.9.0
*/

/**
\fn OGRErr OGRLayer::ReorderFields( int* panMap );

\brief Reorder all the fields of a layer.

You must use this to reorder existing fields
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
to reflect the reordering of the fields.  Applications should never modify the OGRFeatureDefn
used by a layer directly.

This method should not be called while there are feature objects in existence that
were obtained or created with the previous layer definition.

panMap is such that,for each field definition at position i after reordering,
its position before reordering was panMap[i].

For example, let suppose the fields were "0","1","2","3","4" initially.
ReorderFields([0,2,3,1,4]) will reorder them as "0","2","3","1","4".

Not all drivers support this method. You can query a layer to check if it supports it
with the OLCReorderFields capability. Some drivers may only support this method while
there are still no features in the layer. When it is supported, the existings features of the
backing file/database should be updated accordingly.

This function is the same as the C function OGR_L_ReorderFields().

@param panMap an array of GetLayerDefn()->GetFieldCount() elements which
is a permutation of [0, GetLayerDefn()->GetFieldCount()-1].

@return OGRERR_NONE on success.

@since OGR 1.9.0
*/

/**
\fn OGRErr OGRLayer::ReorderField( int iOldFieldPos, int iNewFieldPos );

\brief Reorder an existing field on a layer.

This method is a conveniency wrapper of ReorderFields() dedicated to move a single field.
It is a non-virtual method, so drivers should implement ReorderFields() instead.

You must use this to reorder existing fields
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
to reflect the reordering of the fields.  Applications should never modify the OGRFeatureDefn
used by a layer directly.

This method should not be called while there are feature objects in existence that
were obtained or created with the previous layer definition.

The field definition that was at initial position iOldFieldPos will be moved at
position iNewFieldPos, and elements between will be shuffled accordingly.

For example, let suppose the fields were "0","1","2","3","4" initially.
ReorderField(1, 3) will reorder them as "0","2","3","1","4".

Not all drivers support this method. You can query a layer to check if it supports it
with the OLCReorderFields capability. Some drivers may only support this method while
there are still no features in the layer. When it is supported, the existings features of the
backing file/database should be updated accordingly.

This function is the same as the C function OGR_L_ReorderField().

@param iOldFieldPos previous position of the field to move. Must be in the range [0,GetFieldCount()-1].
@param iNewFieldPos new position of the field to move. Must be in the range [0,GetFieldCount()-1].

@return OGRERR_NONE on success.

@since OGR 1.9.0
*/

/**
\fn OGRErr OGRLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );

\brief Alter the definition of an existing field on a layer.

You must use this to alter the definition of an existing field of a real layer.
Internally the OGRFeatureDefn for the layer will be updated
to reflect the altered field.  Applications should never modify the OGRFeatureDefn
used by a layer directly.

This method should not be called while there are feature objects in existence that
were obtained or created with the previous layer definition.

Not all drivers support this method. You can query a layer to check if it supports it
with the OLCAlterFieldDefn capability. Some drivers may only support this method while
there are still no features in the layer. When it is supported, the existings features of the
backing file/database should be updated accordingly. Some drivers might also not support
all update flags.

This function is the same as the C function OGR_L_AlterFieldDefn().

@param iField index of the field whose definition must be altered.
@param poNewFieldDefn new field definition
@param nFlags combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG and ALTER_WIDTH_PRECISION_FLAG
to indicate which of the name and/or type and/or width and precision fields from the new field
definition must be taken into account.

@return OGRERR_NONE on success.

@since OGR 1.9.0
*/

添加了三个新的层功能:

OLCDeleteField / "DeleteField": TRUE if this layer can delete
existing fields on the current layer using DeleteField(), otherwise FALSE.

OLCReorderFields / "ReorderFields": TRUE if this layer can reorder
existing fields on the current layer using ReorderField() or ReorderFields(), otherwise FALSE.

OLCAlterFieldDefn / "AlterFieldDefn": TRUE if this layer can alter
the definition of an existing field on the current layer using AlterFieldDefn(), otherwise FALSE.

新方法映射到C API:

OGRErr CPL_DLL OGR_L_DeleteField( OGRLayerH, int iField );
OGRErr CPL_DLL OGR_L_ReorderFields( OGRLayerH, int* panMap );
OGRErr CPL_DLL OGR_L_ReorderField( OGRLayerH, int iOldFieldPos, int iNewFieldPos );
OGRErr CPL_DLL OGR_L_AlterFieldDefn( OGRLayerH, int iField, OGRFieldDefnH hNewFieldDefn, int nFlags );

为了实现,还向OGRFeatureDefn类添加了新方法:

OGRErr      DeleteFieldDefn( int iField );
OGRErr      ReorderFieldDefns( int* panMap );

一个OGRErr OGRCheckPermutation(int * panPermutation,int nSize)函数被添加到ogrutils.cpp中,以检查数组是否是 [0,nSize-1] . 它被OGRFeatureDefn::ReorderFieldDefns()使用,并且可以被实现OGRLayer::ReorderFields()的所有驱动程序用来验证panMap参数。

更改字段类型

此RFC不试图保证可以进行哪些类型转换。这将取决于实现驱动程序的能力。例如,对于数据库驱动程序,操作将直接在服务器端完成(通过PG驱动程序的“ALTER TABLE my_TABLE ALTER COLUMN my_COLUMN TYPE new_TYPE”命令)。所以有些转变是可能的,有些则不是。。。

但是,在大多数情况下,当AlterFieldDefn()被支持时,将支持从任何类型转换为OFTString。

不支持转换并且需要转换的驱动程序(ALTER_TYPE_FLAG set和new_TYPE!=old_type)应发出显式错误。

兼容性问题

没有

更改的驱动程序

shapefile驱动程序将实现DeleteField()、ReorderFields()和AlterFieldDefn()。Shapelib将使用DBFReorderFields()和dbfalterfieldefn()进行扩展。

注意:Shapefile驱动程序中AlterFieldDefn()的实现不支持更改字段类型,除非转换为OFTString。如果宽度或精度更改,则不会重新格式化现有要素的数值。但是,如果改变宽度,则会发生适当的字段截断或扩展。

其他驱动程序,主要是数据库驱动程序(PG、MySQL、SQLite),可以通过发出适当的SQL命令(ALTER TABLE foo DROP COLUMN bar、ALTER TABLE foo ALTER COLUMN bar,…)轻松地扩展以实现新的API。PG驱动程序中的DeleteField()和AlterFieldDefn()的实现确实已经计划好了,只要采用了这个RFC。内存驱动程序也将更新为支持DeleteField()、ReorderFields()和AlterFieldDefn()。

SWIG绑定

DeleteField()、ReorderField()、ReorderFields()和AlterFieldDefn()将映射到SWIG。

测试套件

autotest套件将被扩展以测试Shapefile驱动程序的新API的实现。新API的使用示例附在ticket#2671上 (rfc35_test.py _)并将转换为单元测试。

实施

甚至ruault也将在GDAL/OGR主干中实现。Shapelib提交者需要将Shapelib中的更改推送到上游CVS中。建议的实施作为补丁附在标签#2671中 (rfc35_v3.patch ②)

投票历史

+法兰克,丹尼尔姆,霍华德,塔马斯和埃文