PostgreSQL Source Code  git master
gistproc.c File Reference
#include "postgres.h"
#include <float.h>
#include <math.h>
#include "access/gist.h"
#include "access/stratnum.h"
#include "utils/builtins.h"
#include "utils/geo_decls.h"
Include dependency graph for gistproc.c:

Go to the source code of this file.

Data Structures

struct  CommonEntry
 
struct  ConsiderSplitContext
 
struct  SplitInterval
 

Macros

#define LIMIT_RATIO   0.3
 
#define FLOAT8_EQ(a, b)   (float8_cmp_internal(a, b) == 0)
 
#define FLOAT8_LT(a, b)   (float8_cmp_internal(a, b) < 0)
 
#define FLOAT8_LE(a, b)   (float8_cmp_internal(a, b) <= 0)
 
#define FLOAT8_GT(a, b)   (float8_cmp_internal(a, b) > 0)
 
#define FLOAT8_GE(a, b)   (float8_cmp_internal(a, b) >= 0)
 
#define FLOAT8_MAX(a, b)   (FLOAT8_GT(a, b) ? (a) : (b))
 
#define FLOAT8_MIN(a, b)   (FLOAT8_LT(a, b) ? (a) : (b))
 
#define PLACE_LEFT(box, off)
 
#define PLACE_RIGHT(box, off)
 
#define point_point_distance(p1, p2)
 
#define GeoStrategyNumberOffset   20
 
#define PointStrategyNumberGroup   0
 
#define BoxStrategyNumberGroup   1
 
#define PolygonStrategyNumberGroup   2
 
#define CircleStrategyNumberGroup   3
 

Functions

static bool gist_box_leaf_consistent (BOX *key, BOX *query, StrategyNumber strategy)
 
static bool rtree_internal_consistent (BOX *key, BOX *query, StrategyNumber strategy)
 
static void rt_box_union (BOX *n, const BOX *a, const BOX *b)
 
static double size_box (const BOX *box)
 
static double box_penalty (const BOX *original, const BOX *new)
 
Datum gist_box_consistent (PG_FUNCTION_ARGS)
 
static void adjustBox (BOX *b, const BOX *addon)
 
Datum gist_box_union (PG_FUNCTION_ARGS)
 
Datum gist_box_penalty (PG_FUNCTION_ARGS)
 
static void fallbackSplit (GistEntryVector *entryvec, GIST_SPLITVEC *v)
 
static int interval_cmp_lower (const void *i1, const void *i2)
 
static int interval_cmp_upper (const void *i1, const void *i2)
 
static float non_negative (float val)
 
static void g_box_consider_split (ConsiderSplitContext *context, int dimNum, double rightLower, int minLeftCount, double leftUpper, int maxLeftCount)
 
static int common_entry_cmp (const void *i1, const void *i2)
 
Datum gist_box_picksplit (PG_FUNCTION_ARGS)
 
Datum gist_box_same (PG_FUNCTION_ARGS)
 
Datum gist_poly_compress (PG_FUNCTION_ARGS)
 
Datum gist_poly_consistent (PG_FUNCTION_ARGS)
 
Datum gist_circle_compress (PG_FUNCTION_ARGS)
 
Datum gist_circle_consistent (PG_FUNCTION_ARGS)
 
Datum gist_point_compress (PG_FUNCTION_ARGS)
 
Datum gist_point_fetch (PG_FUNCTION_ARGS)
 
static double computeDistance (bool isLeaf, BOX *box, Point *point)
 
static bool gist_point_consistent_internal (StrategyNumber strategy, bool isLeaf, BOX *key, Point *query)
 
Datum gist_point_consistent (PG_FUNCTION_ARGS)
 
Datum gist_point_distance (PG_FUNCTION_ARGS)
 
static double gist_bbox_distance (GISTENTRY *entry, Datum query, StrategyNumber strategy, bool *recheck)
 
Datum gist_circle_distance (PG_FUNCTION_ARGS)
 
Datum gist_poly_distance (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ BoxStrategyNumberGroup

#define BoxStrategyNumberGroup   1

Definition at line 1340 of file gistproc.c.

Referenced by gist_point_consistent().

◆ CircleStrategyNumberGroup

#define CircleStrategyNumberGroup   3

Definition at line 1342 of file gistproc.c.

Referenced by gist_point_consistent().

◆ FLOAT8_EQ

#define FLOAT8_EQ (   a,
 
)    (float8_cmp_internal(a, b) == 0)

Definition at line 38 of file gistproc.c.

Referenced by gist_box_picksplit(), and gist_box_same().

◆ FLOAT8_GE

#define FLOAT8_GE (   a,
 
)    (float8_cmp_internal(a, b) >= 0)

Definition at line 42 of file gistproc.c.

Referenced by gist_box_picksplit().

◆ FLOAT8_GT

#define FLOAT8_GT (   a,
 
)    (float8_cmp_internal(a, b) > 0)

Definition at line 41 of file gistproc.c.

Referenced by adjustBox(), and gist_box_picksplit().

◆ FLOAT8_LE

#define FLOAT8_LE (   a,
 
)    (float8_cmp_internal(a, b) <= 0)

Definition at line 40 of file gistproc.c.

Referenced by gist_box_picksplit(), and size_box().

◆ FLOAT8_LT

#define FLOAT8_LT (   a,
 
)    (float8_cmp_internal(a, b) < 0)

Definition at line 39 of file gistproc.c.

Referenced by adjustBox(), and gist_box_picksplit().

◆ FLOAT8_MAX

#define FLOAT8_MAX (   a,
 
)    (FLOAT8_GT(a, b) ? (a) : (b))

Definition at line 43 of file gistproc.c.

Referenced by rt_box_union().

◆ FLOAT8_MIN

#define FLOAT8_MIN (   a,
 
)    (FLOAT8_LT(a, b) ? (a) : (b))

Definition at line 44 of file gistproc.c.

Referenced by rt_box_union().

◆ GeoStrategyNumberOffset

#define GeoStrategyNumberOffset   20

Definition at line 1338 of file gistproc.c.

Referenced by gist_bbox_distance(), gist_point_consistent(), and gist_point_distance().

◆ LIMIT_RATIO

#define LIMIT_RATIO   0.3

Definition at line 35 of file gistproc.c.

Referenced by g_box_consider_split(), and gist_box_picksplit().

◆ PLACE_LEFT

#define PLACE_LEFT (   box,
  off 
)
Value:
do { \
if (v->spl_nleft > 0) \
adjustBox(leftBox, box); \
else \
*leftBox = *(box); \
v->spl_left[v->spl_nleft++] = off; \
} while(0)

Referenced by gist_box_picksplit().

◆ PLACE_RIGHT

#define PLACE_RIGHT (   box,
  off 
)
Value:
do { \
if (v->spl_nright > 0) \
adjustBox(rightBox, box); \
else \
*rightBox = *(box); \
v->spl_right[v->spl_nright++] = off; \
} while(0)

Referenced by gist_box_picksplit().

◆ point_point_distance

#define point_point_distance (   p1,
  p2 
)
Value:
Datum point_distance(PG_FUNCTION_ARGS)
Definition: geo_ops.c:1897
#define DatumGetFloat8(X)
Definition: postgres.h:734
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587
#define PointPGetDatum(X)
Definition: geo_decls.h:138

Definition at line 1224 of file gistproc.c.

Referenced by computeDistance().

◆ PointStrategyNumberGroup

#define PointStrategyNumberGroup   0

Definition at line 1339 of file gistproc.c.

Referenced by gist_bbox_distance(), gist_point_consistent(), and gist_point_distance().

◆ PolygonStrategyNumberGroup

#define PolygonStrategyNumberGroup   2

Definition at line 1341 of file gistproc.c.

Referenced by gist_point_consistent().

Function Documentation

◆ adjustBox()

static void adjustBox ( BOX b,
const BOX addon 
)
static

Definition at line 145 of file gistproc.c.

References FLOAT8_GT, FLOAT8_LT, BOX::high, BOX::low, Point::x, and Point::y.

Referenced by fallbackSplit(), gist_box_picksplit(), and gist_box_union().

146 {
147  if (FLOAT8_LT(b->high.x, addon->high.x))
148  b->high.x = addon->high.x;
149  if (FLOAT8_GT(b->low.x, addon->low.x))
150  b->low.x = addon->low.x;
151  if (FLOAT8_LT(b->high.y, addon->high.y))
152  b->high.y = addon->high.y;
153  if (FLOAT8_GT(b->low.y, addon->low.y))
154  b->low.y = addon->low.y;
155 }
double y
Definition: geo_decls.h:60
double x
Definition: geo_decls.h:60
Point low
Definition: geo_decls.h:104
Point high
Definition: geo_decls.h:104
#define FLOAT8_GT(a, b)
Definition: gistproc.c:41
#define FLOAT8_LT(a, b)
Definition: gistproc.c:39

◆ box_penalty()

static double box_penalty ( const BOX original,
const BOX new 
)
static

Definition at line 96 of file gistproc.c.

References rt_box_union(), and size_box().

Referenced by gist_box_penalty(), and gist_box_picksplit().

97 {
98  BOX unionbox;
99 
100  rt_box_union(&unionbox, original, new);
101  return size_box(&unionbox) - size_box(original);
102 }
Definition: geo_decls.h:102
static double size_box(const BOX *box)
Definition: gistproc.c:68
static void rt_box_union(BOX *n, const BOX *a, const BOX *b)
Definition: gistproc.c:55

◆ common_entry_cmp()

