【发布时间】:2020-09-14 17:05:54
【问题描述】:
我正在编写一个自定义 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 中的结构的类型的正确方法是什么?看来我的问题是由于我在 C 中修改结构时 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: 使用不同的结构进行测试,行为范围从返回 initcond、根本没有行和以下消息:
ERROR: type with OID 0 does not exist
CONTEXT: PL/pgSQL function final_func(search_state) while storing call arguments into local variables
【问题讨论】:
标签: c++ c postgresql postgresql-12