PostgreSQL Source Code  git master
gistproc.c File Reference
#include "postgres.h"
#include <math.h>
#include "access/gist.h"
#include "access/stratnum.h"
#include "utils/builtins.h"
#include "utils/float.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 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 float8 size_box (const BOX *box)
 
static float8 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, float8 rightLower, int minLeftCount, float8 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 float8 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 float8 gist_bbox_distance (GISTENTRY *entry, Datum query, StrategyNumber strategy)
 
Datum gist_box_distance (PG_FUNCTION_ARGS)
 
Datum gist_circle_distance (PG_FUNCTION_ARGS)
 
Datum gist_poly_distance (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ BoxStrategyNumberGroup

#define BoxStrategyNumberGroup   1

Definition at line 1327 of file gistproc.c.

Referenced by gist_point_consistent().

◆ CircleStrategyNumberGroup

#define CircleStrategyNumberGroup   3

Definition at line 1329 of file gistproc.c.

Referenced by gist_point_consistent().

◆ GeoStrategyNumberOffset

#define GeoStrategyNumberOffset   20

Definition at line 1325 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:1950
#define DatumGetFloat8(X)
Definition: postgres.h:728
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619
#define PointPGetDatum(X)
Definition: geo_decls.h:135

Definition at line 1211 of file gistproc.c.

Referenced by computeDistance().

◆ PointStrategyNumberGroup

#define PointStrategyNumberGroup   0

Definition at line 1326 of file gistproc.c.

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

◆ PolygonStrategyNumberGroup

#define PolygonStrategyNumberGroup   2

Definition at line 1328 of file gistproc.c.

Referenced by gist_point_consistent().

Function Documentation

◆ adjustBox()

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

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

138 {
139  if (float8_lt(b->high.x, addon->high.x))
140  b->high.x = addon->high.x;
141  if (float8_gt(b->low.x, addon->low.x))
142  b->low.x = addon->low.x;
143  if (float8_lt(b->high.y, addon->high.y))
144  b->high.y = addon->high.y;
145  if (float8_gt(b->low.y, addon->low.y))
146  b->low.y = addon->low.y;
147 }
float8 x
Definition: geo_decls.h:57
static bool float8_lt(const float8 val1, const float8 val2)
Definition: float.h:314
Point low
Definition: geo_decls.h:101
static bool float8_gt(const float8 val1, const float8 val2)
Definition: float.h:338
float8 y
Definition: geo_decls.h:57
Point high
Definition: geo_decls.h:101

◆ box_penalty()

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

Definition at line 88 of file gistproc.c.

References float8_mi(), rt_box_union(), and size_box().

Referenced by gist_box_penalty(), and gist_box_picksplit().

89 {
90  BOX unionbox;
91 
92  rt_box_union(&unionbox, original, new);
93  return float8_mi(size_box(&unionbox), size_box(original));
94 }
static float8 size_box(const BOX *box)
Definition: gistproc.c:59
Definition: geo_decls.h:99
static void rt_box_union(BOX *n, const BOX *a, const BOX *b)
Definition: gistproc.c:46
static float8 float8_mi(const float8 val1, const float8 val2)
Definition: float.h:209

◆ common_entry_cmp()

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

Definition at line 451 of file gistproc.c.

References float8_cmp_internal().

Referenced by gist_box_picksplit().

452 {
453  float8 delta1 = ((const CommonEntry *) i1)->delta,
454  delta2 = ((const CommonEntry *) i2)->delta;
455 
456  return float8_cmp_internal(delta1, delta2);
457 }
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:919
double float8
Definition: c.h:491

◆ computeDistance()

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

Definition at line 1216 of file gistproc.c.

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

Referenced by gist_bbox_distance(), and gist_point_distance().

1217 {
1218  float8 result = 0.0;
1219 
1220  if (isLeaf)
1221  {
1222  /* simple point to point distance */
1223  result = point_point_distance(point, &box->low);
1224  }
1225  else if (point->x <= box->high.x && point->x >= box->low.x &&
1226  point->y <= box->high.y && point->y >= box->low.y)
1227  {
1228  /* point inside the box */
1229  result = 0.0;
1230  }
1231  else if (point->x <= box->high.x && point->x >= box->low.x)
1232  {
1233  /* point is over or below box */
1234  Assert(box->low.y <= box->high.y);
1235  if (point->y > box->high.y)
1236  result = float8_mi(point->y, box->high.y);
1237  else if (point->y < box->low.y)
1238  result = float8_mi(box->low.y, point->y);
1239  else
1240  elog(ERROR, "inconsistent point values");
1241  }
1242  else if (point->y <= box->high.y && point->y >= box->low.y)
1243  {
1244  /* point is to left or right of box */
1245  Assert(box->low.x <= box->high.x);
1246  if (point->x > box->high.x)
1247  result = float8_mi(point->x, box->high.x);
1248  else if (point->x < box->low.x)
1249  result = float8_mi(box->low.x, point->x);
1250  else
1251  elog(ERROR, "inconsistent point values");
1252  }
1253  else
1254  {
1255  /* closest point will be a vertex */
1256  Point p;
1257  float8 subresult;
1258 
1259  result = point_point_distance(point, &box->low);
1260 
1261  subresult = point_point_distance(point, &box->high);
1262  if (result > subresult)
1263  result = subresult;
1264 
1265  p.x = box->low.x;
1266  p.y = box->high.y;
1267  subresult = point_point_distance(point, &p);
1268  if (result > subresult)
1269  result = subresult;
1270 
1271  p.x = box->high.x;
1272  p.y = box->low.y;
1273  subresult = point_point_distance(point, &p);
1274  if (result > subresult)
1275  result = subresult;
1276  }
1277 
1278  return result;
1279 }
float8 x
Definition: geo_decls.h:57
#define point_point_distance(p1, p2)
Definition: gistproc.c:1211
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:491
static float8 float8_mi(const float8 val1, const float8 val2)
Definition: float.h:209
Point low
Definition: geo_decls.h:101
#define Assert(condition)
Definition: c.h:732
float8 y
Definition: geo_decls.h:57
Point high
Definition: geo_decls.h:101
#define elog(elevel,...)
Definition: elog.h:226

◆ fallbackSplit()

static void fallbackSplit ( GistEntryVector entryvec,
GIST_SPLITVEC v 
)
static

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

208 {
209  OffsetNumber i,
210  maxoff;
211  BOX *unionL = NULL,
212  *unionR = NULL;
213  int nbytes;
214 
215  maxoff = entryvec->n - 1;
216 
217  nbytes = (maxoff + 2) * sizeof(OffsetNumber);
218  v->spl_left = (OffsetNumber *) palloc(nbytes);
219  v->spl_right = (OffsetNumber *) palloc(nbytes);
220  v->spl_nleft = v->spl_nright = 0;
221 
222  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
223  {
224  BOX *cur = DatumGetBoxP(entryvec->vector[i].key);
225 
226  if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
227  {
228  v->spl_left[v->spl_nleft] = i;
229  if (unionL == NULL)
230  {
231  unionL = (BOX *) palloc(sizeof(BOX));
232  *unionL = *cur;
233  }
234  else
235  adjustBox(unionL, cur);
236 
237  v->spl_nleft++;
238  }
239  else
240  {
241  v->spl_right[v->spl_nright] = i;
242  if (unionR == NULL)
243  {
244  unionR = (BOX *) palloc(sizeof(BOX));
245  *unionR = *cur;
246  }
247  else
248  adjustBox(unionR, cur);
249 
250  v->spl_nright++;
251  }
252  }
253 
254  v->spl_ldatum = BoxPGetDatum(unionL);
255  v->spl_rdatum = BoxPGetDatum(unionR);
256 }
Definition: geo_decls.h:99
OffsetNumber * spl_left
Definition: gist.h:113
Datum spl_rdatum
Definition: gist.h:120
int32 n
Definition: gist.h:206
struct cursor * cur
Definition: ecpg.c:28
int spl_nleft
Definition: gist.h:114
uint16 OffsetNumber
Definition: off.h:24
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:207
int spl_nright
Definition: gist.h:119
Datum key
Definition: gist.h:131
#define FirstOffsetNumber
Definition: off.h:27
static void adjustBox(BOX *b, const BOX *addon)
Definition: gistproc.c:137
#define BoxPGetDatum(X)
Definition: geo_decls.h:157
Datum spl_ldatum
Definition: gist.h:115
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
OffsetNumber * spl_right
Definition: gist.h:118
#define DatumGetBoxP(X)
Definition: geo_decls.h:156
void * palloc(Size size)
Definition: mcxt.c:949
int i

◆ g_box_consider_split()

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

Definition at line 342 of file gistproc.c.

References ConsiderSplitContext::boundingBox, ConsiderSplitContext::dim, ConsiderSplitContext::entriesCount, ConsiderSplitContext::first, float4_div(), float8_div(), float8_mi(), 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().

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

◆ gist_bbox_distance()

static float8 gist_bbox_distance ( GISTENTRY entry,
Datum  query,
StrategyNumber  strategy 
)
static

Definition at line 1468 of file gistproc.c.

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

Referenced by gist_box_distance(), gist_circle_distance(), and gist_poly_distance().

1469 {
1470  float8 distance;
1471  StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1472 
1473  switch (strategyGroup)
1474  {
1476  distance = computeDistance(false,
1477  DatumGetBoxP(entry->key),
1478  DatumGetPointP(query));
1479  break;
1480  default:
1481  elog(ERROR, "unrecognized strategy number: %d", strategy);
1482  distance = 0.0; /* keep compiler quiet */
1483  }
1484 
1485  return distance;
1486 }
#define GeoStrategyNumberOffset
Definition: gistproc.c:1325
uint16 StrategyNumber
Definition: stratnum.h:22
#define PointStrategyNumberGroup
Definition: gistproc.c:1326
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:491
Datum key
Definition: gist.h:131
static float8 computeDistance(bool isLeaf, BOX *box, Point *point)
Definition: gistproc.c:1216
#define DatumGetPointP(X)
Definition: geo_decls.h:134
#define DatumGetBoxP(X)
Definition: geo_decls.h:156
#define elog(elevel,...)
Definition: elog.h:226

◆ gist_box_consistent()

Datum gist_box_consistent ( PG_FUNCTION_ARGS  )

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

105 {
106  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
107  BOX *query = PG_GETARG_BOX_P(1);
109 
110  /* Oid subtype = PG_GETARG_OID(3); */
111  bool *recheck = (bool *) PG_GETARG_POINTER(4);
112 
113  /* All cases served by this function are exact */
114  *recheck = false;
115 
116  if (DatumGetBoxP(entry->key) == NULL || query == NULL)
117  PG_RETURN_BOOL(false);
118 
119  /*
120  * if entry is not leaf, use rtree_internal_consistent, else use
121  * gist_box_leaf_consistent
122  */
123  if (GIST_LEAF(entry))
125  query,
126  strategy));
127  else
129  query,
130  strategy));
131 }
#define GIST_LEAF(entry)
Definition: gist.h:141
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:950
Definition: geo_decls.h:99
static bool gist_box_leaf_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:863
#define PG_GETARG_BOX_P(n)
Definition: geo_decls.h:158
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Datum key
Definition: gist.h:131
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
#define DatumGetBoxP(X)
Definition: geo_decls.h:156
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267

