我想用C语言在postgres中创建用户自定义聚合。下面是我的代码。
sql代码:
CREATE FUNCTION res_tras_crimes_c(state_c, int64)
RETURNS state_c
AS 'MODULE_PATHNAME', 'res_tras_crimes'
LANGUAGE C
IMMUTABLE
PARALLEL SAFE;
CREATE FUNCTION finalize_trans_crimes_c(state_c)
RETURNS ArrayType
AS 'MODULE_PATHNAME'
LANGUAGE C
IMMUTABLE
PARALLEL SAFE;
CREATE AGGREGATE reservoir_sampling_c(int64)
(
sfunc = res_tras_crimes,
stype = state_c,
FINALFUNC = finalize_trans_crimes,
);
对于C代码:
typedef struct state_c
{
int64 *reservoir;
int32 poscnt;
int32 reservoir_size;
} state_c;
PG_FUNCTION_INFO_V1(res_tras);
Datum
res_tras(PG_FUNCTION_ARGS)
{
//state_c *d1 = malloc(sizeof(state_c));
//struct state_c st;
// st = (state_c *)PG_GETARG_DATUM(0);
struct state_c *st = (state_c *)PG_GETARG_POINTER(0);
int64 newsample = PG_GETARG_INT64(1);
if(st == NULL) {
int64 r[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int64 *a = r;
st->poscnt = 1;
st->reservoir_size = 100;
st->reservoir = a;
}
if(st->poscnt <= st->reservoir_size){
int32 p = st->poscnt;
*(st->reservoir+p-1) = newsample;
st->poscnt ++;
}else{
int32 pos = rand() % st->poscnt ; //0 - postcnt -1
if(pos < st->reservoir_size){
*(st->reservoir+pos) = newsample;
}
st->poscnt ++;
}
PG_RETURN_POINTER(st);
}
PG_FUNCTION_INFO_V1(finalize_trans);
Datum
finalize_trans_(PG_FUNCTION_ARGS)
{
struct state_c *st = (state_c *) PG_GETARG_POINTER(0);
PG_RETURN_ARRAYTYPE_P(st->reservoir);
}
我可以在转换函数中传递我的结构体指针吗?我想在最终函数中返回ARRAYTYPE。我不知道如何处理它。你能帮助我吗?谢谢!
我想知道如何在postgres中处理c语言中的数组类型和结构
1条答案
按热度按时间nc1teljy1#
我没有运行你的代码,但原则上应该可以,你可以使用
internal
作为CREATE AGGREGATE
中的STYPE
,并作为状态转换函数的第一个参数。您可以查看PostgreSQL源代码中的示例:
array_agg
使用internal
作为STYPE
,您可以查看src/backend/utils/adt/array_userfuncs.c
中状态转换函数array_agg_array_transfn
的定义。