You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by al...@apache.org on 2019/07/03 01:10:01 UTC

[incubator-datasketches-postgresql] branch gcc_4_8_5 created (now e0f508b)

This is an automated email from the ASF dual-hosted git repository.

alsay pushed a change to branch gcc_4_8_5
in repository https://gitbox.apache.org/repos/asf/incubator-datasketches-postgresql.git.


      at e0f508b  GCC 4.8.5 compatibility

This branch includes the following new commits:

     new e0f508b  GCC 4.8.5 compatibility

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org


[incubator-datasketches-postgresql] 01/01: GCC 4.8.5 compatibility

Posted by al...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

alsay pushed a commit to branch gcc_4_8_5
in repository https://gitbox.apache.org/repos/asf/incubator-datasketches-postgresql.git

commit e0f508be73bb6510f5405f4e04ab175ea26c71df
Author: Alexander Saydakov <Al...@users.noreply.github.com>
AuthorDate: Wed Jul 3 00:47:33 2019 +0000

    GCC 4.8.5 compatibility
---
 Makefile                                   |  2 +-
 src/allocator.h                            |  9 +++-
 src/common.c                               | 26 +++++++++-
 src/cpc_sketch_c_adapter.cpp               | 26 +++++-----
 src/frequent_strings_sketch_c_adapter.cpp  | 37 ++++++++------
 src/frequent_strings_sketch_c_adapter.h    |  9 ++--
 src/frequent_strings_sketch_pg_functions.c |  7 +--
 src/hll_sketch_c_adapter.cpp               | 58 ++++++++++++---------
 src/hll_sketch_c_adapter.h                 | 11 ++--
 src/hll_sketch_pg_functions.c              | 24 +++++----
 src/kll_float_sketch_c_adapter.cpp         | 56 ++++++++++++---------
 src/kll_float_sketch_c_adapter.h           | 15 +++---
 src/kll_float_sketch_pg_functions.c        | 12 +++--
 src/postgres_h_substitute.h                | 49 ++++++++++++++++++
 src/theta_sketch_c_adapter.cpp             | 81 +++++++++++++++++-------------
 src/theta_sketch_c_adapter.h               | 11 ++--
 src/theta_sketch_pg_functions.c            | 37 ++++++++------
 17 files changed, 306 insertions(+), 164 deletions(-)

diff --git a/Makefile b/Makefile
index 2d24a99..d5995c8 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ OBJS += $(CPC)/cpc_sketch.o $(CPC)/fm85.o $(CPC)/fm85Compression.o $(CPC)/fm85Co
 
 DATA = sql/datasketches_cpc_sketch.sql sql/datasketches_kll_float_sketch.sql sql/datasketches_theta_sketch.sql sql/datasketches_frequent_strings_sketch.sql sql/datasketches_hll_sketch.sql
 
-PG_CPPFLAGS = -I/usr/local/include -I$(CORE)/kll/include -I$(CORE)/common/include -I$(CORE)/cpc/include -I$(CORE)/theta/include -I$(CORE)/fi/include -I$(CORE)/hll/include
+PG_CPPFLAGS = -std=c++11 -I/usr/local/include -I$(CORE)/kll/include -I$(CORE)/common/include -I$(CORE)/cpc/include -I$(CORE)/theta/include -I$(CORE)/fi/include -I$(CORE)/hll/include
 SHLIB_LINK = -lstdc++ -L/usr/local/lib
 
 PG_CONFIG = pg_config
diff --git a/src/allocator.h b/src/allocator.h
index 4d7ed00..c66a0a9 100644
--- a/src/allocator.h
+++ b/src/allocator.h
@@ -17,8 +17,13 @@
  * under the License.
  */
 
+#ifndef PALLOC_ALLOCATOR_H
+#define PALLOC_ALLOCATOR_H
+
+// these extern declarations are to avoid including postgres.h in C++ code
 extern "C" {
-#include <postgres.h>
+extern void *palloc(unsigned long long size);
+extern void pfree(void *pointer);
 }
 
 #include <new>
@@ -90,3 +95,5 @@ template <class T>
 inline bool operator!=(const palloc_allocator<T>&, const palloc_allocator<T>&) {
   return false;
 }
+
+#endif
diff --git a/src/common.c b/src/common.c
index ffd2838..f9a11f1 100644
--- a/src/common.c
+++ b/src/common.c
@@ -30,6 +30,10 @@ PG_FUNCTION_INFO_V1(pg_sketch_out);
 Datum pg_sketch_in(PG_FUNCTION_ARGS);
 Datum pg_sketch_out(PG_FUNCTION_ARGS);
 