static int common_entry_cmp ( const void *  i1,
const void *  i2 
)
static

Definition at line 459 of file gistproc.c.

Referenced by gist_box_picksplit().

460 {
461  double delta1 = ((const CommonEntry *) i1)->delta,
462  delta2 = ((const CommonEntry *) i2)->delta;
463 
464  if (delta1 < delta2)
465  return -1;
466  else if (delta1 > delta2)
467  return 1;
468  else
469  return 0;
470 }

◆ computeDistance()

static double computeDistance ( bool  isLeaf,
BOX box,
Point point 
)
static

Definition at line 1229 of file gistproc.c.

References Assert, elog, ERROR, BOX::high, BOX::low, point_point_distance, Point::x, and Point::y.

Referenced by gist_bbox_distance(), and gist_point_distance().

1230 {
1231  double result = 0.0;
1232 
1233  if (isLeaf)
1234  {
1235  /* simple point to point distance */
1236  result = point_point_distance(point, &box->low);
1237  }
1238  else if (point->x <= box->high.x && point->x >= box->low.x &&
1239  point->y <= box->high.y && point->y >= box->low.y)
1240  {
1241  /* point inside the box */
1242  result = 0.0;
1243  }
1244  else if (point->x <= box->high.x && point->x >= box->low.x)
1245  {
1246  /* point is over or below box */
1247  Assert(box->low.y <= box->high.y);
1248  if (point->y > box->high.y)
1249  result = point->y - box->high.y;
1250  else if (point->y < box->low.y)
1251  result = box->low.y - point->y;
1252  else
1253  elog(ERROR, "inconsistent point values");
1254  }
1255  else if (point->y <= box->high.y && point->y >= box->low.y)
1256  {
1257  /* point is to left or right of box */
1258  Assert(box->low.x <= box->high.x);
1259  if (point->x > box->high.x)
1260  result = point->x - box->high.x;
1261  else if (point->x < box->low.x)
1262  result = box->low.x - point->x;
1263  else
1264  elog(ERROR, "inconsistent point values");
1265  }
1266  else
1267  {
1268  /* closest point will be a vertex */
1269  Point p;
1270  double subresult;
1271 
1272  result = point_point_distance(point, &box->low);
1273 
1274  subresult = point_point_distance(point, &box->high);
1275  if (result > subresult)
1276  result = subresult;
1277 
1278  p.x = box->low.x;
1279  p.y = box->high.y;
1280  subresult = point_point_distance(point, &p);
1281  if (result > subresult)
1282  result = subresult;
1283 
1284  p.x = box->high.x;
1285  p.y = box->low.y;
1286  subresult = point_point_distance(point, &p);
1287  if (result > subresult)
1288  result = subresult;
1289  }
1290 
1291  return result;
1292 }
double y
Definition: geo_decls.h:60
double x
Definition: geo_decls.h:60
#define point_point_distance(p1, p2)
Definition: gistproc.c:1224
#define ERROR
Definition: elog.h:43
Point low
Definition: geo_decls.h:104
#define Assert(condition)
Definition: c.h:670
Point high
Definition: geo_decls.h:104
#define elog
Definition: elog.h:219

◆ fallbackSplit()

static void fallbackSplit ( GistEntryVector entryvec,
GIST_SPLITVEC v 
)
static

Definition at line 215 of file gistproc.c.

References adjustBox(), BoxPGetDatum, cur, DatumGetBoxP, FirstOffsetNumber, i, GISTENTRY::key, GistEntryVector::n, OffsetNumberNext, palloc(), 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 GistEntryVector::vector.

Referenced by gist_box_picksplit().

216 {
217  OffsetNumber i,
218  maxoff;
219  BOX *unionL = NULL,
220  *unionR = NULL;
221  int nbytes;
222 
223  maxoff = entryvec->n - 1;
224 
225  nbytes = (maxoff + 2) * sizeof(OffsetNumber);
226  v->spl_left = (OffsetNumber *) palloc(nbytes);
227  v->spl_right = (OffsetNumber *) palloc(nbytes);
228  v->spl_nleft = v->spl_nright = 0;
229 
230  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
231  {
232  BOX *cur = DatumGetBoxP(entryvec->vector[i].key);
233 
234  if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
235  {
236  v->spl_left[v->spl_nleft] = i;
237  if (unionL == NULL)
238  {
239  unionL = (BOX *) palloc(sizeof(BOX));
240  *unionL = *cur;
241  }
242  else
243  adjustBox(unionL, cur);
244 
245  v->spl_nleft++;
246  }
247  else
248  {
249  v->spl_right[v->spl_nright] = i;
250  if (unionR == NULL)
251  {
252  unionR = (BOX *) palloc(sizeof(BOX));
253  *unionR = *cur;
254  }
255  else
256  adjustBox(unionR, cur);
257 
258  v->spl_nright++;
259  }
260  }
261 
262  v->spl_ldatum = BoxPGetDatum(unionL);
263  v->spl_rdatum = BoxPGetDatum(unionR);
264 }
Definition: geo_decls.h:102
OffsetNumber * spl_left
Definition: gist.h:105
Datum spl_rdatum
Definition: gist.h:112
int32 n
Definition: gist.h:160
struct cursor * cur
Definition: ecpg.c:28
int spl_nleft
Definition: gist.h:106
uint16 OffsetNumber
Definition: off.h:24
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:161
int spl_nright
Definition: gist.h:111
Datum key
Definition: gist.h:123
#define FirstOffsetNumber
Definition: off.h:27
static void adjustBox(BOX *b, const BOX *addon)
Definition: gistproc.c:145
#define BoxPGetDatum(X)
Definition: geo_decls.h:160
Datum spl_ldatum
Definition: gist.h:107
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
OffsetNumber * spl_right
Definition: gist.h:110
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
void * palloc(Size size)
Definition: mcxt.c:848
int i

◆ g_box_consider_split()

static void g_box_consider_split ( ConsiderSplitContext context,
int  dimNum,
double  rightLower,
int  minLeftCount,
double  leftUpper,
int  maxLeftCount 
)
inlinestatic

Definition at line 350 of file gistproc.c.

References ConsiderSplitContext::boundingBox, ConsiderSplitContext::dim, ConsiderSplitContext::entriesCount, ConsiderSplitContext::first, BOX::high, ConsiderSplitContext::leftUpper, LIMIT_RATIO, BOX::low, Min, non_negative(), ConsiderSplitContext::overlap, ConsiderSplitContext::range, range(), ConsiderSplitContext::ratio, ConsiderSplitContext::rightLower, Point::x, and Point::y.

Referenced by gist_box_picksplit().

353 {
354  int leftCount,
355  rightCount;
356  float4 ratio,
357  overlap;
358  double range;
359 
360  /*
361  * Calculate entries distribution ratio assuming most uniform distribution
362  * of common entries.
363  */
364  if (minLeftCount >= (context->entriesCount + 1) / 2)
365  {
366  leftCount = minLeftCount;
367  }
368  else
369  {
370  if (maxLeftCount <= context->entriesCount / 2)
371  leftCount = maxLeftCount;
372  else
373  leftCount = context->entriesCount / 2;
374  }
375  rightCount = context->entriesCount - leftCount;
376 
377  /*
378  * Ratio of split - quotient between size of lesser group and total
379  * entries count.
380  */
381  ratio = ((float4) Min(leftCount, rightCount)) /
382  ((float4) context->entriesCount);
383 
384  if (ratio > LIMIT_RATIO)
385  {
386  bool selectthis = false;
387 
388  /*
389  * The ratio is acceptable, so compare current split with previously
390  * selected one. Between splits of one dimension we search for minimal
391  * overlap (allowing negative values) and minimal ration (between same
392  * overlaps. We switch dimension if find less overlap (non-negative)
393  * or less range with same overlap.
394  */
395  if (dimNum == 0)
396  range = context->boundingBox.high.x - context->boundingBox.low.x;
397  else
398  range = context->boundingBox.high.y - context->boundingBox.low.y;
399 
400  overlap = (leftUpper - rightLower) / range;
401 
402  /* If there is no previous selection, select this */
403  if (context->first)
404  selectthis = true;
405  else if (context->dim == dimNum)
406  {
407  /*
408  * Within the same dimension, choose the new split if it has a
409  * smaller overlap, or same overlap but better ratio.
410  */
411  if (overlap < context->overlap ||
412  (overlap == context->overlap && ratio > context->ratio))
413  selectthis = true;
414  }
415  else
416  {
417  /*
418  * Across dimensions, choose the new split if it has a smaller
419  * *non-negative* overlap, or same *non-negative* overlap but
420  * bigger range. This condition differs from the one described in
421  * the article. On the datasets where leaf MBRs don't overlap
422  * themselves, non-overlapping splits (i.e. splits which have zero
423  * *non-negative* overlap) are frequently possible. In this case
424  * splits tends to be along one dimension, because most distant
425  * non-overlapping splits (i.e. having lowest negative overlap)
426  * appears to be in the same dimension as in the previous split.
427  * Therefore MBRs appear to be very prolonged along another
428  * dimension, which leads to bad search performance. Using range
429  * as the second split criteria makes MBRs more quadratic. Using
430  * *non-negative* overlap instead of overlap as the first split
431  * criteria gives to range criteria a chance to matter, because
432  * non-overlapping splits are equivalent in this criteria.
433  */
434  if (non_negative(overlap) < non_negative(context->overlap) ||
435  (range > context->range &&
436  non_negative(overlap) <= non_negative(context->overlap)))
437  selectthis = true;
438  }
439 
440  if (selectthis)
441  {
442  /* save information about selected split */
443  context->first = false;
444  context->ratio = ratio;
445  context->range = range;
446  context->overlap = overlap;
447  context->rightLower = rightLower;
448  context->leftUpper = leftUpper;
449  context->dim = dimNum;
450  }
451  }
452 }
#define Min(x, y)
Definition: c.h:802
double y
Definition: geo_decls.h:60
double x
Definition: geo_decls.h:60
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:416
Point low
Definition: geo_decls.h:104
float float4
Definition: c.h:428
#define LIMIT_RATIO
Definition: gistproc.c:35
static float non_negative(float val)
Definition: gistproc.c:338
Point high
Definition: geo_decls.h:104

