From e676d888834ba9b10c1befa1676d1e2b6051eaad Mon Sep 17 00:00:00 2001 From: AlexanderSaydakov Date: Mon, 17 Jun 2019 15:24:05 -0700 Subject: [PATCH] cpc error bounds --- sql/datasketches_cpc_sketch.sql | 8 ++++++++ src/cpc_sketch_c_adapter.cpp | 16 ++++++++++++---- src/cpc_sketch_c_adapter.h | 3 +++ src/cpc_sketch_pg_functions.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/sql/datasketches_cpc_sketch.sql b/sql/datasketches_cpc_sketch.sql index b86453a..4c293e3 100644 --- a/sql/datasketches_cpc_sketch.sql +++ b/sql/datasketches_cpc_sketch.sql @@ -46,6 +46,14 @@ CREATE OR REPLACE FUNCTION cpc_sketch_get_estimate(cpc_sketch) RETURNS double pr AS '$libdir/datasketches', 'pg_cpc_sketch_get_estimate' LANGUAGE C STRICT IMMUTABLE; +CREATE OR REPLACE FUNCTION cpc_sketch_get_estimate_and_bounds(cpc_sketch) RETURNS double precision[] + AS '$libdir/datasketches', 'pg_cpc_sketch_get_estimate_and_bounds' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION cpc_sketch_get_estimate_and_bounds(cpc_sketch, int) RETURNS double precision[] + AS '$libdir/datasketches', 'pg_cpc_sketch_get_estimate_and_bounds' + LANGUAGE C STRICT IMMUTABLE; + CREATE OR REPLACE FUNCTION cpc_sketch_from_internal(internal) RETURNS cpc_sketch AS '$libdir/datasketches', 'pg_cpc_sketch_from_internal' LANGUAGE C STRICT IMMUTABLE; diff --git a/src/cpc_sketch_c_adapter.cpp b/src/cpc_sketch_c_adapter.cpp index 30c7f24..6900380 100644 --- a/src/cpc_sketch_c_adapter.cpp +++ b/src/cpc_sketch_c_adapter.cpp @@ -19,10 +19,6 @@ #include "cpc_sketch_c_adapter.h" -extern "C" { -#include -} - #include #include @@ -62,6 +58,18 @@ double cpc_sketch_get_estimate(const void* sketchptr) { } } +Datum* cpc_sketch_get_estimate_and_bounds(const void* sketchptr, unsigned num_std_devs) { + try { + Datum* est_and_bounds = (Datum*) palloc(sizeof(Datum) * 3); + est_and_bounds[0] = Float8GetDatum(static_cast(sketchptr)->get_estimate()); + est_and_bounds[1] = Float8GetDatum(static_cast(sketchptr)->get_lower_bound(num_std_devs)); + est_and_bounds[2] = Float8GetDatum(static_cast(sketchptr)->get_upper_bound(num_std_devs)); + return est_and_bounds; + } catch (std::exception& e) { + elog(ERROR, e.what()); + } +} + void cpc_sketch_to_string(const void* sketchptr, char* buffer, unsigned length) { try { std::stringstream s; diff --git a/src/cpc_sketch_c_adapter.h b/src/cpc_sketch_c_adapter.h index 47ab68c..962040e 100644 --- a/src/cpc_sketch_c_adapter.h +++ b/src/cpc_sketch_c_adapter.h @@ -24,12 +24,15 @@ extern "C" { #endif +#include + void* cpc_sketch_new(unsigned lg_k); void cpc_sketch_delete(void* sketchptr); void cpc_sketch_update(void* sketchptr, const void* data, unsigned length); void cpc_sketch_merge(void* sketchptr1, const void* sketchptr2); double cpc_sketch_get_estimate(const void* sketchptr); +Datum* cpc_sketch_get_estimate_and_bounds(const void* sketchptr, unsigned num_std_devs); void cpc_sketch_to_string(const void* sketchptr, char* buffer, unsigned length); void* cpc_sketch_serialize(const void* sketchptr); diff --git a/src/cpc_sketch_pg_functions.c b/src/cpc_sketch_pg_functions.c index f37cde8..6edc5d3 100644 --- a/src/cpc_sketch_pg_functions.c +++ b/src/cpc_sketch_pg_functions.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "cpc_sketch_c_adapter.h" #include "base64.h" @@ -30,6 +32,7 @@ const unsigned DEFAULT_LG_K = 11; /* PG_FUNCTION_INFO_V1 macro to pass functions to postgres */ PG_FUNCTION_INFO_V1(pg_cpc_sketch_add_item); PG_FUNCTION_INFO_V1(pg_cpc_sketch_get_estimate); +PG_FUNCTION_INFO_V1(pg_cpc_sketch_get_estimate_and_bounds); PG_FUNCTION_INFO_V1(pg_cpc_sketch_to_string); PG_FUNCTION_INFO_V1(pg_cpc_sketch_union_agg); PG_FUNCTION_INFO_V1(pg_cpc_sketch_from_internal); @@ -42,6 +45,7 @@ Datum pg_cpc_sketch_recv(PG_FUNCTION_ARGS); Datum pg_cpc_sketch_send(PG_FUNCTION_ARGS); Datum pg_cpc_sketch_add_item(PG_FUNCTION_ARGS); Datum pg_cpc_sketch_get_estimate(PG_FUNCTION_ARGS); +Datum pg_cpc_sketch_get_estimate_and_bounds(PG_FUNCTION_ARGS); Datum pg_cpc_sketch_to_string(PG_FUNCTION_ARGS); Datum pg_cpc_sketch_union_agg(PG_FUNCTION_ARGS); Datum pg_cpc_sketch_from_internal(PG_FUNCTION_ARGS); @@ -111,6 +115,31 @@ Datum pg_cpc_sketch_get_estimate(PG_FUNCTION_ARGS) { PG_RETURN_FLOAT8(estimate); } +Datum pg_cpc_sketch_get_estimate_and_bounds(PG_FUNCTION_ARGS) { + const bytea* bytes_in; + void* sketchptr; + int num_std_devs; + + // output array + Datum* est_and_bounds; + ArrayType* arr_out; + int16 elmlen_out; + bool elmbyval_out; + char elmalign_out; + + bytes_in = PG_GETARG_BYTEA_P(0); + sketchptr = cpc_sketch_deserialize(VARDATA(bytes_in), VARSIZE(bytes_in) - VARHDRSZ); + num_std_devs = PG_GETARG_INT32(1); + if (num_std_devs == 0) num_std_devs = 1; // default + est_and_bounds = cpc_sketch_get_estimate_and_bounds(sketchptr, num_std_devs); + cpc_sketch_delete(sketchptr); + + // construct output array + get_typlenbyvalalign(FLOAT8OID, &elmlen_out, &elmbyval_out, &elmalign_out); + arr_out = construct_array(est_and_bounds, 3, FLOAT8OID, elmlen_out, elmbyval_out, elmalign_out); + PG_RETURN_ARRAYTYPE_P(arr_out); +} + Datum pg_cpc_sketch_to_string(PG_FUNCTION_ARGS) { const bytea* bytes_in; void* sketchptr;