◆ gist_box_distance()

Datum gist_box_distance ( PG_FUNCTION_ARGS  )

Definition at line 1489 of file gistproc.c.

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

1490 {
1491  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1492  Datum query = PG_GETARG_DATUM(1);
1494 
1495  /* Oid subtype = PG_GETARG_OID(3); */
1496  /* bool *recheck = (bool *) PG_GETARG_POINTER(4); */
1497  float8 distance;
1498 
1499  distance = gist_bbox_distance(entry, query, strategy);
1500 
1501  PG_RETURN_FLOAT8(distance);
1502 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
double float8
Definition: c.h:491
uintptr_t Datum
Definition: postgres.h:367
static float8 gist_bbox_distance(GISTENTRY *entry, Datum query, StrategyNumber strategy)
Definition: gistproc.c:1468
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267

◆ gist_box_leaf_consistent()

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

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

864 {
865  bool retval;
866 
867  switch (strategy)
868  {
871  PointerGetDatum(key),
872  PointerGetDatum(query)));
873  break;
876  PointerGetDatum(key),
877  PointerGetDatum(query)));
878  break;
881  PointerGetDatum(key),
882  PointerGetDatum(query)));
883  break;
886  PointerGetDatum(key),
887  PointerGetDatum(query)));
888  break;
891  PointerGetDatum(key),
892  PointerGetDatum(query)));
893  break;
896  PointerGetDatum(key),
897  PointerGetDatum(query)));
898  break;
902  PointerGetDatum(key),
903  PointerGetDatum(query)));
904  break;
908  PointerGetDatum(key),
909  PointerGetDatum(query)));
910  break;
913  PointerGetDatum(key),
914  PointerGetDatum(query)));
915  break;
918  PointerGetDatum(key),
919  PointerGetDatum(query)));
920  break;
923  PointerGetDatum(key),
924  PointerGetDatum(query)));
925  break;
928  PointerGetDatum(key),
929  PointerGetDatum(query)));
930  break;
931  default:
932  elog(ERROR, "unrecognized strategy number: %d", strategy);
933  retval = false; /* keep compiler quiet */
934  break;
935  }
936  return retval;
937 }
Datum box_right(PG_FUNCTION_ARGS)
Definition: geo_ops.c:597
Datum box_contained(PG_FUNCTION_ARGS)
Definition: geo_ops.c:669
Datum box_same(PG_FUNCTION_ARGS)
Definition: geo_ops.c:539
Datum box_left(PG_FUNCTION_ARGS)
Definition: geo_ops.c:571
#define RTOldContainsStrategyNumber
Definition: stratnum.h:63
#define RTOldContainedByStrategyNumber
Definition: stratnum.h:64
#define RTLeftStrategyNumber
Definition: stratnum.h:51
Datum box_overright(PG_FUNCTION_ARGS)
Definition: geo_ops.c:612
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum box_overlap(PG_FUNCTION_ARGS)
Definition: geo_ops.c:551
#define RTOverBelowStrategyNumber
Definition: stratnum.h:59
#define RTContainedByStrategyNumber
Definition: stratnum.h:58
#define RTBelowStrategyNumber
Definition: stratnum.h:60
#define RTOverAboveStrategyNumber
Definition: stratnum.h:62
#define ERROR
Definition: elog.h:43
Datum box_contain(PG_FUNCTION_ARGS)
Definition: geo_ops.c:680
Datum box_above(PG_FUNCTION_ARGS)
Definition: geo_ops.c:646
#define DatumGetBool(X)
Definition: postgres.h:393
#define RTSameStrategyNumber
Definition: stratnum.h:56
#define RTOverRightStrategyNumber
Definition: stratnum.h:54
#define RTOverLeftStrategyNumber
Definition: stratnum.h:52
Datum box_overbelow(PG_FUNCTION_ARGS)
Definition: geo_ops.c:635
Datum box_below(PG_FUNCTION_ARGS)
Definition: geo_ops.c:623
#define RTAboveStrategyNumber
Definition: stratnum.h:61
#define RTRightStrategyNumber
Definition: stratnum.h:55
Datum box_overleft(PG_FUNCTION_ARGS)
Definition: geo_ops.c:586
#define RTContainsStrategyNumber
Definition: stratnum.h:57
#define elog(elevel,...)
Definition: elog.h:226
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
Datum box_overabove(PG_FUNCTION_ARGS)
Definition: geo_ops.c:658
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619