◆ gist_bbox_distance()

static double gist_bbox_distance ( GISTENTRY entry,
Datum  query,
StrategyNumber  strategy,
bool recheck 
)
static

Definition at line 1491 of file gistproc.c.

References computeDistance(), DatumGetBoxP, DatumGetPointP, elog, ERROR, GeoStrategyNumberOffset, GISTENTRY::key, and PointStrategyNumberGroup.

Referenced by gist_circle_distance(), and gist_poly_distance().

1493 {
1494  double distance;
1495  StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1496 
1497  /* Bounding box distance is always inexact. */
1498  *recheck = true;
1499 
1500  switch (strategyGroup)
1501  {
1503  distance = computeDistance(false,
1504  DatumGetBoxP(entry->key),
1505  DatumGetPointP(query));
1506  break;
1507  default:
1508  elog(ERROR, "unrecognized strategy number: %d", strategy);
1509  distance = 0.0; /* keep compiler quiet */
1510  }
1511 
1512  return distance;
1513 }
#define GeoStrategyNumberOffset
Definition: gistproc.c:1338
uint16 StrategyNumber
Definition: stratnum.h:22
#define PointStrategyNumberGroup
Definition: gistproc.c:1339
#define ERROR
Definition: elog.h:43
Datum key
Definition: gist.h:123
static double computeDistance(bool isLeaf, BOX *box, Point *point)
Definition: gistproc.c:1229
#define DatumGetPointP(X)
Definition: geo_decls.h:137
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
#define elog
Definition: elog.h:219

◆ gist_box_consistent()

Datum gist_box_consistent ( PG_FUNCTION_ARGS  )

Definition at line 112 of file gistproc.c.

References DatumGetBoxP, gist_box_leaf_consistent(), GIST_LEAF, GISTENTRY::key, PG_GETARG_BOX_P, PG_GETARG_POINTER, PG_GETARG_UINT16, PG_RETURN_BOOL, and rtree_internal_consistent().

113 {
114  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
115  BOX *query = PG_GETARG_BOX_P(1);
117 
118  /* Oid subtype = PG_GETARG_OID(3); */
119  bool *recheck = (bool *) PG_GETARG_POINTER(4);
120 
121  /* All cases served by this function are exact */
122  *recheck = false;
123 
124  if (DatumGetBoxP(entry->key) == NULL || query == NULL)
125  PG_RETURN_BOOL(false);
126 
127  /*
128  * if entry is not leaf, use rtree_internal_consistent, else use
129  * gist_box_leaf_consistent
130  */
131  if (GIST_LEAF(entry))
133  query,
134  strategy));
135  else
137  query,
138  strategy));
139 }
#define GIST_LEAF(entry)
Definition: gist.h:133
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:963
Definition: geo_decls.h:102
static bool gist_box_leaf_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:876
#define PG_GETARG_BOX_P(n)
Definition: geo_decls.h:161
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum key
Definition: gist.h:123
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:237

◆ gist_box_leaf_consistent()

static bool gist_box_leaf_consistent ( BOX key,
BOX query,
StrategyNumber  strategy 
)
static

Definition at line 876 of file gistproc.c.

References box_above(), box_below(), box_contain(), box_contained(), box_left(), box_overabove(), box_overbelow(), box_overlap(), box_overleft(), box_overright(), box_right(), box_same(), DatumGetBool, DirectFunctionCall2, elog, ERROR, PointerGetDatum, RTAboveStrategyNumber, RTBelowStrategyNumber, RTContainedByStrategyNumber, RTContainsStrategyNumber, RTLeftStrategyNumber, RTOldContainedByStrategyNumber, RTOldContainsStrategyNumber, RTOverAboveStrategyNumber, RTOverBelowStrategyNumber, RTOverlapStrategyNumber, RTOverLeftStrategyNumber, RTOverRightStrategyNumber, RTRightStrategyNumber, and RTSameStrategyNumber.

Referenced by gist_box_consistent().

877 {
878  bool retval;
879 
880  switch (strategy)
881  {
884  PointerGetDatum(key),
885  PointerGetDatum(query)));
886  break;
889  PointerGetDatum(key),
890  PointerGetDatum(query)));
891  break;
894  PointerGetDatum(key),
895  PointerGetDatum(query)));
896  break;
899  PointerGetDatum(key),
900  PointerGetDatum(query)));
901  break;
904  PointerGetDatum(key),
905  PointerGetDatum(query)));
906  break;
909  PointerGetDatum(key),
910  PointerGetDatum(query)));
911  break;
915  PointerGetDatum(key),
916  PointerGetDatum(query)));
917  break;
921  PointerGetDatum(key),
922  PointerGetDatum(query)));
923  break;
926  PointerGetDatum(key),
927  PointerGetDatum(query)));
928  break;
931  PointerGetDatum(key),
932  PointerGetDatum(query)));
933  break;
936  PointerGetDatum(key),
937  PointerGetDatum(query)));
938  break;
941  PointerGetDatum(key),
942  PointerGetDatum(query)));
943  break;
944  default:
945  elog(ERROR, "unrecognized strategy number: %d", strategy);
946  retval = false; /* keep compiler quiet */
947  break;
948  }
949  return retval;
950 }
Datum box_right(PG_FUNCTION_ARGS)
Definition: geo_ops.c:564
Datum box_contained(PG_FUNCTION_ARGS)
Definition: geo_ops.c:636
Datum box_same(PG_FUNCTION_ARGS)
Definition: geo_ops.c:504
Datum box_left(PG_FUNCTION_ARGS)
Definition: geo_ops.c:538
#define RTOldContainsStrategyNumber
Definition: stratnum.h:56
#define RTOldContainedByStrategyNumber
Definition: stratnum.h:57
#define RTLeftStrategyNumber
Definition: stratnum.h:44
Datum box_overright(PG_FUNCTION_ARGS)
Definition: geo_ops.c:579
#define PointerGetDatum(X)
Definition: postgres.h:562
Datum box_overlap(PG_FUNCTION_ARGS)
Definition: geo_ops.c:518
#define RTOverBelowStrategyNumber
Definition: stratnum.h:52
#define RTContainedByStrategyNumber
Definition: stratnum.h:51
#define RTBelowStrategyNumber
Definition: stratnum.h:53
#define RTOverAboveStrategyNumber
Definition: stratnum.h:55
#define ERROR
Definition: elog.h:43
Datum box_contain(PG_FUNCTION_ARGS)
Definition: geo_ops.c:650
Datum box_above(PG_FUNCTION_ARGS)
Definition: geo_ops.c:613
#define DatumGetBool(X)
Definition: postgres.h:399
#define RTSameStrategyNumber
Definition: stratnum.h:49
#define RTOverRightStrategyNumber
Definition: stratnum.h:47
#define RTOverLeftStrategyNumber
Definition: stratnum.h:45
Datum box_overbelow(PG_FUNCTION_ARGS)
Definition: geo_ops.c:602
Datum box_below(PG_FUNCTION_ARGS)
Definition: geo_ops.c:590
#define RTAboveStrategyNumber
Definition: stratnum.h:54
#define RTRightStrategyNumber
Definition: stratnum.h:48
Datum box_overleft(PG_FUNCTION_ARGS)
Definition: geo_ops.c:553
#define RTContainsStrategyNumber
Definition: stratnum.h:50
#define RTOverlapStrategyNumber
Definition: stratnum.h:46
Datum box_overabove(PG_FUNCTION_ARGS)
Definition: geo_ops.c:625
#define elog
Definition: elog.h:219
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587

◆ gist_box_penalty()

Datum gist_box_penalty ( PG_FUNCTION_ARGS  )

Definition at line 198 of file gistproc.c.

References box_penalty(), DatumGetBoxP, GISTENTRY::key, PG_GETARG_POINTER, and PG_RETURN_POINTER.

