in src/theta_sketch_pg_functions.c [64:120]
Datum pg_theta_sketch_build_agg(PG_FUNCTION_ARGS) {
struct agg_state* stateptr;
float p;
// 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, "theta_sketch_build_agg called in non-aggregate context");
}
oldcontext = MemoryContextSwitchTo(aggcontext);
if (PG_ARGISNULL(0)) {
stateptr = palloc(sizeof(struct agg_state));
stateptr->type = MUTABLE_SKETCH;
stateptr->lg_k = PG_NARGS() > 2 ? PG_GETARG_INT32(2) : 0;
p = PG_NARGS() > 3 ? PG_GETARG_FLOAT4(3) : 0;
if (stateptr->lg_k) {
stateptr->ptr = p ? theta_sketch_new_lgk_p(stateptr->lg_k, p) : theta_sketch_new_lgk(stateptr->lg_k);
} else {
stateptr->ptr = theta_sketch_new_default();
}
} else {
stateptr = (struct 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
theta_sketch_update(stateptr->ptr, VARDATA_ANY(element), VARSIZE_ANY_EXHDR(element));
} else if (typbyval) {
// fixed-length passed by value
theta_sketch_update(stateptr->ptr, &element, typlen);
} else {
// fixed-length passed by reference
theta_sketch_update(stateptr->ptr, (void*)element, typlen);
}
MemoryContextSwitchTo(oldcontext);
PG_RETURN_POINTER(stateptr);
}