PostgreSQL中CStringGetDatum与CStringGetTextDatum的区别是什么?
问题根本原因
PostgreSQL中SQL层的VARCHAR、TEXT、CHAR等文本类型,底层存储使用的是自定义的text结构体,和原生C语言中以\0结尾的char*字符串(通常叫cstring)内存结构完全不同:
text结构体开头包含VARHDRSZ长度的头部,存储整个结构体的总字节数- 头部后紧跟实际字符串内容,不需要以
\0结尾
两个宏的行为差异直接导致了问题:
CStringGetDatum(X)本质是PointerGetDatum(X),直接把输入的cstring指针强转成Datum类型返回,没有做任何结构转换,返回的Datum指向的还是原生cstring内存CStringGetTextDatum(s)会先调用cstring_to_text申请额外内存,把cstring转换成符合PG规范的text结构体,再把结构体指针强转成Datum返回
当你给VARCHAR字段传入CStringGetDatum的结果时,PG内核会把传入的cstring指针当成text结构体解析:字符串开头的几个字符会被误识别为长度头部,后续的内容解析也会完全错位,自然会出现数据异常、崩溃等问题;换成CStringGetTextDatum后传入的是符合规范的text结构,就能正常读写。
CStringGetDatum的适用场景
只有当交互的对象明确要求使用cstring类型的Datum时,才需要使用CStringGetDatum,常见场景包括:
- 自定义C函数的参数/返回值在PG定义中声明为
cstring伪类型 - 调用PG内核提供的、明确要求入参为
cstring类型Datum的工具函数
所有和SQL层的TEXT、VARCHAR、CHAR等常规文本类型交互的场景,都应该优先使用CStringGetTextDatum做转换。
内容的提问来源于stack exchange,提问作者Hyrikan
相关产品推荐
相关产品推荐

