c - 如何使用数组编写 Postgres 用户定义类型
问题描述
我在 Postgres 中编写了一个名为 personname 的用户定义类型:
#define FLXIBLE_ARRAY_MEMBER 0
PG_MODULE_MAGIC;
typedef struct personname{
int familyLen;
int givenLen;
int givenStart;
char pname[FLXIBLE_ARRAY_MEMBER];
}personname;
我大致这样编写 personname_in 和 personname_out 函数:
PG_FUNCTION_INFO_V1(pname_in);
Datum
pname_in(PG_FUNCTION_ARGS){
char* str = PG_GETARG_CSTRING(0);
personname *name;
...
name = (personname*) palloc(sizeof(personname) + strlen(str) + 1);
name->familyLen = familyNameLen;
name->givenLen = givenNameLen;
name->givenStart = givenNameStart;
strcpy(name->pname, str);
PG_RETURN_POINTER(name);
}
PG_FUNCTION_INFO_V1(pname_out);
Datum
pname_out(PG_FUNCTION_ARGS){
personname *name = (personname*) PG_GETARG_POINTER(0);
char* family = getFamily(name);
char* given = getGiven(name);
char* nameStr;
nameStr = psprintf("%s,%s", family, given);
pfree(family);
pfree(given);
PG_RETURN_CSTRING(nameStr);
}
我的sql是这样的:
CREATE FUNCTION pname_in(cstring)
RETURNS personname
AS '_OBJWD_/pname'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION pname_out(personname)
RETURNS cstring
AS '_OBJWD_/pname'
LANGUAGE C IMMUTABLE STRICT;
CREATE TYPE personname (
internallength = 12,
input = pname_in,
output = pname_out
);
现在我的代码可以正确响应select "NAME" :: personname;
,并且当我插入和选择时,它可以正确访问除 pname 数组之外的 personname 中的所有参数。
当我输入 select * from users 时,我创建了一个名为 users 的表,其中包含 pname 数组;它显示了这一点:
但是,当我将 personname_in 和 personname_out 代码复制并粘贴到另一个 c 文件中时,将 palloc 替换为 malloc 并使用来自终端的一些输入字符串对其进行测试,它可以打印正确的 pname 值。
有人可以告诉我我在哪里做错了,或者在 PostgreSQL 中使用数组创建新类型的正确方法是什么?
解决方案
该CREATE TYPE
语句与代码不符,varlena
缺少 4 字节标头。
Qoth文档:
虽然新类型的内部表示的细节只有 I/O 函数和您创建以使用该类型的其他函数知道,但内部表示的几个属性必须向 PostgreSQL 声明。其中最重要的是
internallength
. 基本数据类型可以是固定长度的,在这种情况下internallength
是一个正整数或可变长度,通过设置internallength
来表示VARIABLE
。(在内部,这通过设置typlen
为 -1 来表示。)所有可变长度类型的内部表示必须以一个 4 字节整数开头,给出该类型值的总长度。(请注意,长度字段通常是编码的,如第 68.2 节所述;直接访问它是不明智的。)
您必须使用
INTERNALLENGTH = VARIABLE
并且结构必须以 4 字节整数开头。
我没有检查其他错误。
推荐阅读
- angular - 离开页面后 Angular 组件重新加载
- html - HTML + CSS 表单在标题后面滚动但仍然可见
- go - Scanf 值在终端中作为命令执行
- python - 模型运行预测时出错
- node.js - 即使在终端关闭后也保持 webpack dev-server 运行
- css - 为什么 max-width 设置固定元素的宽度?
- mysql - Laravel 让 MySQL 在 Eloquent 模型中查询 Builder 语句
- git - 如何在git中检测新分支是否有提交?
- python - 如何根据熊猫中的另一个值更改数据框中的值?
- django - 如何在 django 中运行脚本 shell