199 {
200  GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
201  GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
202  float *result = (float *) PG_GETARG_POINTER(2);
203  BOX *origbox = DatumGetBoxP(origentry->key);
204  BOX *newbox = DatumGetBoxP(newentry->key);
205 
206  *result = (float) box_penalty(origbox, newbox);
207  PG_RETURN_POINTER(result);
208 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
Definition: geo_decls.h:102
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum key
Definition: gist.h:123
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
static double box_penalty(const BOX *original, const BOX *new)
Definition: gistproc.c:96

◆ gist_box_picksplit()

Datum gist_box_picksplit ( PG_FUNCTION_ARGS  )

Definition at line 499 of file gistproc.c.

References Abs, adjustBox(), Assert, ConsiderSplitContext::boundingBox, box_penalty(), common_entry_cmp(), DatumGetBoxP, CommonEntry::delta, ConsiderSplitContext::dim, ConsiderSplitContext::entriesCount, fallbackSplit(), ConsiderSplitContext::first, FirstOffsetNumber, FLOAT8_EQ, FLOAT8_GE, FLOAT8_GT, FLOAT8_LE, FLOAT8_LT, g_box_consider_split(), BOX::high, i, CommonEntry::index, interval_cmp_lower(), interval_cmp_upper(), GISTENTRY::key, ConsiderSplitContext::leftUpper, LIMIT_RATIO, BOX::low, lower(), SplitInterval::lower, GistEntryVector::n, OffsetNumberNext, palloc(), palloc0(), PG_GETARG_POINTER, PG_RETURN_POINTER, PLACE_LEFT, PLACE_RIGHT, PointerGetDatum, qsort, ConsiderSplitContext::rightLower, GIST_SPLITVEC::spl_ldatum, GIST_SPLITVEC::spl_left, GIST_SPLITVEC::spl_nleft, GIST_SPLITVEC::spl_nright, GIST_SPLITVEC::spl_rdatum, GIST_SPLITVEC::spl_right, upper(), SplitInterval::upper, GistEntryVector::vector, Point::x, and Point::y.

500 {
503  OffsetNumber i,
504  maxoff;
505  ConsiderSplitContext context;
506  BOX *box,
507  *leftBox,
508  *rightBox;
509  int dim,
510  commonEntriesCount;
511  SplitInterval *intervalsLower,
512  *intervalsUpper;
513  CommonEntry *commonEntries;
514  int nentries;
515 
516  memset(&context, 0, sizeof(ConsiderSplitContext));
517 
518  maxoff = entryvec->n - 1;
519  nentries = context.entriesCount = maxoff - FirstOffsetNumber + 1;
520 
521  /* Allocate arrays for intervals along axes */
522  intervalsLower = (SplitInterval *) palloc(nentries * sizeof(SplitInterval));
523  intervalsUpper = (SplitInterval *) palloc(nentries * sizeof(SplitInterval));
524 
525  /*
526  * Calculate the overall minimum bounding box over all the entries.
527  */
528  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
529  {
530  box = DatumGetBoxP(entryvec->vector[i].key);
531  if (i == FirstOffsetNumber)
532  context.boundingBox = *box;
533  else
534  adjustBox(&context.boundingBox, box);
535  }
536 
537  /*
538  * Iterate over axes for optimal split searching.
539  */
540  context.first = true; /* nothing selected yet */
541  for (dim = 0; dim < 2; dim++)
542  {
543  double leftUpper,
544  rightLower;
545  int i1,
546  i2;
547 
548  /* Project each entry as an interval on the selected axis. */
549  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
550  {
551  box = DatumGetBoxP(entryvec->vector[i].key);
552  if (dim == 0)
553  {
554  intervalsLower[i - FirstOffsetNumber].lower = box->low.x;
555  intervalsLower[i - FirstOffsetNumber].upper = box->high.x;
556  }
557  else
558  {
559  intervalsLower[i - FirstOffsetNumber].lower = box->low.y;
560  intervalsLower[i - FirstOffsetNumber].upper = box->high.y;
561  }
562  }
563 
564  /*
565  * Make two arrays of intervals: one sorted by lower bound and another
566  * sorted by upper bound.
567  */
568  memcpy(intervalsUpper, intervalsLower,
569  sizeof(SplitInterval) * nentries);
570  qsort(intervalsLower, nentries, sizeof(SplitInterval),
572  qsort(intervalsUpper, nentries, sizeof(SplitInterval),
574 
575  /*----
576  * The goal is to form a left and right interval, so that every entry
577  * interval is contained by either left or right interval (or both).
578  *
579  * For example, with the intervals (0,1), (1,3), (2,3), (2,4):
580  *
581  * 0 1 2 3 4
582  * +-+
583  * +---+
584  * +-+
585  * +---+
586  *
587  * The left and right intervals are of the form (0,a) and (b,4).
588  * We first consider splits where b is the lower bound of an entry.
589  * We iterate through all entries, and for each b, calculate the
590  * smallest possible a. Then we consider splits where a is the
591  * upper bound of an entry, and for each a, calculate the greatest
592  * possible b.
593  *
594  * In the above example, the first loop would consider splits:
595  * b=0: (0,1)-(0,4)
596  * b=1: (0,1)-(1,4)
597  * b=2: (0,3)-(2,4)
598  *
599  * And the second loop:
600  * a=1: (0,1)-(1,4)
601  * a=3: (0,3)-(2,4)
602  * a=4: (0,4)-(2,4)
603  */
604 
605  /*
606  * Iterate over lower bound of right group, finding smallest possible
607  * upper bound of left group.
608  */
609  i1 = 0;
610  i2 = 0;
611  rightLower = intervalsLower[i1].lower;
612  leftUpper = intervalsUpper[i2].lower;
613  while (true)
614  {
615  /*
616  * Find next lower bound of right group.
617  */
618  while (i1 < nentries &&
619  FLOAT8_EQ(rightLower, intervalsLower[i1].lower))
620  {
621  if (FLOAT8_LT(leftUpper, intervalsLower[i1].upper))
622  leftUpper = intervalsLower[i1].upper;
623  i1++;
624  }
625  if (i1 >= nentries)
626  break;
627  rightLower = intervalsLower[i1].lower;
628 
629  /*
630  * Find count of intervals which anyway should be placed to the
631  * left group.
632  */
633  while (i2 < nentries &&
634  FLOAT8_LE(intervalsUpper[i2].upper, leftUpper))
635  i2++;
636 
637  /*
638  * Consider found split.
639  */
640  g_box_consider_split(&context, dim, rightLower, i1, leftUpper, i2);
641  }
642 
643  /*
644  * Iterate over upper bound of left group finding greatest possible
645  * lower bound of right group.
646  */
647  i1 = nentries - 1;
648  i2 = nentries - 1;
649  rightLower = intervalsLower[i1].upper;
650  leftUpper = intervalsUpper[i2].upper;
651  while (true)
652  {
653  /*
654  * Find next upper bound of left group.
655  */
656  while (i2 >= 0 && FLOAT8_EQ(leftUpper, intervalsUpper[i2].upper))
657  {
658  if (FLOAT8_GT(rightLower, intervalsUpper[i2].lower))
659  rightLower = intervalsUpper[i2].lower;
660  i2--;
661  }
662  if (i2 < 0)
663  break;
664  leftUpper = intervalsUpper[i2].upper;
665 
666  /*
667  * Find count of intervals which anyway should be placed to the
668  * right group.
669  */
670  while (i1 >= 0 && FLOAT8_GE(intervalsLower[i1].lower, rightLower))
671  i1--;
672 
673  /*
674  * Consider found split.
675  */
676  g_box_consider_split(&context, dim,
677  rightLower, i1 + 1, leftUpper, i2 + 1);
678  }
679  }
680 
681  /*
682  * If we failed to find any acceptable splits, use trivial split.
683  */
684  if (context.first)
685  {
686  fallbackSplit(entryvec, v);
688  }
689 
690  /*
691  * Ok, we have now selected the split across one axis.
692  *
693  * While considering the splits, we already determined that there will be
694  * enough entries in both groups to reach the desired ratio, but we did
695  * not memorize which entries go to which group. So determine that now.
696  */
697 
698  /* Allocate vectors for results */
699  v->spl_left = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
700  v->spl_right = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
701  v->spl_nleft = 0;
702  v->spl_nright = 0;
703 
704  /* Allocate bounding boxes of left and right groups */
705  leftBox = palloc0(sizeof(BOX));
706  rightBox = palloc0(sizeof(BOX));
707 
708  /*
709  * Allocate an array for "common entries" - entries which can be placed to
710  * either group without affecting overlap along selected axis.
711  */
712  commonEntriesCount = 0;
713  commonEntries = (CommonEntry *) palloc(nentries * sizeof(CommonEntry));
714 
715  /* Helper macros to place an entry in the left or right group */
716 #define PLACE_LEFT(box, off) \
717  do { \
718  if (v->spl_nleft > 0) \
719  adjustBox(leftBox, box); \
720  else \
721  *leftBox = *(box); \
722  v->spl_left[v->spl_nleft++] = off; \
723  } while(0)
724 
725 #define PLACE_RIGHT(box, off) \
726  do { \
727  if (v->spl_nright > 0) \
728  adjustBox(rightBox, box); \
729  else \
730  *rightBox = *(box); \
731  v->spl_right[v->spl_nright++] = off; \
732  } while(0)
733 
734  /*
735  * Distribute entries which can be distributed unambiguously, and collect
736  * common entries.
737  */
738  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
739  {
740  double lower,
741  upper;
742 
743  /*
744  * Get upper and lower bounds along selected axis.
745  */
746  box = DatumGetBoxP(entryvec->vector[i].key);
747  if (context.dim == 0)
748  {
749  lower = box->low.x;
750  upper = box->high.x;
751  }
752  else
753  {
754  lower = box->low.y;
755  upper = box->high.y;
756  }
757 
758  if (FLOAT8_LE(upper, context.leftUpper))
759  {
760  /* Fits to the left group */
761  if (FLOAT8_GE(lower, context.rightLower))
762  {
763  /* Fits also to the right group, so "common entry" */
764  commonEntries[commonEntriesCount++].index = i;
765  }
766  else
767  {
768  /* Doesn't fit to the right group, so join to the left group */
769  PLACE_LEFT(box, i);
770  }
771  }
772  else
773  {
774  /*
775  * Each entry should fit on either left or right group. Since this
776  * entry didn't fit on the left group, it better fit in the right
777  * group.
778  */
779  Assert(FLOAT8_GE(lower, context.rightLower));
780 
781  /* Doesn't fit to the left group, so join to the right group */
782  PLACE_RIGHT(box, i);
783  }
784  }
785 
786  /*
787  * Distribute "common entries", if any.
788  */
789  if (commonEntriesCount > 0)
790  {
791  /*
792  * Calculate minimum number of entries that must be placed in both
793  * groups, to reach LIMIT_RATIO.
794  */
795  int m = ceil(LIMIT_RATIO * (double) nentries);
796 
797  /*
798  * Calculate delta between penalties of join "common entries" to
799  * different groups.
800  */
801  for (i = 0; i < commonEntriesCount; i++)
802  {
803  box = DatumGetBoxP(entryvec->vector[commonEntries[i].index].key);
804  commonEntries[i].delta = Abs(box_penalty(leftBox, box) -
805  box_penalty(rightBox, box));
806  }
807 
808  /*
809  * Sort "common entries" by calculated deltas in order to distribute
810  * the most ambiguous entries first.
811  */
812  qsort(commonEntries, commonEntriesCount, sizeof(CommonEntry), common_entry_cmp);
813 
814  /*
815  * Distribute "common entries" between groups.
816  */
817  for (i = 0; i < commonEntriesCount; i++)
818  {
819  box = DatumGetBoxP(entryvec->vector[commonEntries[i].index].key);
820 
821  /*
822  * Check if we have to place this entry in either group to achieve
823  * LIMIT_RATIO.
824  */
825  if (v->spl_nleft + (commonEntriesCount - i) <= m)
826  PLACE_LEFT(box, commonEntries[i].index);
827  else if (v->spl_nright + (commonEntriesCount - i) <= m)
828  PLACE_RIGHT(box, commonEntries[i].index);
829  else
830  {
831  /* Otherwise select the group by minimal penalty */
832  if (box_penalty(leftBox, box) < box_penalty(rightBox, box))
833  PLACE_LEFT(box, commonEntries[i].index);
834  else
835  PLACE_RIGHT(box, commonEntries[i].index);
836  }
837  }
838  }
839 
840  v->spl_ldatum = PointerGetDatum(leftBox);
841  v->spl_rdatum = PointerGetDatum(rightBox);
843 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
Definition: geo_decls.h:102
#define PLACE_LEFT(box, off)
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:43
static int interval_cmp_lower(const void *i1, const void *i2)
Definition: gistproc.c:314
#define PointerGetDatum(X)
Definition: postgres.h:562
static int interval_cmp_upper(const void *i1, const void *i2)
Definition: gistproc.c:326
double y
Definition: geo_decls.h:60
OffsetNumber * spl_left
Definition: gist.h:105
Datum spl_rdatum
Definition: gist.h:112
static int common_entry_cmp(const void *i1, const void *i2)
Definition: gistproc.c:459
int32 n
Definition: gist.h:160
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:74
int spl_nleft
Definition: gist.h:106
#define PLACE_RIGHT(box, off)
uint16 OffsetNumber
Definition: off.h:24
double delta
Definition: gistproc.c:275
#define Abs(x)
Definition: c.h:808
double x
Definition: geo_decls.h:60
Definition: type.h:89
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:161
#define FLOAT8_GE(a, b)
Definition: gistproc.c:42
int spl_nright
Definition: gist.h:111
static void g_box_consider_split(ConsiderSplitContext *context, int dimNum, double rightLower, int minLeftCount, double leftUpper, int maxLeftCount)
Definition: gistproc.c:350
#define FLOAT8_LE(a, b)
Definition: gistproc.c:40
Datum key
Definition: gist.h:123
#define FirstOffsetNumber
Definition: off.h:27
static void fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
Definition: gistproc.c:215
double lower
Definition: gistproc.c:306
#define FLOAT8_EQ(a, b)
Definition: gistproc.c:38
static void adjustBox(BOX *b, const BOX *addon)
Definition: gistproc.c:145
Point low
Definition: geo_decls.h:104
void * palloc0(Size size)
Definition: mcxt.c:877
#define LIMIT_RATIO
Definition: gistproc.c:35
Datum spl_ldatum
Definition: gist.h:107
#define Assert(condition)
Definition: c.h:670
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
OffsetNumber * spl_right
Definition: gist.h:110
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
Point high
Definition: geo_decls.h:104
static double box_penalty(const BOX *original, const BOX *new)
Definition: gistproc.c:96
void * palloc(Size size)
Definition: mcxt.c:848
int i
#define FLOAT8_GT(a, b)
Definition: gistproc.c:41
#define qsort(a, b, c, d)
Definition: port.h:408
#define FLOAT8_LT(a, b)
Definition: gistproc.c:39
double upper
Definition: gistproc.c:306

◆ gist_box_same()

Datum gist_box_same ( PG_FUNCTION_ARGS  )

Definition at line 856 of file gistproc.c.

References FLOAT8_EQ, BOX::high, BOX::low, PG_GETARG_BOX_P, PG_GETARG_POINTER, PG_RETURN_POINTER, Point::x, and Point::y.

857 {
858  BOX *b1 = PG_GETARG_BOX_P(0);
859  BOX *b2 = PG_GETARG_BOX_P(1);
860  bool *result = (bool *) PG_GETARG_POINTER(2);
861 
862  if (b1 && b2)
863  *result = (FLOAT8_EQ(b1->low.x, b2->low.x) &&
864  FLOAT8_EQ(b1->low.y, b2->low.y) &&
865  FLOAT8_EQ(b1->high.x, b2->high.x) &&
866  FLOAT8_EQ(b1->high.y, b2->high.y));
867  else
868  *result = (b1 == NULL && b2 == NULL);
869  PG_RETURN_POINTER(result);
870 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
Definition: geo_decls.h:102
#define PG_GETARG_BOX_P(n)
Definition: geo_decls.h:161
double y
Definition: geo_decls.h:60
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
double x
Definition: geo_decls.h:60
#define FLOAT8_EQ(a, b)
Definition: gistproc.c:38
Point low
Definition: geo_decls.h:104
Point high
Definition: geo_decls.h:104

◆ gist_box_union()

Datum gist_box_union ( PG_FUNCTION_ARGS  )

Definition at line 163 of file gistproc.c.

References adjustBox(), cur, DatumGetBoxP, i, GISTENTRY::key, GistEntryVector::n, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, and GistEntryVector::vector.

164 {
166  int *sizep = (int *) PG_GETARG_POINTER(1);
167  int numranges,
168  i;
169  BOX *cur,
170  *pageunion;
171 
172  numranges = entryvec->n;
173  pageunion = (BOX *) palloc(sizeof(BOX));
174  cur = DatumGetBoxP(entryvec->vector[0].key);
175  memcpy((void *) pageunion, (void *) cur, sizeof(BOX));
176 
177  for (i = 1; i < numranges; i++)
178  {
179  cur = DatumGetBoxP(entryvec->vector[i].key);
180  adjustBox(pageunion, cur);
181  }
182  *sizep = sizeof(BOX);
183 
184  PG_RETURN_POINTER(pageunion);
185 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
Definition: geo_decls.h:102
int32 n
Definition: gist.h:160
struct cursor * cur
Definition: ecpg.c:28
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:161
Datum key
Definition: gist.h:123
static void adjustBox(BOX *b, const BOX *addon)
Definition: gistproc.c:145
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
void * palloc(Size size)
Definition: mcxt.c:848
int i

◆ gist_circle_compress()

Datum gist_circle_compress ( PG_FUNCTION_ARGS  )

Definition at line 1108 of file gistproc.c.

References CIRCLE::center, DatumGetCircleP, gistentryinit, BOX::high, GISTENTRY::key, GISTENTRY::leafkey, BOX::low, GISTENTRY::offset, GISTENTRY::page, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum, CIRCLE::radius, GISTENTRY::rel, Point::x, and Point::y.

1109 {
1110  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1111  GISTENTRY *retval;
1112 
1113  if (entry->leafkey)
1114  {
1115  CIRCLE *in = DatumGetCircleP(entry->key);
1116  BOX *r;
1117 
1118  r = (BOX *) palloc(sizeof(BOX));
1119  r->high.x = in->center.x + in->radius;
1120  r->low.x = in->center.x - in->radius;
1121  r->high.y = in->center.y + in->radius;
1122  r->low.y = in->center.y - in->radius;
1123 
1124  retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
1125  gistentryinit(*retval, PointerGetDatum(r),
1126  entry->rel, entry->page,
1127  entry->offset, false);
1128  }
1129  else
1130  retval = entry;
1131  PG_RETURN_POINTER(retval);
1132 }
Relation rel
Definition: gist.h:124
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
Definition: geo_decls.h:102
#define PointerGetDatum(X)
Definition: postgres.h:562
double radius
Definition: geo_decls.h:127
double y
Definition: geo_decls.h:60
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Page page
Definition: gist.h:125
double x
Definition: geo_decls.h:60
Datum key
Definition: gist.h:123
#define DatumGetCircleP(X)
Definition: geo_decls.h:171
bool leafkey
Definition: gist.h:127
Point low
Definition: geo_decls.h:104
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:169
Point high
Definition: geo_decls.h:104
Point center
Definition: geo_decls.h:126
void * palloc(Size size)
Definition: mcxt.c:848
OffsetNumber offset
Definition: gist.h:126

◆ gist_circle_consistent()

Datum gist_circle_consistent ( PG_FUNCTION_ARGS  )

Definition at line 1138 of file gistproc.c.

References CIRCLE::center, DatumGetBoxP, BOX::high, GISTENTRY::key, BOX::low, PG_GETARG_CIRCLE_P, PG_GETARG_POINTER, PG_GETARG_UINT16, PG_RETURN_BOOL, CIRCLE::radius, rtree_internal_consistent(), Point::x, and Point::y.

Referenced by gist_point_consistent().

1139 {
1140  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1141  CIRCLE *query = PG_GETARG_CIRCLE_P(1);
1143 
1144  /* Oid subtype = PG_GETARG_OID(3); */
1145  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1146  BOX bbox;
1147  bool result;
1148 
1149  /* All cases served by this function are inexact */
1150  *recheck = true;
1151 
1152  if (DatumGetBoxP(entry->key) == NULL || query == NULL)
1153  PG_RETURN_BOOL(false);
1154 
1155  /*
1156  * Since the operators require recheck anyway, we can just use
1157  * rtree_internal_consistent even at leaf nodes. (This works in part
1158  * because the index entries are bounding boxes not circles.)
1159  */
1160  bbox.high.x = query->center.x + query->radius;
1161  bbox.low.x = query->center.x - query->radius;
1162  bbox.high.y = query->center.y + query->radius;
1163  bbox.low.y = query->center.y - query->radius;
1164 
1165  result = rtree_internal_consistent(DatumGetBoxP(entry->key),
1166  &bbox, strategy);
1167 
1168  PG_RETURN_BOOL(result);
1169 }
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:963
Definition: geo_decls.h:102
double radius
Definition: geo_decls.h:127
double y
Definition: geo_decls.h:60
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
double x
Definition: geo_decls.h:60
Datum key
Definition: gist.h:123
Point low
Definition: geo_decls.h:104
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
#define PG_GETARG_CIRCLE_P(n)
Definition: geo_decls.h:173
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
Point high
Definition: geo_decls.h:104
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:237
Point center
Definition: geo_decls.h:126

◆ gist_circle_distance()

Datum gist_circle_distance ( PG_FUNCTION_ARGS  )

Definition at line 1516 of file gistproc.c.

References gist_bbox_distance(), PG_GETARG_DATUM, PG_GETARG_POINTER, PG_GETARG_UINT16, and PG_RETURN_FLOAT8.

1517 {
1518  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1519  Datum query = PG_GETARG_DATUM(1);
1521 
1522  /* Oid subtype = PG_GETARG_OID(3); */
1523  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1524  double distance;
1525 
1526  distance = gist_bbox_distance(entry, query, strategy, recheck);
1527 
1528  PG_RETURN_FLOAT8(distance);
1529 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:326
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
static double gist_bbox_distance(GISTENTRY *entry, Datum query, StrategyNumber strategy, bool *recheck)
Definition: gistproc.c:1491
uintptr_t Datum
Definition: postgres.h:372
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:237

◆ gist_point_compress()

Datum gist_point_compress ( PG_FUNCTION_ARGS  )

Definition at line 1176 of file gistproc.c.

References BoxPGetDatum, DatumGetPointP, gistentryinit, BOX::high, GISTENTRY::key, GISTENTRY::leafkey, BOX::low, GISTENTRY::offset, GISTENTRY::page, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, and GISTENTRY::rel.

1177 {
1178  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1179 
1180  if (entry->leafkey) /* Point, actually */
1181  {
1182  BOX *box = palloc(sizeof(BOX));
1183  Point *point = DatumGetPointP(entry->key);
1184  GISTENTRY *retval = palloc(sizeof(GISTENTRY));
1185 
1186  box->high = box->low = *point;
1187 
1188  gistentryinit(*retval, BoxPGetDatum(box),
1189  entry->rel, entry->page, entry->offset, false);
1190 
1191  PG_RETURN_POINTER(retval);
1192  }
1193 
1194  PG_RETURN_POINTER(entry);
1195 }
Relation rel
Definition: gist.h:124
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
Definition: geo_decls.h:102
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Page page
Definition: gist.h:125
Datum key
Definition: gist.h:123
bool leafkey
Definition: gist.h:127
Point low
Definition: geo_decls.h:104
#define BoxPGetDatum(X)
Definition: geo_decls.h:160
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:169
#define DatumGetPointP(X)
Definition: geo_decls.h:137
Point high
Definition: geo_decls.h:104
void * palloc(Size size)
Definition: mcxt.c:848
OffsetNumber offset
Definition: gist.h:126

◆ gist_point_consistent()

Datum gist_point_consistent ( PG_FUNCTION_ARGS  )

Definition at line 1345 of file gistproc.c.

References Assert, BoxStrategyNumberGroup, circle_contain_pt(), CirclePGetDatum, CircleStrategyNumberGroup, DatumGetBool, DatumGetBoxP, DirectFunctionCall2, DirectFunctionCall5, elog, ERROR, GeoStrategyNumberOffset, gist_circle_consistent(), GIST_LEAF, gist_point_consistent_internal(), gist_poly_consistent(), BOX::high, Int16GetDatum, GISTENTRY::key, BOX::low, PG_GETARG_BOX_P, PG_GETARG_CIRCLE_P, PG_GETARG_POINT_P, PG_GETARG_POINTER, PG_GETARG_POLYGON_P, PG_GETARG_UINT16, PG_RETURN_BOOL, PointerGetDatum, PointPGetDatum, PointStrategyNumberGroup, poly_contain_pt(), PolygonPGetDatum, PolygonStrategyNumberGroup, RTOverlapStrategyNumber, Point::x, and Point::y.

1346 {
1347  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1349  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1350  bool result;
1351  StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1352 
1353  switch (strategyGroup)
1354  {
1357  GIST_LEAF(entry),
1358  DatumGetBoxP(entry->key),
1359  PG_GETARG_POINT_P(1));
1360  *recheck = false;
1361  break;
1363  {
1364  /*
1365  * The only operator in this group is point <@ box (on_pb), so
1366  * we needn't examine strategy again.
1367  *
1368  * For historical reasons, on_pb uses exact rather than fuzzy
1369  * comparisons. We could use box_overlap when at an internal
1370  * page, but that would lead to possibly visiting child pages
1371  * uselessly, because box_overlap uses fuzzy comparisons.
1372  * Instead we write a non-fuzzy overlap test. The same code
1373  * will also serve for leaf-page tests, since leaf keys have
1374  * high == low.
1375  */
1376  BOX *query,
1377  *key;
1378 
1379  query = PG_GETARG_BOX_P(1);
1380  key = DatumGetBoxP(entry->key);
1381 
1382  result = (key->high.x >= query->low.x &&
1383  key->low.x <= query->high.x &&
1384  key->high.y >= query->low.y &&
1385  key->low.y <= query->high.y);
1386  *recheck = false;
1387  }
1388  break;
1390  {
1391  POLYGON *query = PG_GETARG_POLYGON_P(1);
1392 
1395  PointerGetDatum(entry),
1396  PolygonPGetDatum(query),
1398  0, PointerGetDatum(recheck)));
1399 
1400  if (GIST_LEAF(entry) && result)
1401  {
1402  /*
1403  * We are on leaf page and quick check shows overlapping
1404  * of polygon's bounding box and point
1405  */
1406  BOX *box = DatumGetBoxP(entry->key);
1407 
1408  Assert(box->high.x == box->low.x
1409  && box->high.y == box->low.y);
1412  PolygonPGetDatum(query),
1413  PointPGetDatum(&box->high)));
1414  *recheck = false;
1415  }
1416  }
1417  break;
1419  {
1420  CIRCLE *query = PG_GETARG_CIRCLE_P(1);
1421 
1424  PointerGetDatum(entry),
1425  CirclePGetDatum(query),
1427  0, PointerGetDatum(recheck)));
1428 
1429  if (GIST_LEAF(entry) && result)
1430  {
1431  /*
1432  * We are on leaf page and quick check shows overlapping
1433  * of polygon's bounding box and point
1434  */
1435  BOX *box = DatumGetBoxP(entry->key);
1436 
1437  Assert(box->high.x == box->low.x
1438  && box->high.y == box->low.y);
1441  CirclePGetDatum(query),
1442  PointPGetDatum(&box->high)));
1443  *recheck = false;
1444  }
1445  }
1446  break;
1447  default:
1448  elog(ERROR, "unrecognized strategy number: %d", strategy);
1449  result = false; /* keep compiler quiet */
1450  break;
1451  }
1452 
1453  PG_RETURN_BOOL(result);
1454 }
#define GIST_LEAF(entry)
Definition: gist.h:133
#define GeoStrategyNumberOffset
Definition: gistproc.c:1338
Definition: geo_decls.h:102
#define BoxStrategyNumberGroup
Definition: gistproc.c:1340
#define PG_GETARG_BOX_P(n)
Definition: geo_decls.h:161
#define CircleStrategyNumberGroup
Definition: gistproc.c:1342
#define PointerGetDatum(X)
Definition: postgres.h:562
#define PolygonPGetDatum(X)
Definition: geo_decls.h:166
double y
Definition: geo_decls.h:60
#define Int16GetDatum(X)
Definition: postgres.h:457
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Datum poly_contain_pt(PG_FUNCTION_ARGS)
Definition: geo_ops.c:3984
#define PG_GETARG_POLYGON_P(n)
Definition: geo_decls.h:167
#define PointStrategyNumberGroup
Definition: gistproc.c:1339
double x
Definition: geo_decls.h:60
#define CirclePGetDatum(X)
Definition: geo_decls.h:172
#define ERROR
Definition: elog.h:43
#define PG_GETARG_POINT_P(n)
Definition: geo_decls.h:139
Datum key
Definition: gist.h:123
#define DatumGetBool(X)
Definition: postgres.h:399
static bool gist_point_consistent_internal(StrategyNumber strategy, bool isLeaf, BOX *key, Point *query)
Definition: gistproc.c:1295
#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5)
Definition: fmgr.h:593
Point low
Definition: geo_decls.h:104
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
Datum circle_contain_pt(PG_FUNCTION_ARGS)
Definition: geo_ops.c:5013
Datum gist_circle_consistent(PG_FUNCTION_ARGS)
Definition: gistproc.c:1138
#define PolygonStrategyNumberGroup
Definition: gistproc.c:1341
#define PG_GETARG_CIRCLE_P(n)
Definition: geo_decls.h:173
#define Assert(condition)
Definition: c.h:670
Datum gist_poly_consistent(PG_FUNCTION_ARGS)
Definition: gistproc.c:1070
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
Point high
Definition: geo_decls.h:104
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:237
#define RTOverlapStrategyNumber
Definition: stratnum.h:46
#define elog
Definition: elog.h:219
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587
#define PointPGetDatum(X)
Definition: geo_decls.h:138

