#include "roaringbitmap.h" /* Created by ZEROMAX on 2017/3/20.*/ #define MAX_BITMAP_RANGE_END UINT64_C(0x100000000) #define INT4_MIN -2147483648 #define INT4_MAX 2147483647 /* GUC variables */ typedef enum { RBITMAP_OUTPUT_ARRAY, /* output as int array */ RBITMAP_OUTPUT_BYTEA /* output as bytea */ }RBITMAPOutputFormat; static const struct config_enum_entry output_format_options[] = { {"array", RBITMAP_OUTPUT_ARRAY, false}, {"bytea", RBITMAP_OUTPUT_BYTEA, false}, {NULL, 0, false} }; static int rbitmap_output_format; /* output format */ void _PG_init(void); /* * Module load callback */ void _PG_init(void) { /* Define custom GUC variables. */ DefineCustomEnumVariable("roaringbitmap.output_format", "Selects output format of roaringbitmap.", NULL, &rbitmap_output_format, RBITMAP_OUTPUT_BYTEA, output_format_options, PGC_USERSET, 0, NULL, NULL, NULL); } bool ArrayContainsNulls(ArrayType *array) { int nelems; bits8 *bitmap; int bitmask; /* Easy answer if there's no null bitmap */ if (!ARR_HASNULL(array)) return false; nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); bitmap = ARR_NULLBITMAP(array); /* check whole bytes of the bitmap byte-at-a-time */ while (nelems >= 8) { if (*bitmap != 0xFF) return true; bitmap++; nelems -= 8; } /* check last partial byte */ bitmask = 1; while (nelems > 0) { if ((*bitmap & bitmask) == 0) return true; bitmask <<= 1; nelems--; } return false; } //rb_from_bytea Datum rb_from_bytea(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(rb_from_bytea); Datum rb_from_bytea(PG_FUNCTION_ARGS) { bytea *serializedbytes = PG_GETARG_BYTEA_P(0); roaring_bitmap_t *r1; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); roaring_bitmap_free(r1); PG_RETURN_BYTEA_P(serializedbytes); } //roaringbitmap_in Datum roaringbitmap_in(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(roaringbitmap_in); Datum roaringbitmap_in(PG_FUNCTION_ARGS) { char *ptr = PG_GETARG_CSTRING(0); long l; char *badp; roaring_bitmap_t *r1; size_t expectedsize; bytea *serializedbytes; Datum dd; if(*ptr == '\\' && *(ptr+1) == 'x') { /* bytea input */ dd = DirectFunctionCall1(byteain, PG_GETARG_DATUM(0)); serializedbytes = DatumGetByteaP(dd); r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); roaring_bitmap_free(r1); return dd; } /* else int array input */ /* Find the head char '{' */ while (*ptr && isspace((unsigned char) *ptr)) ptr++; if (*ptr !='{') ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("malformed bitmap literal"))); ptr++; r1 = roaring_bitmap_create(); while (*ptr && isspace((unsigned char) *ptr)) ptr++; if (*ptr != '}') { while (*ptr) { /* Parse int element */ errno = 0; l = strtol(ptr, &badp, 10); /* We made no progress parsing the string, so bail out */ if (ptr == badp){ roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for %s: \"%s\"", "integer", ptr))); } if (errno == ERANGE || l < INT4_MIN || l > INT4_MAX ){ roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("value \"%s\" is out of range for type %s", ptr, "integer"))); } /* Add int element to bitmap */ roaring_bitmap_add(r1, l); /* Skip any trailing whitespace after the int element */ ptr = badp; while (*ptr && isspace((unsigned char) *ptr)) ptr++; /* Find the element terminator ',' */ if (*ptr != ',') break; ptr++; /* Skip any trailing whitespace after the terminator */ while (*ptr && isspace((unsigned char) *ptr)) ptr++; } /* Find the tail char '{' */ if (*ptr !='}'){ roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("malformed bitmap literal"))); } } /* Check if input end */ ptr++; while (*ptr && isspace((unsigned char) *ptr)) ptr++; if (*ptr !='\0'){ roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("malformed bitmap literal"))); } expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //roaringbitmap_out Datum roaringbitmap_out(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(roaringbitmap_out); Datum roaringbitmap_out(PG_FUNCTION_ARGS) { bytea *serializedbytes; roaring_uint32_iterator_t iterator; StringInfoData buf; roaring_bitmap_t *r1; if(rbitmap_output_format == RBITMAP_OUTPUT_BYTEA){ return DirectFunctionCall1(byteaout, PG_GETARG_DATUM(0)); } serializedbytes = PG_GETARG_BYTEA_P(0); r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); initStringInfo(&buf); appendStringInfoChar(&buf, '{'); roaring_init_iterator(r1, &iterator); if(iterator.has_value) { appendStringInfo(&buf, "%d", (int)iterator.current_value); roaring_advance_uint32_iterator(&iterator); while(iterator.has_value) { appendStringInfo(&buf, ",%d", (int)iterator.current_value); roaring_advance_uint32_iterator(&iterator); } } appendStringInfoChar(&buf, '}'); PG_RETURN_CSTRING(buf.data); } //roaringbitmap_recv Datum roaringbitmap_recv(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(roaringbitmap_recv); Datum roaringbitmap_recv(PG_FUNCTION_ARGS) { return DirectFunctionCall1(bytearecv, PG_GETARG_DATUM(0)); } //roaringbitmap_send Datum roaringbitmap_send(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(roaringbitmap_send); Datum roaringbitmap_send(PG_FUNCTION_ARGS) { bytea *bp = PG_GETARG_BYTEA_P(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendbytes(&buf, VARDATA(bp), VARSIZE(bp) - VARHDRSZ); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); } //bitmap_or PG_FUNCTION_INFO_V1(rb_or); Datum rb_or(PG_FUNCTION_ARGS); Datum rb_or(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; size_t expectedsize; bytea *serializedbytes; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } roaring_bitmap_or_inplace(r1, r2); roaring_bitmap_free(r2); expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap_or_cardinality PG_FUNCTION_INFO_V1(rb_or_cardinality); Datum rb_or_cardinality(PG_FUNCTION_ARGS); Datum rb_or_cardinality(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; uint64 card1; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } card1 = roaring_bitmap_or_cardinality(r1, r2); roaring_bitmap_free(r1); roaring_bitmap_free(r2); PG_RETURN_INT64(card1); } //bitmap_and PG_FUNCTION_INFO_V1(rb_and); Datum rb_and(PG_FUNCTION_ARGS); Datum rb_and(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; size_t expectedsize; bytea *serializedbytes; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } roaring_bitmap_and_inplace(r1, r2); roaring_bitmap_free(r2); expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap_and_cardinality PG_FUNCTION_INFO_V1(rb_and_cardinality); Datum rb_and_cardinality(PG_FUNCTION_ARGS); Datum rb_and_cardinality(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; uint64 card1; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } card1 = roaring_bitmap_and_cardinality(r1, r2); roaring_bitmap_free(r1); roaring_bitmap_free(r2); PG_RETURN_INT64(card1); } //bitmap_andnot PG_FUNCTION_INFO_V1(rb_andnot); Datum rb_andnot(PG_FUNCTION_ARGS); Datum rb_andnot(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; size_t expectedsize; bytea *serializedbytes; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } roaring_bitmap_andnot_inplace(r1, r2); roaring_bitmap_free(r2); expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap_andnot_cardinality PG_FUNCTION_INFO_V1(rb_andnot_cardinality); Datum rb_andnot_cardinality(PG_FUNCTION_ARGS); Datum rb_andnot_cardinality(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; uint64 card1; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } card1 = roaring_bitmap_andnot_cardinality(r1, r2); roaring_bitmap_free(r1); roaring_bitmap_free(r2); PG_RETURN_INT64(card1); } //bitmap_xor PG_FUNCTION_INFO_V1(rb_xor); Datum rb_xor(PG_FUNCTION_ARGS); Datum rb_xor(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; size_t expectedsize; bytea *serializedbytes; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } roaring_bitmap_xor_inplace(r1, r2); roaring_bitmap_free(r2); expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap_xor_cardinality PG_FUNCTION_INFO_V1(rb_xor_cardinality); Datum rb_xor_cardinality(PG_FUNCTION_ARGS); Datum rb_xor_cardinality(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; uint64 card1; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } card1 = roaring_bitmap_xor_cardinality(r1, r2); roaring_bitmap_free(r1); roaring_bitmap_free(r2); PG_RETURN_INT64(card1); } //bitmap cardinality PG_FUNCTION_INFO_V1(rb_cardinality); Datum rb_cardinality(PG_FUNCTION_ARGS); Datum rb_cardinality(PG_FUNCTION_ARGS) { bytea *data = PG_GETARG_BYTEA_P(0); roaring_bitmap_t *r1; uint64 card1; r1 = roaring_bitmap_portable_deserialize(VARDATA(data)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); card1 = roaring_bitmap_get_cardinality(r1); roaring_bitmap_free(r1); PG_RETURN_INT64(card1); } //bitmap is empty PG_FUNCTION_INFO_V1(rb_is_empty); Datum rb_is_empty(PG_FUNCTION_ARGS); Datum rb_is_empty(PG_FUNCTION_ARGS) { bytea *data = PG_GETARG_BYTEA_P(0); roaring_bitmap_t *r1; bool isempty; r1 = roaring_bitmap_portable_deserialize(VARDATA(data)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); isempty = roaring_bitmap_is_empty(r1); roaring_bitmap_free(r1); PG_RETURN_BOOL(isempty); } //bitmap is empty PG_FUNCTION_INFO_V1(rb_exsit); Datum rb_exsit(PG_FUNCTION_ARGS); Datum rb_exsit(PG_FUNCTION_ARGS) { bytea *data = PG_GETARG_BYTEA_P(0); uint32 value = PG_GETARG_UINT32(1); roaring_bitmap_t *r1; bool isexsit; r1 = roaring_bitmap_portable_deserialize(VARDATA(data)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); isexsit = roaring_bitmap_contains(r1, value); roaring_bitmap_free(r1); PG_RETURN_BOOL(isexsit); } //bitmap equals PG_FUNCTION_INFO_V1(rb_equals); Datum rb_equals(PG_FUNCTION_ARGS); Datum rb_equals(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; bool isequal; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } isequal = roaring_bitmap_equals(r1, r2); roaring_bitmap_free(r1); roaring_bitmap_free(r2); PG_RETURN_BOOL(isequal); } //bitmap not equals PG_FUNCTION_INFO_V1(rb_not_equals); Datum rb_not_equals(PG_FUNCTION_ARGS); Datum rb_not_equals(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; bool isequal; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } isequal = roaring_bitmap_equals(r1, r2); roaring_bitmap_free(r1); roaring_bitmap_free(r2); PG_RETURN_BOOL(!isequal); } //bitmap intersect PG_FUNCTION_INFO_V1(rb_intersect); Datum rb_intersect(PG_FUNCTION_ARGS); Datum rb_intersect(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; bool isintersect; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } isintersect = roaring_bitmap_intersect(r1, r2); roaring_bitmap_free(r1); roaring_bitmap_free(r2); PG_RETURN_BOOL(isintersect); } //bitmap contains PG_FUNCTION_INFO_V1(rb_contains); Datum rb_contains(PG_FUNCTION_ARGS); Datum rb_contains(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; bool iscontain; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } roaring_bitmap_and_inplace(r1, r2); iscontain = roaring_bitmap_equals(r1, r2); roaring_bitmap_free(r1); roaring_bitmap_free(r2); PG_RETURN_BOOL(iscontain); } //bitmap contained PG_FUNCTION_INFO_V1(rb_containedby); Datum rb_containedby(PG_FUNCTION_ARGS); Datum rb_containedby(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; bool iscontained; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } roaring_bitmap_and_inplace(r2, r1); iscontained = roaring_bitmap_equals(r2, r1); roaring_bitmap_free(r1); roaring_bitmap_free(r2); PG_RETURN_BOOL(iscontained); } //bitmap jaccard distance PG_FUNCTION_INFO_V1(rb_jaccard_dist); Datum rb_jaccard_dist(PG_FUNCTION_ARGS); Datum rb_jaccard_dist(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); bytea *serializedbytes2 = PG_GETARG_BYTEA_P(1); roaring_bitmap_t *r1; roaring_bitmap_t *r2; double jaccard_dist; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes2)); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); } jaccard_dist = roaring_bitmap_jaccard_index(r1, r2); roaring_bitmap_free(r1); roaring_bitmap_free(r2); PG_RETURN_FLOAT8(jaccard_dist); } //bitmap add PG_FUNCTION_INFO_V1(rb_add); Datum rb_add(PG_FUNCTION_ARGS); Datum rb_add(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); uint32 value = PG_GETARG_UINT32(1); size_t expectedsize; bytea *serializedbytes; roaring_bitmap_t *r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); roaring_bitmap_add(r1, value); expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap remove PG_FUNCTION_INFO_V1(rb_remove); Datum rb_remove(PG_FUNCTION_ARGS); Datum rb_remove(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); uint32 value = PG_GETARG_UINT32(1); size_t expectedsize; bytea *serializedbytes; roaring_bitmap_t *r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); roaring_bitmap_remove(r1, value); expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap index PG_FUNCTION_INFO_V1(rb_index); Datum rb_index(PG_FUNCTION_ARGS); Datum rb_index(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); uint32 value = PG_GETARG_UINT32(1); int64 index; roaring_bitmap_t *r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); if(roaring_bitmap_contains(r1, value)) { index = (int64) roaring_bitmap_rank(r1,value) - 1; }else { index = -1; } roaring_bitmap_free(r1); PG_RETURN_INT64(index); } //bitmap fill PG_FUNCTION_INFO_V1(rb_fill); Datum rb_fill(PG_FUNCTION_ARGS); Datum rb_fill(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); int64 rangestart = PG_GETARG_INT64(1); int64 rangeend = PG_GETARG_INT64(2); roaring_bitmap_t *r1; roaring_bitmap_t *r2; size_t expectedsize; bytea *serializedbytes; if (rangestart < 0) rangestart = 0; if (rangeend < 0) rangeend = 0; if (rangeend > MAX_BITMAP_RANGE_END) { rangeend = MAX_BITMAP_RANGE_END; } r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); if (rangestart < rangeend) { r2 = roaring_bitmap_from_range(rangestart, rangeend, 1); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("failed to create bitmap"))); } roaring_bitmap_or_inplace(r1, r2); roaring_bitmap_free(r2); } expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap clear PG_FUNCTION_INFO_V1(rb_clear); Datum rb_clear(PG_FUNCTION_ARGS); Datum rb_clear(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); int64 rangestart = PG_GETARG_INT64(1); int64 rangeend = PG_GETARG_INT64(2); roaring_bitmap_t *r1; roaring_bitmap_t *r2; size_t expectedsize; bytea *serializedbytes; if (rangestart < 0) rangestart = 0; if (rangeend < 0) rangeend = 0; if (rangeend > MAX_BITMAP_RANGE_END) { rangeend = MAX_BITMAP_RANGE_END; } r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); if (rangestart < rangeend) { r2 = roaring_bitmap_from_range(rangestart, rangeend, 1); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("failed to create bitmap"))); } roaring_bitmap_andnot_inplace(r1, r2); roaring_bitmap_free(r2); } expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap flip PG_FUNCTION_INFO_V1(rb_flip); Datum rb_flip(PG_FUNCTION_ARGS); Datum rb_flip(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); int64 rangestart = PG_GETARG_INT64(1); int64 rangeend = PG_GETARG_INT64(2); roaring_bitmap_t *r1; size_t expectedsize; bytea *serializedbytes; if (rangestart < 0) rangestart = 0; if (rangeend < 0) rangeend = 0; if (rangeend > MAX_BITMAP_RANGE_END) { rangeend = MAX_BITMAP_RANGE_END; } r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); if (rangestart < rangeend) { roaring_bitmap_flip_inplace(r1, rangestart, rangeend); } expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap shiftright PG_FUNCTION_INFO_V1(rb_shiftright); Datum rb_shiftright(PG_FUNCTION_ARGS); Datum rb_shiftright(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); int64 distance = PG_GETARG_INT64(1); uint64 value; roaring_bitmap_t *r1; roaring_bitmap_t *r2; roaring_uint32_iterator_t iterator; size_t expectedsize; bytea *serializedbytes; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); if(distance != 0) { r2 = roaring_bitmap_create(); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("failed to create bitmap"))); } roaring_init_iterator(r1, &iterator); if(distance > 0){ while(iterator.has_value) { value = iterator.current_value + distance; if(value < 0 || value >= MAX_BITMAP_RANGE_END) break; roaring_bitmap_add(r2, (uint32)value); roaring_advance_uint32_iterator(&iterator); } }else{ roaring_move_uint32_iterator_equalorlarger(&iterator, -distance); while(iterator.has_value) { value = iterator.current_value + distance; if(value < 0 || value >= MAX_BITMAP_RANGE_END) break; roaring_bitmap_add(r2, (uint32)value); roaring_advance_uint32_iterator(&iterator); } } roaring_bitmap_free(r1); r1 = r2; } expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap range PG_FUNCTION_INFO_V1(rb_range); Datum rb_range(PG_FUNCTION_ARGS); Datum rb_range(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); int64 rangestart = PG_GETARG_INT64(1); int64 rangeend = PG_GETARG_INT64(2); roaring_bitmap_t *r1; roaring_bitmap_t *r2; roaring_uint32_iterator_t iterator; size_t expectedsize; bytea *serializedbytes; if (rangestart < 0) rangestart = 0; if (rangeend < 0) rangeend = 0; if (rangeend > MAX_BITMAP_RANGE_END) { rangeend = MAX_BITMAP_RANGE_END; } r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_create(); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("failed to create bitmap"))); } roaring_init_iterator(r1, &iterator); roaring_move_uint32_iterator_equalorlarger(&iterator, rangestart); while(iterator.has_value) { if(iterator.current_value >= rangeend) break; roaring_bitmap_add(r2, iterator.current_value); roaring_advance_uint32_iterator(&iterator); } expectedsize = roaring_bitmap_portable_size_in_bytes(r2); serializedbytes = (bytea *) palloc(VARHDRSZ + expectedsize); roaring_bitmap_portable_serialize(r2, VARDATA(serializedbytes)); roaring_bitmap_free(r1); roaring_bitmap_free(r2); SET_VARSIZE(serializedbytes, VARHDRSZ + expectedsize); PG_RETURN_BYTEA_P(serializedbytes); } //bitmap range_cardinality PG_FUNCTION_INFO_V1(rb_range_cardinality); Datum rb_range_cardinality(PG_FUNCTION_ARGS); Datum rb_range_cardinality(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); int64 rangestart = PG_GETARG_INT64(1); int64 rangeend = PG_GETARG_INT64(2); roaring_bitmap_t *r1; roaring_uint32_iterator_t iterator; uint64 card1; if (rangestart < 0) rangestart = 0; if (rangeend < 0) rangeend = 0; if (rangeend > MAX_BITMAP_RANGE_END) { rangeend = MAX_BITMAP_RANGE_END; } r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); card1 = 0; roaring_init_iterator(r1, &iterator); roaring_move_uint32_iterator_equalorlarger(&iterator, rangestart); while(iterator.has_value) { if(iterator.current_value >= rangeend) break; card1++; roaring_advance_uint32_iterator(&iterator); } roaring_bitmap_free(r1); PG_RETURN_INT64(card1); } //bitmap range PG_FUNCTION_INFO_V1(rb_select); Datum rb_select(PG_FUNCTION_ARGS); Datum rb_select(PG_FUNCTION_ARGS) { bytea *serializedbytes1 = PG_GETARG_BYTEA_P(0); int64 limit = PG_GETARG_INT64(1); int64 offset = PG_GETARG_INT64(2); bool reverse = PG_GETARG_BOOL(3); int64 rangestart = PG_GETARG_INT64(4); int64 rangeend = PG_GETARG_INT64(5); int64 count = 0; int64 total_count = 0; roaring_bitmap_t *r1; roaring_bitmap_t *r2; roaring_uint32_iterator_t iterator; size_t expectedsize; bytea *serializedbytes; if (rangestart < 0) rangestart = 0; if (rangeend < 0) rangeend = 0; if (rangeend > MAX_BITMAP_RANGE_END) { rangeend = MAX_BITMAP_RANGE_END; } r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes1)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); r2 = roaring_bitmap_create(); if (!r2) { roaring_bitmap_free(r1); ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("failed to create bitmap"))); } if (limit > 0) { roaring_init_iterator(r1, &iterator); roaring_move_uint32_iterator_equalorlarger(&iterator, rangestart); if (!reverse) { while (iterator.has_value) { if (iterator.current_value >= rangeend || count - offset >= limit) break; if (count >= offset) { roaring_bitmap_add(r2, iterator.current_value); } roaring_advance_uint32_iterator(&iterator); count++; } } else { while (iterator.has_value) { if (iterator.current_value >= rangeend) break; roaring_advance_uint32_iterator(&iterator); total_count++; } if (total_count > offset) { /* calulate new offset for reverse */ offset = total_count - offset - limit; if(offset < 0) offset = 0; roaring_init_iterator(r1, &iterator); roaring_move_uint32_iterator_equalorlarger(&iterator,rangestart); count = 0; while (iterator.has_value) { if (iterator.current_value >= rangeend || count - offset >= limit) break; if (count >= offset) { roaring_bitmap_add(r2, iterator.current_value); } roaring_advance_uint32_iterator(&iterator); count++; } } } } expectedsize = roaring_bitmap_portable_size_in_bytes(r2); serializedbytes = (bytea *) palloc(VARHDRSZ + expectedsize); roaring_bitmap_portable_serialize(r2, VARDATA(serializedbytes)); roaring_bitmap_free(r1); roaring_bitmap_free(r2); SET_VARSIZE(serializedbytes, VARHDRSZ + expectedsize); PG_RETURN_BYTEA_P(serializedbytes); } //bitmap build PG_FUNCTION_INFO_V1(rb_build); Datum rb_build(PG_FUNCTION_ARGS); Datum rb_build(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) PG_GETARG_ARRAYTYPE_P(0); int na, n; int *da; roaring_bitmap_t *r1; size_t expectedsize; bytea *serializedbytes; CHECKARRVALID(a); na = ARRNELEMS(a); da = ARRPTR(a); r1 = roaring_bitmap_create(); for (n = 0; n < na; n++) { roaring_bitmap_add(r1, da[n]); } expectedsize = roaring_bitmap_portable_size_in_bytes(r1); 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); } //bitmap to int[] PG_FUNCTION_INFO_V1(rb_to_array); Datum rb_to_array(PG_FUNCTION_ARGS); Datum rb_to_array(PG_FUNCTION_ARGS) { bytea *serializedbytes = PG_GETARG_BYTEA_P(0); roaring_bitmap_t *r1; roaring_uint32_iterator_t *iterator; ArrayType *result; Datum *out_datums; uint64_t card1; uint32_t counter = 0; r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); card1 = roaring_bitmap_get_cardinality(r1); if (card1 == 0) { result = construct_empty_array(INT4OID); } else { out_datums = (Datum *)palloc(sizeof(Datum) * card1); iterator = roaring_create_iterator(r1); while (iterator->has_value) { out_datums[counter] = Int32GetDatum(iterator->current_value); counter++; roaring_advance_uint32_iterator(iterator); } roaring_free_uint32_iterator(iterator); result = construct_array(out_datums, card1, INT4OID, sizeof(int32), true, 'i'); } roaring_bitmap_free(r1); PG_RETURN_POINTER(result); } //bitmap list PG_FUNCTION_INFO_V1(rb_iterate); Datum rb_iterate(PG_FUNCTION_ARGS); Datum rb_iterate(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; MemoryContext oldcontext; roaring_uint32_iterator_t *fctx; bytea *data; roaring_bitmap_t *r1; if (SRF_IS_FIRSTCALL()) { funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); data = PG_GETARG_BYTEA_P(0); r1 = roaring_bitmap_portable_deserialize(VARDATA(data)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); fctx = roaring_create_iterator(r1); funcctx->user_fctx = fctx; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); fctx = funcctx->user_fctx; if (fctx->has_value) { Datum result; result = fctx->current_value; roaring_advance_uint32_iterator(fctx); SRF_RETURN_NEXT(funcctx, result); } else { roaring_free_uint32_iterator(fctx); SRF_RETURN_DONE(funcctx); } } //bitmap or trans PG_FUNCTION_INFO_V1(rb_or_trans); Datum rb_or_trans(PG_FUNCTION_ARGS); Datum rb_or_trans(PG_FUNCTION_ARGS) { MemoryContext aggctx; MemoryContext oldcontext; 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 outside transition context"))); if (PG_ARGISNULL(1)) { if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); } else { oldcontext = MemoryContextSwitchTo(aggctx); bb = PG_GETARG_BYTEA_P(1); r2 = roaring_bitmap_portable_deserialize(VARDATA(bb)); if (PG_ARGISNULL(0)) { r1 = r2; } else { r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); roaring_bitmap_or_inplace(r1, r2); roaring_bitmap_free(r2); } MemoryContextSwitchTo(oldcontext); } PG_RETURN_POINTER(r1); } //bitmap or combine PG_FUNCTION_INFO_V1(rb_or_combine); Datum rb_or_combine(PG_FUNCTION_ARGS); Datum rb_or_combine(PG_FUNCTION_ARGS) { MemoryContext aggctx; MemoryContext oldcontext; 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_combine outside transition context"))); if (PG_ARGISNULL(1)) { if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); } else { oldcontext = MemoryContextSwitchTo(aggctx); r2 = (roaring_bitmap_t *) PG_GETARG_POINTER(1); if (PG_ARGISNULL(0)) { r1 = roaring_bitmap_copy(r2); } else { r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); roaring_bitmap_or_inplace(r1, r2); } MemoryContextSwitchTo(oldcontext); } PG_RETURN_POINTER(r1); } //bitmap and trans PG_FUNCTION_INFO_V1(rb_and_trans); Datum rb_and_trans(PG_FUNCTION_ARGS); Datum rb_and_trans(PG_FUNCTION_ARGS) { MemoryContext aggctx; MemoryContext oldcontext; 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_and_trans outside transition context"))); if (PG_ARGISNULL(1)) { if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); } else { oldcontext = MemoryContextSwitchTo(aggctx); if (PG_ARGISNULL(0) ) { /* postgres will crash when use PG_GETARG_BYTEA_PP here */ bb = PG_GETARG_BYTEA_P(1); r2 = roaring_bitmap_portable_deserialize(VARDATA(bb)); r1 = r2; } else { r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); if (!roaring_bitmap_is_empty(r1)) { bb = PG_GETARG_BYTEA_P(1); r2 = roaring_bitmap_portable_deserialize(VARDATA(bb)); roaring_bitmap_and_inplace(r1, r2); roaring_bitmap_free(r2); } } MemoryContextSwitchTo(oldcontext); } PG_RETURN_POINTER(r1); } //bitmap and combine PG_FUNCTION_INFO_V1(rb_and_combine); Datum rb_and_combine(PG_FUNCTION_ARGS); Datum rb_and_combine(PG_FUNCTION_ARGS) { MemoryContext aggctx; MemoryContext oldcontext; 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_and_combine outside transition context"))); if (PG_ARGISNULL(1)) { if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); } else { oldcontext = MemoryContextSwitchTo(aggctx); r2 = (roaring_bitmap_t *) PG_GETARG_POINTER(1); if (PG_ARGISNULL(0)) { r1 = roaring_bitmap_copy(r2); } else { r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); roaring_bitmap_and_inplace(r1, r2); } MemoryContextSwitchTo(oldcontext); } PG_RETURN_POINTER(r1); } //bitmap xor trans PG_FUNCTION_INFO_V1(rb_xor_trans); Datum rb_xor_trans(PG_FUNCTION_ARGS); Datum rb_xor_trans(PG_FUNCTION_ARGS) { MemoryContext aggctx; MemoryContext oldcontext; 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_xor_trans outside transition context"))); if (PG_ARGISNULL(1)) { if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); } else { oldcontext = MemoryContextSwitchTo(aggctx); bb = PG_GETARG_BYTEA_P(1); r2 = roaring_bitmap_portable_deserialize(VARDATA(bb)); if (PG_ARGISNULL(0)) { r1 = r2; } else { r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); roaring_bitmap_xor_inplace(r1, r2); roaring_bitmap_free(r2); } MemoryContextSwitchTo(oldcontext); } PG_RETURN_POINTER(r1); } //bitmap xor combine PG_FUNCTION_INFO_V1(rb_xor_combine); Datum rb_xor_combine(PG_FUNCTION_ARGS); Datum rb_xor_combine(PG_FUNCTION_ARGS) { MemoryContext aggctx; MemoryContext oldcontext; 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_xor_combine outside transition context"))); if (PG_ARGISNULL(1)) { if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); } else { oldcontext = MemoryContextSwitchTo(aggctx); r2 = (roaring_bitmap_t *) PG_GETARG_POINTER(1); if (PG_ARGISNULL(0)) { r1 = roaring_bitmap_copy(r2); } else { r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); roaring_bitmap_xor_inplace(r1, r2); } MemoryContextSwitchTo(oldcontext); } PG_RETURN_POINTER(r1); } //bitmap build trans PG_FUNCTION_INFO_V1(rb_build_trans); Datum rb_build_trans(PG_FUNCTION_ARGS); Datum rb_build_trans(PG_FUNCTION_ARGS) { MemoryContext aggctx; MemoryContext oldcontext; roaring_bitmap_t *r1; int i2; // We must be called as a transition routine or we fail. if (!AggCheckCallContext(fcinfo, &aggctx)) ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("rb_build_trans outside transition context"))); if (PG_ARGISNULL(1)) { if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); } else { oldcontext = MemoryContextSwitchTo(aggctx); i2 = PG_GETARG_UINT32(1); if (PG_ARGISNULL(0)) { r1 = roaring_bitmap_create(); } else { r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); } roaring_bitmap_add(r1, i2); MemoryContextSwitchTo(oldcontext); } PG_RETURN_POINTER(r1); } //bitmap Serialize PG_FUNCTION_INFO_V1(rb_serialize); Datum rb_serialize(PG_FUNCTION_ARGS); Datum rb_serialize(PG_FUNCTION_ARGS) { MemoryContext aggctx; roaring_bitmap_t *r1; size_t expectedsize; bytea *serializedbytes; // We must be called as a transition routine or we fail. if (!AggCheckCallContext(fcinfo, &aggctx)) ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("rb_serialize outside aggregate context"))); // Is the first argument a NULL? if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } else { r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); expectedsize = roaring_bitmap_portable_size_in_bytes(r1); serializedbytes = (bytea *) palloc(VARHDRSZ + expectedsize); roaring_bitmap_portable_serialize(r1, VARDATA(serializedbytes)); SET_VARSIZE(serializedbytes, VARHDRSZ + expectedsize); PG_RETURN_BYTEA_P(serializedbytes); } } //bitmap Deserialize PG_FUNCTION_INFO_V1(rb_deserialize); Datum rb_deserialize(PG_FUNCTION_ARGS); Datum rb_deserialize(PG_FUNCTION_ARGS) { MemoryContext aggctx; bytea *serializedbytes; roaring_bitmap_t *r1; // We must be called as a transition routine or we fail. if (!AggCheckCallContext(fcinfo, &aggctx)) ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("rb_deserialize outside aggregate context"))); // Is the first argument a NULL? if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } else { serializedbytes = PG_GETARG_BYTEA_P(0); r1 = roaring_bitmap_portable_deserialize(VARDATA(serializedbytes)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); // PostgreSQL's combine_aggregates() only init fcinfo->isnull once, // set fcinfo->isnull here to avoid bug https://github.com/ChenHuajun/pg_roaringbitmap/issues/6 fcinfo->isnull = false; PG_RETURN_POINTER(r1); } } //bitmap Cardinality trans PG_FUNCTION_INFO_V1(rb_cardinality_final); Datum rb_cardinality_final(PG_FUNCTION_ARGS); Datum rb_cardinality_final(PG_FUNCTION_ARGS) { MemoryContext aggctx; roaring_bitmap_t *r1; uint64 card1; // We must be called as a transition routine or we fail. if (!AggCheckCallContext(fcinfo, &aggctx)) ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("rb_cardinality_final outside aggregate context"))); // Is the first argument a NULL? if (PG_ARGISNULL(0)) { PG_RETURN_NULL(); } else { r1 = (roaring_bitmap_t *) PG_GETARG_POINTER(0); card1 = roaring_bitmap_get_cardinality(r1); PG_RETURN_INT64(card1); } } //bitmap minimum PG_FUNCTION_INFO_V1(rb_min); Datum rb_min(PG_FUNCTION_ARGS); Datum rb_min(PG_FUNCTION_ARGS) { bytea *data = PG_GETARG_BYTEA_P(0); uint32 min1; roaring_bitmap_t *r1 = roaring_bitmap_portable_deserialize(VARDATA(data)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); if(roaring_bitmap_is_empty(r1)) { roaring_bitmap_free(r1); PG_RETURN_NULL(); } min1 = roaring_bitmap_minimum(r1); roaring_bitmap_free(r1); PG_RETURN_UINT32(min1); } //bitmap maximum PG_FUNCTION_INFO_V1(rb_max); Datum rb_max(PG_FUNCTION_ARGS); Datum rb_max(PG_FUNCTION_ARGS) { bytea *data = PG_GETARG_BYTEA_P(0); uint32 max1; roaring_bitmap_t *r1 = roaring_bitmap_portable_deserialize(VARDATA(data)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); if(roaring_bitmap_is_empty(r1)) { roaring_bitmap_free(r1); PG_RETURN_NULL(); } max1 = roaring_bitmap_maximum(r1); roaring_bitmap_free(r1); PG_RETURN_UINT32(max1); } //bitmap rank PG_FUNCTION_INFO_V1(rb_rank); Datum rb_rank(PG_FUNCTION_ARGS); Datum rb_rank(PG_FUNCTION_ARGS) { bytea *data = PG_GETARG_BYTEA_P(0); uint32 value = PG_GETARG_UINT32(1); uint64 rank1; roaring_bitmap_t *r1 = roaring_bitmap_portable_deserialize(VARDATA(data)); if (!r1) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("bitmap format is error"))); rank1 = roaring_bitmap_rank(r1,value); roaring_bitmap_free(r1); PG_RETURN_INT64(rank1); }