PostgreSQL Source Code  git master
_int_gist.c File Reference
#include "postgres.h"
#include <limits.h>
#include "_int.h"
#include "access/gist.h"
#include "access/reloptions.h"
#include "access/stratnum.h"
Include dependency graph for _int_gist.c:

Go to the source code of this file.

Data Structures

struct  SPLITCOST
 

Macros

#define GETENTRY(vec, pos)   ((ArrayType *) DatumGetPointer((vec)->vector[(pos)].key))
 
#define MAXNUMELTS   (Min((MaxAllocSize / sizeof(Datum)),((MaxAllocSize - ARR_OVERHEAD_NONULLS(1)) / sizeof(int)))/2)
 

Functions

 PG_FUNCTION_INFO_V1 (g_int_consistent)
 
 PG_FUNCTION_INFO_V1 (g_int_compress)
 
 PG_FUNCTION_INFO_V1 (g_int_decompress)
 
 PG_FUNCTION_INFO_V1 (g_int_penalty)
 
 PG_FUNCTION_INFO_V1 (g_int_picksplit)
 
 PG_FUNCTION_INFO_V1 (g_int_union)
 
 PG_FUNCTION_INFO_V1 (g_int_same)
 
 PG_FUNCTION_INFO_V1 (g_int_options)
 
Datum g_int_consistent (PG_FUNCTION_ARGS)
 
Datum g_int_union (PG_FUNCTION_ARGS)
 
Datum g_int_compress (PG_FUNCTION_ARGS)
 
Datum g_int_decompress (PG_FUNCTION_ARGS)
 
Datum g_int_penalty (PG_FUNCTION_ARGS)
 
Datum g_int_same (PG_FUNCTION_ARGS)
 
static int comparecost (const void *a, const void *b)
 
Datum g_int_picksplit (PG_FUNCTION_ARGS)
 
Datum g_int_options (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ GETENTRY

#define GETENTRY (   vec,
  pos 
)    ((ArrayType *) DatumGetPointer((vec)->vector[(pos)].key))

Definition at line 13 of file _int_gist.c.

Referenced by g_int_picksplit(), and g_int_union().

◆ MAXNUMELTS

#define MAXNUMELTS   (Min((MaxAllocSize / sizeof(Datum)),((MaxAllocSize - ARR_OVERHEAD_NONULLS(1)) / sizeof(int)))/2)

Definition at line 23 of file _int_gist.c.

Referenced by g_int_compress(), and g_int_decompress().

Function Documentation

◆ comparecost()

static int comparecost ( const void *  a,
const void *  b 
)
static

Definition at line 422 of file _int_gist.c.

Referenced by g_int_picksplit().

423 {
424  if (((const SPLITCOST *) a)->cost == ((const SPLITCOST *) b)->cost)
425  return 0;
426  else
427  return (((const SPLITCOST *) a)->cost > ((const SPLITCOST *) b)->cost) ? 1 : -1;
428 }

◆ g_int_compress()

Datum g_int_compress ( PG_FUNCTION_ARGS  )

Definition at line 162 of file _int_gist.c.

References ARRISEMPTY, ARRNELEMS, ARRPTR, CHECKARRVALID, DatumGetArrayTypeP, DatumGetArrayTypePCopy, DatumGetPointer, elog, ereport, errmsg(), ERROR, G_INT_GET_NUMRANGES, gistentryinit, i, internal_size(), GISTENTRY::key, GISTENTRY::leafkey, MAXNUMELTS, NOTICE, GISTENTRY::offset, GISTENTRY::page, palloc(), pfree(), PG_GETARG_POINTER, PG_INT64_MAX, PG_RETURN_POINTER, PointerGetDatum, PREPAREARR, GISTENTRY::rel, and resize_intArrayType().

