我的问题是关于PostgreSQL中的C函数,我试图接收2个float4[]
数组作为参数,并返回一个float4[]
数组作为array1+array2的和(表中的列也被设置为float4[],但无法实现:
要创建函数:
CREATE OR REPLACE FUNCTION sum(float4[], float4[]) RETURNS float4[]
AS 'example.so', 'sum'
LANGUAGE C STRICT;
-- 'example.so' is already on /usr/lib/postgresql/9.1/lib
以及C代码:
Datum sumar(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(sumar);
Datum sumar(PG_FUNCTION_ARGS)
{
ArrayType *array1, *array2;
// The array element types:
Oid arrayElementType1, arrayElementType2;
// The array element type widths:
int16 arrayElementTypeWidth1, arrayElementTypeWidth2;
// The array element type:
bool arrayElementTypeByValue1, arrayElementTypeByValue2;
// The array element type alignment codes:
char arrayElementTypeAlignmentCode1, arrayElementTypeAlignmentCode2;
// The array contents, as PostgreSQL "datum" objects:
Datum *arrayContent1, *arrayContent2;
// List of "is null" flags for the array contents:
bool *arrayNullFlags1, *arrayNullFlags2;
// The size of each array:
int arrayLength1, arrayLength2;
Datum *sumContent;
int i;
ArrayType* resultArray;
// Extract the PostgreSQL arrays from the parameters passed to this function call.
array1 = PG_GETARG_ARRAYTYPE_P(0);
array2 = PG_GETARG_ARRAYTYPE_P(1);
// Determine the array element types.
arrayElementType1 = ARR_ELEMTYPE(array1);
get_typlenbyvalalign(arrayElementType1, &arrayElementTypeWidth1, &arrayElementTypeByValue1, &arrayElementTypeAlignmentCode1);
arrayElementType2 = ARR_ELEMTYPE(array2);
get_typlenbyvalalign(arrayElementType2, &arrayElementTypeWidth2, &arrayElementTypeByValue2, &arrayElementTypeAlignmentCode2);
// Extract the array contents (as Datum objects).
deconstruct_array(array1, arrayElementType1, arrayElementTypeWidth1, arrayElementTypeByValue1, arrayElementTypeAlignmentCode1, &arrayContent1, &arrayNullFlags1, &arrayLength1);
deconstruct_array(array2,arrayElementType2, arrayElementTypeWidth2, arrayElementTypeByValue2, arrayElementTypeAlignmentCode2, &arrayContent2, &arrayNullFlags2, &arrayLength2);
//Create a new array of sum results (as Datum objects).
sumContent = (Datum *) palloc(sizeof(Datum) * arrayLength1);
// Generate the sums.
for (i = 0; i < arrayLength1; i++)
{
sumContent[i] = arrayContent1[i] + arrayContent2[i];
}
// Wrap the sums in a new PostgreSQL array object.
resultArray = construct_array(sumContent, arrayLength1, arrayElementType1, arrayElementTypeWidth1, arrayElementTypeByValue1, arrayElementTypeAlignmentCode1);
// Return the final PostgreSQL array object.
PG_RETURN_ARRAYTYPE_P(resultArray);
}
当它在末尾返回数组时,它只显示负值(和是错误的),但是当我传递2个int数组时,它工作得很好。我也试过在求和之前进行值的转换,就像:
sumContent[i] = Float4GetDatum(arrayContent1[i]) + Float4GetDatum(arrayContent2[i];)
和
sumContent[i] = DatumGetFloat4arrayContent1[i]) + DatumGetFloat4(arrayContent2[i]);
但它一直给我奇怪的价值观。
最佳答案
deconstruct_array
之后有一个Datum
值数组,每个值都是一个传递值float4,表示为Datum
。
直接添加Datum
无效-这是一种无法实际执行操作的abtract类型。如果C编译器允许我们这样做,那么PostgreSQL项目将使这成为一个错误,但它不会(或者更确切地说,它不会使其他事情变得更可怕)。
要获得float
类型的float4
的CDatum
,您应该使用DatumGetFloat4
。Float4GetDatum
,正如你所使用的,将是相反的方向。同样,如果C编译器允许我们这样做的话,这个项目也会出错。
(插入关于PostgreSQL社区的恼人抱怨,拒绝移动到C++的一个子集,在这里我们可以使用C++的更严格的类型化规则来做这类事情)。
如果您添加:
elog(LOG, "%f", Float4GetDatum(arrayContent1[i]));
您应该在日志中看到正确的值。
要添加它们并存储所需的结果,请执行以下操作:
sumContent[i] = Float4GetDatum( DatumGetFloat4(arrayContent1[i]) +
DatumGetFloat4(arrayContent2[i]) );