RFC 31:OGR 64位整数字段和fid
作者:弗兰克·温特丹,甚至鲁奥
联系方式:warmerdam@pobox.com,甚至是spatialys.com上的dot rouault
状态:采用,在GDAL 2.0中实现
总结
此RFC解决了升级OGR以支持64位整数字段和功能ID的步骤。许多特性数据格式支持宽整数,而无法通过OGR转换这些特性会导致越来越多的问题。
64位FID、特征索引和特征计数
功能id在内部将被处理为“GIntBig”类型而不是“long”。这将包括OGRFeature的nFID字段。OGRFeature上现有的GetFID()和SetFID()方法使用类型long,并改为返回(分别接受)GIntBig。更改GetFID()的返回类型将需要应用程序代码仔细调整以避免潜在的问题(例如,如果在类似printf的表达式中使用GetFID())。SetFID()更改应该主要是透明的。因此OGRFeature类中的更改是:
GIntBig GetFID();
OGRErr SetFID(GIntBig nFID );
在C API级别:
GIntBig CPL_DLL OGR_F_GetFID( OGRFeatureH );
OGRErr CPL_DLL OGR_F_SetFID( OGRFeatureH, GIntBig );
请注意,使用“long”的旧接口在64位操作系统上已经是64位的(不包括Windows目标编译器,即使在64位版本上,long也是32位的),因此对继续在64位操作系统上使用这些接口的应用程序没有什么危害。
如果一个层能够以相对便宜的方式发现它拥有64位FID的特性,那么它应该将OLMDu FID64元数据项公布为“YES”,这样ogr2ogr就可以将FID64创建选项传递给支持它的驱动程序。
OGRLayer类允许基于FID的多个操作。这些签名将是 改变了的 接受吉特比格而不是长。理论上,这不需要对应用程序代码进行任何更改,因为long可以无损地转换为GIntBig。但是,所有现有的OGR驱动程序都需要更改,包括私有驱动程序。这也将导致C ABI的向后不兼容更改。我们希望GetFeatureCount()能够返回超过20亿条记录(当前返回32位整数),从而返回GIntBig。与GetFID()类似,这种返回类型的更改需要在应用程序代码中小心。
所以在OGLeLtC++类级别:
virtual OGRFeature *GetFeature( GIntBig nFID );
virtual OGRErr DeleteFeature( GIntBig nFID );
virtual OGRErr SetNextByIndex( GIntBig nIndex );
virtual GIntBig GetFeatureCount( int bForce = TRUE );
在C API级别:
OGRFeatureH CPL_DLL OGR_L_GetFeature( OGRLayerH, GIntBig );
OGRErr CPL_DLL OGR_L_DeleteFeature( OGRLayerH, GIntBig );
OGRErr CPL_DLL OGR_L_SetNextByIndex( OGRLayerH, GIntBig );
GIntBig CPL_DLL OGR_L_GetFeatureCount( OGRLayerH, int );
64位字段
将为64位整数引入新的字段类型:
OFTInteger64 = 12
OFTInteger64List = 13
奥格菲尔德工会将扩大到包括:
GIntBig Integer64;
struct {
int nCount;
GIntBig *paList;
} Integer64List;
OGRFeature类将使用以下新方法进行扩展:
GIntBig GetFieldAsInteger64( int i );
GIntBig GetFieldAsInteger64( const char *pszFName );
const int *GetFieldAsInteger64List( const char *pszFName,
int *pnCount );
const int *GetFieldAsInteger64List( int i, int *pnCount );
void SetField( int i, GIntBig nValue );
void SetField( int i, int nCount, const GIntBig * panValues );
void SetField( const char *pszFName, GIntBig nValue )
void SetField( const char *pszFName, int nCount,
const GIntBig * panValues )
在C级,添加了以下功能:
GIntBig CPL_DLL OGR_F_GetFieldAsInteger64( OGRFeatureH, int );
const GIntBig CPL_DLL *OGR_F_GetFieldAsInteger64List( OGRFeatureH, int, int * );
void CPL_DLL OGR_F_SetFieldInteger64( OGRFeatureH, int, GIntBig );
void CPL_DLL OGR_F_SetFieldInteger64List( OGRFeatureH, int, int, const GIntBig * );
此外,新的接口将在内部支持设置/获取整型字段,整型字段方法将支持获取/设置64位整型字段,以便在方便的情况下对这两种字段类型都使用一个case(GetFieldAsInteger64List()除外,它只能对Integer64List字段进行操作)
添加一个GDAL_DMD_CREATIONFIELDDATATYPES=“DMD_CREATIONFIELDDATATYPES”驱动程序元数据项,以便驱动程序能够声明它们在创建时支持的字段类型。例如“Integer Integer64 Real String Date Time IntegerList Integer64List RealList StringList Binary”。常用的驱动程序将被更新以声明它。
OGR-SQL
添加了SWQ_INTEGER64内部类型,以便能够映射/来自oftinger64字段。swq_expr_node类的int_value成员从int扩展到GIntBig(因此swq_INTEGER和swq_INTEGER64都引用该成员)。
Python/Java/C#/perl更改
已完成以下更改:
GetFID(),GetFeatureCount()已更改为返回64位整数
SetFID()、GetFeature()、DeleteFeature()、SetNextByIndex()已更改为接受64位整数作为参数
已添加GetFieldAsInteger64()和SetFieldInteger64()
在Python中,GetField(),SetField()可以接受/返回64位值
已添加GetFieldAsInteger64List()和SetFieldInteger64List()(仅限Python,因为缺少其他语言的相关类型映射,但可能会完成)
GetFID()和GetFeatureCount()返回类型的更改可能会在某些语言(Java是、Python不相关、Perl/C#?)的编译时引起警告。对现有方法的所有更改都是对Java字节码的ABI更改。
公用事业
更新了ogr2ogr和ogrinfo以支持新的64位接口。
A new option is added to ogr2ogr : -mapFieldType. Can be used like this -mapFieldType Integer64=Integer,Date=String to mean that Integer64 field in the source layer should be created as Integer, and Date as String. ogr2ogr will also warn if attempting to create a field in an output driver that advertises a GDAL_DMD_CREATIONFIELDDATATYPES metadata item that does not mention the required field type. For Integer64 fields, if it is not advertized in GDAL_DMD_CREATIONFIELDDATATYPES metadata item or GDAL_DMD_CREATIONFIELDDATATYPES is missing, conversion to Real is done by default with a warning. ogr2ogr will also query the source layer to check if the OLMD_FID64 metadata item is declared and if the output driver has the FID64 layer creation option. In which case it will set it.
文档
新的/修改过的API被记录在案。有新选项/行为的驾驶员更新记录在案。MIGRATION_GUIDE.TXT扩展了与此RFC相关的部分。更新了OGR API。
文件格式
适当时,现有的OGR驱动程序已经更新,以支持新的/更新的接口。特别是,已经努力更新了一些数据库驱动程序,以支持64位整数列用作功能id,尽管它们在创建新图层时并不总是默认地将FID列创建为64位,因为这可能会给其他应用程序带来问题。
除了因界面变化引起的机械变化外,详细的变化列表如下:
Shapefile:OFTInteger字段在默认情况下是以9个字符的宽度创建的,因此可以明确地读作OFTInteger(如果指定需要10或11个字符的整数)。该字段是动态扩展的,就像托管的(因为有几个版本)。默认情况下,OFTInteger64字段的宽度为18位,因此可以像OFTInteger64一样清晰地读取,如果需要,可以扩展到19或20。宽度介于10和18之间的整数字段将从Integer64开始读取。在上面他们将被视为真正的。在以前的GDAL版本中,整数字段是用默认值10创建的,因此现在将作为OFTInteger64读取。可以指定一个open选项DETECTu TYPE=YES,以便OGR对DBF文件进行完整扫描,以查看大小为10或11的整数字段是否包含32位或64位值,并相应地调整类型(对于大小为19或20的整数字段也是如此,如果64位整数溢出,则选择OFTReal)
PG:更新为读取并创建oftinger64作为INT8,oftinger64list作为bigint[]。支持64位fid。默认情况下,在创建图层时,会将FID字段创建为串行(32位整数)以避免兼容性问题。可以传递FID64=YES创建选项,将其创建为BIGSERIAL。如果需要,驱动程序将动态改变模式,将32位整数FID字段扩展到64位。修改GetFeatureCount()以返回64位值。OLMD_FID64=“YES”在FID列为64位时立即播发。
PGDump:读/写支持Integer64、Integer64List和64位FID。FID64=YES创建选项可用。
GeoJSON:读/写支持Integer64、Integer64List和64位FID。只有在需要时才会报告64位变量,否则将使用oftinger/oftingerlist。OLMD_FID64=“是”如有需要,请在广告中注明
CSV:Integer64支持读/写,包括字段类型的自动检测功能。
GPKG:读/写支持整数64位和64位FID。与GeoPackage规范一致,“INT”或“INTEGER”列被视为64位,而“MEDIUMINT”被视为32位。OLMD_FID64=“YES”在MAX(fid_列)为64位时立即播发。修改GetFeatureCount()以返回64位值。
SQLite:读/写支持整数64位和64位FID。写入时,Integer64被创建为“BIGINT”,读取时,BIGINT或INT8被视为Integer64。但是,其他工具生成的数据库可能是用“INTEGER”创建的,并保存64位值,在这种情况下,OGR将无法检测到它。然后可以传递OGR_PROMOTE_TO_INTEGER64=YES配置选项来解决该问题。OLMD_FID64=“YES”在MAX(fid_列)为64位时立即播发。修改GetFeatureCount()以返回64位值。
MySQL:读/写支持整数64位和64位FID。与PG类似,默认情况下FID列创建为32位,除非指定了FID64=YES创建选项。OLMD_FID64=“YES”在FID列为64位时立即播发。修改GetFeatureCount()以返回64位值。
OCI:读/写支持64位和64位FID整数。在读取时检测Integer/Integer64很棘手,因为只有一个具有字段宽度的数字SQL类型。假设如果宽度<=9或是未指定的值(38),则它是一个整数。在创建时,OGR将oftinger64的宽度设置为20,因此没有小数部分且宽度为20的数字将被视为整数64。
MEM:读/写支持整数64位和64位FID。修改GetFeatureCount()以返回64位值。
VRT:读/写支持Integer64、Integer64List和64位FID。修改GetFeatureCount()以返回64位值。
JML:Integer64支持创建(创建为“OBJECT”)。读取时,以字符串形式返回
GML:读/写支持Integer64、Integer64List和64位FID。修改GetFeatureCount()以返回64位值。
WFS:读/写支持Integer64、Integer64List和64位FID。修改GetFeatureCount()以返回64位值。
CartoDB: Integer64 supported on creation. On read returned as Real (CartoDB only advertises a 'Number' type). GetFeatureCount() modified to return 64 bit values.
XLSX:读/写支持整数64。
ODS:读/写支持整数64。
mssqlspace:GetFeatureCount()已修改以返回64位值。虽然可能实现,但未实现Integer64支持。
OSM:即使在sizeof(long)时,FID也总是被设置的!=8个
LIBKML:KML'uint'广告为Integer64。
MITAB:改变无缝表的FID生成方式,通过使用全64位宽度的IDs,使其更健壮,并接受由任意数量的特性组成的任意数量的索引表
测试套件
扩展测试套件以测试新功能:
核心SetField/GetField方法
更新的驱动程序:Shapefile、PG、GeoJSON、CSV、GPKG、SQLite、MySQL、VRT、GML、XLSX、ODS、MITAB
OGR-SQL
选项-ogr2ogr的mapFieldType
兼容性问题
驱动程序代码更改
实现SetNextByIndex()、DeleteFeature()、GetFeature()和GetFeatureCount()的所有驱动程序都需要更改其原型并进行适当的更改。
如果没有其他可用的(并且bApproxOK为TRUE),则支持CreateField()的驱动程序可能应该扩展为支持整数/real/string字段。如果不注意Integer64支持,ogr2ogr将把Integer64转换为Real
通过调试语句、printf或使用类似sprintfs的语句对FID进行格式化输出的驱动程序已经更新为使用CPLu FRMTu GIB对FID进行格式化。未能进行这些更改可能会导致代码崩溃。由于在CPL函数中使用GCC注解来公布printf()格式语法,我们有理由相信已经对树内驱动程序进行了所需的更改(除了一些专有驱动程序,如SDE、IDB、ingre、ArcObjects,这些驱动程序无法编译和检查)。GetFeatureCount()也是如此
应用程序代码
可能需要更新应用程序代码,以便使用GIntBig作为fid和功能计数,以避免有关下推的警告。
使用类似printf的工具格式化fid或特性计数的应用程序代码也可能需要显式更改为downcast或使用CPL FRMT GIB。
应用程序代码可能需要添加Integer64处理以利用宽字段。
行为改变
以前被shapefile驱动程序视为“real”或integer的宽整型字段现在将被视为Integer64,这可能对某些应用程序不起作用,转换为其他格式可能会失败。
实施
实施将由甚至鲁奥完成 (Spatialys _),并由 LINZ (Land Information New Zealand) .
建议的实现位于 https://github.com/rouault/gdal2/tree/rfc31_64bit 储存库。
投票历史
+1名来自JukkaR,DanielM,TamasS,HowardB和Ever