PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
gistproc.c File Reference
#include "postgres.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_compress (PG_FUNCTION_ARGS)
 
Datum gist_box_decompress (PG_FUNCTION_ARGS)
 
Datum gist_box_fetch (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

#define BoxStrategyNumberGroup   1

Definition at line 1367 of file gistproc.c.

Referenced by gist_point_consistent().

#define CircleStrategyNumberGroup   3

Definition at line 1369 of file gistproc.c.

Referenced by gist_point_consistent().

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

Definition at line 37 of file gistproc.c.

Referenced by gist_box_picksplit(), and gist_box_same().

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

Definition at line 41 of file gistproc.c.

Referenced by gist_box_picksplit().

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

Definition at line 40 of file gistproc.c.

Referenced by adjustBox(), and gist_box_picksplit().

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

Definition at line 39 of file gistproc.c.

Referenced by gist_box_picksplit(), and size_box().

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

Definition at line 38 of file gistproc.c.

Referenced by adjustBox(), and gist_box_picksplit().

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

Definition at line 42 of file gistproc.c.

Referenced by rt_box_union().

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

Definition at line 43 of file gistproc.c.

Referenced by rt_box_union().

#define GeoStrategyNumberOffset   20

Definition at line 1365 of file gistproc.c.

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

#define LIMIT_RATIO   0.3

Definition at line 34 of file gistproc.c.

Referenced by g_box_consider_split(), and gist_box_picksplit().

#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)
static void adjustBox(BOX *b, const BOX *addon)
Definition: gistproc.c:144

Referenced by gist_box_picksplit().

#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)
static void adjustBox(BOX *b, const BOX *addon)
Definition: gistproc.c:144

Referenced by gist_box_picksplit().

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

Definition at line 1251 of file gistproc.c.

Referenced by computeDistance().

#define PointStrategyNumberGroup   0

Definition at line 1366 of file gistproc.c.

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

#define PolygonStrategyNumberGroup   2

Definition at line 1368 of file gistproc.c.

Referenced by gist_point_consistent().

Function Documentation

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

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

145 {
146  if (FLOAT8_LT(b->high.x, addon->high.x))
147  b->high.x = addon->high.x;
148  if (FLOAT8_GT(b->low.x, addon->low.x))
149  b->low.x = addon->low.x;
150  if (FLOAT8_LT(b->high.y, addon->high.y))
151  b->high.y = addon->high.y;
152  if (FLOAT8_GT(b->low.y, addon->low.y))
153  b->low.y = addon->low.y;
154 }
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:40
#define FLOAT8_LT(a, b)
Definition: gistproc.c:38
static double box_penalty ( const BOX original,
const BOX new 
)
static

Definition at line 95 of file gistproc.c.

References rt_box_union(), and size_box().

Referenced by gist_box_penalty(), and gist_box_picksplit().

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

Definition at line 486 of file gistproc.c.

Referenced by gist_box_picksplit().

487 {
488  double delta1 = ((const CommonEntry *) i1)->delta,
489  delta2 = ((const CommonEntry *) i2)->delta;
490 
491  if (delta1 < delta2)
492  return -1;
493  else if (delta1 > delta2)
494  return 1;
495  else
496  return 0;
497 }
static double computeDistance ( bool  isLeaf,
BOX box,
Point point 
)
static

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

1257 {
1258  double result = 0.0;
1259 
1260  if (isLeaf)
1261  {
1262  /* simple point to point distance */
1263  result = point_point_distance(point, &box->low);
1264  }
1265  else if (point->x <= box->high.x && point->x >= box->low.x &&
1266  point->y <= box->high.y && point->y >= box->low.y)
1267  {
1268  /* point inside the box */
1269  result = 0.0;
1270  }
1271  else if (point->x <= box->high.x && point->x >= box->low.x)
1272  {
1273  /* point is over or below box */
1274  Assert(box->low.y <= box->high.y);
1275  if (point->y > box->high.y)
1276  result = point->y - box->high.y;
1277  else if (point->y < box->low.y)
1278  result = box->low.y - point->y;
1279  else
1280  elog(ERROR, "inconsistent point values");
1281  }
1282  else if (point->y <= box->high.y && point->y >= box->low.y)
1283  {
1284  /* point is to left or right of box */
1285  Assert(box->low.x <= box->high.x);
1286  if (point->x > box->high.x)
1287  result = point->x - box->high.x;
1288  else if (point->x < box->low.x)
1289  result = box->low.x - point->x;
1290  else
1291  elog(ERROR, "inconsistent point values");
1292  }
1293  else
1294  {
1295  /* closest point will be a vertex */
1296  Point p;
1297  double subresult;
1298 
1299  result = point_point_distance(point, &box->low);
1300 
1301  subresult = point_point_distance(point, &box->high);
1302  if (result > subresult)
1303  result = subresult;
1304 
1305  p.x = box->low.x;
1306  p.y = box->high.y;
1307  subresult = point_point_distance(point, &p);
1308  if (result > subresult)
1309  result = subresult;
1310 
1311  p.x = box->high.x;
1312  p.y = box->low.y;
1313  subresult = point_point_distance(point, &p);
1314  if (result > subresult)
1315  result = subresult;
1316  }
1317 
1318  return result;
1319 }
double y
Definition: geo_decls.h:60
double x
Definition: geo_decls.h:60
#define point_point_distance(p1, p2)
Definition: gistproc.c:1251
#define ERROR
Definition: elog.h:43
Point low
Definition: geo_decls.h:104
#define Assert(condition)
Definition: c.h:671
Point high
Definition: geo_decls.h:104
#define elog
Definition: elog.h:219
static void fallbackSplit ( GistEntryVector entryvec,
GIST_SPLITVEC v 
)
static

Definition at line 242 of file gistproc.c.

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

243 {
244  OffsetNumber i,
245  maxoff;
246  BOX *unionL = NULL,
247  *unionR = NULL;
248  int nbytes;
249 
250  maxoff = entryvec->n - 1;
251 
252  nbytes = (maxoff + 2) * sizeof(OffsetNumber);
253  v->spl_left = (OffsetNumber *) palloc(nbytes);
254  v->spl_right = (OffsetNumber *) palloc(nbytes);
255  v->spl_nleft = v->spl_nright = 0;
256 
257  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
258  {
259  BOX *cur = DatumGetBoxP(entryvec->vector[i].key);
260 
261  if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
262  {
263  v->spl_left[v->spl_nleft] = i;
264  if (unionL == NULL)
265  {
266  unionL = (BOX *) palloc(sizeof(BOX));
267  *unionL = *cur;
268  }
269  else
270  adjustBox(unionL, cur);
271 
272  v->spl_nleft++;
273  }
274  else
275  {
276  v->spl_right[v->spl_nright] = i;
277  if (unionR == NULL)
278  {
279  unionR = (BOX *) palloc(sizeof(BOX));
280  *unionR = *cur;
281  }
282  else
283  adjustBox(unionR, cur);
284 
285  v->spl_nright++;
286  }
287  }
288 
289  v->spl_ldatum = BoxPGetDatum(unionL);
290  v->spl_rdatum = BoxPGetDatum(unionR);
291 }
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:144
#define BoxPGetDatum(X)
Definition: geo_decls.h:160
Datum spl_ldatum
Definition: gist.h:107
#define NULL
Definition: c.h:226
#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:891
int i
static void g_box_consider_split ( ConsiderSplitContext context,
int  dimNum,
double  rightLower,
int  minLeftCount,
double  leftUpper,
int  maxLeftCount 
)
inlinestatic

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

380 {
381  int leftCount,
382  rightCount;
383  float4 ratio,
384  overlap;
385  double range;
386 
387  /*
388  * Calculate entries distribution ratio assuming most uniform distribution
389  * of common entries.
390  */
391  if (minLeftCount >= (context->entriesCount + 1) / 2)
392  {
393  leftCount = minLeftCount;
394  }
395  else
396  {
397  if (maxLeftCount <= context->entriesCount / 2)
398  leftCount = maxLeftCount;
399  else
400  leftCount = context->entriesCount / 2;
401  }
402  rightCount = context->entriesCount - leftCount;
403 
404  /*
405  * Ratio of split - quotient between size of lesser group and total
406  * entries count.
407  */
408  ratio = ((float4) Min(leftCount, rightCount)) /
409  ((float4) context->entriesCount);
410 
411  if (ratio > LIMIT_RATIO)
412  {
413  bool selectthis = false;
414 
415  /*
416  * The ratio is acceptable, so compare current split with previously
417  * selected one. Between splits of one dimension we search for minimal
418  * overlap (allowing negative values) and minimal ration (between same
419  * overlaps. We switch dimension if find less overlap (non-negative)
420  * or less range with same overlap.
421  */
422  if (dimNum == 0)
423  range = context->boundingBox.high.x - context->boundingBox.low.x;
424  else
425  range = context->boundingBox.high.y - context->boundingBox.low.y;
426 
427  overlap = (leftUpper - rightLower) / range;
428 
429  /* If there is no previous selection, select this */
430  if (context->first)
431  selectthis = true;
432  else if (context->dim == dimNum)
433  {
434  /*
435  * Within the same dimension, choose the new split if it has a
436  * smaller overlap, or same overlap but better ratio.
437  */
438  if (overlap < context->overlap ||
439  (overlap == context->overlap && ratio > context->ratio))
440  selectthis = true;
441  }
442  else
443  {
444  /*
445  * Across dimensions, choose the new split if it has a smaller
446  * *non-negative* overlap, or same *non-negative* overlap but
447  * bigger range. This condition differs from the one described in
448  * the article. On the datasets where leaf MBRs don't overlap
449  * themselves, non-overlapping splits (i.e. splits which have zero
450  * *non-negative* overlap) are frequently possible. In this case
451  * splits tends to be along one dimension, because most distant
452  * non-overlapping splits (i.e. having lowest negative overlap)
453  * appears to be in the same dimension as in the previous split.
454  * Therefore MBRs appear to be very prolonged along another
455  * dimension, which leads to bad search performance. Using range
456  * as the second split criteria makes MBRs more quadratic. Using
457  * *non-negative* overlap instead of overlap as the first split
458  * criteria gives to range criteria a chance to matter, because
459  * non-overlapping splits are equivalent in this criteria.
460  */
461  if (non_negative(overlap) < non_negative(context->overlap) ||
462  (range > context->range &&
463  non_negative(overlap) <= non_negative(context->overlap)))
464  selectthis = true;
465  }
466 
467  if (selectthis)
468  {
469  /* save information about selected split */
470  context->first = false;
471  context->ratio = ratio;
472  context->range = range;
473  context->overlap = overlap;
474  context->rightLower = rightLower;
475  context->leftUpper = leftUpper;
476  context->dim = dimNum;
477  }
478  }
479 }
#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:377
#define LIMIT_RATIO
Definition: gistproc.c:34
static float non_negative(float val)
Definition: gistproc.c:365
Point high
Definition: geo_decls.h:104
static double gist_bbox_distance ( GISTENTRY entry,
Datum  query,
StrategyNumber  strategy,
bool recheck 
)
static

Definition at line 1518 of file gistproc.c.

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

Referenced by gist_circle_distance(), and gist_poly_distance().

1520 {
1521  double distance;
1522  StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1523 
1524  /* Bounding box distance is always inexact. */
1525  *recheck = true;
1526 
1527  switch (strategyGroup)
1528  {
1530  distance = computeDistance(false,
1531  DatumGetBoxP(entry->key),
1532  DatumGetPointP(query));
1533  break;
1534  default:
1535  elog(ERROR, "unrecognized strategy number: %d", strategy);
1536  distance = 0.0; /* keep compiler quiet */
1537  }
1538 
1539  return distance;
1540 }
#define GeoStrategyNumberOffset
Definition: gistproc.c:1365
uint16 StrategyNumber
Definition: stratnum.h:22
#define PointStrategyNumberGroup
Definition: gistproc.c:1366
#define ERROR
Definition: elog.h:43
Datum key
Definition: gist.h:123
static double computeDistance(bool isLeaf, BOX *box, Point *point)
Definition: gistproc.c:1256
#define DatumGetPointP(X)
Definition: geo_decls.h:137
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
#define elog
Definition: elog.h:219
Datum gist_box_compress ( PG_FUNCTION_ARGS  )

Definition at line 192 of file gistproc.c.

References PG_GETARG_POINTER, and PG_RETURN_POINTER.

193 {
195 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
Datum gist_box_consistent ( PG_FUNCTION_ARGS  )

Definition at line 111 of file gistproc.c.

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

112 {
113  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
114  BOX *query = PG_GETARG_BOX_P(1);
116 
117  /* Oid subtype = PG_GETARG_OID(3); */
118  bool *recheck = (bool *) PG_GETARG_POINTER(4);
119 
120  /* All cases served by this function are exact */
121  *recheck = false;
122 
123  if (DatumGetBoxP(entry->key) == NULL || query == NULL)
125 
126  /*
127  * if entry is not leaf, use rtree_internal_consistent, else use
128  * gist_box_leaf_consistent
129  */
130  if (GIST_LEAF(entry))
132  query,
133  strategy));
134  else
136  query,
137  strategy));
138 }
#define GIST_LEAF(entry)
Definition: gist.h:133
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:990
Definition: geo_decls.h:102
static bool gist_box_leaf_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:903
#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:232
#define FALSE
Definition: c.h:218
Datum key
Definition: gist.h:123
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
#define NULL
Definition: c.h:226
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:228
Datum gist_box_decompress ( PG_FUNCTION_ARGS  )