◆ gist_point_consistent_internal()

static bool gist_point_consistent_internal ( StrategyNumber  strategy,
bool  isLeaf,
BOX key,
Point query 
)
static

Definition at line 1295 of file gistproc.c.

References elog, ERROR, FPeq, FPge, FPgt, FPle, FPlt, BOX::high, BOX::low, RTAboveStrategyNumber, RTBelowStrategyNumber, RTLeftStrategyNumber, RTRightStrategyNumber, RTSameStrategyNumber, Point::x, and Point::y.

Referenced by gist_point_consistent().

1297 {
1298  bool result = false;
1299 
1300  switch (strategy)
1301  {
1302  case RTLeftStrategyNumber:
1303  result = FPlt(key->low.x, query->x);
1304  break;
1305  case RTRightStrategyNumber:
1306  result = FPgt(key->high.x, query->x);
1307  break;
1308  case RTAboveStrategyNumber:
1309  result = FPgt(key->high.y, query->y);
1310  break;
1311  case RTBelowStrategyNumber:
1312  result = FPlt(key->low.y, query->y);
1313  break;
1314  case RTSameStrategyNumber:
1315  if (isLeaf)
1316  {
1317  /* key.high must equal key.low, so we can disregard it */
1318  result = (FPeq(key->low.x, query->x) &&
1319  FPeq(key->low.y, query->y));
1320  }
1321  else
1322  {
1323  result = (FPle(query->x, key->high.x) &&
1324  FPge(query->x, key->low.x) &&
1325  FPle(query->y, key->high.y) &&
1326  FPge(query->y, key->low.y));
1327  }
1328  break;
1329  default:
1330  elog(ERROR, "unrecognized strategy number: %d", strategy);
1331  result = false; /* keep compiler quiet */
1332  break;
1333  }
1334 
1335  return result;
1336 }
#define RTLeftStrategyNumber
Definition: stratnum.h:44
double y
Definition: geo_decls.h:60
#define RTBelowStrategyNumber
Definition: stratnum.h:53
double x
Definition: geo_decls.h:60
#define FPgt(A, B)
Definition: geo_decls.h:41
#define ERROR
Definition: elog.h:43
#define RTSameStrategyNumber
Definition: stratnum.h:49
#define FPeq(A, B)
Definition: geo_decls.h:37
Point low
Definition: geo_decls.h:104
#define RTAboveStrategyNumber
Definition: stratnum.h:54
#define FPlt(A, B)
Definition: geo_decls.h:39
#define RTRightStrategyNumber
Definition: stratnum.h:48
Point high
Definition: geo_decls.h:104
#define FPge(A, B)
Definition: geo_decls.h:42
#define elog
Definition: elog.h:219
#define FPle(A, B)
Definition: geo_decls.h:40

