mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-24 01:29:19 +03:00 
			
		
		
		
	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>
		
			
				
	
	
		
			438 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			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);
 | |
| }
 |