Definition at line 204 of file gistproc.c.

References PG_GETARG_POINTER, and PG_RETURN_POINTER.

205 {
207 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
Datum gist_box_fetch ( PG_FUNCTION_ARGS  )

Definition at line 214 of file gistproc.c.

References PG_GETARG_POINTER, and PG_RETURN_POINTER.

215 {
217 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
static bool gist_box_leaf_consistent ( BOX key,
BOX query,
StrategyNumber  strategy 
)
static

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

904 {
905  bool retval;
906 
907  switch (strategy)
908  {
911  PointerGetDatum(key),
912  PointerGetDatum(query)));
913  break;
916  PointerGetDatum(key),
917  PointerGetDatum(query)));
918  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;
942  PointerGetDatum(key),
943  PointerGetDatum(query)));
944  break;
948  PointerGetDatum(key),
949  PointerGetDatum(query)));
950  break;
953  PointerGetDatum(key),
954  PointerGetDatum(query)));
955  break;
958  PointerGetDatum(key),
959  PointerGetDatum(query)));
960  break;
963  PointerGetDatum(key),
964  PointerGetDatum(query)));
965  break;
968  PointerGetDatum(key),
969  PointerGetDatum(query)));
970  break;
971  default:
972  elog(ERROR, "unrecognized strategy number: %d", strategy);
973  retval = false; /* keep compiler quiet */
974  break;
975  }
976  return retval;
977 }
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:564
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:401
#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:557
Datum gist_box_penalty ( PG_FUNCTION_ARGS  )