163 {
164  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
165  GISTENTRY *retval;
166  ArrayType *r;
167  int num_ranges = G_INT_GET_NUMRANGES();
168  int len,
169  lenr;
170  int *dr;
171  int i,
172  j,
173  cand;
174  int64 min;
175 
176  if (entry->leafkey)
177  {
178  r = DatumGetArrayTypePCopy(entry->key);
179  CHECKARRVALID(r);
180  PREPAREARR(r);
181 
182  if (ARRNELEMS(r) >= 2 * num_ranges)
183  elog(NOTICE, "input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead",
184  2 * num_ranges - 1, ARRNELEMS(r));
185 
186  retval = palloc(sizeof(GISTENTRY));
187  gistentryinit(*retval, PointerGetDatum(r),
188  entry->rel, entry->page, entry->offset, false);
189 
190  PG_RETURN_POINTER(retval);
191  }
192 
193  /*
194  * leaf entries never compress one more time, only when entry->leafkey
195  * ==true, so now we work only with internal keys
196  */
197 
198  r = DatumGetArrayTypeP(entry->key);
199  CHECKARRVALID(r);
200  if (ARRISEMPTY(r))
201  {
202  if (r != (ArrayType *) DatumGetPointer(entry->key))
203  pfree(r);
204  PG_RETURN_POINTER(entry);
205  }
206 
207  if ((len = ARRNELEMS(r)) >= 2 * num_ranges)
208  { /* compress */
209  if (r == (ArrayType *) DatumGetPointer(entry->key))
210  r = DatumGetArrayTypePCopy(entry->key);
211  r = resize_intArrayType(r, 2 * (len));
212 
213  dr = ARRPTR(r);
214 
215  /*
216  * "len" at this point is the number of ranges we will construct.
217  * "lenr" is the number of ranges we must eventually remove by
218  * merging, we must be careful to remove no more than this number.
219  */
220  lenr = len - num_ranges;
221 
222  /*
223  * Initially assume we can merge consecutive ints into a range. but we
224  * must count every value removed and stop when lenr runs out
225  */
226  for (j = i = len - 1; i > 0 && lenr > 0; i--, j--)
227  {
228  int r_end = dr[i];
229  int r_start = r_end;
230 
231  while (i > 0 && lenr > 0 && dr[i - 1] == r_start - 1)
232  --r_start, --i, --lenr;
233  dr[2 * j] = r_start;
234  dr[2 * j + 1] = r_end;
235  }
236  /* just copy the rest, if any, as trivial ranges */
237  for (; i >= 0; i--, j--)
238  dr[2 * j] = dr[2 * j + 1] = dr[i];
239 
240  if (++j)
241  {
242  /*
243  * shunt everything down to start at the right place
244  */
245  memmove((void *) &dr[0], (void *) &dr[2 * j], 2 * (len - j) * sizeof(int32));
246  }
247 
248  /*
249  * make "len" be number of array elements, not ranges
250  */
251  len = 2 * (len - j);
252  cand = 1;
253  while (len > num_ranges * 2)
254  {
255  min = PG_INT64_MAX;
256  for (i = 2; i < len; i += 2)
257  if (min > ((int64) dr[i] - (int64) dr[i - 1]))
258  {
259  min = ((int64) dr[i] - (int64) dr[i - 1]);
260  cand = i;
261  }
262  memmove((void *) &dr[cand - 1], (void *) &dr[cand + 1], (len - cand - 1) * sizeof(int32));
263  len -= 2;
264  }
265 
266  /*
267  * check sparseness of result
268  */
269  lenr = internal_size(dr, len);
270  if (lenr < 0 || lenr > MAXNUMELTS)
271  ereport(ERROR,
272  (errmsg("data is too sparse, recreate index using gist__intbig_ops opclass instead")));
273 
274  r = resize_intArrayType(r, len);
275  retval = palloc(sizeof(GISTENTRY));
276  gistentryinit(*retval, PointerGetDatum(r),
277  entry->rel, entry->page, entry->offset, false);
278  PG_RETURN_POINTER(retval);
279  }
280  else
281  PG_RETURN_POINTER(entry);
282 }
Relation rel
Definition: gist.h:152
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PG_INT64_MAX
Definition: c.h:460
#define PointerGetDatum(X)
Definition: postgres.h:556
#define CHECKARRVALID(x)
Definition: _int.h:30
#define PREPAREARR(x)
Definition: _int.h:49
#define MAXNUMELTS
Definition: _int_gist.c:23
int internal_size(int *a, int len)
Definition: _int_tool.c:292
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
signed int int32
Definition: c.h:362
Page page
Definition: gist.h:153
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
ArrayType * resize_intArrayType(ArrayType *a, int num)
Definition: _int_tool.c:249
Datum key
Definition: gist.h:151
#define ARRISEMPTY(x)
Definition: _int.h:38
bool leafkey
Definition: gist.h:155
#define DatumGetArrayTypePCopy(X)
Definition: array.h:250
#define ereport(elevel,...)
Definition: elog.h:144
#define NOTICE
Definition: elog.h:37
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:235
#define ARRNELEMS(x)
Definition: cube.c:25
#define DatumGetPointer(X)
Definition: postgres.h:549
#define G_INT_GET_NUMRANGES()
Definition: _int.h:14
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
int i
#define ARRPTR(x)
Definition: cube.c:24
OffsetNumber offset
Definition: gist.h:154
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ g_int_consistent()

