Example #1
0
bool
inner_int_overlap(ArrayType *a, ArrayType *b)
{
	int			na,
				nb;
	int			i,
				j;
	int		   *da,
			   *db;

	CHECKARRVALID(a);
	CHECKARRVALID(b);

	if (ARRISVOID(a) || ARRISVOID(b))
		return FALSE;

	na = ARRNELEMS(a);
	nb = ARRNELEMS(b);
	da = ARRPTR(a);
	db = ARRPTR(b);

	i = j = 0;
	while (i < na && j < nb)
		if (da[i] < db[j])
			i++;
		else if (da[i] == db[j])
			return TRUE;
		else
			j++;

	return FALSE;
}
Example #2
0
ArrayType *
inner_int_union(ArrayType *a, ArrayType *b)
{
	ArrayType  *r = NULL;

	CHECKARRVALID(a);
	CHECKARRVALID(b);

	if (ARRISVOID(a) && ARRISVOID(b))
		return new_intArrayType(0);
	if (ARRISVOID(a))
		r = copy_intArrayType(b);
	if (ARRISVOID(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;
}
Example #3
0
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;

	CHECKARRVALID(a);
	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)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("second parameter must be \"ASC\" or \"DESC\"")));
	QSORT(a, dir);
	PG_RETURN_POINTER(a);
}
Example #4
0
Datum
intarray_del_elem(PG_FUNCTION_ARGS)
{
	ArrayType  *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
	int32		elem = PG_GETARG_INT32(1);
	int32		c;
	int32	   *aa;
	int32		n = 0,
				i;

	CHECKARRVALID(a);
	if (!ARRISVOID(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);
}
Example #5
0
ArrayType *
intarray_concat_arrays(ArrayType *a, ArrayType *b)
{
	ArrayType  *result;
	int32		ac = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
	int32		bc = (ARRISVOID(b)) ? 0 : ARRNELEMS(b);

	CHECKARRVALID(a);
	CHECKARRVALID(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;
}
Example #6
0
Datum
boolop(PG_FUNCTION_ARGS)
{
	ArrayType  *val = (ArrayType *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
	QUERYTYPE  *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
	CHKVAL		chkval;
	bool		result;

	CHECKARRVALID(val);
	if (ARRISVOID(val))
	{
		pfree(val);
		PG_FREE_IF_COPY(query, 1);
		PG_RETURN_BOOL(false);
	}

	PREPAREARR(val);
	chkval.arrb = ARRPTR(val);
	chkval.arre = chkval.arrb + ARRNELEMS(val);
	result = execute(
					 GETQUERY(query) + query->size - 1,
					 &chkval, true,
					 checkcondition_arr
		);
	pfree(val);

	PG_FREE_IF_COPY(query, 1);
	PG_RETURN_BOOL(result);
}
Example #7
0
/*
** The GiST Consistent method for _intments
** Should return false if for all data items x below entry,
** the predicate x op query == FALSE, where op is the oper
** corresponding to strategy in the pg_amop table.
*/
Datum
g_int_consistent(PG_FUNCTION_ARGS)
{
	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
	ArrayType  *query = (ArrayType *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(1));
	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
	bool		retval;

	if (strategy == BooleanSearchStrategy) {
		 retval =execconsistent((QUERYTYPE *) query,
							   (ArrayType *) DatumGetPointer(entry->key),
				  ISLEAFKEY((ArrayType *) DatumGetPointer(entry->key)));
		pfree( query );

		PG_RETURN_BOOL(retval);
	}

	/* sort query for fast search, key is already sorted */
	if (ARRISVOID(query)) {
		pfree( query );
		PG_RETURN_BOOL(false);
	}
	PREPAREARR(query);

	switch (strategy)
	{
		case RTOverlapStrategyNumber:
			retval = inner_int_overlap((ArrayType *) DatumGetPointer(entry->key),
									   query);
			break;
		case RTSameStrategyNumber:
			if (GIST_LEAF(entry))
				DirectFunctionCall3(
									g_int_same,
									entry->key,
									PointerGetDatum(query),
									PointerGetDatum(&retval)
					);
			else
				retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key),
											query);
			break;
		case RTContainsStrategyNumber:
			retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key),
										query);
			break;
		case RTContainedByStrategyNumber:
			if (GIST_LEAF(entry))
				retval = inner_int_contains(query,
							  (ArrayType *) DatumGetPointer(entry->key));
			else
				retval = inner_int_overlap((ArrayType *) DatumGetPointer(entry->key),
										   query);
			break;
		default:
			retval = FALSE;
	}
	pfree( query );
	PG_RETURN_BOOL(retval);
}
Example #8
0
Datum
_int_same(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)));
	int			na,
				nb;
	int			n;
	int		   *da,
			   *db;
	bool		result;
	bool		avoid;
	bool		bvoid;

	CHECKARRVALID(a);
	CHECKARRVALID(b);
	avoid = ARRISVOID(a);
	bvoid = ARRISVOID(b);
	if (avoid || bvoid)
		return (avoid && bvoid) ? TRUE : FALSE;

	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);
}
Example #9
0
ArrayType *
inner_int_inter(ArrayType *a, ArrayType *b)
{
	ArrayType  *r;
	int			na,
				nb;
	int		   *da,
			   *db,
			   *dr;
	int			i,
				j;

	CHECKARRVALID(a);
	CHECKARRVALID(b);

	if (ARRISVOID(a) || ARRISVOID(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));
}
Example #10
0
Datum
_int_contains(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)));
	bool		res;

	CHECKARRVALID(a);
	CHECKARRVALID(b);
	if (ARRISVOID(a) || ARRISVOID(b))
		return FALSE;

	PREPAREARR(a);
	PREPAREARR(b);
	res = inner_int_contains(a, b);
	pfree(a);
	pfree(b);
	PG_RETURN_BOOL(res);
}
Example #11
0
/*
** The GiST Consistent method for _intments
** Should return false if for all data items x below entry,
** the predicate x op query == FALSE, where op is the oper
** corresponding to strategy in the pg_amop table.
*/
Datum
g_int_consistent(PG_FUNCTION_ARGS)
{
    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
    ArrayType  *query = (ArrayType *) PG_GETARG_POINTER(1);
    StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
    bool		retval;

    if (strategy == BooleanSearchStrategy)
        PG_RETURN_BOOL(execconsistent((QUERYTYPE *) query,
                                      (ArrayType *) DatumGetPointer(entry->key),
                                      ISLEAFKEY((ArrayType *) DatumGetPointer(entry->key))));

    /* XXX are we sure it's safe to scribble on the query object here? */
    /* XXX what about toasted input? */
    /* sort query for fast search, key is already sorted */
    if (ARRISVOID(query))
        PG_RETURN_BOOL(false);
    PREPAREARR(query);

    switch (strategy)
    {
    case RTOverlapStrategyNumber:
        retval = inner_int_overlap((ArrayType *) DatumGetPointer(entry->key),
                                   query);
        break;
    case RTSameStrategyNumber:
        if (GIST_LEAF(entry))
            DirectFunctionCall3(
                g_int_same,
                entry->key,
                PointerGetDatum(query),
                PointerGetDatum(&retval)
            );
        else
            retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key),
                                        query);
        break;
    case RTContainsStrategyNumber:
        retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key),
                                    query);
        break;
    case RTContainedByStrategyNumber:
        if (GIST_LEAF(entry))
            retval = inner_int_contains(query,
                                        (ArrayType *) DatumGetPointer(entry->key));
        else
            retval = inner_int_overlap((ArrayType *) DatumGetPointer(entry->key),
                                       query);
        break;
    default:
        retval = FALSE;
    }
    PG_RETURN_BOOL(retval);
}
Example #12
0
Datum
uniq(PG_FUNCTION_ARGS)
{
	ArrayType  *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));

	CHECKARRVALID(a);
	if (ARRISVOID(a) || ARRNELEMS(a) < 2)
		PG_RETURN_POINTER(a);
	a = _int_unique(a);
	PG_RETURN_POINTER(a);
}
Example #13
0
Datum
sort_desc(PG_FUNCTION_ARGS)
{
	ArrayType  *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));

	CHECKARRVALID(a);
	if (ARRISVOID(a))
		PG_RETURN_POINTER(a);
	QSORT(a, 0);
	PG_RETURN_POINTER(a);
}
Example #14
0
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 = (ArrayType *) PG_DETOAST_DATUM(entry->key);

    if (ARRISVOID(in))
        PG_RETURN_POINTER(entry);

    lenin = ARRNELEMS(in);

    if (lenin < 2 * MAXNUMRANGE || ISLEAFKEY(in))
    {   /* not compressed value */
        if (in != (ArrayType *) DatumGetPointer(entry->key))
        {
            retval = palloc(sizeof(GISTENTRY));
            gistentryinit(*retval, PointerGetDatum(in),
                          entry->rel, entry->page, entry->offset, VARSIZE(in), 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, VARSIZE(r), FALSE);

    PG_RETURN_POINTER(retval);
}
Example #15
0
Datum
_int_inter(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;

	CHECKARRVALID(a);
	CHECKARRVALID(b);
	if (ARRISVOID(a) || ARRISVOID(b))
		PG_RETURN_POINTER(new_intArrayType(0));

	SORT(a);
	SORT(b);

	result = inner_int_inter(a, b);

	pfree(a);
	pfree(b);

	PG_RETURN_POINTER(result);
}
Example #16
0
Datum
idx(PG_FUNCTION_ARGS)
{
	ArrayType  *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
	int32		result;

	CHECKARRVALID(a);
	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);
}
Example #17
0
/*	_int_overlap -- does a overlap b?
 */