Definition at line 225 of file gistproc.c.

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

226 {
227  GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
228  GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
229  float *result = (float *) PG_GETARG_POINTER(2);
230  BOX *origbox = DatumGetBoxP(origentry->key);
231  BOX *newbox = DatumGetBoxP(newentry->key);
232 
233  *result = (float) box_penalty(origbox, newbox);
234  PG_RETURN_POINTER(result);
235 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
Definition: geo_decls.h:102
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
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:95
Datum gist_box_picksplit ( PG_FUNCTION_ARGS  )

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

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

Definition at line 883 of file gistproc.c.

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

884 {
885  BOX *b1 = PG_GETARG_BOX_P(0);
886  BOX *b2 = PG_GETARG_BOX_P(1);
887  bool *result = (bool *) PG_GETARG_POINTER(2);
888 
889  if (b1 && b2)
890  *result = (FLOAT8_EQ(b1->low.x, b2->low.x) &&
891  FLOAT8_EQ(b1->low.y, b2->low.y) &&
892  FLOAT8_EQ(b1->high.x, b2->high.x) &&
893  FLOAT8_EQ(b1->high.y, b2->high.y));
894  else
895  *result = (b1 == NULL && b2 == NULL);
896  PG_RETURN_POINTER(result);
897 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
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:232
double x
Definition: geo_decls.h:60
#define FLOAT8_EQ(a, b)
Definition: gistproc.c:37
Point low
Definition: geo_decls.h:104
#define NULL
Definition: c.h:226
Point high
Definition: geo_decls.h:104
Datum gist_box_union ( PG_FUNCTION_ARGS  )

Definition at line 162 of file gistproc.c.

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

163 {
165  int *sizep = (int *) PG_GETARG_POINTER(1);
166  int numranges,
167  i;
168  BOX *cur,
169  *pageunion;
170 
171  numranges = entryvec->n;
172  pageunion = (BOX *) palloc(sizeof(BOX));
173  cur = DatumGetBoxP(entryvec->vector[0].key);
174  memcpy((void *) pageunion, (void *) cur, sizeof(BOX));
175 
176  for (i = 1; i < numranges; i++)
177  {
178  cur = DatumGetBoxP(entryvec->vector[i].key);
179  adjustBox(pageunion, cur);
180  }
181  *sizep = sizeof(BOX);
182 
183  PG_RETURN_POINTER(pageunion);
184 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
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:232
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:144
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
void * palloc(Size size)
Definition: mcxt.c:891
int i
Datum gist_circle_compress ( PG_FUNCTION_ARGS  )

Definition at line 1135 of file gistproc.c.

References CIRCLE::center, DatumGetCircleP, FALSE, 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.

1136 {
1137  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1138  GISTENTRY *retval;
1139 
1140  if (entry->leafkey)
1141  {
1142  CIRCLE *in = DatumGetCircleP(entry->key);
1143  BOX *r;
1144 
1145  r = (BOX *) palloc(sizeof(BOX));
1146  r->high.x = in->center.x + in->radius;
1147  r->low.x = in->center.x - in->radius;
1148  r->high.y = in->center.y + in->radius;
1149  r->low.y = in->center.y - in->radius;
1150 
1151  retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
1152  gistentryinit(*retval, PointerGetDatum(r),
1153  entry->rel, entry->page,
1154  entry->offset, FALSE);
1155  }
1156  else
1157  retval = entry;
1158  PG_RETURN_POINTER(retval);
1159 }
Relation rel
Definition: gist.h:124
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
Definition: geo_decls.h:102
#define PointerGetDatum(X)
Definition: postgres.h:564
double radius
Definition: geo_decls.h:127
double y
Definition: geo_decls.h:60
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
Page page
Definition: gist.h:125
double x
Definition: geo_decls.h:60
#define FALSE
Definition: c.h:218
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:891
OffsetNumber offset
Definition: gist.h:126
Datum gist_circle_consistent ( PG_FUNCTION_ARGS  )

Definition at line 1165 of file gistproc.c.

References CIRCLE::center, DatumGetBoxP, FALSE, BOX::high, GISTENTRY::key, BOX::low, NULL, 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().

1166 {
1167  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1168  CIRCLE *query = PG_GETARG_CIRCLE_P(1);
1170 
1171  /* Oid subtype = PG_GETARG_OID(3); */
1172  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1173  BOX bbox;
1174  bool result;
1175 
1176  /* All cases served by this function are inexact */
1177  *recheck = true;
1178 
1179  if (DatumGetBoxP(entry->key) == NULL || query == NULL)
1181 
1182  /*
1183  * Since the operators require recheck anyway, we can just use
1184  * rtree_internal_consistent even at leaf nodes. (This works in part
1185  * because the index entries are bounding boxes not circles.)
1186  */
1187  bbox.high.x = query->center.x + query->radius;
1188  bbox.low.x = query->center.x - query->radius;
1189  bbox.high.y = query->center.y + query->radius;
1190  bbox.low.y = query->center.y - query->radius;
1191 
1192  result = rtree_internal_consistent(DatumGetBoxP(entry->key),
1193  &bbox, strategy);
1194 
1195  PG_RETURN_BOOL(result);
1196 }
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:990
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:232
double x
Definition: geo_decls.h:60
#define FALSE
Definition: c.h:218
Datum key
Definition: gist.h:123
Point low
Definition: geo_decls.h:104
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
#define PG_GETARG_CIRCLE_P(n)
Definition: geo_decls.h:173
#define NULL
Definition: c.h:226
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
Point high
Definition: geo_decls.h:104
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:228
Point center
Definition: geo_decls.h:126
Datum gist_circle_distance ( PG_FUNCTION_ARGS  )

Definition at line 1543 of file gistproc.c.

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

1544 {
1545  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1546  Datum query = PG_GETARG_DATUM(1);
1548 
1549  /* Oid subtype = PG_GETARG_OID(3); */
1550  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1551  double distance;
1552 
1553  distance = gist_bbox_distance(entry, query, strategy, recheck);
1554 
1555  PG_RETURN_FLOAT8(distance);
1556 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:310
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
static double gist_bbox_distance(GISTENTRY *entry, Datum query, StrategyNumber strategy, bool *recheck)
Definition: gistproc.c:1518
uintptr_t Datum
Definition: postgres.h:374
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:228
Datum gist_point_compress ( PG_FUNCTION_ARGS  )

Definition at line 1203 of file gistproc.c.

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

1204 {
1205  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1206 
1207  if (entry->leafkey) /* Point, actually */
1208  {
1209  BOX *box = palloc(sizeof(BOX));
1210  Point *point = DatumGetPointP(entry->key);
1211  GISTENTRY *retval = palloc(sizeof(GISTENTRY));
1212 
1213  box->high = box->low = *point;
1214 
1215  gistentryinit(*retval, BoxPGetDatum(box),
1216  entry->rel, entry->page, entry->offset, FALSE);
1217 
1218  PG_RETURN_POINTER(retval);
1219  }
1220 
1221  PG_RETURN_POINTER(entry);
1222 }
Relation rel
Definition: gist.h:124
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
Definition: geo_decls.h:102
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
Page page
Definition: gist.h:125
#define FALSE
Definition: c.h:218
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:891
OffsetNumber offset
Definition: gist.h:126
Datum gist_point_consistent ( PG_FUNCTION_ARGS  )

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

1373 {
1374  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1376  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1377  bool result;
1378  StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1379 
1380  switch (strategyGroup)
1381  {
1384  GIST_LEAF(entry),
1385  DatumGetBoxP(entry->key),
1386  PG_GETARG_POINT_P(1));
1387  *recheck = false;
1388  break;
1390  {
1391  /*
1392  * The only operator in this group is point <@ box (on_pb), so
1393  * we needn't examine strategy again.
1394  *
1395  * For historical reasons, on_pb uses exact rather than fuzzy
1396  * comparisons. We could use box_overlap when at an internal
1397  * page, but that would lead to possibly visiting child pages
1398  * uselessly, because box_overlap uses fuzzy comparisons.
1399  * Instead we write a non-fuzzy overlap test. The same code
1400  * will also serve for leaf-page tests, since leaf keys have
1401  * high == low.
1402  */
1403  BOX *query,
1404  *key;
1405 
1406  query = PG_GETARG_BOX_P(1);
1407  key = DatumGetBoxP(entry->key);
1408 
1409  result = (key->high.x >= query->low.x &&
1410  key->low.x <= query->high.x &&
1411  key->high.y >= query->low.y &&
1412  key->low.y <= query->high.y);
1413  *recheck = false;
1414  }
1415  break;
1417  {
1418  POLYGON *query = PG_GETARG_POLYGON_P(1);
1419 
1422  PointerGetDatum(entry),
1423  PolygonPGetDatum(query),
1425  0, PointerGetDatum(recheck)));
1426 
1427  if (GIST_LEAF(entry) && result)
1428  {
1429  /*
1430  * We are on leaf page and quick check shows overlapping
1431  * of polygon's bounding box and point
1432  */
1433  BOX *box = DatumGetBoxP(entry->key);
1434 
1435  Assert(box->high.x == box->low.x
1436  && box->high.y == box->low.y);
1439  PolygonPGetDatum(query),
1440  PointPGetDatum(&box->high)));
1441  *recheck = false;
1442  }
1443  }
1444  break;
1446  {
1447  CIRCLE *query = PG_GETARG_CIRCLE_P(1);
1448 
1451  PointerGetDatum(entry),
1452  CirclePGetDatum(query),
1454  0, PointerGetDatum(recheck)));
1455 
1456  if (GIST_LEAF(entry) && result)
1457  {
1458  /*
1459  * We are on leaf page and quick check shows overlapping
1460  * of polygon's bounding box and point
1461  */
1462  BOX *box = DatumGetBoxP(entry->key);
1463 
1464  Assert(box->high.x == box->low.x
1465  && box->high.y == box->low.y);
1468  CirclePGetDatum(query),
1469  PointPGetDatum(&box->high)));
1470  *recheck = false;
1471  }
1472  }
1473  break;
1474  default:
1475  elog(ERROR, "unrecognized strategy number: %d", strategy);
1476  result = false; /* keep compiler quiet */
1477  break;
1478  }
1479 
1480  PG_RETURN_BOOL(result);
1481 }
#define GIST_LEAF(entry)
Definition: gist.h:133
#define GeoStrategyNumberOffset
Definition: gistproc.c:1365
Definition: geo_decls.h:102
#define BoxStrategyNumberGroup
Definition: gistproc.c:1367
#define PG_GETARG_BOX_P(n)
Definition: geo_decls.h:161
#define CircleStrategyNumberGroup
Definition: gistproc.c:1369
#define PointerGetDatum(X)
Definition: postgres.h:564
#define PolygonPGetDatum(X)
Definition: geo_decls.h:166
double y
Definition: geo_decls.h:60
#define Int16GetDatum(X)
Definition: postgres.h:459
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
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:1366
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:401
static bool gist_point_consistent_internal(StrategyNumber strategy, bool isLeaf, BOX *key, Point *query)
Definition: gistproc.c:1322
#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5)
Definition: fmgr.h:563
Point low
Definition: geo_decls.h:104
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
Datum circle_contain_pt(PG_FUNCTION_ARGS)
Definition: geo_ops.c:5013
Datum gist_circle_consistent(PG_FUNCTION_ARGS)
Definition: gistproc.c:1165
#define PolygonStrategyNumberGroup
Definition: gistproc.c:1368
#define PG_GETARG_CIRCLE_P(n)
Definition: geo_decls.h:173
#define Assert(condition)
Definition: c.h:671
Datum gist_poly_consistent(PG_FUNCTION_ARGS)
Definition: gistproc.c:1097
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
Point high
Definition: geo_decls.h:104
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:228
#define RTOverlapStrategyNumber
Definition: stratnum.h:46
#define elog
Definition: elog.h:219
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:557
#define PointPGetDatum(X)
Definition: geo_decls.h:138
static bool gist_point_consistent_internal ( StrategyNumber  strategy,
bool  isLeaf,
BOX key,
Point query 
)
static

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