Datum g_int_consistent ( PG_FUNCTION_ARGS  )

Definition at line 46 of file _int_gist.c.

References BooleanSearchStrategy, CHECKARRVALID, DatumGetPointer, DirectFunctionCall3, execconsistent(), g_int_same(), GIST_LEAF, inner_int_contains(), inner_int_overlap(), GISTENTRY::key, pfree(), PG_GETARG_ARRAYTYPE_P_COPY, PG_GETARG_POINTER, PG_GETARG_UINT16, PG_RETURN_BOOL, PointerGetDatum, PREPAREARR, RTContainedByStrategyNumber, RTContainsStrategyNumber, RTOldContainedByStrategyNumber, RTOldContainsStrategyNumber, RTOverlapStrategyNumber, and RTSameStrategyNumber.

47 {
48  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
51 
52  /* Oid subtype = PG_GETARG_OID(3); */
53  bool *recheck = (bool *) PG_GETARG_POINTER(4);
54  bool retval;
55 
56  /* this is exact except for RTSameStrategyNumber */
57  *recheck = (strategy == RTSameStrategyNumber);
58 
59  if (strategy == BooleanSearchStrategy)
60  {
61  retval = execconsistent((QUERYTYPE *) query,
62  (ArrayType *) DatumGetPointer(entry->key),
63  GIST_LEAF(entry));
64 
65  pfree(query);
66  PG_RETURN_BOOL(retval);
67  }
68 
69  /* sort query for fast search, key is already sorted */
70  CHECKARRVALID(query);
71  PREPAREARR(query);
72 
73  switch (strategy)
74  {
76  retval = inner_int_overlap((ArrayType *) DatumGetPointer(entry->key),
77  query);
78  break;
80  if (GIST_LEAF(entry))
82  entry->key,
83  PointerGetDatum(query),
84  PointerGetDatum(&retval));
85  else
86  retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key),
87  query);
88  break;
91  retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key),
92  query);
93  break;
96 
97  /*
98  * This code is unreachable as of intarray 1.4, because the <@
99  * operator has been removed from the opclass. We keep it for now
100  * to support older versions of the SQL definitions.
101  */
102  if (GIST_LEAF(entry))
103  retval = inner_int_contains(query,
104  (ArrayType *) DatumGetPointer(entry->key));
105  else
106  {
107  /*
108  * Unfortunately, because empty arrays could be anywhere in
109  * the index, we must search the whole tree.
110  */
111  retval = true;
112  }
113  break;
114  default:
115  retval = false;
116  }
117  pfree(query);
118  PG_RETURN_BOOL(retval);
119 }
#define GIST_LEAF(entry)
Definition: gist.h:161
#define RTOldContainsStrategyNumber
Definition: stratnum.h:63
#define RTOldContainedByStrategyNumber
Definition: stratnum.h:64
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:252
#define PointerGetDatum(X)
Definition: postgres.h:556
#define CHECKARRVALID(x)
Definition: _int.h:30
#define PREPAREARR(x)
Definition: _int.h:49
uint16 StrategyNumber
Definition: stratnum.h:22
#define RTContainedByStrategyNumber
Definition: stratnum.h:58
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
Datum g_int_same(PG_FUNCTION_ARGS)
Definition: _int_gist.c:379
void pfree(void *pointer)
Definition: mcxt.c:1056
bool inner_int_overlap(ArrayType *a, ArrayType *b)
Definition: _int_tool.c:49
Datum key
Definition: gist.h:151
#define RTSameStrategyNumber
Definition: stratnum.h:56
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:628
bool inner_int_contains(ArrayType *a, ArrayType *b)
Definition: _int_tool.c:14
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358
bool execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot)
Definition: _int_bool.c:309
#define BooleanSearchStrategy
Definition: _int.h:134
#define RTContainsStrategyNumber
Definition: stratnum.h:57
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:272
#define DatumGetPointer(X)
Definition: postgres.h:549
#define RTOverlapStrategyNumber
Definition: stratnum.h:53

