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