◆ gist_box_penalty()

Datum gist_box_penalty ( PG_FUNCTION_ARGS  )

Definition at line 190 of file gistproc.c.

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

191 {
192  GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
193  GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
194  float *result = (float *) PG_GETARG_POINTER(2);
195  BOX *origbox = DatumGetBoxP(origentry->key);
196  BOX *newbox = DatumGetBoxP(newentry->key);
197 
198  *result = (float) box_penalty(origbox, newbox);
199  PG_RETURN_POINTER(result);
200 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: geo_decls.h:99
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Datum key
Definition: gist.h:131
#define DatumGetBoxP(X)
Definition: geo_decls.h:156
static float8 box_penalty(const BOX *original, const BOX *new)
Definition: gistproc.c:88

◆ gist_box_picksplit()

Datum gist_box_picksplit ( PG_FUNCTION_ARGS  )

Definition at line 486 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(), float8_mi(), 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.

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

◆ gist_box_same()

Datum gist_box_same ( PG_FUNCTION_ARGS  )

Definition at line 843 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.

844 {
845  BOX *b1 = PG_GETARG_BOX_P(0);
846  BOX *b2 = PG_GETARG_BOX_P(1);
847  bool *result = (bool *) PG_GETARG_POINTER(2);
848 
849  if (b1 && b2)
850  *result = (float8_eq(b1->low.x, b2->low.x) &&
851  float8_eq(b1->low.y, b2->low.y) &&
852  float8_eq(b1->high.x, b2->high.x) &&
853  float8_eq(b1->high.y, b2->high.y));
854  else
855  *result = (b1 == NULL && b2 == NULL);
856  PG_RETURN_POINTER(result);
857 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: geo_decls.h:99
#define PG_GETARG_BOX_P(n)
Definition: geo_decls.h:158
float8 x
Definition: geo_decls.h:57
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Point low
Definition: geo_decls.h:101
float8 y
Definition: geo_decls.h:57
Point high
Definition: geo_decls.h:101
static bool float8_eq(const float8 val1, const float8 val2)
Definition: float.h:290

◆ gist_box_union()

Datum gist_box_union ( PG_FUNCTION_ARGS  )

Definition at line 155 of file gistproc.c.

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

156 {
158  int *sizep = (int *) PG_GETARG_POINTER(1);
159  int numranges,
160  i;
161  BOX *cur,
162  *pageunion;
163 
164  numranges = entryvec->n;
165  pageunion = (BOX *) palloc(sizeof(BOX));
166  cur = DatumGetBoxP(entryvec->vector[0].key);
167  memcpy((void *) pageunion, (void *) cur, sizeof(BOX));
168 
169  for (i = 1; i < numranges; i++)
170  {
171  cur = DatumGetBoxP(entryvec->vector[i].key);
172  adjustBox(pageunion, cur);
173  }
174  *sizep = sizeof(BOX);
175 
176  PG_RETURN_POINTER(pageunion);
177 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: geo_decls.h:99
int32 n
Definition: gist.h:206
struct cursor * cur
Definition: ecpg.c:28
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:207
Datum key
Definition: gist.h:131
static void adjustBox(BOX *b, const BOX *addon)
Definition: gistproc.c:137
#define DatumGetBoxP(X)
Definition: geo_decls.h:156
void * palloc(Size size)
Definition: mcxt.c:949
int i

◆ gist_circle_compress()

Datum gist_circle_compress ( PG_FUNCTION_ARGS  )

Definition at line 1095 of file gistproc.c.

References CIRCLE::center, DatumGetCircleP, float8_mi(), float8_pl(), 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.

1096 {
1097  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1098  GISTENTRY *retval;
1099 
1100  if (entry->leafkey)
1101  {
1102  CIRCLE *in = DatumGetCircleP(entry->key);
1103  BOX *r;
1104 
1105  r = (BOX *) palloc(sizeof(BOX));
1106  r->high.x = float8_pl(in->center.x, in->radius);
1107  r->low.x = float8_mi(in->center.x, in->radius);
1108  r->high.y = float8_pl(in->center.y, in->radius);
1109  r->low.y = float8_mi(in->center.y, in->radius);
1110 
1111  retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
1112  gistentryinit(*retval, PointerGetDatum(r),
1113  entry->rel, entry->page,
1114  entry->offset, false);
1115  }
1116  else
1117  retval = entry;
1118  PG_RETURN_POINTER(retval);
1119 }
Relation rel
Definition: gist.h:132
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: geo_decls.h:99
float8 x
Definition: geo_decls.h:57
float8 radius
Definition: geo_decls.h:124
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Page page
Definition: gist.h:133
Datum key
Definition: gist.h:131
#define DatumGetCircleP(X)
Definition: geo_decls.h:168
static float8 float8_pl(const float8 val1, const float8 val2)
Definition: float.h:187
static float8 float8_mi(const float8 val1, const float8 val2)
Definition: float.h:209
bool leafkey
Definition: gist.h:135
Point low
Definition: geo_decls.h:101
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:215
float8 y
Definition: geo_decls.h:57
Point high
Definition: geo_decls.h:101
Point center
Definition: geo_decls.h:123
void * palloc(Size size)
Definition: mcxt.c:949
OffsetNumber offset
Definition: gist.h:134

◆ gist_circle_consistent()

Datum gist_circle_consistent ( PG_FUNCTION_ARGS  )

Definition at line 1125 of file gistproc.c.

References CIRCLE::center, DatumGetBoxP, float8_mi(), float8_pl(), 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().

1126 {
1127  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1128  CIRCLE *query = PG_GETARG_CIRCLE_P(1);
1130 
1131  /* Oid subtype = PG_GETARG_OID(3); */
1132  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1133  BOX bbox;
1134  bool result;
1135 
1136  /* All cases served by this function are inexact */
1137  *recheck = true;
1138 
1139  if (DatumGetBoxP(entry->key) == NULL || query == NULL)
1140  PG_RETURN_BOOL(false);
1141 
1142  /*
1143  * Since the operators require recheck anyway, we can just use
1144  * rtree_internal_consistent even at leaf nodes. (This works in part
1145  * because the index entries are bounding boxes not circles.)
1146  */
1147  bbox.high.x = float8_pl(query->center.x, query->radius);
1148  bbox.low.x = float8_mi(query->center.x, query->radius);
1149  bbox.high.y = float8_pl(query->center.y, query->radius);
1150  bbox.low.y = float8_mi(query->center.y, query->radius);
1151 
1152  result = rtree_internal_consistent(DatumGetBoxP(entry->key),
1153  &bbox, strategy);
1154 
1155  PG_RETURN_BOOL(result);
1156 }
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:950
Definition: geo_decls.h:99
float8 x
Definition: geo_decls.h:57
float8 radius
Definition: geo_decls.h:124
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Datum key
Definition: gist.h:131
static float8 float8_pl(const float8 val1, const float8 val2)
Definition: float.h:187
static float8 float8_mi(const float8 val1, const float8 val2)
Definition: float.h:209
Point low
Definition: geo_decls.h:101
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
#define PG_GETARG_CIRCLE_P(n)
Definition: geo_decls.h:170
float8 y
Definition: geo_decls.h:57
#define DatumGetBoxP(X)
Definition: geo_decls.h:156
Point high
Definition: geo_decls.h:101
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267
Point center
Definition: geo_decls.h:123

◆ gist_circle_distance()

Datum gist_circle_distance ( PG_FUNCTION_ARGS  )

Definition at line 1515 of file gistproc.c.

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

1516 {
1517  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1518  Datum query = PG_GETARG_DATUM(1);
1520 
1521  /* Oid subtype = PG_GETARG_OID(3); */
1522  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1523  float8 distance;
1524 
1525  distance = gist_bbox_distance(entry, query, strategy);
1526  *recheck = true;
1527 
1528  PG_RETURN_FLOAT8(distance);
1529 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
double float8
Definition: c.h:491
uintptr_t Datum
Definition: postgres.h:367
static float8 gist_bbox_distance(GISTENTRY *entry, Datum query, StrategyNumber strategy)
Definition: gistproc.c:1468
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267

◆ gist_point_compress()

Datum gist_point_compress ( PG_FUNCTION_ARGS  )

Definition at line 1163 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.

1164 {
1165  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1166 
1167  if (entry->leafkey) /* Point, actually */
1168  {
1169  BOX *box = palloc(sizeof(BOX));
1170  Point *point = DatumGetPointP(entry->key);
1171  GISTENTRY *retval = palloc(sizeof(GISTENTRY));
1172 
1173  box->high = box->low = *point;
1174 
1175  gistentryinit(*retval, BoxPGetDatum(box),
1176  entry->rel, entry->page, entry->offset, false);
1177 
1178  PG_RETURN_POINTER(retval);
1179  }
1180 
1181  PG_RETURN_POINTER(entry);
1182 }
Relation rel
Definition: gist.h:132
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: geo_decls.h:99
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Page page
Definition: gist.h:133
Datum key
Definition: gist.h:131
bool leafkey
Definition: gist.h:135
Point low
Definition: geo_decls.h:101
#define BoxPGetDatum(X)
Definition: geo_decls.h:157
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:215
#define DatumGetPointP(X)
Definition: geo_decls.h:134
Point high
Definition: geo_decls.h:101
void * palloc(Size size)
Definition: mcxt.c:949
OffsetNumber offset
Definition: gist.h:134

◆ gist_point_consistent()

Datum gist_point_consistent ( PG_FUNCTION_ARGS  )

Definition at line 1332 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, sort-test::key, 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.

1333 {
1334  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1336  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1337  bool result;
1338  StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1339 
1340  switch (strategyGroup)
1341  {
1344  GIST_LEAF(entry),
1345  DatumGetBoxP(entry->key),
1346  PG_GETARG_POINT_P(1));
1347  *recheck = false;
1348  break;
1350  {
1351  /*
1352  * The only operator in this group is point <@ box (on_pb), so
1353  * we needn't examine strategy again.
1354  *
1355  * For historical reasons, on_pb uses exact rather than fuzzy
1356  * comparisons. We could use box_overlap when at an internal
1357  * page, but that would lead to possibly visiting child pages
1358  * uselessly, because box_overlap uses fuzzy comparisons.
1359  * Instead we write a non-fuzzy overlap test. The same code
1360  * will also serve for leaf-page tests, since leaf keys have
1361  * high == low.
1362  */
1363  BOX *query,
1364  *key;
1365 
1366  query = PG_GETARG_BOX_P(1);
1367  key = DatumGetBoxP(entry->key);
1368 
1369  result = (key->high.x >= query->low.x &&
1370  key->low.x <= query->high.x &&
1371  key->high.y >= query->low.y &&
1372  key->low.y <= query->high.y);
1373  *recheck = false;
1374  }
1375  break;
1377  {
1378  POLYGON *query = PG_GETARG_POLYGON_P(1);
1379 
1382  PointerGetDatum(entry),
1383  PolygonPGetDatum(query),
1385  0, PointerGetDatum(recheck)));
1386 
1387  if (GIST_LEAF(entry) && result)
1388  {
1389  /*
1390  * We are on leaf page and quick check shows overlapping
1391  * of polygon's bounding box and point
1392  */
1393  BOX *box = DatumGetBoxP(entry->key);
1394 
1395  Assert(box->high.x == box->low.x
1396  && box->high.y == box->low.y);
1399  PolygonPGetDatum(query),
1400  PointPGetDatum(&box->high)));
1401  *recheck = false;
1402  }
1403  }
1404  break;
1406  {
1407  CIRCLE *query = PG_GETARG_CIRCLE_P(1);
1408 
1411  PointerGetDatum(entry),
1412  CirclePGetDatum(query),
1414  0, PointerGetDatum(recheck)));
1415 
1416  if (GIST_LEAF(entry) && result)
1417  {
1418  /*
1419  * We are on leaf page and quick check shows overlapping
1420  * of polygon's bounding box and point
1421  */
1422  BOX *box = DatumGetBoxP(entry->key);
1423 
1424  Assert(box->high.x == box->low.x
1425  && box->high.y == box->low.y);
1428  CirclePGetDatum(query),
1429  PointPGetDatum(&box->high)));
1430  *recheck = false;
1431  }
1432  }
1433  break;
1434  default:
1435  elog(ERROR, "unrecognized strategy number: %d", strategy);
1436  result = false; /* keep compiler quiet */
1437  break;
1438  }
1439 
1440  PG_RETURN_BOOL(result);
1441 }
#define GIST_LEAF(entry)
Definition: gist.h:141
#define GeoStrategyNumberOffset
Definition: gistproc.c:1325
Definition: geo_decls.h:99
#define BoxStrategyNumberGroup
Definition: gistproc.c:1327
#define PG_GETARG_BOX_P(n)
Definition: geo_decls.h:158
float8 x
Definition: geo_decls.h:57
#define CircleStrategyNumberGroup
Definition: gistproc.c:1329
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PolygonPGetDatum(X)
Definition: geo_decls.h:163
#define Int16GetDatum(X)
Definition: postgres.h:451
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Datum poly_contain_pt(PG_FUNCTION_ARGS)
Definition: geo_ops.c:4041
#define PG_GETARG_POLYGON_P(n)
Definition: geo_decls.h:164
#define PointStrategyNumberGroup
Definition: gistproc.c:1326
#define CirclePGetDatum(X)
Definition: geo_decls.h:169
#define ERROR
Definition: elog.h:43
#define PG_GETARG_POINT_P(n)
Definition: geo_decls.h:136
Datum key
Definition: gist.h:131
#define DatumGetBool(X)
Definition: postgres.h:393
static bool gist_point_consistent_internal(StrategyNumber strategy, bool isLeaf, BOX *key, Point *query)
Definition: gistproc.c:1282
#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5)
Definition: fmgr.h:625
Point low
Definition: geo_decls.h:101
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
Datum circle_contain_pt(PG_FUNCTION_ARGS)
Definition: geo_ops.c:5074
Datum gist_circle_consistent(PG_FUNCTION_ARGS)
Definition: gistproc.c:1125
#define PolygonStrategyNumberGroup
Definition: gistproc.c:1328
#define PG_GETARG_CIRCLE_P(n)
Definition: geo_decls.h:170
#define Assert(condition)
Definition: c.h:732
float8 y
Definition: geo_decls.h:57
Datum gist_poly_consistent(PG_FUNCTION_ARGS)
Definition: gistproc.c:1057
#define DatumGetBoxP(X)
Definition: geo_decls.h:156
Point high
Definition: geo_decls.h:101
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267
#define elog(elevel,...)
Definition: elog.h:226
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619
#define PointPGetDatum(X)
Definition: geo_decls.h:135