◆ g_int_decompress()

Datum g_int_decompress ( PG_FUNCTION_ARGS  )

Definition at line 285 of file _int_gist.c.

References ARRISEMPTY, ARRNELEMS, ARRPTR, CHECKARRVALID, DatumGetArrayTypeP, DatumGetPointer, ereport, errmsg(), ERROR, G_INT_GET_NUMRANGES, gistentryinit, i, internal_size(), GISTENTRY::key, MAXNUMELTS, new_intArrayType(), GISTENTRY::offset, GISTENTRY::page, palloc(), pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum, and GISTENTRY::rel.

286 {
287  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
288  GISTENTRY *retval;
289  ArrayType *r;
290  int num_ranges = G_INT_GET_NUMRANGES();
291  int *dr,
292  lenr;
293  ArrayType *in;
294  int lenin;
295  int *din;
296  int i,
297  j;
298 
299  in = DatumGetArrayTypeP(entry->key);
300 
301  CHECKARRVALID(in);
302  if (ARRISEMPTY(in))
303  {
304  if (in != (ArrayType *) DatumGetPointer(entry->key))
305  {
306  retval = palloc(sizeof(GISTENTRY));
307  gistentryinit(*retval, PointerGetDatum(in),
308  entry->rel, entry->page, entry->offset, false);
309  PG_RETURN_POINTER(retval);
310  }
311 
312  PG_RETURN_POINTER(entry);
313  }
314 
315  lenin = ARRNELEMS(in);
316 
317  if (lenin < 2 * num_ranges)
318  { /* not compressed value */
319  if (in != (ArrayType *) DatumGetPointer(entry->key))
320  {
321  retval = palloc(sizeof(GISTENTRY));
322  gistentryinit(*retval, PointerGetDatum(in),
323  entry->rel, entry->page, entry->offset, false);
324 
325  PG_RETURN_POINTER(retval);
326  }
327  PG_RETURN_POINTER(entry);
328  }
329 
330  din = ARRPTR(in);
331  lenr = internal_size(din, lenin);
332  if (lenr < 0 || lenr > MAXNUMELTS)
333  ereport(ERROR,
334  (errmsg("compressed array is too big, recreate index using gist__intbig_ops opclass instead")));
335 
336  r = new_intArrayType(lenr);
337  dr = ARRPTR(r);
338 
339  for (i = 0; i < lenin; i += 2)
340  for (j = din[i]; j <= din[i + 1]; j++)
341  if ((!i) || *(dr - 1) != j)
342  *dr++ = j;
343 
344  if (in != (ArrayType *) DatumGetPointer(entry->key))
345  pfree(in);
346  retval = palloc(sizeof(GISTENTRY));
347  gistentryinit(*retval, PointerGetDatum(r),
348  entry->rel, entry->page, entry->offset, false);
349 
350  PG_RETURN_POINTER(retval);
351 }
Relation rel
Definition: gist.h:152
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PointerGetDatum(X)
Definition: postgres.h:556
#define CHECKARRVALID(x)
Definition: _int.h:30
#define MAXNUMELTS
Definition: _int_gist.c:23
int internal_size(int *a, int len)
Definition: _int_tool.c:292
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
Page page
Definition: gist.h:153
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
Datum key
Definition: gist.h:151
#define ARRISEMPTY(x)
Definition: _int.h:38
ArrayType * new_intArrayType(int num)
Definition: _int_tool.c:221
#define ereport(elevel,...)
Definition: elog.h:144
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:235
#define ARRNELEMS(x)
Definition: cube.c:25
#define DatumGetPointer(X)
Definition: postgres.h:549
#define G_INT_GET_NUMRANGES()
Definition: _int.h:14
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
#define ARRPTR(x)
Definition: cube.c:24
OffsetNumber offset
Definition: gist.h:154
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ g_int_options()

