in src/hll_sketch_pg_functions.c [66:124]
Datum pg_hll_sketch_build_agg(PG_FUNCTION_ARGS) {
struct hll_agg_state* stateptr;
// anyelement
Oid element_type;
Datum element;
int16 typlen;
bool typbyval;
char typalign;
MemoryContext oldcontext;
MemoryContext aggcontext;
if (PG_ARGISNULL(0) && PG_ARGISNULL(1)) {
PG_RETURN_NULL();
} else if (PG_ARGISNULL(1)) {
PG_RETURN_POINTER(PG_GETARG_POINTER(0)); // no update value. return unmodified state
}
if (!AggCheckCallContext(fcinfo, &aggcontext)) {
elog(ERROR, "hll_sketch_build_agg called in non-aggregate context");
}
oldcontext = MemoryContextSwitchTo(aggcontext);
if (PG_ARGISNULL(0)) {
stateptr = palloc(sizeof(struct hll_agg_state));
stateptr->type = SKETCH;
stateptr->lg_k = PG_NARGS() > 2 ? PG_GETARG_INT32(2) : HLL_DEFAULT_LG_K;
stateptr->tgt_type = PG_NARGS() > 3 ? PG_GETARG_INT32(3) : 0;
if (stateptr->tgt_type) {
if ((stateptr->tgt_type != 4) && (stateptr->tgt_type != 6) && (stateptr->tgt_type != 8)) {
elog(ERROR, "hll_sketch_build_agg: unsupported target type, must be 4, 6 or 8");
}
stateptr->ptr = hll_sketch_new_tgt_type(stateptr->lg_k, stateptr->tgt_type);
} else {
stateptr->ptr = hll_sketch_new(stateptr->lg_k);
}
} else {
stateptr = (struct hll_agg_state*) PG_GETARG_POINTER(0);
}
element_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
element = PG_GETARG_DATUM(1);
get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
if (typlen == -1) {
// varlena
hll_sketch_update(stateptr->ptr, VARDATA_ANY(element), VARSIZE_ANY_EXHDR(element));
} else if (typbyval) {
// fixed-length passed by value
hll_sketch_update(stateptr->ptr, &element, typlen);
} else {
// fixed-length passed by reference
hll_sketch_update(stateptr->ptr, (void*)element, typlen);
}
MemoryContextSwitchTo(oldcontext);
PG_RETURN_POINTER(stateptr);
}