| /* |
| * contrib/intarray/_int_op.c |
| */ |
| #include "postgres.h" |
| |
| #include "_int.h" |
| |
| PG_MODULE_MAGIC; |
| |
| 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_contained(PG_FUNCTION_ARGS) |
| { |
| /* just reverse the operands and call _int_contains */ |
| return DirectFunctionCall2(_int_contains, |
| PG_GETARG_DATUM(1), |
| PG_GETARG_DATUM(0)); |
| } |
| |
| Datum |
| _int_contains(PG_FUNCTION_ARGS) |
| { |
| /* Force copy so we can modify the arrays in-place */ |
| ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1); |
| bool res; |
| |
| CHECKARRVALID(a); |
| CHECKARRVALID(b); |
| 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 = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1); |
| int na, |
| nb; |
| int n; |
| int *da, |
| *db; |
| bool result; |
| |
| CHECKARRVALID(a); |
| CHECKARRVALID(b); |
| na = ARRNELEMS(a); |
| nb = ARRNELEMS(b); |
| da = ARRPTR(a); |
| db = ARRPTR(b); |
| |
| result = false; |
| |
| if (na == nb) |
| { |
| SORT(a); |
| SORT(b); |
| 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 = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1); |
| bool result; |
| |
| CHECKARRVALID(a); |
| CHECKARRVALID(b); |
| if (ARRISEMPTY(a) || ARRISEMPTY(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 = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1); |
| ArrayType *result; |
| |
| CHECKARRVALID(a); |
| CHECKARRVALID(b); |
| |
| SORT(a); |
| SORT(b); |
| |
| result = inner_int_union(a, b); |
| |
| pfree(a); |
| pfree(b); |
| |
| PG_RETURN_POINTER(result); |
| } |
| |
| Datum |
| _int_inter(PG_FUNCTION_ARGS) |
| { |
| ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1); |
| ArrayType *result; |
| |
| CHECKARRVALID(a); |
| CHECKARRVALID(b); |
| |
| 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) |
| { |
| PG_RETURN_POINTER(int_to_intset(PG_GETARG_INT32(0))); |
| } |
| |
| Datum |
| icount(PG_FUNCTION_ARGS) |
| { |
| ArrayType *a = PG_GETARG_ARRAYTYPE_P(0); |
| int32 count = ARRNELEMS(a); |
| |
| PG_FREE_IF_COPY(a, 0); |
| PG_RETURN_INT32(count); |
| } |
| |
| Datum |
| sort(PG_FUNCTION_ARGS) |
| { |
| ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| text *dirstr = (fcinfo->nargs == 2) ? PG_GETARG_TEXT_PP(1) : NULL; |
| int32 dc = (dirstr) ? VARSIZE_ANY_EXHDR(dirstr) : 0; |
| char *d = (dirstr) ? VARDATA_ANY(dirstr) : NULL; |
| int dir = -1; |
| |
| CHECKARRVALID(a); |
| if (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) |
| ereport(ERROR, |
| (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| errmsg("second parameter must be \"ASC\" or \"DESC\""))); |
| QSORT(a, dir); |
| PG_RETURN_POINTER(a); |
| } |
| |
| Datum |
| sort_asc(PG_FUNCTION_ARGS) |
| { |
| ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| |
| CHECKARRVALID(a); |
| QSORT(a, 1); |
| PG_RETURN_POINTER(a); |
| } |
| |
| Datum |
| sort_desc(PG_FUNCTION_ARGS) |
| { |
| ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| |
| CHECKARRVALID(a); |
| QSORT(a, 0); |
| PG_RETURN_POINTER(a); |
| } |
| |
| Datum |
| uniq(PG_FUNCTION_ARGS) |
| { |
| ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| |
| CHECKARRVALID(a); |
| if (ARRNELEMS(a) < 2) |
| PG_RETURN_POINTER(a); |
| a = _int_unique(a); |
| PG_RETURN_POINTER(a); |
| } |
| |
| Datum |
| idx(PG_FUNCTION_ARGS) |
| { |
| ArrayType *a = PG_GETARG_ARRAYTYPE_P(0); |
| int32 result; |
| |
| CHECKARRVALID(a); |
| result = 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 = PG_GETARG_ARRAYTYPE_P(0); |
| int32 start = PG_GETARG_INT32(1); |
| int32 len = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0; |
| int32 end = 0; |
| int32 c; |
| ArrayType *result; |
| |
| start = (start > 0) ? start - 1 : start; |
| |
| CHECKARRVALID(a); |
| if (ARRISEMPTY(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 = PG_GETARG_ARRAYTYPE_P(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 = PG_GETARG_ARRAYTYPE_P(0); |
| ArrayType *b = PG_GETARG_ARRAYTYPE_P(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 = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| int32 elem = PG_GETARG_INT32(1); |
| int32 c; |
| int32 *aa; |
| int32 n = 0, |
| i; |
| |
| CHECKARRVALID(a); |
| if (!ARRISEMPTY(a)) |
| { |
| c = ARRNELEMS(a); |
| aa = ARRPTR(a); |
| for (i = 0; i < c; i++) |
| { |
| if (aa[i] != elem) |
| { |
| if (i > n) |
| aa[n++] = aa[i]; |
| else |
| n++; |
| } |
| } |
| a = resize_intArrayType(a, n); |
| } |
| PG_RETURN_POINTER(a); |
| } |
| |
| Datum |
| intset_union_elem(PG_FUNCTION_ARGS) |
| { |
| ArrayType *a = PG_GETARG_ARRAYTYPE_P(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 = PG_GETARG_ARRAYTYPE_P_COPY(0); |
| ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1); |
| ArrayType *result; |
| int32 ca; |
| int32 cb; |
| int32 *aa, |
| *bb, |
| *r; |
| int32 n = 0, |
| i = 0, |
| k = 0; |
| |
| CHECKARRVALID(a); |
| CHECKARRVALID(b); |
| |
| 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); |
| } |