ArrayType * inner_int_union(ArrayType *a, ArrayType *b) { ArrayType *r = NULL; CHECKARRVALID(a); CHECKARRVALID(b); if (ARRISEMPTY(a) && ARRISEMPTY(b)) return new_intArrayType(0); if (ARRISEMPTY(a)) r = copy_intArrayType(b); if (ARRISEMPTY(b)) r = copy_intArrayType(a); if (!r) { int na = ARRNELEMS(a), nb = ARRNELEMS(b); int *da = ARRPTR(a), *db = ARRPTR(b); int i, j, *dr; r = new_intArrayType(na + nb); dr = ARRPTR(r); /* union */ i = j = 0; while (i < na && j < nb) { if (da[i] == db[j]) { *dr++ = da[i++]; j++; } else if (da[i] < db[j]) *dr++ = da[i++]; else *dr++ = db[j++]; } while (i < na) *dr++ = da[i++]; while (j < nb) *dr++ = db[j++]; r = resize_intArrayType(r, dr - ARRPTR(r)); } if (ARRNELEMS(r) > 1) r = _int_unique(r); return r; }
Datum intarray_del_elem(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) 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); }
ArrayType * inner_int_inter(ArrayType *a, ArrayType *b) { ArrayType *r; int na, nb; int *da, *db, *dr; int i, j, k; if (ARRISEMPTY(a) || ARRISEMPTY(b)) return new_intArrayType(0); na = ARRNELEMS(a); nb = ARRNELEMS(b); da = ARRPTR(a); db = ARRPTR(b); r = new_intArrayType(Min(na, nb)); dr = ARRPTR(r); i = j = k = 0; while (i < na && j < nb) { if (da[i] < db[j]) i++; else if (da[i] == db[j]) { if (k == 0 || dr[k - 1] != db[j]) dr[k++] = db[j]; i++; j++; } else j++; } if (k == 0) { pfree(r); return new_intArrayType(0); } else return resize_intArrayType(r, k); }
ArrayType * inner_int_inter(ArrayType *a, ArrayType *b) { ArrayType *r; int na, nb; int *da, *db, *dr; int i, j; if (ARRISEMPTY(a) || ARRISEMPTY(b)) return new_intArrayType(0); na = ARRNELEMS(a); nb = ARRNELEMS(b); da = ARRPTR(a); db = ARRPTR(b); r = new_intArrayType(Min(na, nb)); dr = ARRPTR(r); i = j = 0; while (i < na && j < nb) { if (da[i] < db[j]) i++; else if (da[i] == db[j]) { if (i + j == 0 || (i + j > 0 && *(dr - 1) != db[j])) *dr++ = db[j]; i++; j++; } else j++; } if ((dr - ARRPTR(r)) == 0) { pfree(r); return new_intArrayType(0); } else return resize_intArrayType(r, dr - ARRPTR(r)); }
/* _int_overlap -- does a overlap b? */ Datum _int_overlap(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) PG_GETARG_ARRAYTYPE_P_COPY(0); ArrayType *b = (ArrayType *) 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 subarray(PG_FUNCTION_ARGS) { ArrayType *a = (ArrayType *) 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 g_int_decompress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval; ArrayType *r; int *dr, lenr; ArrayType *in; int lenin; int *din; int i, j; in = DatumGetArrayTypeP(entry->key); CHECKARRVALID(in); if (ARRISEMPTY(in)) { if (in != (ArrayType *) DatumGetPointer(entry->key)) { retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(in), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } PG_RETURN_POINTER(entry); } lenin = ARRNELEMS(in); if (lenin < 2 * MAXNUMRANGE) { /* not compressed value */ if (in != (ArrayType *) DatumGetPointer(entry->key)) { retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(in), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } PG_RETURN_POINTER(entry); } din = ARRPTR(in); lenr = internal_size(din, lenin); r = new_intArrayType(lenr); dr = ARRPTR(r); for (i = 0; i < lenin; i += 2) for (j = din[i]; j <= din[i + 1]; j++) if ((!i) || *(dr - 1) != j) *dr++ = j; if (in != (ArrayType *) DatumGetPointer(entry->key)) pfree(in); retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); }
/* ** GiST Compress and Decompress methods */ Datum g_int_compress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval; ArrayType *r; int len; int *dr; int i, min, cand; if (entry->leafkey) { r = DatumGetArrayTypePCopy(entry->key); CHECKARRVALID(r); PREPAREARR(r); if (ARRNELEMS(r) >= 2 * MAXNUMRANGE) elog(NOTICE, "input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead", 2 * MAXNUMRANGE - 1, ARRNELEMS(r)); retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } /* * leaf entries never compress one more time, only when entry->leafkey * ==true, so now we work only with internal keys */ r = DatumGetArrayTypeP(entry->key); CHECKARRVALID(r); if (ARRISEMPTY(r)) { if (r != (ArrayType *) DatumGetPointer(entry->key)) pfree(r); PG_RETURN_POINTER(entry); } if ((len = ARRNELEMS(r)) >= 2 * MAXNUMRANGE) { /* compress */ if (r == (ArrayType *) DatumGetPointer(entry->key)) r = DatumGetArrayTypePCopy(entry->key); r = resize_intArrayType(r, 2 * (len)); dr = ARRPTR(r); for (i = len - 1; i >= 0; i--) dr[2 * i] = dr[2 * i + 1] = dr[i]; len *= 2; cand = 1; while (len > MAXNUMRANGE * 2) { min = INT_MAX; for (i = 2; i < len; i += 2) if (min > (dr[i] - dr[i - 1])) { min = (dr[i] - dr[i - 1]); cand = i; } memmove((void *) &dr[cand - 1], (void *) &dr[cand + 1], (len - cand - 1) * sizeof(int32)); len -= 2; } r = resize_intArrayType(r, len); retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); } else PG_RETURN_POINTER(entry); }
Datum g_intbig_compress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); if (entry->leafkey) { GISTENTRY *retval; ArrayType *in = DatumGetArrayTypeP(entry->key); int32 *ptr; int num; GISTTYPE *res = (GISTTYPE *) palloc0(CALCGTSIZE(0)); CHECKARRVALID(in); if (ARRISEMPTY(in)) { ptr = NULL; num = 0; } else { ptr = ARRPTR(in); num = ARRNELEMS(in); } SET_VARSIZE(res, CALCGTSIZE(0)); while (num--) { HASH(GETSIGN(res), *ptr); ptr++; } retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(res), entry->rel, entry->page, entry->offset, FALSE); if (in != DatumGetArrayTypeP(entry->key)) pfree(in); PG_RETURN_POINTER(retval); } else if (!ISALLTRUE(DatumGetPointer(entry->key))) { GISTENTRY *retval; int i; BITVECP sign = GETSIGN(DatumGetPointer(entry->key)); GISTTYPE *res; LOOPBYTE { if ((sign[i] & 0xff) != 0xff) PG_RETURN_POINTER(entry); } res = (GISTTYPE *) palloc(CALCGTSIZE(ALLISTRUE)); SET_VARSIZE(res, CALCGTSIZE(ALLISTRUE)); res->flag = ALLISTRUE; retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(res), entry->rel, entry->page, entry->offset, FALSE); PG_RETURN_POINTER(retval); }