1324 {
1325  bool result = false;
1326 
1327  switch (strategy)
1328  {
1329  case RTLeftStrategyNumber:
1330  result = FPlt(key->low.x, query->x);
1331  break;
1332  case RTRightStrategyNumber:
1333  result = FPgt(key->high.x, query->x);
1334  break;
1335  case RTAboveStrategyNumber:
1336  result = FPgt(key->high.y, query->y);
1337  break;
1338  case RTBelowStrategyNumber:
1339  result = FPlt(key->low.y, query->y);
1340  break;
1341  case RTSameStrategyNumber:
1342  if (isLeaf)
1343  {
1344  /* key.high must equal key.low, so we can disregard it */
1345  result = (FPeq(key->low.x, query->x) &&
1346  FPeq(key->low.y, query->y));
1347  }
1348  else
1349  {
1350  result = (FPle(query->x, key->high.x) &&
1351  FPge(query->x, key->low.x) &&
1352  FPle(query->y, key->high.y) &&
1353  FPge(query->y, key->low.y));
1354  }
1355  break;
1356  default:
1357  elog(ERROR, "unrecognized strategy number: %d", strategy);
1358  result = false; /* keep compiler quiet */
1359  break;
1360  }
1361 
1362  return result;
1363 }
#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
Datum gist_point_distance ( PG_FUNCTION_ARGS  )

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