◆ gist_point_distance()

Datum gist_point_distance ( PG_FUNCTION_ARGS  )

Definition at line 1457 of file gistproc.c.

References computeDistance(), DatumGetBoxP, elog, ERROR, GeoStrategyNumberOffset, GIST_LEAF, GISTENTRY::key, PG_GETARG_POINT_P, PG_GETARG_POINTER, PG_GETARG_UINT16, PG_RETURN_FLOAT8, and PointStrategyNumberGroup.

1458 {
1459  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1461  double distance;
1462  StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1463 
1464  switch (strategyGroup)
1465  {
1467  distance = computeDistance(GIST_LEAF(entry),
1468  DatumGetBoxP(entry->key),
1469  PG_GETARG_POINT_P(1));
1470  break;
1471  default:
1472  elog(ERROR, "unrecognized strategy number: %d", strategy);
1473  distance = 0.0; /* keep compiler quiet */
1474  break;
1475  }
1476 
1477  PG_RETURN_FLOAT8(distance);
1478 }
#define GIST_LEAF(entry)
Definition: gist.h:133
#define GeoStrategyNumberOffset
Definition: gistproc.c:1338
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:326
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define PointStrategyNumberGroup
Definition: gistproc.c:1339
#define ERROR
Definition: elog.h:43
#define PG_GETARG_POINT_P(n)
Definition: geo_decls.h:139
Datum key
Definition: gist.h:123
static double computeDistance(bool isLeaf, BOX *box, Point *point)
Definition: gistproc.c:1229
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:237
#define elog
Definition: elog.h:219

