aboutsummaryrefslogtreecommitdiff
path: root/contrib/intarray/_int_op.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/intarray/_int_op.c')
-rw-r--r--contrib/intarray/_int_op.c444
1 files changed, 444 insertions, 0 deletions
diff --git a/contrib/intarray/_int_op.c b/contrib/intarray/_int_op.c
new file mode 100644
index 00000000000..5aa27f039d1
--- /dev/null
+++ b/contrib/intarray/_int_op.c
@@ -0,0 +1,444 @@
+#include "_int.h"
+
+#include "lib/stringinfo.h"
+
+PG_FUNCTION_INFO_V1(_int_different);
+PG_FUNCTION_INFO_V1(_int_same);
+PG_FUNCTION_INFO_V1(_int_contains);
+PG_FUNCTION_INFO_V1(_int_contained);
+PG_FUNCTION_INFO_V1(_int_overlap);
+PG_FUNCTION_INFO_V1(_int_union);
+PG_FUNCTION_INFO_V1(_int_inter);
+
+Datum _int_different(PG_FUNCTION_ARGS);
+Datum _int_same(PG_FUNCTION_ARGS);
+Datum _int_contains(PG_FUNCTION_ARGS);
+Datum _int_contained(PG_FUNCTION_ARGS);
+Datum _int_overlap(PG_FUNCTION_ARGS);
+Datum _int_union(PG_FUNCTION_ARGS);
+Datum _int_inter(PG_FUNCTION_ARGS);
+
+Datum
+_int_contained(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_BOOL(DatumGetBool(
+ DirectFunctionCall2(
+ _int_contains,
+ PointerGetDatum(PG_GETARG_POINTER(1)),
+ PointerGetDatum(PG_GETARG_POINTER(0))
+ )
+ ));
+}
+
+Datum
+_int_contains(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ bool res;
+
+ if (ARRISVOID(a) || ARRISVOID(b))
+ return FALSE;
+
+ PREPAREARR(a);
+ PREPAREARR(b);
+ res = inner_int_contains(a, b);
+ pfree(a);
+ pfree(b);
+ PG_RETURN_BOOL(res);
+}
+
+Datum
+_int_different(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_BOOL(!DatumGetBool(
+ DirectFunctionCall2(
+ _int_same,
+ PointerGetDatum(PG_GETARG_POINTER(0)),
+ PointerGetDatum(PG_GETARG_POINTER(1))
+ )
+ ));
+}
+
+Datum
+_int_same(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ int na,
+ nb;
+ int n;
+ int *da,
+ *db;
+ bool result;
+ bool avoid = ARRISVOID(a);
+ bool bvoid = ARRISVOID(b);
+
+ if (avoid || bvoid)
+ return (avoid && bvoid) ? TRUE : FALSE;
+
+ SORT(a);
+ SORT(b);
+ na = ARRNELEMS(a);
+ nb = ARRNELEMS(b);
+ da = ARRPTR(a);
+ db = ARRPTR(b);
+
+ result = FALSE;
+
+ if (na == nb)
+ {
+ result = TRUE;
+ for (n = 0; n < na; n++)
+ if (da[n] != db[n])
+ {
+ result = FALSE;
+ break;
+ }
+ }
+
+ pfree(a);
+ pfree(b);
+
+ PG_RETURN_BOOL(result);
+}
+
+/* _int_overlap -- does a overlap b?
+ */
+Datum
+_int_overlap(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ bool result;
+
+ if (ARRISVOID(a) || ARRISVOID(b))
+ return FALSE;
+
+ SORT(a);
+ SORT(b);
+
+ result = inner_int_overlap(a, b);
+
+ pfree(a);
+ pfree(b);
+
+ PG_RETURN_BOOL(result);
+}
+
+Datum
+_int_union(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *result;
+
+ if (!ARRISVOID(a))
+ SORT(a);
+ if (!ARRISVOID(b))
+ SORT(b);
+
+ result = inner_int_union(a, b);
+
+ if (a)
+ pfree(a);
+ if (b)
+ pfree(b);
+
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+_int_inter(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *result;
+
+ if (ARRISVOID(a) || ARRISVOID(b))
+ PG_RETURN_POINTER(new_intArrayType(0));
+
+ SORT(a);
+ SORT(b);
+
+ result = inner_int_inter(a, b);
+
+ pfree(a);
+ pfree(b);
+
+ PG_RETURN_POINTER(result);
+}
+
+
+PG_FUNCTION_INFO_V1(intset);
+PG_FUNCTION_INFO_V1(icount);
+PG_FUNCTION_INFO_V1(sort);
+PG_FUNCTION_INFO_V1(sort_asc);
+PG_FUNCTION_INFO_V1(sort_desc);
+PG_FUNCTION_INFO_V1(uniq);
+PG_FUNCTION_INFO_V1(idx);
+PG_FUNCTION_INFO_V1(subarray);
+PG_FUNCTION_INFO_V1(intarray_push_elem);
+PG_FUNCTION_INFO_V1(intarray_push_array);
+PG_FUNCTION_INFO_V1(intarray_del_elem);
+PG_FUNCTION_INFO_V1(intset_union_elem);
+PG_FUNCTION_INFO_V1(intset_subtract);
+Datum intset(PG_FUNCTION_ARGS);
+Datum icount(PG_FUNCTION_ARGS);
+Datum sort(PG_FUNCTION_ARGS);
+Datum sort_asc(PG_FUNCTION_ARGS);
+Datum sort_desc(PG_FUNCTION_ARGS);
+Datum uniq(PG_FUNCTION_ARGS);
+Datum idx(PG_FUNCTION_ARGS);
+Datum subarray(PG_FUNCTION_ARGS);
+Datum intarray_push_elem(PG_FUNCTION_ARGS);
+Datum intarray_push_array(PG_FUNCTION_ARGS);
+Datum intarray_del_elem(PG_FUNCTION_ARGS);
+Datum intset_union_elem(PG_FUNCTION_ARGS);
+Datum intset_subtract(PG_FUNCTION_ARGS);
+
+#define QSORT(a, direction) \
+if (ARRNELEMS(a) > 1) \
+ qsort((void*)ARRPTR(a), ARRNELEMS(a),sizeof(int4), \
+ (direction) ? compASC : compDESC )
+
+
+Datum
+intset(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_POINTER(int_to_intset(PG_GETARG_INT32(0)));
+}
+
+Datum
+icount(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ int32 count = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_INT32(count);
+}
+
+Datum
+sort(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ text *dirstr = (fcinfo->nargs == 2) ? PG_GETARG_TEXT_P(1) : NULL;
+ int32 dc = (dirstr) ? VARSIZE(dirstr) - VARHDRSZ : 0;
+ char *d = (dirstr) ? VARDATA(dirstr) : NULL;
+ int dir = -1;
+
+ if (ARRISVOID(a) || ARRNELEMS(a) < 2)
+ PG_RETURN_POINTER(a);
+
+ if (dirstr == NULL || (dc == 3
+ && (d[0] == 'A' || d[0] == 'a')
+ && (d[1] == 'S' || d[1] == 's')
+ && (d[2] == 'C' || d[2] == 'c')))
+ dir = 1;
+ else if (dc == 4
+ && (d[0] == 'D' || d[0] == 'd')
+ && (d[1] == 'E' || d[1] == 'e')
+ && (d[2] == 'S' || d[2] == 's')
+ && (d[3] == 'C' || d[3] == 'c'))
+ dir = 0;
+ if (dir == -1)
+ elog(ERROR, "Invalid second parameter in function sort. It must be 'ASC' or 'DESC'.");
+ QSORT(a, dir);
+ PG_RETURN_POINTER(a);
+}
+
+Datum
+sort_asc(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+
+ if (ARRISVOID(a))
+ PG_RETURN_POINTER(a);
+ QSORT(a, 1);
+ PG_RETURN_POINTER(a);
+}
+
+Datum
+sort_desc(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+
+ if (ARRISVOID(a))
+ PG_RETURN_POINTER(a);
+ QSORT(a, 0);
+ PG_RETURN_POINTER(a);
+}
+
+Datum
+uniq(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+
+ if (ARRISVOID(a) || ARRNELEMS(a) < 2)
+ PG_RETURN_POINTER(a);
+ a = _int_unique(a);
+ PG_RETURN_POINTER(a);
+}
+
+Datum
+idx(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ int32 result = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+
+ if (result)
+ result = intarray_match_first(a, PG_GETARG_INT32(1));
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_INT32(result);
+}
+
+Datum
+subarray(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *result;
+ int32 start = (PG_GETARG_INT32(1) > 0) ? PG_GETARG_INT32(1) - 1 : PG_GETARG_INT32(1);
+ int32 len = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
+ int32 end = 0;
+ int32 c;
+
+ if (ARRISVOID(a))
+ {
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_POINTER(new_intArrayType(0));
+ }
+
+ c = ARRNELEMS(a);
+
+ if (start < 0)
+ start = c + start;
+
+ if (len < 0)
+ end = c + len;
+ else if (len == 0)
+ end = c;
+ else
+ end = start + len;
+
+ if (end > c)
+ end = c;
+
+ if (start < 0)
+ start = 0;
+
+ if (start >= end || end <= 0)
+ {
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_POINTER(new_intArrayType(0));
+ }
+
+
+ result = new_intArrayType(end - start);
+ if (end - start > 0)
+ memcpy(ARRPTR(result), ARRPTR(a) + start, (end - start) * sizeof(int32));
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+intarray_push_elem(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *result;
+
+ result = intarray_add_elem(a, PG_GETARG_INT32(1));
+ PG_FREE_IF_COPY(a, 0);
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+intarray_push_array(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
+ ArrayType *result;
+
+ result = intarray_concat_arrays(a, b);
+ PG_FREE_IF_COPY(a, 0);
+ PG_FREE_IF_COPY(b, 1);
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+intarray_del_elem(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ int32 c = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+ int32 *aa = ARRPTR(a);
+ int32 n = 0,
+ i;
+ int32 elem = PG_GETARG_INT32(1);
+
+ for (i = 0; i < c; i++)
+ if (aa[i] != elem)
+ {
+ if (i > n)
+ aa[n++] = aa[i];
+ else
+ n++;
+ }
+ if (c > 0)
+ a = resize_intArrayType(a, n);
+ PG_RETURN_POINTER(a);
+}
+
+Datum
+intset_union_elem(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *result;
+
+ result = intarray_add_elem(a, PG_GETARG_INT32(1));
+ PG_FREE_IF_COPY(a, 0);
+ QSORT(result, 1);
+ PG_RETURN_POINTER(_int_unique(result));
+}
+
+Datum
+intset_subtract(PG_FUNCTION_ARGS)
+{
+ ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *result;
+ int32 ca = ARRISVOID(a);
+ int32 cb = ARRISVOID(b);
+ int32 *aa,
+ *bb,
+ *r;
+ int32 n = 0,
+ i = 0,
+ k = 0;
+
+ QSORT(a, 1);
+ a = _int_unique(a);
+ ca = ARRNELEMS(a);
+ QSORT(b, 1);
+ b = _int_unique(b);
+ cb = ARRNELEMS(b);
+ result = new_intArrayType(ca);
+ aa = ARRPTR(a);
+ bb = ARRPTR(b);
+ r = ARRPTR(result);
+ while (i < ca)
+ {
+ if (k == cb || aa[i] < bb[k])
+ r[n++] = aa[i++];
+ else if (aa[i] == bb[k])
+ {
+ i++;
+ k++;
+ }
+ else
+ k++;
+ }
+ result = resize_intArrayType(result, n);
+ pfree(a);
+ pfree(b);
+ PG_RETURN_POINTER(result);
+}