◆ gist_point_consistent_internal()

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

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

1284 {
1285  bool result = false;
1286 
1287  switch (strategy)
1288  {
1289  case RTLeftStrategyNumber:
1290  result = FPlt(key->low.x, query->x);
1291  break;
1292  case RTRightStrategyNumber:
1293  result = FPgt(key->high.x, query->x);
1294  break;
1295  case RTAboveStrategyNumber:
1296  result = FPgt(key->high.y, query->y);
1297  break;
1298  case RTBelowStrategyNumber:
1299  result = FPlt(key->low.y, query->y);
1300  break;
1301  case RTSameStrategyNumber:
1302  if (isLeaf)
1303  {
1304  /* key.high must equal key.low, so we can disregard it */
1305  result = (FPeq(key->low.x, query->x) &&
1306  FPeq(key->low.y, query->y));
1307  }
1308  else
1309  {
1310  result = (FPle(query->x, key->high.x) &&
1311  FPge(query->x, key->low.x) &&
1312  FPle(query->y, key->high.y) &&
1313  FPge(query->y, key->low.y));
1314  }
1315  break;
1316  default:
1317  elog(ERROR, "unrecognized strategy number: %d", strategy);
1318  result = false; /* keep compiler quiet */
1319  break;
1320  }
1321 
1322  return result;
1323 }
float8 x
Definition: geo_decls.h:57
#define RTLeftStrategyNumber
Definition: stratnum.h:51
#define RTBelowStrategyNumber
Definition: stratnum.h:60
#define FPgt(A, B)
Definition: geo_decls.h:38
#define ERROR
Definition: elog.h:43
#define RTSameStrategyNumber
Definition: stratnum.h:56
#define FPeq(A, B)
Definition: geo_decls.h:34
Point low
Definition: geo_decls.h:101
#define RTAboveStrategyNumber
Definition: stratnum.h:61
#define FPlt(A, B)
Definition: geo_decls.h:36
float8 y
Definition: geo_decls.h:57
#define RTRightStrategyNumber
Definition: stratnum.h:55
Point high
Definition: geo_decls.h:101
#define FPge(A, B)
Definition: geo_decls.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define FPle(A, B)
Definition: geo_decls.h:37

