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 416 of file _int_gist.c.

Referenced by g_int_picksplit().

417 {
418  if (((const SPLITCOST *) a)->cost == ((const SPLITCOST *) b)->cost)
419  return 0;
420  else
421  return (((const SPLITCOST *) a)->cost > ((const SPLITCOST *) b)->cost) ? 1 : -1;
422 }

◆ g_int_compress()

Datum g_int_compress ( PG_FUNCTION_ARGS  )

Definition at line 156 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().

157 {
158  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
159  GISTENTRY *retval;
160  ArrayType *r;
161  int num_ranges = G_INT_GET_NUMRANGES();
162  int len,
163  lenr;
164  int *dr;
165  int i,
166  j,
167  cand;
168  int64 min;
169 
170  if (entry->leafkey)
171  {
172  r = DatumGetArrayTypePCopy(entry->key);
173  CHECKARRVALID(r);
174  PREPAREARR(r);
175 
176  if (ARRNELEMS(r) >= 2 * num_ranges)
177  elog(NOTICE, "input array is too big (%d maximum allowed, %d current), use gist__intbig_ops opclass instead",
178  2 * num_ranges - 1, ARRNELEMS(r));
179 
180  retval = palloc(sizeof(GISTENTRY));
181  gistentryinit(*retval, PointerGetDatum(r),
182  entry->rel, entry->page, entry->offset, false);
183 
184  PG_RETURN_POINTER(retval);
185  }
186 
187  /*
188  * leaf entries never compress one more time, only when entry->leafkey
189  * ==true, so now we work only with internal keys
190  */
191 
192  r = DatumGetArrayTypeP(entry->key);
193  CHECKARRVALID(r);
194  if (ARRISEMPTY(r))
195  {
196  if (r != (ArrayType *) DatumGetPointer(entry->key))
197  pfree(r);
198  PG_RETURN_POINTER(entry);
199  }
200 
201  if ((len = ARRNELEMS(r)) >= 2 * num_ranges)
202  { /* compress */
203  if (r == (ArrayType *) DatumGetPointer(entry->key))
204  r = DatumGetArrayTypePCopy(entry->key);
205  r = resize_intArrayType(r, 2 * (len));
206 
207  dr = ARRPTR(r);
208 
209  /*
210  * "len" at this point is the number of ranges we will construct.
211  * "lenr" is the number of ranges we must eventually remove by
212  * merging, we must be careful to remove no more than this number.
213  */
214  lenr = len - num_ranges;
215 
216  /*
217  * Initially assume we can merge consecutive ints into a range. but we
218  * must count every value removed and stop when lenr runs out
219  */
220  for (j = i = len - 1; i > 0 && lenr > 0; i--, j--)
221  {
222  int r_end = dr[i];
223  int r_start = r_end;
224 
225  while (i > 0 && lenr > 0 && dr[i - 1] == r_start - 1)
226  --r_start, --i, --lenr;
227  dr[2 * j] = r_start;
228  dr[2 * j + 1] = r_end;
229  }
230  /* just copy the rest, if any, as trivial ranges */
231  for (; i >= 0; i--, j--)
232  dr[2 * j] = dr[2 * j + 1] = dr[i];
233 
234  if (++j)
235  {
236  /*
237  * shunt everything down to start at the right place
238  */
239  memmove((void *) &dr[0], (void *) &dr[2 * j], 2 * (len - j) * sizeof(int32));
240  }
241 
242  /*
243  * make "len" be number of array elements, not ranges
244  */
245  len = 2 * (len - j);
246  cand = 1;
247  while (len > num_ranges * 2)
248  {
249  min = PG_INT64_MAX;
250  for (i = 2; i < len; i += 2)
251  if (min > ((int64) dr[i] - (int64) dr[i - 1]))
252  {
253  min = ((int64) dr[i] - (int64) dr[i - 1]);
254  cand = i;
255  }
256  memmove((void *) &dr[cand - 1], (void *) &dr[cand + 1], (len - cand - 1) * sizeof(int32));
257  len -= 2;
258  }
259 
260  /*
261  * check sparseness of result
262  */
263  lenr = internal_size(dr, len);
264  if (lenr < 0 || lenr > MAXNUMELTS)
265  ereport(ERROR,
266  (errmsg("data is too sparse, recreate index using gist__intbig_ops opclass instead")));
267 
268  r = resize_intArrayType(r, len);
269  retval = palloc(sizeof(GISTENTRY));
270  gistentryinit(*retval, PointerGetDatum(r),
271  entry->rel, entry->page, entry->offset, false);
272  PG_RETURN_POINTER(retval);
273  }
274  else
275  PG_RETURN_POINTER(entry);
276 }
Relation rel
Definition: gist.h:152
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
#define PG_INT64_MAX
Definition: c.h:453
#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:355
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  if (GIST_LEAF(entry))
97  retval = inner_int_contains(query,
98  (ArrayType *) DatumGetPointer(entry->key));
99  else
100  {
101  /*
102  * Unfortunately, because empty arrays could be anywhere in
103  * the index, we must search the whole tree.
104  */
105  retval = true;
106  }
107  break;
108  default:
109  retval = false;
110  }
111  pfree(query);
112  PG_RETURN_BOOL(retval);
113 }
#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:373
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 279 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.

