PostgreSQL C函数中自定义类型的访问数组
我有以下自定义类型:PostgreSQL C函数中自定义类型的访问数组,c,arrays,postgresql,function,postgresql-9.5,C,Arrays,Postgresql,Function,Postgresql 9.5,我有以下自定义类型: CREATE TYPE int2_lo_hi AS ( lo int2, hi int2 ); 我想将它们作为数组(int2\u lo\u hi[])传递给C函数。但是,我不知道访问元素的正确方法 以下是我迄今为止编辑的代码: 标题(不再使用): C: PG_功能_信息_V1(阵列测试); PGMODULEEXPORT基准阵列测试(PG函数参数) { ArrayType*a=PG_GETARG_ArrayType_P(0); 如果(ARR_NDIM(a)>1) {
CREATE TYPE int2_lo_hi AS (
lo int2,
hi int2
);
我想将它们作为数组(int2\u lo\u hi[]
)传递给C函数。但是,我不知道访问元素的正确方法
以下是我迄今为止编辑的代码:
标题(不再使用):
C:
PG_功能_信息_V1(阵列测试);
PGMODULEEXPORT基准阵列测试(PG函数参数)
{
ArrayType*a=PG_GETARG_ArrayType_P(0);
如果(ARR_NDIM(a)>1)
{
ereport(ERROR,(errcode(errcode_数组_下标_ERROR),errmsg(“需要一维数组”));
}
基准*基准;
布尔*空值;
int elemWidth,count;
Oid elemType=ARR_elemType(a);
bool elemTypeByVal,为空;
字符元素编码;
get_typlenbyvalalign(elemType、&elemWidth、&elemTypeByVal、&elemAlignmentCode);
解构_数组(a、elemType、elemWidth、elemTypeByVal、elemAlignmentCode和基准、空值和计数);
int结果=0;
HEAPTLT;
短*字段;
for(int i=0;i
注释掉的部分抛出错误
注意:我得到一个错误,表明OID无效。它的值是28642010,我找不到任何文档参考。在进行了一些小的修复后,此代码可以工作:
PG_FUNCTION_INFO_V1(array_test);
Datum
array_test(PG_FUNCTION_ARGS)
{
ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
Datum *datums;
bool *nulls;
int count;
int16 elemWidth;
Oid elemType = ARR_ELEMTYPE(a);
bool elemTypeByVal, isNull;
char elemAlignmentCode;
int result = 0;
HeapTupleHeader lt;
short field;
if (ARR_NDIM(a) > 1)
ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("1-dimensional array needed")));
get_typlenbyvalalign(elemType, &elemWidth, &elemTypeByVal, &elemAlignmentCode);
deconstruct_array(a, elemType, elemWidth, elemTypeByVal, elemAlignmentCode, &datums, &nulls, &count);
for (int i = 0; i < count; i++)
{
if (nulls[i])
{
result = -result;
}
else
{
lt = DatumGetHeapTupleHeader(datums[i]);
field = DatumGetInt16(GetAttributeByNum(lt, 1, &isNull));
if (!isNull)
result += field;
field = DatumGetInt16(GetAttributeByNum(lt, 2, &isNull));
if (!isNull)
result += field;
}
}
PG_RETURN_INT32(result);
}
PG_功能_信息_V1(阵列测试);
资料
阵列测试(PG函数参数)
{
ArrayType*a=PG_GETARG_ArrayType_P(0);
基准*基准;
布尔*空值;
整数计数;
int16电子宽度;
Oid elemType=ARR_elemType(a);
bool elemTypeByVal,为空;
字符元素编码;
int结果=0;
HEAPTLT;
短场;
如果(ARR_NDIM(a)>1)
ereport(ERROR,(errcode(errcode_数组_下标_ERROR),errmsg(“需要一维数组”));
get_typlenbyvalalign(elemType、&elemWidth、&elemTypeByVal、&elemAlignmentCode);
解构_数组(a、elemType、elemWidth、elemTypeByVal、elemAlignmentCode和基准、空值和计数);
for(int i=0;i
我认为您需要在deconstruct\u array
函数中指定确切的数组元素类型,而不是ANYELEMENTOID
。要确定数组类型,可以使用AARR\u ELEMTYPE
宏。参见我的同事编写的关于如何使用它的示例(见附件),第四个论点可能是,如果您将元素标记为hanks@IldarMusin,则应为false
。我将解构行更改为deconstruct_数组(a,ObjectIdGetDatum(a),4,false,'I',基准,&null,&count)代码>并更改为Int2_lo_hi*elem=palloc(sizeof(Int2_lo_hi))代码>,但这会产生错误(断开服务器连接)。我在你的建议中遗漏了什么吗?如果不研究代码,很难说。我会尝试用gdb
进行调试,看看里面发生了什么。如果你在github或其他地方有回购协议,我可以在今天晚些时候研究。我的意思不是ObjectedAtum
,而是AARR\u ELEMTYPE
。所以它可能是这样的:oidtypeid=AARR_ELEMTYPE(a);解构_数组(a,typeid,4,false,'i',基准,&null,&count)再次感谢,@IIdar Musin
PG_FUNCTION_INFO_V1(array_test);
PGMODULEEXPORT Datum array_test(PG_FUNCTION_ARGS)
{
ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
if (ARR_NDIM(a) > 1)
{
ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("1-dimensional array needed")));
}
Datum *datums;
bool *nulls;
int elemWidth, count;
Oid elemType = ARR_ELEMTYPE(a);
bool elemTypeByVal, isNull;
char elemAlignmentCode;
get_typlenbyvalalign(elemType, &elemWidth, &elemTypeByVal, &elemAlignmentCode);
deconstruct_array(a, elemType, elemWidth, elemTypeByVal, elemAlignmentCode, &datums, &nulls, &count);
int result = 0;
HeapTupleHeader lt;
short *field;
for (int i = 0; i < count; i++)
{
if (nulls[i])
{
result = -result;
}
else
{
lt = DatumGetHeapTupleHeader(datums[i]);
/* field = (short*)GetAttributeByNum(lt, 1, &isNull);
if (!isNull)
{
//result += *field;
}
field = (short*)GetAttributeByNum(lt, 2, &isNull);
if (!isNull)
{
//result += *field;
}*/
}
}
PG_RETURN_INT32(result);
}
PG_FUNCTION_INFO_V1(array_test);
Datum
array_test(PG_FUNCTION_ARGS)
{
ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
Datum *datums;
bool *nulls;
int count;
int16 elemWidth;
Oid elemType = ARR_ELEMTYPE(a);
bool elemTypeByVal, isNull;
char elemAlignmentCode;
int result = 0;
HeapTupleHeader lt;
short field;
if (ARR_NDIM(a) > 1)
ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("1-dimensional array needed")));
get_typlenbyvalalign(elemType, &elemWidth, &elemTypeByVal, &elemAlignmentCode);
deconstruct_array(a, elemType, elemWidth, elemTypeByVal, elemAlignmentCode, &datums, &nulls, &count);
for (int i = 0; i < count; i++)
{
if (nulls[i])
{
result = -result;
}
else
{
lt = DatumGetHeapTupleHeader(datums[i]);
field = DatumGetInt16(GetAttributeByNum(lt, 1, &isNull));
if (!isNull)
result += field;
field = DatumGetInt16(GetAttributeByNum(lt, 2, &isNull));
if (!isNull)
result += field;
}
}
PG_RETURN_INT32(result);
}