Datum
_int_overlap(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)));
	bool		result;

	CHECKARRVALID(a);
	CHECKARRVALID(b);
	if (ARRISVOID(a) || ARRISVOID(b))
		return FALSE;

	SORT(a);
	SORT(b);

	result = inner_int_overlap(a, b);

	pfree(a);
	pfree(b);

	PG_RETURN_BOOL(result);
}
Example #18
0
bool
inner_int_contains(ArrayType *a, ArrayType *b)
{
	int			na,
				nb;
	int			i,
				j,
				n;
	int		   *da,
			   *db;

	CHECKARRVALID(a);
	CHECKARRVALID(b);

	if (ARRISVOID(a) || ARRISVOID(b))
		return FALSE;

	na = ARRNELEMS(a);
	nb = ARRNELEMS(b);
	da = ARRPTR(a);
	db = ARRPTR(b);

	i = j = n = 0;
	while (i < na && j < nb)
		if (da[i] < db[j])
			i++;
		else if (da[i] == db[j])
		{
			n++;
			i++;
			j++;
		}
		else
			break;

	return (n == nb) ? TRUE : FALSE;
}
Example #19
0
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;

	CHECKARRVALID(a);
	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);
}
Example #20
0
ArrayType *
intarray_add_elem(ArrayType *a, int32 elem)
{
	ArrayType  *result;
	int32	   *r;
	int32		c;

	CHECKARRVALID(a);
	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;
}
Example #21
0
int32
intarray_match_first(ArrayType *a, int32 elem)
{
	int32	   *aa,
				c,
				i;

	CHECKARRVALID(a);
	if (ARRISVOID(a))
		return 0;
	c = ARRNELEMS(a);
	aa = ARRPTR(a);
	for (i = 0; i < c; i++)
		if (aa[i] == elem)
			return (i + 1);
	return 0;
}
/*
** 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 = (ArrayType *) PG_DETOAST_DATUM_COPY(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 = (ArrayType *) PG_DETOAST_DATUM(entry->key);
	CHECKARRVALID(r);
	if (ARRISVOID(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 = (ArrayType *) PG_DETOAST_DATUM_COPY(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 = 0x7fffffff;
			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);

	PG_RETURN_POINTER(entry);
}
Example #23
0
/*
** 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 = (ArrayType *) PG_DETOAST_DATUM_COPY(entry->key);
        PREPAREARR(r);
        r->flags |= LEAFKEY;
        retval = palloc(sizeof(GISTENTRY));
        gistentryinit(*retval, PointerGetDatum(r),
                      entry->rel, entry->page, entry->offset, VARSIZE(r), FALSE);

        PG_RETURN_POINTER(retval);
    }

    r = (ArrayType *) PG_DETOAST_DATUM(entry->key);
    if (ISLEAFKEY(r) || ARRISVOID(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 = (ArrayType *) PG_DETOAST_DATUM_COPY(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 = 0x7fffffff;
            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(int));
            len -= 2;
        }
        r = resize_intArrayType(r, len);
        retval = palloc(sizeof(GISTENTRY));
        gistentryinit(*retval, PointerGetDatum(r),
                      entry->rel, entry->page, entry->offset, VARSIZE(r), FALSE);
        PG_RETURN_POINTER(retval);
    }
    else
        PG_RETURN_POINTER(entry);

    PG_RETURN_POINTER(entry);
}