GB18030(200020052022)

Unicode是自USC(ISO/IEC 10646)发展而来的国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。

E000至F8FF 私用区 Private Use Area(在 GB 18030-2000 的时代,有一些汉字还没有被 Unicode 标准正式收录,被收录到此区域)

4E00至9FFF 中日韩统一表意文字 CJK Unified Ideographs

F900至FAFF 中日韩兼容表意文字 CJK Compatibility Ideographs 解决历史遗留一字多码

GB 18030-2000,兼容 Unicode 3.0 中日韩统一表意文字,共收27533个汉字;

GB 18030-2005,更新至 Unicode 4.1 中日韩统一表意文字及增加少数民族文字,共有70244个汉字;

GB 18030-2022,更新至 Unicode 15中日韩统一表意文字及增加少数民族文字,共有87887个汉字;2024年10月补充了9793个汉字,使得该标准收录汉字达到97680个。

GB18030的设计思路可以概括到以下几点:

1单字节部分与Unicode一致。

2双字节部分与GBK兼容。适当调整一些字符与Unicode的映射。

    这些字符原来因为Unicode没有收录而被映射到PUA,现在因为Unicode已经收录而调整到非PUA的Unicode码位。

3将Unicode BMP部分还没有映射的39420个码位顺序映射到从0x81308130开始的四字节部分。

4将Unicode BMP以外的16个辅助平面映射到39420个码位顺序映射到从0x90308130开始的四字节部分。

GB 18030-2022

GB18030码位分配

GB18030编码采用单字节、双字节和四字节三种方式对字符编码。

1单字节部分采用GB/T 11383的编码结构与规则,使用0x00至0x7F码位(对应ASCII码位)。

2双字节部分,首字节码位从0x81至0xFE,尾字节码位分别是0x40至0x7E和0x80至0xFE。

3四字节部分采用GB/T 11383未采用的0x30到0x39作为对双字节编码扩充的后缀,这样扩充的四字节编码,其范围为0x81308130到0xFE39FE39。其中第一、三个字节编码码位均为0x81至0xFE,第二、四个字节编码码位均为0x30至0x39。

1.GB18030作为服务端编码

1.1 为什么pg中GB18030不支持作为服务端编码?

1.1.1 GB18030 在pg中是ASCII不安全的编码

GB18030编码采用单字节、双字节和四字节三种方式对字符编码。

1单字节部分采用GB/T 11383的编码结构与规则,使用0x00至0x7F码位(对应ASCII码位)。

2双字节部分,首字节码位从0x81至0xFE,尾字节码位分别是0x40至0x7E和0x80至0xFE。

3四字节部分采用GB/T 11383未采用的0x30到0x39作为对双字节编码扩充的后缀,这样扩充的四字节编码,其范围为0x81308130到0xFE39FE39。其中第一、三个字节编码码位均为0x81至0xFE,第二、四个字节编码码位均为0x30至0x39。

目前,PostgreSQL 的 SQL 解析器,都假定了一个前提——字符串数据中的任何一个字节都不会与有特殊含义的 ASCII 字节相混淆。然而,由于 GB18030 编码的第二个和第四个字节的取值范围在 0x40 到 0x7E 之间(这与许多 ASCII 字符重叠),将会对后端造成混淆。

1.1.2 pg_wchar.h中pg_enc枚举编号限制

pg_wchar.h是PostgreSQL源码中负责多字节字符处理的核心头文件之一。其中定义了一个名为pg_enc的枚举类型,它的作用是为pg支持的每一种字符集分配一个唯一的整数ID作为内部使用

2. GB18030和UTF8的转换

2.1 转换的map文件从哪里来?

Map文件记录着gb18030和unicode的转换表,是通过perl脚本读取ICU维护的数据文件生成的。 数据文件分为三种,按时间先后顺序是txt,xml,ucm。

早期pg引入PG18030时,使用txt数据文件,后来更换为ICU组织维护的xml文件。因为xml文件为了提高转换效率,只列出了无规则需要查表的编码,有规则的大块连续区域使用偏移函数计算。

目前pg17在使用的是GB18030-2000.xml。ICU维护的GB18030-2005、2022版编码文件,因为xml格式无法表示一字双码,现在只维护ucm格式。

2. 修改GB18030编码的属性和函数

1)将GB18030的内部编码ID设置可作为为服务端编码 2)设置最大最小字节 3)设置wchar的转换函数,长度计算函数

ICU/gb18030-2022.ucm

ICU-data/gb18030-2000.xml

ICU-data/gb18030-2005.ucm

https://www.cnblogs.com/shangdawei/archive/2013/05/07/3065496.html

OceanBase支持gb18030-2022:完整的.c数据文件

OpenGauss支持gb18030-2022:增加GB18030-2000基础上的新表,增加一个新的编码

工具: 汉字字符集编码查询

pg讨论: Retire GB18030 https://www.postgresql.org/message-id/flat/aC68DmpyYer87rau%40paquier.xyz

May “PostgreSQL server side GB18030 character set support” reconsidered? https://www.postgresql.org/message-id/flat/20201006.121142.2002518154310370203.t-ishii%40sraoss.co.jp#d9b9258c7d05c66e7252e76a7949110f