在PostgreSQL C函数中访问自定义类型的数组

时间:2021-09-20 22:56:07

I have the following custom type:

我有以下自定义类型:

CREATE TYPE int2_lo_hi AS (
  lo int2,
  hi int2
);

I want to pass these as an array (int2_lo_hi[]) to a C function. However, I don't know the correct way to access elements.

我想将这些作为数组传递给一个C函数。但是,我不知道访问元素的正确方式。

Here's my code so far, edited:

以下是我迄今为止编辑过的代码:

Header (no longer used):

头(不再使用):

typedef struct
{
    short   lo,
            hi;
} Int2_lo_hi;

C:

C:

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);
}

The part that is commented out is throwing an error.

注释掉的部分是抛出一个错误。

Note: I'm getting an error that indicates that OID is invalid. Its value is 28642010, which I cannot find any documentation reference to.

注意:我得到的错误表明OID是无效的。它的值是28642010,我找不到任何文档参考。

1 个解决方案

#1


4  

After minor fixes this code works:

在小修正之后,这个代码工作:

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);
}

#1


4  

After minor fixes this code works:

在小修正之后,这个代码工作:

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);
}