+void pg_error(const char* message);
+Datum pg_float4_get_datum(float x);
+Datum pg_float8_get_datum(double x);
+
 // cstring to type
 Datum pg_sketch_in(PG_FUNCTION_ARGS) {
   // not invoked for nulls
@@ -52,5 +56,25 @@ Datum pg_sketch_out(PG_FUNCTION_ARGS) {
   encoded = palloc(encoded_length + 1);
   b64_encode(VARDATA(bytes), VARSIZE(bytes) - VARHDRSZ, encoded);
   encoded[encoded_length] = '\0';
-  PG_RETURN_CSTRING(encoded); // who should free it?
+  PG_RETURN_CSTRING(encoded);
+}
+
+// These are implementations of redirects defined in postgres_h_substitute.h
+
+Datum pg_float4_get_datum(float x) {
+  return Float4GetDatum(x);
+}
+
+Datum pg_float8_get_datum(double x) {
+  return Float8GetDatum(x);
+}
+
+void pg_error(const char* message) {
+  ereport(
+    ERROR,
+    (
+      errcode(ERRCODE_INTERNAL_ERROR),
+      errmsg("%s", message)
+    )
+  );
 }
diff --git a/src/cpc_sketch_c_adapter.cpp b/src/cpc_sketch_c_adapter.cpp
index 6900380..d6d4520 100644
--- a/src/cpc_sketch_c_adapter.cpp
+++ b/src/cpc_sketch_c_adapter.cpp
@@ -29,7 +29,7 @@ void* cpc_sketch_new(unsigned lg_k) {
     datasketches::cpc_init(&palloc, &pfree);
     return new (palloc(sizeof(datasketches::cpc_sketch))) datasketches::cpc_sketch(lg_k, datasketches::DEFAULT_SEED);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -38,7 +38,7 @@ void cpc_sketch_delete(void* sketchptr) {
     static_cast<datasketches::cpc_sketch*>(sketchptr)->~cpc_sketch();
     pfree(sketchptr);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -46,7 +46,7 @@ void cpc_sketch_update(void* sketchptr, const void* data, unsigned length) {
   try {
     static_cast<datasketches::cpc_sketch*>(sketchptr)->update(data, length);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -54,7 +54,7 @@ double cpc_sketch_get_estimate(const void* sketchptr) {
   try {
     return static_cast<const datasketches::cpc_sketch*>(sketchptr)->get_estimate();
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -66,7 +66,7 @@ Datum* cpc_sketch_get_estimate_and_bounds(const void* sketchptr, unsigned num_st
     est_and_bounds[2] = Float8GetDatum(static_cast<const datasketches::cpc_sketch*>(sketchptr)->get_upper_bound(num_std_devs));
     return est_and_bounds;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -74,9 +74,9 @@ void cpc_sketch_to_string(const void* sketchptr, char* buffer, unsigned length)
   try {
     std::stringstream s;
     s << *(static_cast<const datasketches::cpc_sketch*>(sketchptr));
-    snprintf(buffer, length, s.str().c_str());
+    snprintf(buffer, length, "%s", s.str().c_str());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -88,7 +88,7 @@ void* cpc_sketch_serialize(const void* sketchptr) {
     SET_VARSIZE(buffer, length);
     return buffer;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -98,7 +98,7 @@ void* cpc_sketch_deserialize(const char* buffer, unsigned length) {
     auto ptr = datasketches::cpc_sketch::deserialize(buffer, length, datasketches::DEFAULT_SEED);
     return ptr.release();
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -107,7 +107,7 @@ void* cpc_union_new(unsigned lg_k) {
     datasketches::cpc_init(&palloc, &pfree);
     return new (palloc(sizeof(datasketches::cpc_union))) datasketches::cpc_union(lg_k, datasketches::DEFAULT_SEED);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -116,7 +116,7 @@ void cpc_union_delete(void* unionptr) {
     static_cast<datasketches::cpc_union*>(unionptr)->~cpc_union();
     pfree(unionptr);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -124,7 +124,7 @@ void cpc_union_update(void* unionptr, const void* sketchptr) {
   try {
     static_cast<datasketches::cpc_union*>(unionptr)->update(*static_cast<const datasketches::cpc_sketch*>(sketchptr));
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
 
@@ -133,6 +133,6 @@ void* cpc_union_get_result(void* unionptr) {
     auto ptr = static_cast<datasketches::cpc_union*>(unionptr)->get_result();
     return ptr.release();
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    elog(ERROR, "%s", e.what());
   }
 }
diff --git a/src/frequent_strings_sketch_c_adapter.cpp b/src/frequent_strings_sketch_c_adapter.cpp
index a1c4d4e..c2687d8 100644
--- a/src/frequent_strings_sketch_c_adapter.cpp
+++ b/src/frequent_strings_sketch_c_adapter.cpp
@@ -19,6 +19,7 @@
 
 #include "frequent_strings_sketch_c_adapter.h"
 #include "allocator.h"
+#include "postgres_h_substitute.h"
 
 #include <string>
 #include <sstream>
@@ -90,8 +91,9 @@ void* frequent_strings_sketch_new(unsigned lg_k) {
   try {
     return new (palloc(sizeof(frequent_strings_sketch))) frequent_strings_sketch(lg_k);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void frequent_strings_sketch_delete(void* sketchptr) {
@@ -99,7 +101,7 @@ void frequent_strings_sketch_delete(void* sketchptr) {
     static_cast<frequent_strings_sketch*>(sketchptr)->~frequent_strings_sketch();
     pfree(sketchptr);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -107,7 +109,7 @@ void frequent_strings_sketch_update(void* sketchptr, const char* str, unsigned l
   try {
     static_cast<frequent_strings_sketch*>(sketchptr)->update(string(str, length), weight);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -115,7 +117,7 @@ void frequent_strings_sketch_merge(void* sketchptr1, const void* sketchptr2) {
   try {
     static_cast<frequent_strings_sketch*>(sketchptr1)->merge(*static_cast<const frequent_strings_sketch*>(sketchptr2));
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -128,20 +130,22 @@ char* frequent_strings_sketch_to_string(const void* sketchptr, bool print_items)
     strncpy(buffer, s.str().c_str(), len);
     return buffer;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
-void* frequent_strings_sketch_serialize(const void* sketchptr) {
+ptr_with_size frequent_strings_sketch_serialize(const void* sketchptr, unsigned header_size) {
   try {
-    auto data = static_cast<const frequent_strings_sketch*>(sketchptr)->serialize(VARHDRSZ);
-    bytea* buffer = (bytea*) data.first.release();
-    const size_t length = data.second;
-    SET_VARSIZE(buffer, length);
-    return buffer;
+    ptr_with_size p;
+    auto data = static_cast<const frequent_strings_sketch*>(sketchptr)->serialize(header_size);
+    p.ptr = data.first.release();
+    p.size = data.second;
+    return p;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* frequent_strings_sketch_deserialize(const char* buffer, unsigned length) {
@@ -150,16 +154,18 @@ void* frequent_strings_sketch_deserialize(const char* buffer, unsigned length) {
       frequent_strings_sketch(frequent_strings_sketch::deserialize(buffer, length));
     return sketchptr;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 unsigned frequent_strings_sketch_get_serialized_size_bytes(const void* sketchptr) {
   try {
     return static_cast<const frequent_strings_sketch*>(sketchptr)->get_serialized_size_bytes();
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 frequent_strings_sketch_result* frequent_strings_sketch_get_frequent_items(void* sketchptr, bool no_false_positives, unsigned long long threshold) {
@@ -184,6 +190,7 @@ frequent_strings_sketch_result* frequent_strings_sketch_get_frequent_items(void*
     result->num = data.size();
     return result;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
diff --git a/src/frequent_strings_sketch_c_adapter.h b/src/frequent_strings_sketch_c_adapter.h
index 549c21d..ab0fd3b 100644
--- a/src/frequent_strings_sketch_c_adapter.h
+++ b/src/frequent_strings_sketch_c_adapter.h
@@ -24,8 +24,6 @@
 extern "C" {
 #endif
 
-#include <postgres.h>
-
 void* frequent_strings_sketch_new(unsigned lg_k);
 void frequent_strings_sketch_delete(void* sketchptr);
 
@@ -33,7 +31,12 @@ void frequent_strings_sketch_update(void* sketchptr, const char* str, unsigned l
 void frequent_strings_sketch_merge(void* sketchptr1, const void* sketchptr2);
 char* frequent_strings_sketch_to_string(const void* sketchptr, bool print_items);
 
-void* frequent_strings_sketch_serialize(const void* sketchptr);
+struct ptr_with_size {
+  void* ptr;
+  unsigned long long size;
+};
+
+struct ptr_with_size frequent_strings_sketch_serialize(const void* sketchptr, unsigned header_size);
 void* frequent_strings_sketch_deserialize(const char* buffer, unsigned length);
 unsigned frequent_strings_sketch_get_serialized_size_bytes(const void* sketchptr);
 
diff --git a/src/frequent_strings_sketch_pg_functions.c b/src/frequent_strings_sketch_pg_functions.c
index c9c44ac..dced821 100644
--- a/src/frequent_strings_sketch_pg_functions.c
+++ b/src/frequent_strings_sketch_pg_functions.c
@@ -131,16 +131,17 @@ Datum pg_frequent_strings_sketch_merge(PG_FUNCTION_ARGS) {
 
 Datum pg_frequent_strings_sketch_from_internal(PG_FUNCTION_ARGS) {
   void* sketchptr;
-  bytea* bytes_out;
+  struct ptr_with_size bytes_out;
   MemoryContext aggcontext;
   if (PG_ARGISNULL(0)) PG_RETURN_NULL();
   if (!AggCheckCallContext(fcinfo, &aggcontext)) {
     elog(ERROR, "frequent_strings_sketch_from_internal called in non-aggregate context");
   }
   sketchptr = PG_GETARG_POINTER(0);
-  bytes_out = frequent_strings_sketch_serialize(sketchptr);
+  bytes_out = frequent_strings_sketch_serialize(sketchptr, VARHDRSZ);
   frequent_strings_sketch_delete(sketchptr);
-  PG_RETURN_BYTEA_P(bytes_out);
+  SET_VARSIZE(bytes_out.ptr, bytes_out.size);
+  PG_RETURN_BYTEA_P(bytes_out.ptr);
 }
 
 Datum pg_frequent_strings_sketch_to_string(PG_FUNCTION_ARGS) {
diff --git a/src/hll_sketch_c_adapter.cpp b/src/hll_sketch_c_adapter.cpp
index 53320f9..b830099 100644
--- a/src/hll_sketch_c_adapter.cpp
+++ b/src/hll_sketch_c_adapter.cpp
@@ -19,6 +19,7 @@
 
 #include "hll_sketch_c_adapter.h"
 #include "allocator.h"
+#include "postgres_h_substitute.h"
 
 #include <sstream>
 
@@ -31,8 +32,9 @@ void* hll_sketch_new(unsigned lg_k) {
   try {
     return new (palloc(sizeof(hll_sketch))) hll_sketch(lg_k);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* hll_sketch_new_tgt_type(unsigned lg_k, unsigned tgt_type) {
@@ -42,8 +44,9 @@ void* hll_sketch_new_tgt_type(unsigned lg_k, unsigned tgt_type) {
       tgt_type == 4 ? datasketches::TgtHllType::HLL_4 : tgt_type == 6 ? datasketches::TgtHllType::HLL_6 : datasketches::TgtHllType::HLL_8
     );
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void hll_sketch_delete(void* sketchptr) {
@@ -51,7 +54,7 @@ void hll_sketch_delete(void* sketchptr) {
     static_cast<hll_sketch*>(sketchptr)->~hll_sketch();
     pfree(sketchptr);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -59,7 +62,7 @@ void hll_sketch_update(void* sketchptr, const void* data, unsigned length) {
   try {
     static_cast<hll_sketch*>(sketchptr)->update(data, length);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -67,42 +70,45 @@ double hll_sketch_get_estimate(const void* sketchptr) {
   try {
     return static_cast<const hll_sketch*>(sketchptr)->getEstimate();
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 Datum* hll_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<const hll_sketch*>(sketchptr)->getEstimate());
-    est_and_bounds[1] = Float8GetDatum(static_cast<const hll_sketch*>(sketchptr)->getLowerBound(num_std_devs));
-    est_and_bounds[2] = Float8GetDatum(static_cast<const hll_sketch*>(sketchptr)->getUpperBound(num_std_devs));
+    est_and_bounds[0] = pg_float8_get_datum(static_cast<const hll_sketch*>(sketchptr)->getEstimate());
+    est_and_bounds[1] = pg_float8_get_datum(static_cast<const hll_sketch*>(sketchptr)->getLowerBound(num_std_devs));
+    est_and_bounds[2] = pg_float8_get_datum(static_cast<const hll_sketch*>(sketchptr)->getUpperBound(num_std_devs));
     return est_and_bounds;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void hll_sketch_to_string(const void* sketchptr, char* buffer, unsigned length) {
   try {
     std::stringstream s;
     static_cast<const hll_sketch*>(sketchptr)->to_string(s);
-    snprintf(buffer, length, s.str().c_str());
+    snprintf(buffer, length, "%s", s.str().c_str());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
-void* hll_sketch_serialize(const void* sketchptr) {
+ptr_with_size hll_sketch_serialize(const void* sketchptr, unsigned header_size) {
   try {
-    auto data = static_cast<const hll_sketch*>(sketchptr)->serializeCompact(VARHDRSZ);
-    bytea* buffer = (bytea*) data.first.release();
-    const size_t length = data.second;
-    SET_VARSIZE(buffer, length);
-    return buffer;
+    ptr_with_size p;
+    auto data = static_cast<const hll_sketch*>(sketchptr)->serializeCompact(header_size);
+    p.ptr = data.first.release();
+    p.size = data.second;
+    return p;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* hll_sketch_deserialize(const char* buffer, unsigned length) {
@@ -110,16 +116,18 @@ void* hll_sketch_deserialize(const char* buffer, unsigned length) {
     hll_sketch* sketchptr = new (palloc(sizeof(hll_sketch))) hll_sketch(hll_sketch::deserialize(buffer, length));
     return sketchptr;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* hll_union_new(unsigned lg_k) {
   try {
     return new (palloc(sizeof(hll_union))) hll_union(lg_k);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void hll_union_delete(void* unionptr) {
@@ -127,7 +135,7 @@ void hll_union_delete(void* unionptr) {
     static_cast<hll_union*>(unionptr)->~hll_union();
     pfree(unionptr);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -135,7 +143,7 @@ void hll_union_update(void* unionptr, const void* sketchptr) {
   try {
     static_cast<hll_union*>(unionptr)->update(*static_cast<const hll_sketch*>(sketchptr));
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -143,8 +151,9 @@ void* hll_union_get_result(void* unionptr) {
   try {
     return new (palloc(sizeof(hll_sketch))) hll_sketch(static_cast<hll_union*>(unionptr)->getResult());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* hll_union_get_result_tgt_type(void* unionptr, unsigned tgt_type) {
@@ -153,6 +162,7 @@ void* hll_union_get_result_tgt_type(void* unionptr, unsigned tgt_type) {
       tgt_type == 4 ? datasketches::TgtHllType::HLL_4 : tgt_type == 6 ? datasketches::TgtHllType::HLL_6 : datasketches::TgtHllType::HLL_8
     ));
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
diff --git a/src/hll_sketch_c_adapter.h b/src/hll_sketch_c_adapter.h
index 1f291a1..394fab2 100644
--- a/src/hll_sketch_c_adapter.h
+++ b/src/hll_sketch_c_adapter.h
@@ -24,8 +24,6 @@
 extern "C" {
 #endif
 
-#include <postgres.h>
-
 void* hll_sketch_new(unsigned lg_k);
 void* hll_sketch_new_tgt_type(unsigned lg_k, unsigned tgt_type);
 void hll_sketch_delete(void* sketchptr);
@@ -33,10 +31,15 @@ void hll_sketch_delete(void* sketchptr);
 void hll_sketch_update(void* sketchptr, const void* data, unsigned length);
 void hll_sketch_merge(void* sketchptr1, const void* sketchptr2);
 double hll_sketch_get_estimate(const void* sketchptr);
-Datum* hll_sketch_get_estimate_and_bounds(const void* sketchptr, unsigned num_std_devs);
+void** hll_sketch_get_estimate_and_bounds(const void* sketchptr, unsigned num_std_devs);
 void hll_sketch_to_string(const void* sketchptr, char* buffer, unsigned length);
 
-void* hll_sketch_serialize(const void* sketchptr);
+struct ptr_with_size {
+  void* ptr;
+  unsigned long long size;
+};
+
+struct ptr_with_size hll_sketch_serialize(const void* sketchptr, unsigned header_size);
 void* hll_sketch_deserialize(const char* buffer, unsigned length);
 
 void* hll_union_new(unsigned lg_k);
diff --git a/src/hll_sketch_pg_functions.c b/src/hll_sketch_pg_functions.c
index 59cdbe2..8cea03b 100644
--- a/src/hll_sketch_pg_functions.c
+++ b/src/hll_sketch_pg_functions.c
@@ -141,7 +141,7 @@ Datum pg_hll_sketch_get_estimate_and_bounds(PG_FUNCTION_ARGS) {
   sketchptr = hll_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 = hll_sketch_get_estimate_and_bounds(sketchptr, num_std_devs);
+  est_and_bounds = (Datum*) hll_sketch_get_estimate_and_bounds(sketchptr, num_std_devs);
   hll_sketch_delete(sketchptr);
 
   // construct output array
@@ -212,7 +212,7 @@ Datum pg_hll_sketch_union_agg(PG_FUNCTION_ARGS) {
 
 Datum pg_hll_sketch_from_internal(PG_FUNCTION_ARGS) {
   void* sketchptr;
-  bytea* bytes_out;
+  struct ptr_with_size bytes_out;
 
   MemoryContext oldcontext;
   MemoryContext aggcontext;
@@ -225,12 +225,13 @@ Datum pg_hll_sketch_from_internal(PG_FUNCTION_ARGS) {
   oldcontext = MemoryContextSwitchTo(aggcontext);
 
   sketchptr = PG_GETARG_POINTER(0);
-  bytes_out = hll_sketch_serialize(sketchptr);
+  bytes_out = hll_sketch_serialize(sketchptr, VARHDRSZ);
   hll_sketch_delete(sketchptr);
+  SET_VARSIZE(bytes_out.ptr, bytes_out.size);
 
   MemoryContextSwitchTo(oldcontext);
 
-  PG_RETURN_BYTEA_P(bytes_out);
+  PG_RETURN_BYTEA_P(bytes_out.ptr);
 }
 
 Datum pg_hll_sketch_get_estimate_from_internal(PG_FUNCTION_ARGS) {
@@ -259,7 +260,7 @@ Datum pg_hll_sketch_get_estimate_from_internal(PG_FUNCTION_ARGS) {
 Datum pg_hll_union_get_result(PG_FUNCTION_ARGS) {
   struct hll_union_state* stateptr;
   void* sketchptr;
-  bytea* bytes_out;
+  struct ptr_with_size bytes_out;
 
   MemoryContext oldcontext;
   MemoryContext aggcontext;
@@ -277,14 +278,15 @@ Datum pg_hll_union_get_result(PG_FUNCTION_ARGS) {
   } else {
     sketchptr = hll_union_get_result(stateptr->unionptr);
   }
-  bytes_out = hll_sketch_serialize(sketchptr);
+  bytes_out = hll_sketch_serialize(sketchptr, VARHDRSZ);
   hll_sketch_delete(sketchptr);
   hll_union_delete(stateptr->unionptr);
   pfree(stateptr);
+  SET_VARSIZE(bytes_out.ptr, bytes_out.size);
 
   MemoryContextSwitchTo(oldcontext);
 
-  PG_RETURN_BYTEA_P(bytes_out);
+  PG_RETURN_BYTEA_P(bytes_out.ptr);
 }
 
 Datum pg_hll_sketch_union(PG_FUNCTION_ARGS) {
@@ -294,7 +296,7 @@ Datum pg_hll_sketch_union(PG_FUNCTION_ARGS) {
   void* sketchptr2;
   void* unionptr;
   void* sketchptr;
-  bytea* bytes_out;
+  struct ptr_with_size bytes_out;
   unsigned lg_k;
   unsigned tgt_type;
 
@@ -324,7 +326,9 @@ Datum pg_hll_sketch_union(PG_FUNCTION_ARGS) {
     sketchptr = hll_union_get_result(unionptr);
   }
   hll_union_delete(unionptr);
-  bytes_out = hll_sketch_serialize(sketchptr);
+  bytes_out = hll_sketch_serialize(sketchptr, VARHDRSZ);
   hll_sketch_delete(sketchptr);
-  PG_RETURN_BYTEA_P(bytes_out);
+  SET_VARSIZE(bytes_out.ptr, bytes_out.size);
+  
+  PG_RETURN_BYTEA_P(bytes_out.ptr);
 }
diff --git a/src/kll_float_sketch_c_adapter.cpp b/src/kll_float_sketch_c_adapter.cpp
index 5285882..c9db67c 100644
--- a/src/kll_float_sketch_c_adapter.cpp
+++ b/src/kll_float_sketch_c_adapter.cpp
@@ -19,6 +19,7 @@
 
 #include "kll_float_sketch_c_adapter.h"
 #include "allocator.h"
+#include "postgres_h_substitute.h"
 
 #include <sstream>
 
@@ -30,8 +31,9 @@ void* kll_float_sketch_new(unsigned k) {
   try {
     return new (palloc(sizeof(kll_float_sketch))) kll_float_sketch(k);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void kll_float_sketch_delete(void* sketchptr) {
@@ -39,7 +41,7 @@ void kll_float_sketch_delete(void* sketchptr) {
     static_cast<kll_float_sketch*>(sketchptr)->~kll_float_sketch();
     pfree(sketchptr);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -47,7 +49,7 @@ void kll_float_sketch_update(void* sketchptr, float value) {
   try {
     static_cast<kll_float_sketch*>(sketchptr)->update(value);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -55,7 +57,7 @@ void kll_float_sketch_merge(void* sketchptr1, const void* sketchptr2) {
   try {
     static_cast<kll_float_sketch*>(sketchptr1)->merge(*static_cast<const kll_float_sketch*>(sketchptr2));
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -63,62 +65,68 @@ double kll_float_sketch_get_rank(const void* sketchptr, float value) {
   try {
     return static_cast<const kll_float_sketch*>(sketchptr)->get_rank(value);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 float kll_float_sketch_get_quantile(const void* sketchptr, double rank) {
   try {
     return static_cast<const kll_float_sketch*>(sketchptr)->get_quantile(rank);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
-uint64 kll_float_sketch_get_n(const void* sketchptr) {
+unsigned long long kll_float_sketch_get_n(const void* sketchptr) {
   try {
     return static_cast<const kll_float_sketch*>(sketchptr)->get_n();
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void kll_float_sketch_to_string(const void* sketchptr, char* buffer, unsigned length) {
   try {
     std::stringstream s;
     static_cast<const kll_float_sketch*>(sketchptr)->to_stream(s);
-    snprintf(buffer, length, s.str().c_str());
+    snprintf(buffer, length, "%s", s.str().c_str());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
-void* kll_float_sketch_serialize(const void* sketchptr) {
+ptr_with_size kll_float_sketch_serialize(const void* sketchptr, unsigned header_size) {
   try {
-    auto data = static_cast<const kll_float_sketch*>(sketchptr)->serialize(VARHDRSZ);
-    bytea* buffer = (bytea*) data.first.release();
-    const size_t length = data.second;
-    SET_VARSIZE(buffer, length);
-    return buffer;
+    ptr_with_size p;
+    auto data = static_cast<const kll_float_sketch*>(sketchptr)->serialize(header_size);
+    p.ptr = data.first.release();
+    p.size = data.second;
+    return p;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* kll_float_sketch_deserialize(const char* buffer, unsigned length) {
   try {
     return new (palloc(sizeof(kll_float_sketch))) kll_float_sketch(kll_float_sketch::deserialize(buffer, length));
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 unsigned kll_float_sketch_get_serialized_size_bytes(const void* sketchptr) {
   try {
     return static_cast<const kll_float_sketch*>(sketchptr)->get_serialized_size_bytes();
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 Datum* kll_float_sketch_get_pmf(const void* sketchptr, const float* split_points, unsigned num_split_points) {
@@ -126,12 +134,13 @@ Datum* kll_float_sketch_get_pmf(const void* sketchptr, const float* split_points
     auto ptr = static_cast<const kll_float_sketch*>(sketchptr)->get_PMF(split_points, num_split_points);
     Datum* pmf = (Datum*) palloc(sizeof(Datum) * (num_split_points + 1));
     for (unsigned i = 0; i < num_split_points + 1; i++) {
-      pmf[i] = Float8GetDatum(ptr[i]);
+      pmf[i] = pg_float8_get_datum(ptr[i]);
     }
     return pmf;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 Datum* kll_float_sketch_get_quantiles(const void* sketchptr, const double* fractions, unsigned num_fractions) {
@@ -139,10 +148,11 @@ Datum* kll_float_sketch_get_quantiles(const void* sketchptr, const double* fract
     auto ptr = static_cast<const kll_float_sketch*>(sketchptr)->get_quantiles(fractions, num_fractions);
     Datum* quantiles = (Datum*) palloc(sizeof(Datum) * num_fractions);
     for (unsigned i = 0; i < num_fractions; i++) {
-      quantiles[i] = Float4GetDatum(ptr[i]);
+      quantiles[i] = pg_float4_get_datum(ptr[i]);
     }
     return quantiles;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
diff --git a/src/kll_float_sketch_c_adapter.h b/src/kll_float_sketch_c_adapter.h
index eb573a5..9aefc91 100644
--- a/src/kll_float_sketch_c_adapter.h
+++ b/src/kll_float_sketch_c_adapter.h
@@ -24,8 +24,6 @@
 extern "C" {
 #endif
 
-#include <postgres.h>
-
 void* kll_float_sketch_new(unsigned k);
 void kll_float_sketch_delete(void* sketchptr);
 
@@ -33,15 +31,20 @@ void kll_float_sketch_update(void* sketchptr, float value);
 void kll_float_sketch_merge(void* sketchptr1, const void* sketchptr2);
 double kll_float_sketch_get_rank(const void* sketchptr, float value);
 float kll_float_sketch_get_quantile(const void* sketchptr, double rank);
-uint64 kll_float_sketch_get_n(const void* sketchptr);
+unsigned long long kll_float_sketch_get_n(const void* sketchptr);
 void kll_float_sketch_to_string(const void* sketchptr, char* buffer, unsigned length);
 
-void* kll_float_sketch_serialize(const void* sketchptr);
+struct ptr_with_size {
+  void* ptr;
+  unsigned long long size;
+};
+
+struct ptr_with_size kll_float_sketch_serialize(const void* sketchptr, unsigned header_size);
 void* kll_float_sketch_deserialize(const char* buffer, unsigned length);
 unsigned kll_float_sketch_get_serialized_size_bytes(const void* sketchptr);
 
-Datum* kll_float_sketch_get_pmf(const void* sketchptr, const float* split_points, unsigned num_split_points);
-Datum* kll_float_sketch_get_quantiles(const void* sketchptr, const double* fractions, unsigned num_fractions);
+void** kll_float_sketch_get_pmf(const void* sketchptr, const float* split_points, unsigned num_split_points);
+void** kll_float_sketch_get_quantiles(const void* sketchptr, const double* fractions, unsigned num_fractions);
 
 #ifdef __cplusplus
 }
diff --git a/src/kll_float_sketch_pg_functions.c b/src/kll_float_sketch_pg_functions.c
index 5ed3f4d..3284bb4 100644
--- a/src/kll_float_sketch_pg_functions.c
+++ b/src/kll_float_sketch_pg_functions.c
@@ -174,16 +174,18 @@ Datum pg_kll_float_sketch_merge(PG_FUNCTION_ARGS) {
 
 Datum pg_kll_float_sketch_from_internal(PG_FUNCTION_ARGS) {
   void* sketchptr;
-  bytea* bytes_out;
+  struct ptr_with_size bytes_out;
   MemoryContext aggcontext;
+
   if (PG_ARGISNULL(0)) PG_RETURN_NULL();
   if (!AggCheckCallContext(fcinfo, &aggcontext)) {
     elog(ERROR, "kll_float_sketch_from_internal called in non-aggregate context");
   }
   sketchptr = PG_GETARG_POINTER(0);
-  bytes_out = kll_float_sketch_serialize(sketchptr);
+  bytes_out = kll_float_sketch_serialize(sketchptr, VARHDRSZ);
   kll_float_sketch_delete(sketchptr);
-  PG_RETURN_BYTEA_P(bytes_out);
+  SET_VARSIZE(bytes_out.ptr, bytes_out.size);
+  PG_RETURN_BYTEA_P(bytes_out.ptr);
 }
 
 Datum pg_kll_float_sketch_get_pmf(PG_FUNCTION_ARGS) {
@@ -223,7 +225,7 @@ Datum pg_kll_float_sketch_get_pmf(PG_FUNCTION_ARGS) {
   for (i = 0; i < arr_len_in; i++) {
     split_points[i] = DatumGetFloat4(data_in[i]);
   }
-  pmf = kll_float_sketch_get_pmf(sketchptr, split_points, arr_len_in);
+  pmf = (Datum*) kll_float_sketch_get_pmf(sketchptr, split_points, arr_len_in);
   pfree(split_points);
 
   // construct output array of fractions
@@ -272,7 +274,7 @@ Datum pg_kll_float_sketch_get_quantiles(PG_FUNCTION_ARGS) {
   for (i = 0; i < arr_len; i++) {
     fractions[i] = DatumGetFloat8(data_in[i]);
   }
-  quantiles = kll_float_sketch_get_quantiles(sketchptr, fractions, arr_len);
+  quantiles = (Datum*) kll_float_sketch_get_quantiles(sketchptr, fractions, arr_len);
   pfree(fractions);
 
   // construct output array of quantiles
diff --git a/src/postgres_h_substitute.h b/src/postgres_h_substitute.h
new file mode 100644
index 0000000..b3aa320
--- /dev/null
+++ b/src/postgres_h_substitute.h
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// There is some problem compiling C++ code using GCC 4.8.5 (standard on current RHEL)
+// with postgres.h included. This is to avoid including postgres.h
+
+#ifndef POSTGRES_H_SUBSTITUTE
+#define POSTGRES_H_SUBSTITUTE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* Datum;
+extern Datum pg_float4_get_datum(float x);
+extern Datum pg_float8_get_datum(double x);
+
+extern void pg_error(const char* message);
+
+// from postgresql c.h to hint compiler and avoid warnings
+#if defined(HAVE__BUILTIN_UNREACHABLE) && !defined(USE_ASSERT_CHECKING)
+#define pg_unreachable() __builtin_unreachable()
+#elif defined(_MSC_VER) && !defined(USE_ASSERT_CHECKING)
+#define pg_unreachable() __assume(0)
+#else
+#define pg_unreachable() abort()
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/theta_sketch_c_adapter.cpp b/src/theta_sketch_c_adapter.cpp
index 120dc62..4056759 100644
--- a/src/theta_sketch_c_adapter.cpp
+++ b/src/theta_sketch_c_adapter.cpp
@@ -19,10 +19,7 @@
 
 #include "theta_sketch_c_adapter.h"
 #include "allocator.h"
-
-extern "C" {
-#include <postgres.h>
-}
+#include "postgres_h_substitute.h"
 
 #include <sstream>
 
@@ -42,24 +39,27 @@ void* theta_sketch_new_default() {
   try {
     return new (palloc(sizeof(update_theta_sketch_pg))) update_theta_sketch_pg(update_theta_sketch_pg::builder().build());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* theta_sketch_new_lgk(unsigned lg_k) {
   try {
     return new (palloc(sizeof(update_theta_sketch_pg))) update_theta_sketch_pg(update_theta_sketch_pg::builder().set_lg_k(lg_k).build());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* theta_sketch_new_lgk_p(unsigned lg_k, float p) {
   try {
     return new (palloc(sizeof(update_theta_sketch_pg))) update_theta_sketch_pg(update_theta_sketch_pg::builder().set_lg_k(lg_k).set_p(p).build());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void theta_sketch_delete(void* sketchptr) {
@@ -67,7 +67,7 @@ void theta_sketch_delete(void* sketchptr) {
     static_cast<theta_sketch_pg*>(sketchptr)->~theta_sketch_pg();
     pfree(sketchptr);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -75,7 +75,7 @@ void theta_sketch_update(void* sketchptr, const void* data, unsigned length) {
   try {
     static_cast<update_theta_sketch_pg*>(sketchptr)->update(data, length);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -86,50 +86,54 @@ void* theta_sketch_compact(void* sketchptr) {
     pfree(sketchptr);
     return newptr;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 double theta_sketch_get_estimate(const void* sketchptr) {
   try {
     return static_cast<const theta_sketch_pg*>(sketchptr)->get_estimate();
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 Datum* theta_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<const theta_sketch_pg*>(sketchptr)->get_estimate());
-    est_and_bounds[1] = Float8GetDatum(static_cast<const theta_sketch_pg*>(sketchptr)->get_lower_bound(num_std_devs));
-    est_and_bounds[2] = Float8GetDatum(static_cast<const theta_sketch_pg*>(sketchptr)->get_upper_bound(num_std_devs));
+    est_and_bounds[0] = pg_float8_get_datum(static_cast<const theta_sketch_pg*>(sketchptr)->get_estimate());
+    est_and_bounds[1] = pg_float8_get_datum(static_cast<const theta_sketch_pg*>(sketchptr)->get_lower_bound(num_std_devs));
+    est_and_bounds[2] = pg_float8_get_datum(static_cast<const theta_sketch_pg*>(sketchptr)->get_upper_bound(num_std_devs));
     return est_and_bounds;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void theta_sketch_to_string(const void* sketchptr, char* buffer, unsigned length) {
   try {
     std::stringstream s;
     static_cast<const theta_sketch_pg*>(sketchptr)->to_stream(s);
-    snprintf(buffer, length, s.str().c_str());
+    snprintf(buffer, length, "%s", s.str().c_str());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
-void* theta_sketch_serialize(const void* sketchptr) {
+ptr_with_size theta_sketch_serialize(const void* sketchptr, unsigned header_size) {
   try {
-    auto data = static_cast<const theta_sketch_pg*>(sketchptr)->serialize(VARHDRSZ);
-    bytea* buffer = (bytea*) data.first.release();
-    const size_t length = data.second;
-    SET_VARSIZE(buffer, length);
-    return buffer;
+    ptr_with_size p;
+    auto data = static_cast<const theta_sketch_pg*>(sketchptr)->serialize(header_size);
+    p.ptr = data.first.release();
+    p.size = data.second;
+    return p;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* theta_sketch_deserialize(const char* buffer, unsigned length) {
@@ -137,24 +141,27 @@ void* theta_sketch_deserialize(const char* buffer, unsigned length) {
     auto ptr = theta_sketch_pg::deserialize(buffer, length);
     return ptr.release();
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* theta_union_new_default() {
   try {
     return new (palloc(sizeof(theta_union_pg))) theta_union_pg(theta_union_pg::builder().build());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* theta_union_new(unsigned lg_k) {
   try {
     return new (palloc(sizeof(theta_union_pg))) theta_union_pg(theta_union_pg::builder().set_lg_k(lg_k).build());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void theta_union_delete(void* unionptr) {
@@ -162,7 +169,7 @@ void theta_union_delete(void* unionptr) {
     static_cast<theta_union_pg*>(unionptr)->~theta_union_pg();
     pfree(unionptr);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -170,7 +177,7 @@ void theta_union_update(void* unionptr, const void* sketchptr) {
   try {
     static_cast<theta_union_pg*>(unionptr)->update(*static_cast<const theta_sketch_pg*>(sketchptr));
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -178,16 +185,18 @@ void* theta_union_get_result(const void* unionptr) {
   try {
     return new (palloc(sizeof(compact_theta_sketch_pg))) compact_theta_sketch_pg(static_cast<const theta_union_pg*>(unionptr)->get_result());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* theta_intersection_new_default() {
   try {
     return new (palloc(sizeof(theta_intersection_pg))) theta_intersection_pg;
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void theta_intersection_delete(void* interptr) {
@@ -195,7 +204,7 @@ void theta_intersection_delete(void* interptr) {
     static_cast<theta_intersection_pg*>(interptr)->~theta_intersection_pg();
     pfree(interptr);
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -203,7 +212,7 @@ void theta_intersection_update(void* interptr, const void* sketchptr) {
   try {
     static_cast<theta_intersection_pg*>(interptr)->update(*static_cast<const theta_sketch_pg*>(sketchptr));
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
 }
 
@@ -211,8 +220,9 @@ void* theta_intersection_get_result(const void* interptr) {
   try {
     return new (palloc(sizeof(compact_theta_sketch_pg))) compact_theta_sketch_pg(static_cast<const theta_intersection_pg*>(interptr)->get_result());
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
 
 void* theta_a_not_b(const void* sketchptr1, const void* sketchptr2) {
@@ -223,6 +233,7 @@ void* theta_a_not_b(const void* sketchptr1, const void* sketchptr2) {
       *static_cast<const theta_sketch_pg*>(sketchptr2)
     ));
   } catch (std::exception& e) {
-    elog(ERROR, e.what());
+    pg_error(e.what());
   }
+  pg_unreachable();
 }
diff --git a/src/theta_sketch_c_adapter.h b/src/theta_sketch_c_adapter.h
index 1cc1d5b..4a411d9 100644
--- a/src/theta_sketch_c_adapter.h
+++ b/src/theta_sketch_c_adapter.h
@@ -24,8 +24,6 @@
 extern "C" {
 #endif
 
-#include <postgres.h>
-
 void* theta_sketch_new_default();
 void* theta_sketch_new_lgk(unsigned lg_k);
 void* theta_sketch_new_lgk_p(unsigned lg_k, float p);
@@ -35,10 +33,15 @@ void theta_sketch_update(void* sketchptr, const void* data, unsigned length);
 void* theta_sketch_compact(void* sketchptr);
 void theta_sketch_union(void* sketchptr1, const void* sketchptr2);
 double theta_sketch_get_estimate(const void* sketchptr);
-Datum* theta_sketch_get_estimate_and_bounds(const void* sketchptr, unsigned num_std_devs);
+void** theta_sketch_get_estimate_and_bounds(const void* sketchptr, unsigned num_std_devs);
 void theta_sketch_to_string(const void* sketchptr, char* buffer, unsigned length);
 
-void* theta_sketch_serialize(const void* sketchptr);
+struct ptr_with_size {
+  void* ptr;
+  unsigned long long size;
+};
+
+struct ptr_with_size theta_sketch_serialize(const void* sketchptr, unsigned header_size);
 void* theta_sketch_deserialize(const char* buffer, unsigned length);
 
 void* theta_union_new_default();
diff --git a/src/theta_sketch_pg_functions.c b/src/theta_sketch_pg_functions.c
index feb2583..ff99d7b 100644
--- a/src/theta_sketch_pg_functions.c
+++ b/src/theta_sketch_pg_functions.c
@@ -139,7 +139,7 @@ Datum pg_theta_sketch_get_estimate_and_bounds(PG_FUNCTION_ARGS) {
   sketchptr = theta_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 = theta_sketch_get_estimate_and_bounds(sketchptr, num_std_devs);
+  est_and_bounds = (Datum*) theta_sketch_get_estimate_and_bounds(sketchptr, num_std_devs);
   theta_sketch_delete(sketchptr);
 
   // construct output array
@@ -198,7 +198,7 @@ Datum pg_theta_sketch_union_agg(PG_FUNCTION_ARGS) {
 
 Datum pg_theta_sketch_from_internal(PG_FUNCTION_ARGS) {
   void* sketchptr;
-  bytea* bytes_out;
+  struct ptr_with_size bytes_out;
 
   MemoryContext oldcontext;
   MemoryContext aggcontext;
@@ -212,12 +212,13 @@ Datum pg_theta_sketch_from_internal(PG_FUNCTION_ARGS) {
 
   sketchptr = PG_GETARG_POINTER(0);
   sketchptr = theta_sketch_compact(sketchptr);
-  bytes_out = theta_sketch_serialize(sketchptr);
+  bytes_out = theta_sketch_serialize(sketchptr, VARHDRSZ);
   theta_sketch_delete(sketchptr);
+  SET_VARSIZE(bytes_out.ptr, bytes_out.size);
 
   MemoryContextSwitchTo(oldcontext);
 
-  PG_RETURN_BYTEA_P(bytes_out);
+  PG_RETURN_BYTEA_P(bytes_out.ptr);
 }
 
 Datum pg_theta_sketch_get_estimate_from_internal(PG_FUNCTION_ARGS) {
@@ -246,7 +247,7 @@ Datum pg_theta_sketch_get_estimate_from_internal(PG_FUNCTION_ARGS) {
 Datum pg_theta_union_get_result(PG_FUNCTION_ARGS) {
   void* unionptr;
   void* sketchptr;
-  bytea* bytes_out;
+  struct ptr_with_size bytes_out;
 
   MemoryContext oldcontext;
   MemoryContext aggcontext;
@@ -260,13 +261,14 @@ Datum pg_theta_union_get_result(PG_FUNCTION_ARGS) {
 
   unionptr = PG_GETARG_POINTER(0);
   sketchptr = theta_union_get_result(unionptr);
-  bytes_out = theta_sketch_serialize(sketchptr);
+  bytes_out = theta_sketch_serialize(sketchptr, VARHDRSZ);
   theta_sketch_delete(sketchptr);
   theta_union_delete(unionptr);
+  SET_VARSIZE(bytes_out.ptr, bytes_out.size);
 
   MemoryContextSwitchTo(oldcontext);
 
-  PG_RETURN_BYTEA_P(bytes_out);
+  PG_RETURN_BYTEA_P(bytes_out.ptr);
 }
 
 Datum pg_theta_sketch_union(PG_FUNCTION_ARGS) {
@@ -276,7 +278,7 @@ Datum pg_theta_sketch_union(PG_FUNCTION_ARGS) {
   void* sketchptr2;
   void* unionptr;
   void* sketchptr;
-  bytea* bytes_out;
+  struct ptr_with_size bytes_out;
   int lg_k;
   
   lg_k = PG_GETARG_INT32(2);
@@ -295,9 +297,10 @@ Datum pg_theta_sketch_union(PG_FUNCTION_ARGS) {
   }
   sketchptr = theta_union_get_result(unionptr);
   theta_union_delete(unionptr);
-  bytes_out = theta_sketch_serialize(sketchptr);
+  bytes_out = theta_sketch_serialize(sketchptr, VARHDRSZ);
   theta_sketch_delete(sketchptr);
-  PG_RETURN_BYTEA_P(bytes_out);
+  SET_VARSIZE(bytes_out.ptr, bytes_out.size);
+  PG_RETURN_BYTEA_P(bytes_out.ptr);
 }
 
 Datum pg_theta_sketch_intersection(PG_FUNCTION_ARGS) {
@@ -307,7 +310,7 @@ Datum pg_theta_sketch_intersection(PG_FUNCTION_ARGS) {
   void* sketchptr2;
   void* interptr;
   void* sketchptr;
-  bytea* bytes_out;
+  struct ptr_with_size bytes_out;
   
   interptr = theta_intersection_new_default();
   if (!PG_ARGISNULL(0)) {
@@ -324,9 +327,10 @@ Datum pg_theta_sketch_intersection(PG_FUNCTION_ARGS) {
   }
   sketchptr = theta_intersection_get_result(interptr);
   theta_intersection_delete(interptr);
-  bytes_out = theta_sketch_serialize(sketchptr);
+  bytes_out = theta_sketch_serialize(sketchptr, VARHDRSZ);
   theta_sketch_delete(sketchptr);
-  PG_RETURN_BYTEA_P(bytes_out);
+  SET_VARSIZE(bytes_out.ptr, bytes_out.size);
+  PG_RETURN_BYTEA_P(bytes_out.ptr);
 }
 
 Datum pg_theta_sketch_a_not_b(PG_FUNCTION_ARGS) {
@@ -335,7 +339,7 @@ Datum pg_theta_sketch_a_not_b(PG_FUNCTION_ARGS) {
   void* sketchptr1;
   void* sketchptr2;
   void* sketchptr;
-  bytea* bytes_out;
+  struct ptr_with_size bytes_out;
 
   if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) {
     elog(ERROR, "theta_a_not_b expects two valid theta sketches");
@@ -348,7 +352,8 @@ Datum pg_theta_sketch_a_not_b(PG_FUNCTION_ARGS) {
   sketchptr = theta_a_not_b(sketchptr1, sketchptr2);
   theta_sketch_delete(sketchptr1);
   theta_sketch_delete(sketchptr2);
-  bytes_out = theta_sketch_serialize(sketchptr);
+  bytes_out = theta_sketch_serialize(sketchptr, VARHDRSZ);
   theta_sketch_delete(sketchptr);
-  PG_RETURN_BYTEA_P(bytes_out);
+  SET_VARSIZE(bytes_out.ptr, bytes_out.size);
+  PG_RETURN_BYTEA_P(bytes_out.ptr);
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org