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

时间:2012-01-10 10:55:32

标签: c postgresql shared-libraries postgresql-9.1

Postgresql 9.1.0。 OS 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 functcion。

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

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

我做错了什么以及如何正确地做到了?

1 个答案:

答案 0 :(得分:1)

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

您已将x声明为整数,但尝试将其作为int64读取(PostgreSQL对整数类型使用int4,除非您明确将列指定为int8)。

最后但并非最不重要的是,在调用返回Datums的函数时使用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函数对数据库的访问: http://www.postgresql.org/docs/current/interactive/spi.html