增加多层聚合功能:
注意要点:
(1)如果stype为internal,则prefunc/combinefunc参数和返回值均为internal
(2)sfunc 参数比aggregate参数多一个arg_0(第一个参数),作为内部状态保存并进行计算迭代。
(3)参数为internal的combinefunc必须提供serialfunc/deserialfunc
(4)finalfunc在combinefunc结束后调用一次,对最终结果进行转换
(5)执行逻辑:
多层聚合:sfunc在segment上执行,prefunc/combinefunc在master上执行
单层聚合:sfunc在master上执行
(6)prefunc必须保证context为aggregate
(7)serialfunc/deserialfunc的context为当前内存 context即可
roaringbitmap.sql:
CREATE OR REPLACE FUNCTION rb_or_trans_pre(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME', 'rb_or_trans_pre'
LANGUAGE C IMMUTABLE;
CREATE AGGREGATE rb_or_agg(roaringbitmap)(
SFUNC = rb_or_trans,
PREFUNC = rb_or_trans_pre,
STYPE = internal,
FINALFUNC = rb_serialize,
SERIALFUNC = rb_serialfunc,
DESERIALFUNC = rb_deserialfunc
);
roaringbitmap.c:
//bitmap or trans pre
PG_FUNCTION_INFO_V1(rb_or_trans_pre);
Datum rb_or_trans_pre(PG_FUNCTION_ARGS);
Datum
rb_or_trans_pre(PG_FUNCTION_ARGS)
{
MemoryContext aggctx;
bytea *bb;
roaring_bitmap_t *r1;
roaring_bitmap_t *r2;
// We must be called as a transition routine or we fail.
if (!AggCheckCallContext(fcinfo, &aggctx))
ereport(ERROR,
(errcode(ERRCODE_DATA_EXCEPTION),
errmsg("rb_or_trans_pre outside transition context")));
// Is the first argument a NULL?
if (PG_ARGISNULL(0))
{
r1 = setup_roaringbitmap(aggctx);
}
else
{
r1 = (roaring_bitmap_t *)PG_GETARG_POINTER(0);
}
// Is the second argument non-null?
if (!PG_ARGISNULL(1))
{
r2 = (roaring_bitmap_t *) PG_GETARG_POINTER(1);
if (PG_ARGISNULL(0))
{
r1 = roaring_bitmap_copy(r2);
}
else
{
roaring_bitmap_xor_inplace(r1, r2);
}
roaring_bitmap_free(r2);
}
PG_RETURN_POINTER(r1);
}
Datum rb_serialfunc(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(rb_serialfunc);
Datum
rb_serialfunc(PG_FUNCTION_ARGS)
{
roaring_bitmap_t *r1;
bytea *bb;
bytea *result;
if (PG_ARGISNULL(0))
{
PG_RETURN_NULL();
}else{
r1 = (roaring_bitmap_t *)PG_GETARG_POINTER(0);
if(r1!=NULL){
size_t expectedsize = roaring_bitmap_portable_size_in_bytes(r1);
bytea *serializedbytes = (bytea *)palloc(VARHDRSZ + expectedsize);
roaring_bitmap_portable_serialize(r1, VARDATA(serializedbytes));
roaring_bitmap_free(r1);
SET_VARSIZE(serializedbytes, VARHDRSZ + expectedsize);
PG_RETURN_BYTEA_P(serializedbytes);
}else{
PG_RETURN_NULL();
}
}
}
PG_FUNCTION_INFO_V1(rb_deserialfunc);
Datum rb_deserialfunc(PG_FUNCTION_ARGS);
Datum
rb_deserialfunc(PG_FUNCTION_ARGS)
{
bytea *bb ;
roaring_bitmap_t *r1;
if (PG_ARGISNULL(0))
{
PG_RETURN_NULL();
}else{
bb = PG_GETARG_BYTEA_P(0);
r1 = roaring_bitmap_portable_deserialize(VARDATA(bb));
PG_RETURN_POINTER(r1);
}
}
select * from pg_aggregate where aggfnoid='rb_and_cardinality_agg'::regproc;