1485 {
1486  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1488  double distance;
1489  StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1490 
1491  switch (strategyGroup)
1492  {
1494  distance = computeDistance(GIST_LEAF(entry),
1495  DatumGetBoxP(entry->key),
1496  PG_GETARG_POINT_P(1));
1497  break;
1498  default:
1499  elog(ERROR, "unrecognized strategy number: %d", strategy);
1500  distance = 0.0; /* keep compiler quiet */
1501  break;
1502  }
1503 
1504  PG_RETURN_FLOAT8(distance);
1505 }
#define GIST_LEAF(entry)
Definition: gist.h:133
#define GeoStrategyNumberOffset
Definition: gistproc.c:1365
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:310
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define PointStrategyNumberGroup
Definition: gistproc.c:1366
#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:1256
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:228
#define elog
Definition: elog.h:219
Datum gist_point_fetch ( PG_FUNCTION_ARGS  )

Definition at line 1231 of file gistproc.c.

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

1232 {
1233  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1234  BOX *in = DatumGetBoxP(entry->key);
1235  Point *r;
1236  GISTENTRY *retval;
1237 
1238  retval = palloc(sizeof(GISTENTRY));
1239 
1240  r = (Point *) palloc(sizeof(Point));
1241  r->x = in->high.x;
1242  r->y = in->high.y;
1243  gistentryinit(*retval, PointerGetDatum(r),
1244  entry->rel, entry->page,
1245  entry->offset, FALSE);
1246 
1247  PG_RETURN_POINTER(retval);
1248 }
Relation rel
Definition: gist.h:124
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
Definition: geo_decls.h:102
#define PointerGetDatum(X)
Definition: postgres.h:564
double y
Definition: geo_decls.h:60
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
Page page
Definition: gist.h:125
double x
Definition: geo_decls.h:60
#define FALSE
Definition: c.h:218
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:891
OffsetNumber offset
Definition: gist.h:126
Datum gist_poly_compress ( PG_FUNCTION_ARGS  )