◆ gist_point_distance()

Datum gist_point_distance ( PG_FUNCTION_ARGS  )

Definition at line 1444 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.

1445 {
1446  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1448  float8 distance;
1449  StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1450 
1451  switch (strategyGroup)
1452  {
1454  distance = computeDistance(GIST_LEAF(entry),
1455  DatumGetBoxP(entry->key),
1456  PG_GETARG_POINT_P(1));
1457  break;
1458  default:
1459  elog(ERROR, "unrecognized strategy number: %d", strategy);
1460  distance = 0.0; /* keep compiler quiet */
1461  break;
1462  }
1463 
1464  PG_RETURN_FLOAT8(distance);
1465 }
#define GIST_LEAF(entry)
Definition: gist.h:141
#define GeoStrategyNumberOffset
Definition: gistproc.c:1325
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define PointStrategyNumberGroup
Definition: gistproc.c:1326
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:491
#define PG_GETARG_POINT_P(n)
Definition: geo_decls.h:136
Datum key
Definition: gist.h:131
static float8 computeDistance(bool isLeaf, BOX *box, Point *point)
Definition: gistproc.c:1216
#define DatumGetBoxP(X)
Definition: geo_decls.h:156
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267
#define elog(elevel,...)
Definition: elog.h:226

◆ gist_point_fetch()