280 {
281  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
282  GISTENTRY *retval;
283  ArrayType *r;
284  int num_ranges = G_INT_GET_NUMRANGES();
285  int *dr,
286  lenr;
287  ArrayType *in;
288  int lenin;
289  int *din;
290  int i,
291  j;
292 
293  in = DatumGetArrayTypeP(entry->key);
294 
295  CHECKARRVALID(in);
296  if (ARRISEMPTY(in))
297  {
298  if (in != (ArrayType *) DatumGetPointer(entry->key))
299  {
300  retval = palloc(sizeof(GISTENTRY));
301  gistentryinit(*retval, PointerGetDatum(in),
302  entry->rel, entry->page, entry->offset, false);
303  PG_RETURN_POINTER(retval);
304  }
305 
306  PG_RETURN_POINTER(entry);
307  }
308 
309  lenin = ARRNELEMS(in);
310 
311  if (lenin < 2 * num_ranges)
312  { /* not compressed value */
313  if (in != (ArrayType *) DatumGetPointer(entry->key))
314  {
315  retval = palloc(sizeof(GISTENTRY));
316  gistentryinit(*retval, PointerGetDatum(in),
317  entry->rel, entry->page, entry->offset, false);
318 
319  PG_RETURN_POINTER(retval);
320  }
321  PG_RETURN_POINTER(entry);
322  }
323 
324  din = ARRPTR(in);
325  lenr = internal_size(din, lenin);
326  if (lenr < 0 || lenr > MAXNUMELTS)
327  ereport(ERROR,
328  (errmsg("compressed array is too big, recreate index using gist__intbig_ops opclass instead")));
329 
330  r = new_intArrayType(lenr);
331  dr = ARRPTR(r);
332 
333  for (i = 0; i < lenin; i += 2)
334  for (j = din[i]; j <= din[i + 1]; j++)
335  if ((!i) || *(dr - 1) != j)
336  *dr++ = j;
337 
338  if (in != (ArrayType *) DatumGetPointer(entry->key))
339  pfree(in);
340  retval = palloc(sizeof(GISTENTRY));
341  gistentryinit(*retval, PointerGetDatum(r),
342  entry->rel, entry->page, entry->offset, false);
343 
344  PG_RETURN_POINTER(retval);
345 }
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 613 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.

614 {
616 
617  init_local_reloptions(relopts, sizeof(GISTIntArrayOptions));
618  add_local_int_reloption(relopts, "numranges",
619  "number of ranges for compression",
621  offsetof(GISTIntArrayOptions, num_ranges));
622 
623  PG_RETURN_VOID();
624 }
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:661

◆ g_int_penalty()

Datum g_int_penalty ( PG_FUNCTION_ARGS  )

Definition at line 351 of file _int_gist.c.

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

352 {
353  GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
354  GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
355  float *result = (float *) PG_GETARG_POINTER(2);
356  ArrayType *ud;
357  float tmp1,
358  tmp2;
359 
360  ud = inner_int_union((ArrayType *) DatumGetPointer(origentry->key),
361  (ArrayType *) DatumGetPointer(newentry->key));
362  rt__int_size(ud, &tmp1);
363  rt__int_size((ArrayType *) DatumGetPointer(origentry->key), &tmp2);
364  *result = tmp1 - tmp2;
365  pfree(ud);
366 
367  PG_RETURN_POINTER(result);
368 }
#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 429 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.

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

374 {
377  bool *result = (bool *) PG_GETARG_POINTER(2);
378  int32 n = ARRNELEMS(a);
379  int32 *da,
380  *db;
381 
382  CHECKARRVALID(a);
383  CHECKARRVALID(b);
384 
385  if (n != ARRNELEMS(b))
386  {
387  *result = false;
388  PG_RETURN_POINTER(result);
389  }
390  *result = true;
391  da = ARRPTR(a);
392  db = ARRPTR(b);
393  while (n--)
394  {
395  if (*da++ != *db++)
396  {
397  *result = false;
398  break;
399  }
400  }
401 
402  PG_RETURN_POINTER(result);
403 }
#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:355
#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 116 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.

117 {
119  int *size = (int *) PG_GETARG_POINTER(1);
120  int32 i,
121  *ptr;
122  ArrayType *res;
123  int totlen = 0;
124 
125  for (i = 0; i < entryvec->n; i++)
126  {
127  ArrayType *ent = GETENTRY(entryvec, i);
128 
129  CHECKARRVALID(ent);
130  totlen += ARRNELEMS(ent);
131  }
132 
133  res = new_intArrayType(totlen);
134  ptr = ARRPTR(res);
135 
136  for (i = 0; i < entryvec->n; i++)
137  {
138  ArrayType *ent = GETENTRY(entryvec, i);
139  int nel;
140 
141  nel = ARRNELEMS(ent);
142  memcpy(ptr, ARRPTR(ent), nel * sizeof(int32));
143  ptr += nel;
144  }
145 
146  QSORT(res, 1);
147  res = _int_unique(res);
148  *size = VARSIZE(res);
149  PG_RETURN_POINTER(res);
150 }
#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:355
#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  )