Definition at line 1070 of file gistproc.c.

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

1071 {
1072  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1073  GISTENTRY *retval;
1074 
1075  if (entry->leafkey)
1076  {
1077  POLYGON *in = DatumGetPolygonP(entry->key);
1078  BOX *r;
1079 
1080  r = (BOX *) palloc(sizeof(BOX));
1081  memcpy((void *) r, (void *) &(in->boundbox), sizeof(BOX));
1082 
1083  retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
1084  gistentryinit(*retval, PointerGetDatum(r),
1085  entry->rel, entry->page,
1086  entry->offset, FALSE);
1087  }
1088  else
1089  retval = entry;
1090  PG_RETURN_POINTER(retval);
1091 }
Relation rel
Definition: gist.h:124
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
Definition: geo_decls.h:102
#define PointerGetDatum(X)
Definition: postgres.h:564
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
Page page
Definition: gist.h:125
#define FALSE
Definition: c.h:218
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:891
OffsetNumber offset
Definition: gist.h:126
Datum gist_poly_consistent ( PG_FUNCTION_ARGS  )

Definition at line 1097 of file gistproc.c.

References POLYGON::boundbox, DatumGetBoxP, FALSE, GISTENTRY::key, NULL, 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().

1098 {
1099  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1100  POLYGON *query = PG_GETARG_POLYGON_P(1);
1102 
1103  /* Oid subtype = PG_GETARG_OID(3); */
1104  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1105  bool result;
1106 
1107  /* All cases served by this function are inexact */
1108  *recheck = true;
1109 
1110  if (DatumGetBoxP(entry->key) == NULL || query == NULL)
1112 
1113  /*
1114  * Since the operators require recheck anyway, we can just use
1115  * rtree_internal_consistent even at leaf nodes. (This works in part
1116  * because the index entries are bounding boxes not polygons.)
1117  */
1118  result = rtree_internal_consistent(DatumGetBoxP(entry->key),
1119  &(query->boundbox), strategy);
1120 
1121  /* Avoid memory leak if supplied poly is toasted */
1122  PG_FREE_IF_COPY(query, 1);
1123 
1124  PG_RETURN_BOOL(result);
1125 }
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:990
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
#define PG_GETARG_POLYGON_P(n)
Definition: geo_decls.h:167
#define FALSE
Definition: c.h:218
Datum key
Definition: gist.h:123
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:303
BOX boundbox
Definition: geo_decls.h:117
#define NULL
Definition: c.h:226
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:216
#define DatumGetBoxP(X)
Definition: geo_decls.h:159
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:228
Datum gist_poly_distance ( PG_FUNCTION_ARGS  )