Datum gist_point_fetch ( PG_FUNCTION_ARGS  )

Definition at line 1191 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.

1192 {
1193  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1194  BOX *in = DatumGetBoxP(entry->key);
1195  Point *r;
1196  GISTENTRY *retval;
1197 
1198  retval = palloc(sizeof(GISTENTRY));
1199 
1200  r = (Point *) palloc(sizeof(Point));
1201  r->x = in->high.x;
1202  r->y = in->high.y;
1203  gistentryinit(*retval, PointerGetDatum(r),
1204  entry->rel, entry->page,
1205  entry->offset, false);
1206 
1207  PG_RETURN_POINTER(retval);
1208 }
Relation rel
Definition: gist.h:132
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: geo_decls.h:99
float8 x
Definition: geo_decls.h:57
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Page page
Definition: gist.h:133
Datum key
Definition: gist.h:131
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:215
float8 y
Definition: geo_decls.h:57
#define DatumGetBoxP(X)
Definition: geo_decls.h:156
Point high
Definition: geo_decls.h:101
void * palloc(Size size)
Definition: mcxt.c:949
OffsetNumber offset
Definition: gist.h:134

◆ gist_poly_compress()

Datum gist_poly_compress ( PG_FUNCTION_ARGS  )

Definition at line 1030 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.