Datum g_int_options ( PG_FUNCTION_ARGS  )

Definition at line 619 of file _int_gist.c.

References add_local_int_reloption(), G_INT_NUMRANGES_DEFAULT, G_INT_NUMRANGES_MAX, init_local_reloptions(), offsetof, PG_GETARG_POINTER, and PG_RETURN_VOID.

620 {
622 
623  init_local_reloptions(relopts, sizeof(GISTIntArrayOptions));
624  add_local_int_reloption(relopts, "numranges",
625  "number of ranges for compression",
627  offsetof(GISTIntArrayOptions, num_ranges));
628 
629  PG_RETURN_VOID();
630 }
void init_local_reloptions(local_relopts *opts, Size relopt_struct_size)
Definition: reloptions.c:710
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define G_INT_NUMRANGES_MAX
Definition: _int.h:12
#define G_INT_NUMRANGES_DEFAULT
Definition: _int.h:11
void add_local_int_reloption(local_relopts *relopts, const char *name, const char *desc, int default_val, int min_val, int max_val, int offset)
Definition: reloptions.c:894
#define PG_RETURN_VOID()
Definition: fmgr.h:348
#define offsetof(type, field)
Definition: c.h:668

◆ g_int_penalty()

Datum g_int_penalty ( PG_FUNCTION_ARGS  )

Definition at line 357 of file _int_gist.c.

References DatumGetPointer, inner_int_union(), GISTENTRY::key, pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, and rt__int_size().