◆ gist_point_fetch()

Datum gist_point_fetch ( PG_FUNCTION_ARGS  )

Definition at line 1204 of file gistproc.c.

References DatumGetBoxP, gistentryinit, BOX::high, GISTENTRY::key, GISTENTRY::offset, GISTENTRY::page, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum, GISTENTRY::rel, Point::x, and Point::y.

1205 {
1206  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1207  BOX *in = DatumGetBoxP(entry->key);
1208  Point *r;
1209  GISTENTRY *retval;
1210 
1211  retval = palloc(sizeof(GISTENTRY));
1212 
1213  r = (Point *) palloc(sizeof(Point));
1214  r->x = in->high.x;
1215  r->y = in->high.y;
1216  gistentryinit(*retval, PointerGetDatum(r),
1217  entry->rel, entry->page,
1218  entry->offset, false);
1219 
1220  PG_RETURN_POINTER(retval);
1221 }
Relation rel
Definition: gist.h:124
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
Definition: geo_decls.h:102
#define PointerGetDatum(X)
Definition: postgres.h:562
double y
Definition: geo_decls.h:60
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Page page
Definition: gist.h:125
double x
Definition: geo_decls.h:60
Datum key
Definition: gist.h:123
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:169
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
Point high
Definition: geo_decls.h:104
void * palloc(Size size)
Definition: mcxt.c:848
OffsetNumber offset
Definition: gist.h:126

◆ gist_poly_compress()

Datum gist_poly_compress ( PG_FUNCTION_ARGS  )

Definition at line 1043 of file gistproc.c.

References POLYGON::boundbox, DatumGetPolygonP, gistentryinit, GISTENTRY::key, GISTENTRY::leafkey, GISTENTRY::offset, GISTENTRY::page, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum, and GISTENTRY::rel.

1044 {
1045  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1046  GISTENTRY *retval;
1047 
1048  if (entry->leafkey)
1049  {
1050  POLYGON *in = DatumGetPolygonP(entry->key);
1051  BOX *r;
1052 
1053  r = (BOX *) palloc(sizeof(BOX));
1054  memcpy((void *) r, (void *) &(in->boundbox), sizeof(BOX));
1055 
1056  retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
1057  gistentryinit(*retval, PointerGetDatum(r),
1058  entry->rel, entry->page,
1059  entry->offset, false);
1060  }
1061  else
1062  retval = entry;
1063  PG_RETURN_POINTER(retval);
1064 }
Relation rel
Definition: gist.h:124
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
Definition: geo_decls.h:102
#define PointerGetDatum(X)
Definition: postgres.h:562
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Page page
Definition: gist.h:125
Datum key
Definition: gist.h:123
bool leafkey
Definition: gist.h:127
BOX boundbox
Definition: geo_decls.h:117
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:169
#define DatumGetPolygonP(X)
Definition: geo_decls.h:164
void * palloc(Size size)
Definition: mcxt.c:848
OffsetNumber offset
Definition: gist.h:126

◆ gist_poly_consistent()

Datum gist_poly_consistent ( PG_FUNCTION_ARGS  )

Definition at line 1070 of file gistproc.c.

References POLYGON::boundbox, DatumGetBoxP, GISTENTRY::key, PG_FREE_IF_COPY, PG_GETARG_POINTER, PG_GETARG_POLYGON_P, PG_GETARG_UINT16, PG_RETURN_BOOL, and rtree_internal_consistent().

Referenced by gist_point_consistent().

1071 {
1072  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1073  POLYGON *query = PG_GETARG_POLYGON_P(1);
1075 
1076  /* Oid subtype = PG_GETARG_OID(3); */
1077  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1078  bool result;
1079 
1080  /* All cases served by this function are inexact */
1081  *recheck = true;
1082 
1083  if (DatumGetBoxP(entry->key) == NULL || query == NULL)
1084  PG_RETURN_BOOL(false);
1085 
1086  /*
1087  * Since the operators require recheck anyway, we can just use
1088  * rtree_internal_consistent even at leaf nodes. (This works in part
1089  * because the index entries are bounding boxes not polygons.)
1090  */
1091  result = rtree_internal_consistent(DatumGetBoxP(entry->key),
1092  &(query->boundbox), strategy);
1093 
1094  /* Avoid memory leak if supplied poly is toasted */
1095  PG_FREE_IF_COPY(query, 1);
1096 
1097  PG_RETURN_BOOL(result);
1098 }
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:963
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define PG_GETARG_POLYGON_P(n)
Definition: geo_decls.h:167
Datum key
Definition: gist.h:123
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
BOX boundbox
Definition: geo_decls.h:117
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:225
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:237