1031 {
1032  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1033  GISTENTRY *retval;
1034 
1035  if (entry->leafkey)
1036  {
1037  POLYGON *in = DatumGetPolygonP(entry->key);
1038  BOX *r;
1039 
1040  r = (BOX *) palloc(sizeof(BOX));
1041  memcpy((void *) r, (void *) &(in->boundbox), sizeof(BOX));
1042 
1043  retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
1044  gistentryinit(*retval, PointerGetDatum(r),
1045  entry->rel, entry->page,
1046  entry->offset, false);
1047  }
1048  else
1049  retval = entry;
1050  PG_RETURN_POINTER(retval);
1051 }
Relation rel
Definition: gist.h:132
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: geo_decls.h:99
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
Page page
Definition: gist.h:133
Datum key
Definition: gist.h:131
bool leafkey
Definition: gist.h:135
BOX boundbox
Definition: geo_decls.h:114
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:215
#define DatumGetPolygonP(X)
Definition: geo_decls.h:161
void * palloc(Size size)
Definition: mcxt.c:949
OffsetNumber offset
Definition: gist.h:134

◆ gist_poly_consistent()

Datum gist_poly_consistent ( PG_FUNCTION_ARGS  )

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

1058 {
1059  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1060  POLYGON *query = PG_GETARG_POLYGON_P(1);
1062 
1063  /* Oid subtype = PG_GETARG_OID(3); */
1064  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1065  bool result;
1066 
1067  /* All cases served by this function are inexact */
1068  *recheck = true;
1069 
1070  if (DatumGetBoxP(entry->key) == NULL || query == NULL)
1071  PG_RETURN_BOOL(false);
1072 
1073  /*
1074  * Since the operators require recheck anyway, we can just use
1075  * rtree_internal_consistent even at leaf nodes. (This works in part
1076  * because the index entries are bounding boxes not polygons.)
1077  */
1078  result = rtree_internal_consistent(DatumGetBoxP(entry->key),
1079  &(query->boundbox), strategy);
1080 
1081  /* Avoid memory leak if supplied poly is toasted */
1082  PG_FREE_IF_COPY(query, 1);
1083 
1084  PG_RETURN_BOOL(result);
1085 }
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:950
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
#define PG_GETARG_POLYGON_P(n)
Definition: geo_decls.h:164
Datum key
Definition: gist.h:131
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
BOX boundbox
Definition: geo_decls.h:114
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:255
#define DatumGetBoxP(X)
Definition: geo_decls.h:156
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267

◆ 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  float8 distance;
1541 
1542  distance = gist_bbox_distance(entry, query, strategy);
1543  *recheck = true;
1544 
1545  PG_RETURN_FLOAT8(distance);
1546 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
double float8
Definition: c.h:491
uintptr_t Datum
Definition: postgres.h:367
static float8 gist_bbox_distance(GISTENTRY *entry, Datum query, StrategyNumber strategy)
Definition: gistproc.c:1468
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:267

◆ interval_cmp_lower()

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

Definition at line 306 of file gistproc.c.

References float8_cmp_internal().

Referenced by gist_box_picksplit().

307 {
308  float8 lower1 = ((const SplitInterval *) i1)->lower,
309  lower2 = ((const SplitInterval *) i2)->lower;
310 
311  return float8_cmp_internal(lower1, lower2);
312 }
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:919
double float8
Definition: c.h:491

◆ interval_cmp_upper()

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

Definition at line 318 of file gistproc.c.

References float8_cmp_internal().

Referenced by gist_box_picksplit().

319 {
320  float8 upper1 = ((const SplitInterval *) i1)->upper,
321  upper2 = ((const SplitInterval *) i2)->upper;
322 
323  return float8_cmp_internal(upper1, upper2);
324 }
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:919
double float8
Definition: c.h:491

◆ non_negative()

static float non_negative ( float  val)
inlinestatic

Definition at line 330 of file gistproc.c.

References val.

Referenced by g_box_consider_split().

331 {
332  if (val >= 0.0f)
333  return val;
334  else
335  return 0.0f;
336 }
long val
Definition: informix.c:684

◆ rt_box_union()

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

Definition at line 46 of file gistproc.c.

References float8_max(), float8_min(), BOX::high, BOX::low, Point::x, and Point::y.

Referenced by box_penalty().

