将Postgres自定义类型映射到C结构吗?

问题描述

我正在编写一个自定义的Postgres C AGGREGATE扩展名。我想知道如何正确地将Psql中定义的类型映射到C中定义的结构。我已经尽力做到了,但是我没有得到结果,测试时得到的是空行。 >

C结构具有以下形式:

typedef struct {
    int64_t row_idx;     //Row number in the processing order (NOT thread safe)
    int64_t data1_size;   
    int64_t data2_size;     
    char data2[ 1<<10 ];    
    char data1[ 1<<10 ];    
} search_state;

我不确定获取数据的char指针是否更好,还是如上所述静态分配前端。我已经尝试了两种方法来达到相同的效果。我知道用pmalloc进行分配,以保留对行的调用间的数据。我也尝试过使用postgres类型的“文本”,但在聚合结束时仍然没有数据,结果也没有行。

在Psql方面,我有

CREATE TYPE search_state AS (
    row_idx    int8,data1_size int8,data2_size int8,data1      char[1<<10],data2      char[1<<10]
);

同样,我尝试使用data1或data2的文本类型,但是我不知道如何使它工作。

问题是,如上所述,在psql获取将精确映射到结构的类型的正确方法是什么?看来我的问题出在我在C中修改struct时,postgres无法找到数据。

在聚合过程中将此结构用作中介状态的函数类似于:

 Datum fancy_select(PG_FUNCTION_ARGS){
        //Get the Postgres C-Extension Parameters
        search_state *state   = (search_state * ) PG_GETARG_POINTER(0);
        char *inputText       = PG_GETARG_CSTRING(1);
        uint64_t numeric_id   = PG_GETARG_INT64(2);

        //Make object to store state from Now on.
        search_state *new_state   = (search_state *) palloc( 2*(1<<10) + 8*3 );

        //Small Test updating the state
        new_state->row_idx    = 1;
        new_state->data1[0]   = 'T'
        new_state->data1[1]   = '\0'
        new_state->data2[0]   = 'H'
        new_state->data2[1]   = '\0'
        new_state->data1_size = strlen( new_state->data1 ) ;
        new_state->data2_size = strlen( new_state->data2 ) ;

        //Return state
        PG_RETURN_POINTER( new_state );
   };
}

此聚合有一个最终函数,该函数实际上采用该结构,获取data1,然后返回最后存储在其中的文本。我还应该提到此扩展是在C ++中实现的,而不是纯C语言,但是我使用的是尽可能多的C和尽可能少的C ++。

注意1::使用不同的结构测试行为的范围从return initcond,根本没有行以及以下消息:

ERROR:  type with OID 0 does not exist
CONTEXT:  PL/pgsql function final_func(search_state) while storing call arguments into local variables

解决方法

我可以给你一些建议。

首先,我假设您了解caveats when writing server code in C++

您的数据类型的内部表示可以是任何东西,但是我分配的内存不会超出需要。

内部和外部表示之间的映射完全取决于您,并且由您编写的输入和输出函数的类型决定。

但是我不明白为什么如果要编写的只是聚合函数,为什么需要用C编写的特殊类型。

我只是

CREATE TYPE search_state AS (
   row_idx bigint,data2 text,data1 text
);

,并在您的函数中使用此复合类型。在您的C代码中获取该类型的组件并不难,这将为您省去编写很多样板代码的麻烦。