Definition at line 1559 of file gistproc.c.

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

1560 {
1561  GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1562  Datum query = PG_GETARG_DATUM(1);
1564 
1565  /* Oid subtype = PG_GETARG_OID(3); */
1566  bool *recheck = (bool *) PG_GETARG_POINTER(4);
1567  double distance;
1568 
1569  distance = gist_bbox_distance(entry, query, strategy, recheck);
1570 
1571  PG_RETURN_FLOAT8(distance);
1572 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:224
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:310
uint16 StrategyNumber
Definition: stratnum.h:22
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
static double gist_bbox_distance(GISTENTRY *entry, Datum query, StrategyNumber strategy, bool *recheck)
Definition: gistproc.c:1518
uintptr_t Datum
Definition: postgres.h:374
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:228
static int interval_cmp_lower ( const void *  i1,
const void *  i2 
)
static

Definition at line 341 of file gistproc.c.

References float8_cmp_internal().

Referenced by gist_box_picksplit().

342 {
343  double lower1 = ((const SplitInterval *) i1)->lower,
344  lower2 = ((const SplitInterval *) i2)->lower;
345 
346  return float8_cmp_internal(lower1, lower2);
347 }
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:1052
static int interval_cmp_upper ( const void *  i1,
const void *  i2 
)
static

Definition at line 353 of file gistproc.c.

References float8_cmp_internal().

Referenced by gist_box_picksplit().

354 {
355  double upper1 = ((const SplitInterval *) i1)->upper,
356  upper2 = ((const SplitInterval *) i2)->upper;
357 
358  return float8_cmp_internal(upper1, upper2);
359 }
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:1052
static float non_negative ( float  val)
inlinestatic

Definition at line 365 of file gistproc.c.

References val.

Referenced by g_box_consider_split().

366 {
367  if (val >= 0.0f)
368  return val;
369  else
370  return 0.0f;
371 }
long val
Definition: informix.c:689
static void rt_box_union ( BOX n,
const BOX a,
const BOX b 
)
static

Definition at line 54 of file gistproc.c.

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

Referenced by box_penalty().

55 {
56  n->high.x = FLOAT8_MAX(a->high.x, b->high.x);
57  n->high.y = FLOAT8_MAX(a->high.y, b->high.y);
58  n->low.x = FLOAT8_MIN(a->low.x, b->low.x);
59  n->low.y = FLOAT8_MIN(a->low.y, b->low.y);
60 }
#define FLOAT8_MAX(a, b)
Definition: gistproc.c:42
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:43
Point high
Definition: geo_decls.h:104
static bool rtree_internal_consistent ( BOX key,
BOX query,
StrategyNumber  strategy 
)
static

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

991 {
992  bool retval;
993 
994  switch (strategy)
995  {
998  PointerGetDatum(key),
999  PointerGetDatum(query)));
1000  break;
1003  PointerGetDatum(key),
1004  PointerGetDatum(query)));
1005  break;
1008  PointerGetDatum(key),
1009  PointerGetDatum(query)));
1010  break;
1013  PointerGetDatum(key),
1014  PointerGetDatum(query)));
1015  break;
1016  case RTRightStrategyNumber:
1018  PointerGetDatum(key),
1019  PointerGetDatum(query)));
1020  break;
1021  case RTSameStrategyNumber:
1025  PointerGetDatum(key),
1026  PointerGetDatum(query)));
1027  break;
1031  PointerGetDatum(key),
1032  PointerGetDatum(query)));
1033  break;
1036  PointerGetDatum(key),
1037  PointerGetDatum(query)));
1038  break;
1039  case RTBelowStrategyNumber:
1041  PointerGetDatum(key),
1042  PointerGetDatum(query)));
1043  break;
1044  case RTAboveStrategyNumber:
1046  PointerGetDatum(key),
1047  PointerGetDatum(query)));
1048  break;
1051  PointerGetDatum(key),
1052  PointerGetDatum(query)));
1053  break;
1054  default:
1055  elog(ERROR, "unrecognized strategy number: %d", strategy);
1056  retval = false; /* keep compiler quiet */
1057  break;
1058  }
1059  return retval;
1060 }
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:564
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:401
#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:557
static double size_box ( const BOX box)
static

Definition at line 67 of file gistproc.c.

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

Referenced by box_penalty().

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