47 {
48  n->high.x = float8_max(a->high.x, b->high.x);
49  n->high.y = float8_max(a->high.y, b->high.y);
50  n->low.x = float8_min(a->low.x, b->low.x);
51  n->low.y = float8_min(a->low.y, b->low.y);
52 }
float8 x
Definition: geo_decls.h:57
static float8 float8_min(const float8 val1, const float8 val2)
Definition: float.h:362
Point low
Definition: geo_decls.h:101
float8 y
Definition: geo_decls.h:57
Point high
Definition: geo_decls.h:101
static float8 float8_max(const float8 val1, const float8 val2)
Definition: float.h:374

◆ rtree_internal_consistent()

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

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

951 {
952  bool retval;
953 
954  switch (strategy)
955  {
958  PointerGetDatum(key),
959  PointerGetDatum(query)));
960  break;
963  PointerGetDatum(key),
964  PointerGetDatum(query)));
965  break;
968  PointerGetDatum(key),
969  PointerGetDatum(query)));
970  break;
973  PointerGetDatum(key),
974  PointerGetDatum(query)));
975  break;
978  PointerGetDatum(key),
979  PointerGetDatum(query)));
980  break;
985  PointerGetDatum(key),
986  PointerGetDatum(query)));
987  break;
991  PointerGetDatum(key),
992  PointerGetDatum(query)));
993  break;
996  PointerGetDatum(key),
997  PointerGetDatum(query)));
998  break;
1001  PointerGetDatum(key),
1002  PointerGetDatum(query)));
1003  break;
1004  case RTAboveStrategyNumber:
1006  PointerGetDatum(key),
1007  PointerGetDatum(query)));
1008  break;
1011  PointerGetDatum(key),
1012  PointerGetDatum(query)));
1013  break;
1014  default:
1015  elog(ERROR, "unrecognized strategy number: %d", strategy);
1016  retval = false; /* keep compiler quiet */
1017  break;
1018  }
1019  return retval;
1020 }
Datum box_right(PG_FUNCTION_ARGS)
Definition: geo_ops.c:597
Datum box_left(PG_FUNCTION_ARGS)
Definition: geo_ops.c:571
#define RTOldContainsStrategyNumber
Definition: stratnum.h:63
#define RTOldContainedByStrategyNumber
Definition: stratnum.h:64
#define RTLeftStrategyNumber
Definition: stratnum.h:51
Datum box_overright(PG_FUNCTION_ARGS)
Definition: geo_ops.c:612
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum box_overlap(PG_FUNCTION_ARGS)
Definition: geo_ops.c:551
#define RTOverBelowStrategyNumber
Definition: stratnum.h:59
#define RTContainedByStrategyNumber
Definition: stratnum.h:58
#define RTBelowStrategyNumber
Definition: stratnum.h:60
#define RTOverAboveStrategyNumber
Definition: stratnum.h:62
#define ERROR
Definition: elog.h:43
Datum box_contain(PG_FUNCTION_ARGS)
Definition: geo_ops.c:680
Datum box_above(PG_FUNCTION_ARGS)
Definition: geo_ops.c:646
#define DatumGetBool(X)
Definition: postgres.h:393
#define RTSameStrategyNumber
Definition: stratnum.h:56
#define RTOverRightStrategyNumber
Definition: stratnum.h:54
#define RTOverLeftStrategyNumber
Definition: stratnum.h:52
Datum box_overbelow(PG_FUNCTION_ARGS)
Definition: geo_ops.c:635
Datum box_below(PG_FUNCTION_ARGS)
Definition: geo_ops.c:623
#define RTAboveStrategyNumber
Definition: stratnum.h:61
#define RTRightStrategyNumber
Definition: stratnum.h:55
Datum box_overleft(PG_FUNCTION_ARGS)
Definition: geo_ops.c:586
#define RTContainsStrategyNumber
Definition: stratnum.h:57
#define elog(elevel,...)
Definition: elog.h:226
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
Datum box_overabove(PG_FUNCTION_ARGS)
Definition: geo_ops.c:658
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619

◆ size_box()

static float8 size_box ( const BOX box)
static

Definition at line 59 of file gistproc.c.

References float8_le(), float8_mi(), float8_mul(), get_float8_infinity(), BOX::high, BOX::low, Point::x, and Point::y.

Referenced by box_penalty().

60 {
61  /*
62  * Check for zero-width cases. Note that we define the size of a zero-
63  * by-infinity box as zero. It's important to special-case this somehow,
64  * as naively multiplying infinity by zero will produce NaN.
65  *
66  * The less-than cases should not happen, but if they do, say "zero".
67  */
68  if (float8_le(box->high.x, box->low.x) ||
69  float8_le(box->high.y, box->low.y))
70  return 0.0;
71 
72  /*
73  * We treat NaN as larger than +Infinity, so any distance involving a NaN
74  * and a non-NaN is infinite. Note the previous check eliminated the
75  * possibility that the low fields are NaNs.
76  */
77  if (isnan(box->high.x) || isnan(box->high.y))
78  return get_float8_infinity();
79  return float8_mul(float8_mi(box->high.x, box->low.x),
80  float8_mi(box->high.y, box->low.y));
81 }
static float8 get_float8_infinity(void)
Definition: float.h:90
float8 x
Definition: geo_decls.h:57
static bool float8_le(const float8 val1, const float8 val2)
Definition: float.h:326
static float8 float8_mul(const float8 val1, const float8 val2)
Definition: float.h:232
static float8 float8_mi(const float8 val1, const float8 val2)
Definition: float.h:209
Point low
Definition: geo_decls.h:101
float8 y
Definition: geo_decls.h:57
Point high
Definition: geo_decls.h:101