Sql C中带嵌套结构的Postgres UDT

Sql C中带嵌套结构的Postgres UDT,sql,c,postgresql,Sql,C,Postgresql,嗨,我正在尝试创建一个用C编写的postgres UDT。它是一种分数类型。 我正在尝试使用结构mixednumber进行实验,其中包含int64和结构分数 #include "postgres.h" #include "fmgr.h" #include <stdbool.h> PG_MODULE_MAGIC; typedef struct Fraction { int64 numerator; int64 denominator; } Fraction; P

嗨,我正在尝试创建一个用C编写的postgres UDT。它是一种分数类型。 我正在尝试使用结构mixednumber进行实验,其中包含int64和结构分数

#include "postgres.h"
#include "fmgr.h"
#include <stdbool.h>

PG_MODULE_MAGIC;

typedef struct Fraction
{
    int64 numerator; 
    int64 denominator;
} Fraction;

PG_FUNCTION_INFO_V1(fraction_in);

Datum
fraction_in(PG_FUNCTION_ARGS)
{
    char *input = PG_GETARG_CSTRING(0);
    int64 n, d;
    bool valid;

    Fraction *result;

    valid = sscanf(input, "(%ld/%ld)", &n, &d) == 2;

    if (!valid)
        ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
             errmsg("invalid input syntax for fraction: \"%s\"", input)));

    if (d == 0) 
        ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                 errmsg("denominator cannot be \"%ld\" in \"%s\"", d, input)));

    result = (Fraction *) palloc(sizeof(Fraction));

    result->numerator    = n;
    result->denominator  = d;

    PG_RETURN_POINTER(result);
}

PG_FUNCTION_INFO_V1(fraction_out);

Datum
fraction_out(PG_FUNCTION_ARGS)
{
    Fraction *fraction = (Fraction *) PG_GETARG_POINTER(0);
    char          *result;

    result = psprintf("(%ld/%ld)", fraction->numerator, fraction->denominator);

    PG_RETURN_CSTRING(result);
}

//////////////////////////////////////
// Mixed Fractions or Mixed Numbers //
//////////////////////////////////////

typedef struct MixedNumber
{
    int64 wholeNumber; 
    Fraction *fraction;
} MixedNumber;

PG_FUNCTION_INFO_V1(mixednumber_in);

Datum
mixednumber_in(PG_FUNCTION_ARGS)
{
    char *input = PG_GETARG_CSTRING(0);
    int64 w, n, d;
    bool valid;

    MixedNumber *mixed;

    valid = sscanf(input, "(%ld+(%ld/%ld))", &w, &n, &d)
            == 3;

    if (!valid)
        ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
             errmsg("invalid input syntax for fraction: \"%s\"", input)));

    if (d == 0) 
        ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                 errmsg("denominator cannot be \"%ld\" in \"%s\"", d, input)));

    mixed    = (MixedNumber *) palloc(sizeof(MixedNumber));

    mixed->wholeNumber           = w;
    mixed->fraction              = (Fraction *) palloc(sizeof(Fraction));
    mixed->fraction->numerator   = n;
    mixed->fraction->denominator = d;

    PG_RETURN_POINTER(mixed);
}

PG_FUNCTION_INFO_V1(mixednumber_out);

Datum
mixednumber_out(PG_FUNCTION_ARGS)
{
    MixedNumber *mixed = (MixedNumber *) PG_GETARG_POINTER(0);

    char *result;

    result = psprintf("(%ld+(%ld/%ld))", 
        mixed->wholeNumber, mixed->fraction->numerator, mixed->fraction->denominator);

    PG_RETURN_CSTRING(result);
}
插入混合数字测试值('(1+(7/8))、('-1+(-7/8))、('(+1+(7/-8))、('(0+(-7/-8))、('-0+(+7/8))、('(2+(7/+8))、('(9+(+7/+8)))、(

结果是:

"(1+(0/0))"
"(-1+(32/4294967952))"
"(1+(94284056329736/16))"
"(0+(94284055669488/128))"
"(0+(0/94284056646312))"
"(2+(524/94284056644432))"
"(9+(94284055669488/16))"

任何专家都能帮助我理解发生了什么吗?

用户数据类型不能包含指针引用的嵌套结构,因为数据(尤其是
MixedNumber
结构中的
分数*
-指针)按“原样”存储(而不是递归地存储它指向的数据)。因此,如果指针在导入保存的值后取消引用,它可能不再包含原始值

您必须提供连续内存块中的所有数据,可能需要将定义更改为

typedef struct MixedNumber {
   int64 wholeNumber; 
   Fraction fraction;
} MixedNumber;
并相应地更改成员访问权限。另外,不要忘记将内部长度放大到现在的24字节(
sizeof(MixedNumber)

"(1+(0/0))"
"(-1+(32/4294967952))"
"(1+(94284056329736/16))"
"(0+(94284055669488/128))"
"(0+(0/94284056646312))"
"(2+(524/94284056644432))"
"(9+(94284055669488/16))"
typedef struct MixedNumber {
   int64 wholeNumber; 
   Fraction fraction;
} MixedNumber;