PostgreSQL Source Code  git master
_int_gist.c
Go to the documentation of this file.
1 /*
2  * contrib/intarray/_int_gist.c
3  */
4 #include "postgres.h"
5 
6 #include <limits.h>
7 
8 #include "_int.h"
9 #include "access/gist.h"
10 #include "access/reloptions.h"
11 #include "access/stratnum.h"
12 
13 #define GETENTRY(vec,pos) ((ArrayType *) DatumGetPointer((vec)->vector[(pos)].key))
14 
15 /*
16  * Control the maximum sparseness of compressed keys.
17  *
18  * The upper safe bound for this limit is half the maximum allocatable array
19  * size. A lower bound would give more guarantees that pathological data
20  * wouldn't eat excessive CPU and memory, but at the expense of breaking
21  * possibly working (after a fashion) indexes.
22  */
23 #define MAXNUMELTS (Min((MaxAllocSize / sizeof(Datum)),((MaxAllocSize - ARR_OVERHEAD_NONULLS(1)) / sizeof(int)))/2)
24 /* or: #define MAXNUMELTS 1000000 */
25 
26 /*
27 ** GiST support methods
28 */
37 
38 
39 /*
40 ** The GiST Consistent method for _intments
41 ** Should return false if for all data items x below entry,
42 ** the predicate x op query == false, where op is the oper
43 ** corresponding to strategy in the pg_amop table.
44 */
45 Datum
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 }
120 
121 Datum
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 }
157 
158 /*
159 ** GiST Compress and Decompress methods
160 */
161 Datum
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 }
283 
284 Datum
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 }
352 
353 /*
354 ** The GiST Penalty method for _intments
355 */
356 Datum
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 }
375 
376 
377 
378 Datum
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 }
410 
411 /*****************************************************************
412 ** Common GiST Method
413 *****************************************************************/
414 
415 typedef struct
416 {
417  OffsetNumber pos;
418  float cost;
419 } SPLITCOST;
420 
421 static int
422 comparecost(const void *a, const void *b)
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 }
429 
430 /*
431 ** The GiST PickSplit method for _intments
432 ** We use Guttman's poly time split algorithm
433 */
434 Datum
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;
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 }
617 
618 Datum
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 }
#define GIST_LEAF(entry)
Definition: gist.h:162
Relation rel
Definition: gist.h:153
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
OffsetNumber pos
Definition: hstore_gist.c:346
void init_local_reloptions(local_relopts *opts, Size relopt_struct_size)
Definition: reloptions.c:710
#define PG_INT64_MAX
Definition: c.h:460
#define RTOldContainsStrategyNumber
Definition: stratnum.h:63
#define RTOldContainedByStrategyNumber
Definition: stratnum.h:64
#define DEBUG3
Definition: elog.h:23
void rt__int_size(ArrayType *a, float *size)
Definition: _int_tool.c:183
struct NODE * left
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:252
#define VARSIZE(PTR)
Definition: postgres.h:303
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum g_int_penalty(PG_FUNCTION_ARGS)
Definition: _int_gist.c:357
#define CHECKARRVALID(x)
Definition: _int.h:30
Datum g_int_consistent(PG_FUNCTION_ARGS)
Definition: _int_gist.c:46
Datum g_int_compress(PG_FUNCTION_ARGS)
Definition: _int_gist.c:162
OffsetNumber * spl_left
Definition: gist.h:134
Datum spl_rdatum
Definition: gist.h:141
#define PREPAREARR(x)
Definition: _int.h:49
int32 n
Definition: gist.h:227
#define MAXNUMELTS
Definition: _int_gist.c:23
uint16 StrategyNumber
Definition: stratnum.h:22
struct NODE * right
int internal_size(int *a, int len)
Definition: _int_tool.c:292
ArrayType * inner_int_inter(ArrayType *a, ArrayType *b)
Definition: _int_tool.c:135
#define GETENTRY(vec, pos)
Definition: _int_gist.c:13
#define RTContainedByStrategyNumber
Definition: stratnum.h:58
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define G_INT_NUMRANGES_MAX
Definition: _int.h:12
Datum g_int_same(PG_FUNCTION_ARGS)
Definition: _int_gist.c:379
int spl_nleft
Definition: gist.h:135
#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
signed int int32
Definition: c.h:362
int32 cost
Definition: hstore_gist.c:347
#define QSORT(a, direction)
Definition: _int.h:183
uint16 OffsetNumber
Definition: off.h:24
Page page
Definition: gist.h:154
#define Abs(x)
Definition: c.h:933
Datum g_int_union(PG_FUNCTION_ARGS)
Definition: _int_gist.c:122
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
void pfree(void *pointer)
Definition: mcxt.c:1057
#define WISH_F(a, b, c)
Definition: hstore_gist.c:76
#define ERROR
Definition: elog.h:43
ArrayType * copy_intArrayType(ArrayType *a)
Definition: _int_tool.c:280
int spl_nright
Definition: gist.h:140
Datum g_int_options(PG_FUNCTION_ARGS)
Definition: _int_gist.c:619
bool inner_int_overlap(ArrayType *a, ArrayType *b)
Definition: _int_tool.c:49
ArrayType * resize_intArrayType(ArrayType *a, int num)
Definition: _int_tool.c:249
Datum key
Definition: gist.h:152
PG_FUNCTION_INFO_V1(g_int_consistent)
#define FirstOffsetNumber
Definition: off.h:27
#define ARRISEMPTY(x)
Definition: _int.h:38
#define RTSameStrategyNumber
Definition: stratnum.h:56
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:628
bool leafkey
Definition: gist.h:156
bool inner_int_contains(ArrayType *a, ArrayType *b)
Definition: _int_tool.c:14
ArrayType * new_intArrayType(int num)
Definition: _int_tool.c:221
ArrayType * _int_unique(ArrayType *a)
Definition: _int_tool.c:310
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:358
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetArrayTypePCopy(X)
Definition: array.h:250
static int comparecost(const void *a, const void *b)
Definition: _int_gist.c:422
Datum g_int_decompress(PG_FUNCTION_ARGS)
Definition: _int_gist.c:285
#define ereport(elevel,...)
Definition: elog.h:144
#define NOTICE
Definition: elog.h:37
bool execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot)
Definition: _int_bool.c:309
#define PG_RETURN_VOID()
Definition: fmgr.h:348
ArrayType * inner_int_union(ArrayType *a, ArrayType *b)
Definition: _int_tool.c:78
Datum spl_ldatum
Definition: gist.h:136
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:236
float cost
Definition: _int_gist.c:418
#define BooleanSearchStrategy
Definition: _int.h:134
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
OffsetNumber * spl_right
Definition: gist.h:139
#define RTContainsStrategyNumber
Definition: stratnum.h:57
#define ARRNELEMS(x)
Definition: cube.c:25
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:272
#define DatumGetPointer(X)
Definition: postgres.h:549
#define G_INT_GET_NUMRANGES()
Definition: _int.h:14
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
int i
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define ARRPTR(x)
Definition: cube.c:24
#define qsort(a, b, c, d)
Definition: port.h:475
OffsetNumber offset
Definition: gist.h:155
Datum g_int_picksplit(PG_FUNCTION_ARGS)
Definition: _int_gist.c:435
#define offsetof(type, field)
Definition: c.h:668
#define DatumGetArrayTypeP(X)
Definition: array.h:249