如何从插入C触发器的行中获取数据?

如何从插入C触发器的行中获取数据?,c,postgresql,shared-libraries,postgresql-9.1,C,Postgresql,Shared Libraries,Postgresql 9.1,Postgresql 9.1.0。操作系统Ubuntu 11.10。编译器gcc 4.6.1 这是我的桌子: CREATE TABLE ttest ( x integer, str text ) WITH ( OIDS=FALSE ); ALTER TABLE ttest OWNER TO postgres; CREATE TRIGGER tb BEFORE INSERT ON ttest FOR EACH ROW EXECUTE PROCEDURE out_trig(); o

Postgresql 9.1.0。操作系统Ubuntu 11.10。编译器gcc 4.6.1

这是我的桌子:

CREATE TABLE ttest
(
  x integer,
  str text
 )
 WITH (
 OIDS=FALSE
);
ALTER TABLE ttest OWNER TO postgres;

CREATE TRIGGER tb
BEFORE INSERT
ON ttest
FOR EACH ROW
EXECUTE PROCEDURE out_trig();
out_trig是C函数

现在我试图从插入的每一行中获取数据。代码如下:

if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
{
    rettuple = trigdata->tg_trigtuple;
    bool isnull = false;
    uint32 x=rettuple->t_len;
    int64 f;
        f = (int64) GetAttributeByNum(rettuple->t_data, 1, &isnull);//error here
    elog(INFO,"len of tuple: %d",x);
    elog(INFO,"first column being inserted x: %d",f);
 }
我得到错误:记录类型尚未注册

SQL状态:42809

我做错了什么以及如何正确执行?

GetAttributeByNum(或GetAttributeByName)仅适用于基准,而不适用于磁盘元组,请改用heap\u getattr

您已将x声明为整数,但试图将其读取为int64(PostgreSQL将int4用于整数类型,除非您显式地将列指定为int8)

最后但并非最不重要的一点是,在调用返回基准的函数时使用DatumGet[YourType]宏,将值直接转换为所需的类型会破坏可移植性

长短不一,代码应该是这样的:

if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
{
    HeapTuple rettuple = trigdata->tg_trigtuple;
    TupleDesc tupdesc = trigdata->tg_relation->rd_att;
    bool isnull = false;
    uint32 x=rettuple->t_len;
    int32 att = DatumGetInt32(heap_getattr(rettuple, 1, tupdesc, &isnull));
    elog(INFO,"len of tuple: %d",x);
    if (!isnull)
        elog(INFO,"first column being inserted x: %d",att);
    else
        elog(INFO,"first column being inserted x: NULL"); 
 }
您可能还想看看SPI接口,它简化了从用户定义的C函数访问数据库的过程:

GetAttributeByNum(或GetAttributeByName)仅适用于基准,而不适用于磁盘元组,请改用heap_getattr

您已将x声明为整数,但试图将其读取为int64(PostgreSQL将int4用于整数类型,除非您显式地将列指定为int8)

最后但并非最不重要的一点是,在调用返回基准的函数时使用DatumGet[YourType]宏,将值直接转换为所需的类型会破坏可移植性

长短不一,代码应该是这样的:

if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
{
    HeapTuple rettuple = trigdata->tg_trigtuple;
    TupleDesc tupdesc = trigdata->tg_relation->rd_att;
    bool isnull = false;
    uint32 x=rettuple->t_len;
    int32 att = DatumGetInt32(heap_getattr(rettuple, 1, tupdesc, &isnull));
    elog(INFO,"len of tuple: %d",x);
    if (!isnull)
        elog(INFO,"first column being inserted x: %d",att);
    else
        elog(INFO,"first column being inserted x: NULL"); 
 }
您可能还想看看SPI接口,它简化了从用户定义的C函数访问数据库的过程:

您有什么理由必须使用C来触发此触发器吗?您知道抛出错误的是哪一行吗?原因是我想在同一函数中插入新行时通过tcp\ip发送消息。并在带有注释的行中抛出错误。您有任何理由必须使用C作为此触发器吗?您知道抛出错误的是哪一行吗?原因是我想在同一函数中插入新行时通过tcp\ip发送消息。并在注释行中抛出错误。谢谢。已经用SPI完成了,但是你的版本也可以。谢谢。已经用SPI完成了,但是你的版本也可以。