diff -cr contrib/intarray.orig/README.intarray contrib/intarray/README.intarray *** contrib/intarray.orig/README.intarray Thu Oct 4 19:41:14 2001 --- contrib/intarray/README.intarray Tue Aug 6 21:13:42 2002 *************** *** 8,17 **** All work was done by Teodor Sigaev (teodor@stack.net) and Oleg Bartunov (oleg@sai.msu.su). See http://www.sai.msu.su/~megera/postgres/gist ! for additional information. CHANGES: October 1, 2001 1. Change search method in array to binary September 28, 2001 --- 8,49 ---- All work was done by Teodor Sigaev (teodor@stack.net) and Oleg Bartunov (oleg@sai.msu.su). See http://www.sai.msu.su/~megera/postgres/gist ! for additional information. Andrey Oktyabrski has done a great work on ! adding new functions and operations. ! ! ! FUNCTIONS: ! ! int icount(int[]) - the number of elements in intarray ! int[] sort(int[], 'asc' | 'desc') - sort intarray ! int[] sort(int[]) - sort in ascending order ! int[] sort_asc(int[]),sort_desc(int[]) - shortcuts for sort ! int[] uniq(int[]) - returns unique elements ! int idx(int[], int item) - returns index of first intarray matching element to item, or ! '0' if matching failed. ! int[] subarray(int[],int START [, int LEN]) - returns part of intarray starting from ! element number START (from 1) and length LEN. ! ! OPERATIONS: ! ! int[] && int[] - overlap - returns TRUE if arrays has at least one common elements. ! int[] @ int[] - contains - returns TRUE if left array contains right array ! int[] ~ int[] - contained - returns TRUE if left array is contained in right array ! # int[] - return the number of elements in array ! int[] + int - push element to array ( add to end of array) ! int[] + int[] - merge of arrays (right array added to the end of left one) ! int[] - int - remove entries matched by right argument from array ! int[] - int[] - remove left array from right ! int[] | int - returns intarray - union of arguments ! int[] | int[] - returns intarray as a union of two arrays ! int[] & int[] - returns intersection of arrays CHANGES: + August 6, 2002 + 1. Reworked patch from Andrey Oktyabrski (ano@spider.ru) with + functions: icount, sort, sort_asc, uniq, idx, subarray + operations: #, +, -, |, & October 1, 2001 1. Change search method in array to binary September 28, 2001 diff -cr contrib/intarray.orig/_int.c contrib/intarray/_int.c *** contrib/intarray.orig/_int.c Sat Jun 8 01:52:33 2002 --- contrib/intarray/_int.c Tue Aug 6 20:49:37 2002 *************** *** 2217,2219 **** --- 2217,2519 ---- PG_RETURN_POINTER( res ); } + + /* + ** Additional array functions + */ + static int32 intarray_match_first(ArrayType *a, int32 elem); + static ArrayType *intarray_add_elem(ArrayType *a, int32 elem); + static ArrayType *intarray_concat_arrays(ArrayType *a, ArrayType *b); + static ArrayType *int_to_intset(int32 elem); + + 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); + + static int32 + intarray_match_first(ArrayType *a, int32 elem) { + int32 *aa, c, i; + c = (ARRISVOID(a)) ? 0 : ARRNELEMS(a); + aa = ARRPTR(a); + for (i = 0; i < c; i++) + if (aa[i] == elem) return (i + 1); + return 0; + } + + static ArrayType * + intarray_add_elem(ArrayType *a, int32 elem) { + ArrayType *result; + int32 *r; + int32 c = (ARRISVOID(a)) ? 0 : ARRNELEMS(a); + result = new_intArrayType(c + 1); + r = ARRPTR(result); + if (c > 0) memcpy(r, ARRPTR(a), c * sizeof(int32)); + r[c] = elem; + return result; + } + + static ArrayType * + intarray_concat_arrays(ArrayType *a, ArrayType *b) { + ArrayType *result; + int32 ac = (ARRISVOID(a)) ? 0 : ARRNELEMS(a); + int32 bc = (ARRISVOID(b)) ? 0 : ARRNELEMS(b); + result = new_intArrayType(ac+bc); + if ( ac ) + memcpy(ARRPTR(result), ARRPTR(a), ac * sizeof(int32)); + if ( bc ) + memcpy(ARRPTR(result) + ac, ARRPTR(b), bc * sizeof(int32)); + return result; + } + + static ArrayType * + int_to_intset(int32 n) { + ArrayType *result; + int32 *aa; + result = new_intArrayType(1); + aa = ARRPTR(result); + aa[0] = n; + return result; + } + + static int + compASC(const void *a, const void *b) { + if ( *(int4*)a == *(int4*)b ) return 0; + return ( *(int4*)a > *(int4*)b ) ? 1 : -1; + } + + static int + compDESC(const void *a, const void *b) { + if ( *(int4*)a == *(int4*)b ) return 0; + return ( *(int4*)a < *(int4*)b ) ? 1 : -1; + } + + #define QSORT(a, direction) \ + if (ARRNELEMS(a) > 1) \ + qsort((void*)ARRPTR(a), ARRNELEMS(a),sizeof(int4), \ + (direction) ? compASC : compDESC ) + + #define UNIX_UNIQ(a) a = resize_intArrayType(a, unix_uniq(ARRPTR(a), ARRNELEMS(a))) + + static int32 + unix_uniq(int32 *array, int32 count) { + register int32 i, k = 0; + for (i = 1; i < count; i++) + if (array[k] != array[i]) { + k++; + if (i > k) array[k] = array[i]; + } + return (k+1); + } + + 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); + UNIX_UNIQ(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); + UNIX_UNIQ(result); + PG_RETURN_POINTER(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); UNIX_UNIQ(a); ca = ARRNELEMS(a); + QSORT(b, 1); UNIX_UNIQ(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); + } + Only in contrib/intarray.orig: _int.so Only in contrib/intarray.orig: _int.sql diff -cr contrib/intarray.orig/_int.sql.in contrib/intarray/_int.sql.in *** contrib/intarray.orig/_int.sql.in Tue Jul 30 02:14:10 2002 --- contrib/intarray/_int.sql.in Tue Aug 6 20:49:37 2002 *************** *** 123,128 **** --- 123,203 ---- COMMUTATOR = '@', RESTRICT = contsel, JOIN = contjoinsel ); + -------------- + CREATE FUNCTION intset(int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + + CREATE FUNCTION icount(_int4) RETURNS int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + CREATE OPERATOR # ( + RIGHTARG = _int4, PROCEDURE = icount + ); + + CREATE FUNCTION sort(_int4, text) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + + CREATE FUNCTION sort(_int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + + CREATE FUNCTION sort_asc(_int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + + CREATE FUNCTION sort_desc(_int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + + CREATE FUNCTION uniq(_int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + + CREATE FUNCTION idx(_int4, int4) RETURNS int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + CREATE OPERATOR # ( + LEFTARG = _int4, RIGHTARG = int4, PROCEDURE = idx + ); + + CREATE FUNCTION subarray(_int4, int4, int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + + CREATE FUNCTION subarray(_int4, int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + + CREATE FUNCTION intarray_push_elem(_int4, int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + CREATE OPERATOR + ( + LEFTARG = _int4, RIGHTARG = int4, PROCEDURE = intarray_push_elem + ); + + CREATE FUNCTION intarray_push_array(_int4, _int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + CREATE OPERATOR + ( + LEFTARG = _int4, RIGHTARG = _int4, COMMUTATOR = +, PROCEDURE = intarray_push_array + ); + + CREATE FUNCTION intarray_del_elem(_int4, int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + CREATE OPERATOR - ( + LEFTARG = _int4, RIGHTARG = int4, PROCEDURE = intarray_del_elem + ); + + CREATE FUNCTION intset_union_elem(_int4, int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + CREATE OPERATOR | ( + LEFTARG = _int4, RIGHTARG = int4, PROCEDURE = intset_union_elem + ); + + CREATE OPERATOR | ( + LEFTARG = _int4, RIGHTARG = _int4, COMMUTATOR = |, PROCEDURE = _int_union + ); + + CREATE FUNCTION intset_subtract(_int4, _int4) RETURNS _int4 + AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict, isCachable); + CREATE OPERATOR - ( + LEFTARG = _int4, RIGHTARG = _int4, PROCEDURE = intset_subtract + ); + + CREATE OPERATOR & ( + LEFTARG = _int4, RIGHTARG = _int4, COMMUTATOR = &, PROCEDURE = _int_inter + ); + -------------- -- define the GiST support methods CREATE FUNCTION g_int_consistent(opaque,_int4,int4) RETURNS bool diff -cr contrib/intarray.orig/expected/_int.out contrib/intarray/expected/_int.out *** contrib/intarray.orig/expected/_int.out Sun Sep 30 20:15:59 2001 --- contrib/intarray/expected/_int.out Tue Aug 6 20:49:37 2002 *************** *** 3,8 **** --- 3,146 ---- -- does not depend on contents of seg.sql. -- \set ECHO none + select intset(1234); + intset + -------- + {1234} + (1 row) + + select icount('{1234234,234234}'); + icount + -------- + 2 + (1 row) + + select sort('{1234234,-30,234234}'); + sort + ---------------------- + {-30,234234,1234234} + (1 row) + + select sort('{1234234,-30,234234}','asc'); + sort + ---------------------- + {-30,234234,1234234} + (1 row) + + select sort('{1234234,-30,234234}','desc'); + sort + ---------------------- + {1234234,234234,-30} + (1 row) + + select sort_asc('{1234234,-30,234234}'); + sort_asc + ---------------------- + {-30,234234,1234234} + (1 row) + + select sort_desc('{1234234,-30,234234}'); + sort_desc + ---------------------- + {1234234,234234,-30} + (1 row) + + select uniq('{1234234,-30,-30,234234,-30}'); + uniq + -------------------------- + {1234234,-30,234234,-30} + (1 row) + + select uniq(sort_asc('{1234234,-30,-30,234234,-30}')); + uniq + ---------------------- + {-30,234234,1234234} + (1 row) + + select idx('{1234234,-30,-30,234234,-30}',-30); + idx + ----- + 2 + (1 row) + + select subarray('{1234234,-30,-30,234234,-30}',2,3); + subarray + ------------------ + {-30,-30,234234} + (1 row) + + select subarray('{1234234,-30,-30,234234,-30}',-1,1); + subarray + ---------- + {-30} + (1 row) + + select subarray('{1234234,-30,-30,234234,-30}',0,-1); + subarray + -------------------------- + {1234234,-30,-30,234234} + (1 row) + + select #'{1234234,234234}'::int[]; + ?column? + ---------- + 2 + (1 row) + + select '{123,623,445}'::int[] + 1245; + ?column? + -------------------- + {123,623,445,1245} + (1 row) + + select '{123,623,445}'::int[] + 445; + ?column? + ------------------- + {123,623,445,445} + (1 row) + + select '{123,623,445}'::int[] + '{1245,87,445}'; + ?column? + --------------------------- + {123,623,445,1245,87,445} + (1 row) + + select '{123,623,445}'::int[] - 623; + ?column? + ----------- + {123,445} + (1 row) + + select '{123,623,445}'::int[] - '{1623,623}'; + ?column? + ----------- + {123,445} + (1 row) + + select '{123,623,445}'::int[] | 623; + ?column? + --------------- + {123,445,623} + (1 row) + + select '{123,623,445}'::int[] | 1623; + ?column? + -------------------- + {123,445,623,1623} + (1 row) + + select '{123,623,445}'::int[] | '{1623,623}'; + ?column? + -------------------- + {123,445,623,1623} + (1 row) + + select '{123,623,445}'::int[] & '{1623,623}'; + ?column? + ---------- + {623} + (1 row) + --test query_int select '1'::query_int; query_int Only in contrib/intarray.orig: results diff -cr contrib/intarray.orig/sql/_int.sql contrib/intarray/sql/_int.sql *** contrib/intarray.orig/sql/_int.sql Sun Sep 23 08:16:16 2001 --- contrib/intarray/sql/_int.sql Tue Aug 6 20:49:37 2002 *************** *** 6,11 **** --- 6,37 ---- \i _int.sql \set ECHO all + select intset(1234); + select icount('{1234234,234234}'); + select sort('{1234234,-30,234234}'); + select sort('{1234234,-30,234234}','asc'); + select sort('{1234234,-30,234234}','desc'); + select sort_asc('{1234234,-30,234234}'); + select sort_desc('{1234234,-30,234234}'); + select uniq('{1234234,-30,-30,234234,-30}'); + select uniq(sort_asc('{1234234,-30,-30,234234,-30}')); + select idx('{1234234,-30,-30,234234,-30}',-30); + select subarray('{1234234,-30,-30,234234,-30}',2,3); + select subarray('{1234234,-30,-30,234234,-30}',-1,1); + select subarray('{1234234,-30,-30,234234,-30}',0,-1); + + select #'{1234234,234234}'::int[]; + select '{123,623,445}'::int[] + 1245; + select '{123,623,445}'::int[] + 445; + select '{123,623,445}'::int[] + '{1245,87,445}'; + select '{123,623,445}'::int[] - 623; + select '{123,623,445}'::int[] - '{1623,623}'; + select '{123,623,445}'::int[] | 623; + select '{123,623,445}'::int[] | 1623; + select '{123,623,445}'::int[] | '{1623,623}'; + select '{123,623,445}'::int[] & '{1623,623}'; + + --test query_int select '1'::query_int; select ' 1'::query_int;