358 {
359  GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
360  GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
361  float *result = (float *) PG_GETARG_POINTER(2);
362  ArrayType *ud;
363  float tmp1,
364  tmp2;
365 
366  ud = inner_int_union((ArrayType *) DatumGetPointer(origentry->key),
367  (ArrayType *) DatumGetPointer(newentry->key));
368  rt__int_size(ud, &tmp1);
369  rt__int_size((ArrayType *) DatumGetPointer(origentry->key), &tmp2);
370  *result = tmp1 - tmp2;
371  pfree(ud);
372 
373  PG_RETURN_POINTER(result);
374 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
void rt__int_size(ArrayType *a, float *size)
Definition: _int_tool.c:183
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
void pfree(void *pointer)
Definition: mcxt.c:1056
Datum key
Definition: gist.h:151
ArrayType * inner_int_union(ArrayType *a, ArrayType *b)
Definition: _int_tool.c:78
#define DatumGetPointer(X)
Definition: postgres.h:549

◆ g_int_picksplit()

Datum g_int_picksplit ( PG_FUNCTION_ARGS  )

Definition at line 435 of file _int_gist.c.

References Abs, comparecost(), copy_intArrayType(), SPLITCOST::cost, DEBUG3, elog, FirstOffsetNumber, GETENTRY, i, inner_int_inter(), inner_int_union(), NODE::left, GistEntryVector::n, OffsetNumberNext, palloc(), pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum, SPLITCOST::pos, qsort, NODE::right, rt__int_size(), GIST_SPLITVEC::spl_ldatum, GIST_SPLITVEC::spl_left, GIST_SPLITVEC::spl_nleft, GIST_SPLITVEC::spl_nright, GIST_SPLITVEC::spl_rdatum, GIST_SPLITVEC::spl_right, and WISH_F.

436 {
439  OffsetNumber i,
440  j;
441  ArrayType *datum_alpha,
442  *datum_beta;
443  ArrayType *datum_l,
444  *datum_r;
445  ArrayType *union_d,
446  *union_dl,
447  *union_dr;
448  ArrayType *inter_d;
449  bool firsttime;
450  float size_alpha,
451  size_beta,
452  size_union,
453  size_inter;
454  float size_waste,
455  waste;
456  float size_l,
457  size_r;
458  int nbytes;
459  OffsetNumber seed_1 = 0,
460  seed_2 = 0;
461  OffsetNumber *left,
462  *right;
463  OffsetNumber maxoff;
464  SPLITCOST *costvector;
465 
466 #ifdef GIST_DEBUG
467  elog(DEBUG3, "--------picksplit %d", entryvec->n);
468 #endif
469 
470  maxoff = entryvec->n - 2;
471  nbytes = (maxoff + 2) * sizeof(OffsetNumber);
472  v->spl_left = (OffsetNumber *) palloc(nbytes);
473  v->spl_right = (OffsetNumber *) palloc(nbytes);
474 
475  firsttime = true;
476  waste = 0.0;
477  for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i))
478  {
479  datum_alpha = GETENTRY(entryvec, i);
480  for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j))
481  {
482  datum_beta = GETENTRY(entryvec, j);
483 
484  /* compute the wasted space by unioning these guys */
485  /* size_waste = size_union - size_inter; */
486  union_d = inner_int_union(datum_alpha, datum_beta);
487  rt__int_size(union_d, &size_union);
488  inter_d = inner_int_inter(datum_alpha, datum_beta);
489  rt__int_size(inter_d, &size_inter);
490  size_waste = size_union - size_inter;
491 
492  pfree(union_d);
493  pfree(inter_d);
494 
495  /*
496  * are these a more promising split that what we've already seen?
497  */
498 
499  if (size_waste > waste || firsttime)
500  {
501  waste = size_waste;
502  seed_1 = i;
503  seed_2 = j;
504  firsttime = false;
505  }
506  }
507  }
508 
509  left = v->spl_left;
510  v->spl_nleft = 0;
511  right = v->spl_right;
512  v->spl_nright = 0;
513  if (seed_1 == 0 || seed_2 == 0)
514  {
515  seed_1 = 1;
516  seed_2 = 2;
517  }
518 
519  datum_alpha = GETENTRY(entryvec, seed_1);
520  datum_l = copy_intArrayType(datum_alpha);
521  rt__int_size(datum_l, &size_l);
522  datum_beta = GETENTRY(entryvec, seed_2);
523  datum_r = copy_intArrayType(datum_beta);
524  rt__int_size(datum_r, &size_r);
525 
526  maxoff = OffsetNumberNext(maxoff);
527 
528  /*
529  * sort entries
530  */
531  costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
532  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
533  {
534  costvector[i - 1].pos = i;
535  datum_alpha = GETENTRY(entryvec, i);
536  union_d = inner_int_union(datum_l, datum_alpha);
537  rt__int_size(union_d, &size_alpha);
538  pfree(union_d);
539  union_d = inner_int_union(datum_r, datum_alpha);
540  rt__int_size(union_d, &size_beta);
541  pfree(union_d);
542  costvector[i - 1].cost = Abs((size_alpha - size_l) - (size_beta - size_r));
543  }
544  qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
545 
546  /*
547  * Now split up the regions between the two seeds. An important property
548  * of this split algorithm is that the split vector v has the indices of
549  * items to be split in order in its left and right vectors. We exploit
550  * this property by doing a merge in the code that actually splits the
551  * page.
552  *
553  * For efficiency, we also place the new index tuple in this loop. This is
554  * handled at the very end, when we have placed all the existing tuples
555  * and i == maxoff + 1.
556  */
557 
558 
559  for (j = 0; j < maxoff; j++)
560  {
561  i = costvector[j].pos;
562 
563  /*
564  * If we've already decided where to place this item, just put it on
565  * the right list. Otherwise, we need to figure out which page needs
566  * the least enlargement in order to store the item.
567  */
568 
569  if (i == seed_1)
570  {
571  *left++ = i;
572  v->spl_nleft++;
573  continue;
574  }
575  else if (i == seed_2)
576  {
577  *right++ = i;
578  v->spl_nright++;
579  continue;
580  }
581 
582  /* okay, which page needs least enlargement? */
583  datum_alpha = GETENTRY(entryvec, i);
584  union_dl = inner_int_union(datum_l, datum_alpha);
585  union_dr = inner_int_union(datum_r, datum_alpha);
586  rt__int_size(union_dl, &size_alpha);
587  rt__int_size(union_dr, &size_beta);
588 
589  /* pick which page to add it to */
590  if (size_alpha - size_l < size_beta - size_r + WISH_F(v->spl_nleft, v->spl_nright, 0.01))
591  {
592  pfree(datum_l);
593  pfree(union_dr);
594  datum_l = union_dl;
595  size_l = size_alpha;
596  *left++ = i;
597  v->spl_nleft++;
598  }
599  else
600  {
601  pfree(datum_r);
602  pfree(union_dl);
603  datum_r = union_dr;
604  size_r = size_beta;
605  *right++ = i;
606  v->spl_nright++;
607  }
608  }
609  pfree(costvector);
610  *right = *left = FirstOffsetNumber;
611 
612  v->spl_ldatum = PointerGetDatum(datum_l);
613  v->spl_rdatum = PointerGetDatum(datum_r);
614 
616 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
OffsetNumber pos
Definition: hstore_gist.c:346
#define DEBUG3
Definition: elog.h:23
void rt__int_size(ArrayType *a, float *size)
Definition: _int_tool.c:183
#define PointerGetDatum(X)
Definition: postgres.h:556
OffsetNumber * spl_left
Definition: gist.h:133
Datum spl_rdatum
Definition: gist.h:140
int32 n
Definition: gist.h:226
ArrayType * inner_int_inter(ArrayType *a, ArrayType *b)
Definition: _int_tool.c:135
#define GETENTRY(vec, pos)
Definition: _int_gist.c:13
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
int spl_nleft
Definition: gist.h:134
int32 cost
Definition: hstore_gist.c:347
uint16 OffsetNumber
Definition: off.h:24
#define Abs(x)
Definition: c.h:933
void pfree(void *pointer)
Definition: mcxt.c:1056
#define WISH_F(a, b, c)
Definition: hstore_gist.c:76
ArrayType * copy_intArrayType(ArrayType *a)
Definition: _int_tool.c:280
int spl_nright
Definition: gist.h:139
#define FirstOffsetNumber
Definition: off.h:27
static int comparecost(const void *a, const void *b)
Definition: _int_gist.c:422
ArrayType * inner_int_union(ArrayType *a, ArrayType *b)
Definition: _int_tool.c:78
Datum spl_ldatum
Definition: gist.h:135
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
OffsetNumber * spl_right
Definition: gist.h:138
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
int i
#define qsort(a, b, c, d)
Definition: port.h:479