◆ gist_poly_distance()

Datum gist_poly_distance ( PG_FUNCTION_ARGS  )

Definition at line 1532 of file gistproc.c.

References gist_bbox_distance(), PG_GETARG_DATUM, PG_GETARG_POINTER, PG_GETARG_UINT16, and PG_RETURN_FLOAT8.

1533 {
1534  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1535  Datum query = PG_GETARG_DATUM(1);
1537 
1538  /* Oid subtype = PG_GETARG_OID(3); */
1539  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1540  double distance;
1541 
1542  distance = gist_bbox_distance(entry, query, strategy, recheck);
1543 
1544  PG_RETURN_FLOAT8(distance);
1545 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:326
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
static double gist_bbox_distance(GISTENTRY *entry, Datum query, StrategyNumber strategy, bool *recheck)
Definition: gistproc.c:1491
uintptr_t Datum
Definition: postgres.h:372
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:237

◆ interval_cmp_lower()

static int interval_cmp_lower ( const void *  i1,
const void *  i2 
)
static

Definition at line 314 of file gistproc.c.

References float8_cmp_internal().

Referenced by gist_box_picksplit().

315 {
316  double lower1 = ((const SplitInterval *) i1)->lower,
317  lower2 = ((const SplitInterval *) i2)->lower;
318 
319  return float8_cmp_internal(lower1, lower2);
320 }
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:1052

◆ interval_cmp_upper()

static int interval_cmp_upper ( const void *  i1,
const void *  i2 
)
static

Definition at line 326 of file gistproc.c.

References float8_cmp_internal().

Referenced by gist_box_picksplit().

327 {
328  double upper1 = ((const SplitInterval *) i1)->upper,
329  upper2 = ((const SplitInterval *) i2)->upper;
330 
331  return float8_cmp_internal(upper1, upper2);
332 }
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:1052

◆ non_negative()

static float non_negative ( float  val)
inlinestatic

Definition at line 338 of file gistproc.c.

References val.

Referenced by g_box_consider_split().

339 {
340  if (val >= 0.0f)
341  return val;
342  else
343  return 0.0f;
344 }
long val
Definition: informix.c:689

◆ rt_box_union()

static void rt_box_union ( BOX n,
const BOX a,
const BOX b 
)
static

Definition at line 55 of file gistproc.c.

References FLOAT8_MAX, FLOAT8_MIN, BOX::high, BOX::low, Point::x, and Point::y.

Referenced by box_penalty().

56 {
57  n->high.x = FLOAT8_MAX(a->high.x, b->high.x);
58  n->high.y = FLOAT8_MAX(a->high.y, b->high.y);
59  n->low.x = FLOAT8_MIN(a->low.x, b->low.x);
60  n->low.y = FLOAT8_MIN(a->low.y, b->low.y);
61 }
#define FLOAT8_MAX(a, b)
Definition: gistproc.c:43
double y
Definition: geo_decls.h:60
double x
Definition: geo_decls.h:60
Point low
Definition: geo_decls.h:104
#define FLOAT8_MIN(a, b)
Definition: gistproc.c:44
Point high
Definition: geo_decls.h:104

◆ rtree_internal_consistent()

static bool rtree_internal_consistent ( BOX key,
BOX query,
StrategyNumber  strategy 
)
static

Definition at line 963 of file gistproc.c.

References box_above(), box_below(), box_contain(), box_left(), box_overabove(), box_overbelow(), box_overlap(), box_overleft(), box_overright(), box_right(), DatumGetBool, DirectFunctionCall2, elog, ERROR, PointerGetDatum, RTAboveStrategyNumber, RTBelowStrategyNumber, RTContainedByStrategyNumber, RTContainsStrategyNumber, RTLeftStrategyNumber, RTOldContainedByStrategyNumber, RTOldContainsStrategyNumber, RTOverAboveStrategyNumber, RTOverBelowStrategyNumber, RTOverlapStrategyNumber, RTOverLeftStrategyNumber, RTOverRightStrategyNumber, RTRightStrategyNumber, and RTSameStrategyNumber.

Referenced by gist_box_consistent(), gist_circle_consistent(), and gist_poly_consistent().

964 {
965  bool retval;
966 
967  switch (strategy)
968  {
971  PointerGetDatum(key),
972  PointerGetDatum(query)));
973  break;
976  PointerGetDatum(key),
977  PointerGetDatum(query)));
978  break;
981  PointerGetDatum(key),
982  PointerGetDatum(query)));
983  break;
986  PointerGetDatum(key),
987  PointerGetDatum(query)));
988  break;
991  PointerGetDatum(key),
992  PointerGetDatum(query)));
993  break;
998  PointerGetDatum(key),
999  PointerGetDatum(query)));
1000  break;
1004  PointerGetDatum(key),
1005  PointerGetDatum(query)));
1006  break;
1009  PointerGetDatum(key),
1010  PointerGetDatum(query)));
1011  break;
1012  case RTBelowStrategyNumber:
1014  PointerGetDatum(key),
1015  PointerGetDatum(query)));
1016  break;
1017  case RTAboveStrategyNumber:
1019  PointerGetDatum(key),
1020  PointerGetDatum(query)));
1021  break;
1024  PointerGetDatum(key),
1025  PointerGetDatum(query)));
1026  break;
1027  default:
1028  elog(ERROR, "unrecognized strategy number: %d", strategy);
1029  retval = false; /* keep compiler quiet */
1030  break;
1031  }
1032  return retval;
1033 }
Datum box_right(PG_FUNCTION_ARGS)
Definition: geo_ops.c:564
Datum box_left(PG_FUNCTION_ARGS)
Definition: geo_ops.c:538
#define RTOldContainsStrategyNumber
Definition: stratnum.h:56
#define RTOldContainedByStrategyNumber
Definition: stratnum.h:57
#define RTLeftStrategyNumber
Definition: stratnum.h:44
Datum box_overright(PG_FUNCTION_ARGS)
Definition: geo_ops.c:579
#define PointerGetDatum(X)
Definition: postgres.h:562
Datum box_overlap(PG_FUNCTION_ARGS)
Definition: geo_ops.c:518
#define RTOverBelowStrategyNumber
Definition: stratnum.h:52
#define RTContainedByStrategyNumber
Definition: stratnum.h:51
#define RTBelowStrategyNumber
Definition: stratnum.h:53
#define RTOverAboveStrategyNumber
Definition: stratnum.h:55
#define ERROR
Definition: elog.h:43
Datum box_contain(PG_FUNCTION_ARGS)
Definition: geo_ops.c:650
Datum box_above(PG_FUNCTION_ARGS)
Definition: geo_ops.c:613
#define DatumGetBool(X)
Definition: postgres.h:399
#define RTSameStrategyNumber
Definition: stratnum.h:49
#define RTOverRightStrategyNumber
Definition: stratnum.h:47
#define RTOverLeftStrategyNumber
Definition: stratnum.h:45
Datum box_overbelow(PG_FUNCTION_ARGS)
Definition: geo_ops.c:602
Datum box_below(PG_FUNCTION_ARGS)
Definition: geo_ops.c:590
#define RTAboveStrategyNumber
Definition: stratnum.h:54
#define RTRightStrategyNumber
Definition: stratnum.h:48
Datum box_overleft(PG_FUNCTION_ARGS)
Definition: geo_ops.c:553
#define RTContainsStrategyNumber
Definition: stratnum.h:50
#define RTOverlapStrategyNumber
Definition: stratnum.h:46
Datum box_overabove(PG_FUNCTION_ARGS)
Definition: geo_ops.c:625
#define elog
Definition: elog.h:219
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587

◆ size_box()

static double size_box ( const BOX box)
static

Definition at line 68 of file gistproc.c.

References FLOAT8_LE, get_float8_infinity(), BOX::high, BOX::low, Point::x, and Point::y.

Referenced by box_penalty().

69 {
70  /*
71  * Check for zero-width cases. Note that we define the size of a zero-
72  * by-infinity box as zero. It's important to special-case this somehow,
73  * as naively multiplying infinity by zero will produce NaN.
74  *
75  * The less-than cases should not happen, but if they do, say "zero".
76  */
77  if (FLOAT8_LE(box->high.x, box->low.x) ||
78  FLOAT8_LE(box->high.y, box->low.y))
79  return 0.0;
80 
81  /*
82  * We treat NaN as larger than +Infinity, so any distance involving a NaN
83  * and a non-NaN is infinite. Note the previous check eliminated the
84  * possibility that the low fields are NaNs.
85  */
86  if (isnan(box->high.x) || isnan(box->high.y))
87  return get_float8_infinity();
88  return (box->high.x - box->low.x) * (box->high.y - box->low.y);
89 }
double y
Definition: geo_decls.h:60
double x
Definition: geo_decls.h:60
#define FLOAT8_LE(a, b)
Definition: gistproc.c:40
double get_float8_infinity(void)
Definition: float.c:121
Point low
Definition: geo_decls.h:104
Point high
Definition: geo_decls.h:104