postgresql/contrib/intarray/_int_op.c
Peter Eisentraut 2eb4a831e5 Change TRUE/FALSE to true/false
The lower case spellings are C and C++ standard and are used in most
parts of the PostgreSQL sources.  The upper case spellings are only used
in some files/modules.  So standardize on the standard spellings.

The APIs for ICU, Perl, and Windows define their own TRUE and FALSE, so
those are left as is when using those APIs.

In code comments, we use the lower-case spelling for the C concepts and
keep the upper-case spelling for the SQL concepts.

Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
2017-11-08 11:37:28 -05:00

438 lines
7.6 KiB
C

/*
* 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);
}