◆ g_int_same()

Datum g_int_same ( PG_FUNCTION_ARGS  )

Definition at line 379 of file _int_gist.c.

References ARRNELEMS, ARRPTR, CHECKARRVALID, PG_GETARG_ARRAYTYPE_P, PG_GETARG_POINTER, and PG_RETURN_POINTER.

Referenced by g_int_consistent().

380 {
383  bool *result = (bool *) PG_GETARG_POINTER(2);
384  int32 n = ARRNELEMS(a);
385  int32 *da,
386  *db;
387 
388  CHECKARRVALID(a);
389  CHECKARRVALID(b);
390 
391  if (n != ARRNELEMS(b))
392  {
393  *result = false;
394  PG_RETURN_POINTER(result);
395  }
396  *result = true;
397  da = ARRPTR(a);
398  db = ARRPTR(b);
399  while (n--)
400  {
401  if (*da++ != *db++)
402  {
403  *result = false;
404  break;
405  }
406  }
407 
408  PG_RETURN_POINTER(result);
409 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define CHECKARRVALID(x)
Definition: _int.h:30
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
signed int int32
Definition: c.h:362
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ARRNELEMS(x)
Definition: cube.c:25
#define ARRPTR(x)
Definition: cube.c:24

◆ g_int_union()

Datum g_int_union ( PG_FUNCTION_ARGS  )

Definition at line 122 of file _int_gist.c.

References _int_unique(), ARRNELEMS, ARRPTR, CHECKARRVALID, GETENTRY, i, GistEntryVector::n, new_intArrayType(), PG_GETARG_POINTER, PG_RETURN_POINTER, QSORT, and VARSIZE.

123 {
125  int *size = (int *) PG_GETARG_POINTER(1);
126  int32 i,
127  *ptr;
128  ArrayType *res;
129  int totlen = 0;
130 
131  for (i = 0; i < entryvec->n; i++)
132  {
133  ArrayType *ent = GETENTRY(entryvec, i);
134 
135  CHECKARRVALID(ent);
136  totlen += ARRNELEMS(ent);
137  }
138 
139  res = new_intArrayType(totlen);
140  ptr = ARRPTR(res);
141 
142  for (i = 0; i < entryvec->n; i++)
143  {
144  ArrayType *ent = GETENTRY(entryvec, i);
145  int nel;
146 
147  nel = ARRNELEMS(ent);
148  memcpy(ptr, ARRPTR(ent), nel * sizeof(int32));
149  ptr += nel;
150  }
151 
152  QSORT(res, 1);
153  res = _int_unique(res);
154  *size = VARSIZE(res);
155  PG_RETURN_POINTER(res);
156 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define VARSIZE(PTR)
Definition: postgres.h:303
#define CHECKARRVALID(x)
Definition: _int.h:30
int32 n
Definition: gist.h:226
#define GETENTRY(vec, pos)
Definition: _int_gist.c:13
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
signed int int32
Definition: c.h:362
#define QSORT(a, direction)
Definition: _int.h:183
ArrayType * new_intArrayType(int num)
Definition: _int_tool.c:221
ArrayType * _int_unique(ArrayType *a)
Definition: _int_tool.c:310
#define ARRNELEMS(x)
Definition: cube.c:25
int i
#define ARRPTR(x)
Definition: cube.c:24

◆ PG_FUNCTION_INFO_V1() [1/8]

PG_FUNCTION_INFO_V1 ( g_int_consistent  )

◆ PG_FUNCTION_INFO_V1() [2/8]

PG_FUNCTION_INFO_V1 ( g_int_compress  )

◆ PG_FUNCTION_INFO_V1() [3/8]

PG_FUNCTION_INFO_V1 ( g_int_decompress  )

◆ PG_FUNCTION_INFO_V1() [4/8]

PG_FUNCTION_INFO_V1 ( g_int_penalty  )

◆ PG_FUNCTION_INFO_V1() [5/8]

PG_FUNCTION_INFO_V1 ( g_int_picksplit  )

◆ PG_FUNCTION_INFO_V1() [6/8]

PG_FUNCTION_INFO_V1 ( g_int_union  )

◆ PG_FUNCTION_INFO_V1() [7/8]

PG_FUNCTION_INFO_V1 ( g_int_same  )

◆ PG_FUNCTION_INFO_V1() [8/8]

PG_FUNCTION_INFO_V1 ( g_int_options  )