42 #include "access/gist.h"
43 #include "access/itup.h"
44 #include "access/skey.h"
45 #include "utils/sortsupport.h"
47 #include "../postgis_config.h"
51 #include "lwgeom_pg.h"
52 #include "gserialized_gist.h"
58 #define LIMIT_RATIO 0.3333333333333333
61 #define INDEX_TUPLES_PER_PAGE 291
66 #if POSTGIS_DEBUG_LEVEL > 0
67 static int g2d_counter_leaf = 0;
68 static int g2d_counter_internal = 0;
127 return pstrdup(
"<NULLPTR>");
145 BOX2DF *c = (BOX2DF*)palloc(
sizeof(BOX2DF));
146 memcpy((
void*)c, (
void*)b,
sizeof(BOX2DF));
147 POSTGIS_DEBUGF(5,
"copied box2df (%p) to box2df (%p)", b, c);
161 a->xmin = a->xmax = a->ymin = a->ymax =
NAN;
167 if ( ! isfinite(a->xmax) )
169 if ( ! isfinite(a->ymax) )
171 if ( ! isfinite(a->ymin) )
172 a->ymin = -1*FLT_MAX;
173 if ( ! isfinite(a->xmin) )
174 a->xmin = -1*FLT_MAX;
184 if (b_union->xmin > b_new->xmin || isnan(b_union->xmin))
185 b_union->xmin = b_new->xmin;
186 if (b_union->ymin > b_new->ymin || isnan(b_union->ymin))
187 b_union->ymin = b_new->ymin;
189 if (b_union->xmax < b_new->xmax || isnan(b_union->xmax))
190 b_union->xmax = b_new->xmax;
191 if (b_union->ymax < b_new->ymax || isnan(b_union->ymax))
192 b_union->ymax = b_new->ymax;
212 memset(box, 0,
sizeof(
GBOX));
232 if ( b->xmax < b->xmin )
238 if ( b->ymax < b->ymin )
252 if ( (a->xmin > b->xmax) || (b->xmin > a->xmax) ||
253 (a->ymin > b->ymax) || (b->ymin > a->ymax) )
270 if ( (a->xmin > b->xmin) || (a->xmax < b->xmax) ||
271 (a->ymin > b->ymin) || (a->ymax < b->ymax) )
288 if ( (a->xmin < b->xmin) || (a->xmax > b->xmax) ||
289 (a->ymin < b->ymin) || (a->ymax > b->ymax) )
307 else if ((a->xmin == b->xmin) && (a->xmax == b->xmax) && (a->ymin == b->ymin) && (a->ymax == b->ymax))
319 return a->xmax <= b->xmax;
328 return a->xmax < b->xmin;
337 return a->xmin > b->xmax;
346 return a->xmin >= b->xmin;
355 return a->ymax <= b->ymax;
364 return a->ymax < b->ymin;
373 return a->ymin > b->ymax;
382 return a->ymin >= b->ymin;
391 double a_x = (a->xmax + a->xmin) / 2.0;
392 double a_y = (a->ymax + a->ymin) / 2.0;
393 double b_x = (b->xmax + b->xmin) / 2.0;
394 double b_y = (b->ymax + b->ymin) / 2.0;
397 return sqrt((a_x - b_x) * (a_x - b_x) + (a_y - b_y) * (a_y - b_y));
401 static inline double pt_distance(
double ax,
double ay,
double bx,
double by)
403 return sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
418 return pt_distance(a->xmax, a->ymin, b->xmin, b->ymax);
420 return pt_distance(a->xmax, a->ymax, b->xmin, b->ymin);
422 return (
double)b->xmin - (double)a->xmax;
427 return pt_distance(a->xmin, a->ymin, b->xmax, b->ymax);
429 return pt_distance(a->xmin, a->ymax, b->xmax, b->ymin);
431 return (
double)a->xmin - (double)b->xmax;
436 return pt_distance(a->xmax, a->ymin, b->xmin, b->ymax);
438 return pt_distance(a->xmin, a->ymin, b->xmax, b->ymax);
440 return (
double)a->ymin - (double)b->ymax;
445 return pt_distance(a->xmax, a->ymax, b->xmin, b->ymin);
447 return pt_distance(a->xmin, a->ymax, b->xmax, b->ymin);
449 return (
double)b->ymin - (double)a->ymax;
455 static inline uint64_t
463 x.f = (b->xmax + b->xmin) / 2;
464 y.f = (b->ymax + b->ymin) / 2;
479 int need_detoast = PG_GSERIALIZED_DATUM_NEEDS_DETOAST((
struct varlena *)gsdatum);
531 int need_detoast = PG_GSERIALIZED_DATUM_NEEDS_DETOAST((
struct varlena *)gsdatum);
545 memcpy(box2df, f,
sizeof(BOX2DF));
586 BOX2DF b1, b2, *br1=NULL, *br2=NULL;
587 POSTGIS_DEBUG(3,
"entered function");
592 if ( predicate(br1, br2) )
603 BOX2DF b2, *br2=NULL;
604 POSTGIS_DEBUG(3,
"entered function");
608 if ( predicate(br1, br2) )
623 POSTGIS_DEBUG(3,
"entered function");
625 PG_RETURN_BOOL(
true);
627 PG_RETURN_BOOL(
false);
633 if (
box2df_contains((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
634 PG_RETURN_BOOL(
true);
636 PG_RETURN_BOOL(
false);
642 POSTGIS_DEBUG(3,
"entered function");
644 PG_RETURN_BOOL(
true);
646 PG_RETURN_BOOL(
false);
652 if (
box2df_within((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
653 PG_RETURN_BOOL(
true);
655 PG_RETURN_BOOL(
false);
661 POSTGIS_DEBUG(3,
"entered function");
663 PG_RETURN_BOOL(
true);
665 PG_RETURN_BOOL(
false);
671 if (
box2df_overlaps((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
672 PG_RETURN_BOOL(
true);
674 PG_RETURN_BOOL(
false);
685 Datum gs1 = PG_GETARG_DATUM(0);
686 Datum gs2 = PG_GETARG_DATUM(1);
688 POSTGIS_DEBUG(3,
"entered function");
698 PG_RETURN_FLOAT8(FLT_MAX);
705 Datum gs1 = PG_GETARG_DATUM(0);
706 Datum gs2 = PG_GETARG_DATUM(1);
708 POSTGIS_DEBUG(3,
"entered function");
718 PG_RETURN_FLOAT8(FLT_MAX);
725 PG_RETURN_BOOL(
true);
727 PG_RETURN_BOOL(
false);
733 POSTGIS_DEBUG(3,
"entered function");
735 PG_RETURN_BOOL(
true);
737 PG_RETURN_BOOL(
false);
743 POSTGIS_DEBUG(3,
"entered function");
745 PG_RETURN_BOOL(
true);
747 PG_RETURN_BOOL(
false);
754 PG_RETURN_BOOL(
true);
756 PG_RETURN_BOOL(
false);
763 PG_RETURN_BOOL(
true);
765 PG_RETURN_BOOL(
false);
772 PG_RETURN_BOOL(
true);
774 PG_RETURN_BOOL(
false);
781 PG_RETURN_BOOL(
true);
783 PG_RETURN_BOOL(
false);
790 PG_RETURN_BOOL(
true);
792 PG_RETURN_BOOL(
false);
799 PG_RETURN_BOOL(
true);
801 PG_RETURN_BOOL(
false);
808 PG_RETURN_BOOL(
true);
810 PG_RETURN_BOOL(
false);
817 PG_RETURN_BOOL(
true);
819 PG_RETURN_BOOL(
false);
826 PG_RETURN_BOOL(
true);
828 PG_RETURN_BOOL(
false);
845 GISTENTRY *entry_in = (GISTENTRY*)PG_GETARG_POINTER(0);
846 GISTENTRY *entry_out = NULL;
850 POSTGIS_DEBUG(4,
"[GIST] 'compress' function called");
856 if ( ! entry_in->leafkey )
858 POSTGIS_DEBUG(4,
"[GIST] non-leafkey entry, returning input unaltered");
859 PG_RETURN_POINTER(entry_in);
862 POSTGIS_DEBUG(4,
"[GIST] processing leafkey input");
863 entry_out = palloc(
sizeof(GISTENTRY));
869 if ( DatumGetPointer(entry_in->key) == NULL )
871 POSTGIS_DEBUG(4,
"[GIST] leafkey is null");
872 gistentryinit(*entry_out, (Datum) 0, entry_in->rel,
873 entry_in->page, entry_in->offset,
false);
874 POSTGIS_DEBUG(4,
"[GIST] returning copy of input");
875 PG_RETURN_POINTER(entry_out);
884 POSTGIS_DEBUG(4,
"[GIST] leafkey is null");
885 gistentryinit(*entry_out, (Datum) 0, entry_in->rel,
886 entry_in->page, entry_in->offset,
false);
887 POSTGIS_DEBUG(4,
"[GIST] returning copy of input");
888 PG_RETURN_POINTER(entry_out);
894 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
895 entry_in->rel, entry_in->page, entry_in->offset,
false);
897 POSTGIS_DEBUG(4,
"[GIST] empty geometry!");
898 PG_RETURN_POINTER(entry_out);
901 POSTGIS_DEBUGF(4,
"[GIST] got entry_in->key: %s",
box2df_to_string(&bbox_out));
904 if ( ! isfinite(bbox_out.xmax) || ! isfinite(bbox_out.xmin) ||
905 ! isfinite(bbox_out.ymax) || ! isfinite(bbox_out.ymin) )
908 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
909 entry_in->rel, entry_in->page, entry_in->offset,
false);
911 POSTGIS_DEBUG(4,
"[GIST] infinite geometry!");
912 PG_RETURN_POINTER(entry_out);
919 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
920 entry_in->rel, entry_in->page, entry_in->offset,
false);
923 POSTGIS_DEBUG(4,
"[GIST] 'compress' function complete");
924 PG_RETURN_POINTER(entry_out);
935 POSTGIS_DEBUG(5,
"[GIST] 'decompress' function called");
937 PG_RETURN_POINTER(PG_GETARG_POINTER(0));
949 POSTGIS_DEBUGF(4,
"[GIST] leaf consistent, strategy [%d], count[%i]",
950 strategy, g2d_counter_leaf++);
956 case RTOverlapStrategyNumber:
959 case RTSameStrategyNumber:
962 case RTContainsStrategyNumber:
963 case RTOldContainsStrategyNumber:
966 case RTContainedByStrategyNumber:
967 case RTOldContainedByStrategyNumber:
972 case RTAboveStrategyNumber:
975 case RTBelowStrategyNumber:
978 case RTRightStrategyNumber:
981 case RTLeftStrategyNumber:
986 case RTOverAboveStrategyNumber:
989 case RTOverBelowStrategyNumber:
992 case RTOverRightStrategyNumber:
995 case RTOverLeftStrategyNumber:
1013 POSTGIS_DEBUGF(4,
"[GIST] internal consistent, strategy [%d], count[%i], query[%s], key[%s]",
1020 case RTOverlapStrategyNumber:
1023 case RTSameStrategyNumber:
1024 case RTContainsStrategyNumber:
1025 case RTOldContainsStrategyNumber:
1028 case RTContainedByStrategyNumber:
1029 case RTOldContainedByStrategyNumber:
1034 case RTAboveStrategyNumber:
1037 case RTBelowStrategyNumber:
1040 case RTRightStrategyNumber:
1043 case RTLeftStrategyNumber:
1048 case RTOverAboveStrategyNumber:
1051 case RTOverBelowStrategyNumber:
1054 case RTOverRightStrategyNumber:
1057 case RTOverLeftStrategyNumber:
1075 GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
1076 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
1078 BOX2DF query_gbox_index;
1082 bool *recheck = (
bool *) PG_GETARG_POINTER(4);
1089 POSTGIS_DEBUG(4,
"[GIST] 'consistent' function called");
1092 if ( DatumGetPointer(PG_GETARG_DATUM(1)) == NULL )
1094 POSTGIS_DEBUG(4,
"[GIST] null query pointer (!?!), returning false");
1095 PG_RETURN_BOOL(
false);
1099 if ( DatumGetPointer(entry->key) == NULL )
1101 POSTGIS_DEBUG(4,
"[GIST] null index entry, returning false");
1102 PG_RETURN_BOOL(
false);
1108 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1109 PG_RETURN_BOOL(
false);
1113 if (GIST_LEAF(entry))
1116 (BOX2DF*)DatumGetPointer(entry->key),
1117 &query_gbox_index, strategy);
1122 (BOX2DF*)DatumGetPointer(entry->key),
1123 &query_gbox_index, strategy);
1149 GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
1152 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
1154 bool *recheck = (
bool *) PG_GETARG_POINTER(4);
1156 POSTGIS_DEBUG(4,
"[GIST] 'distance' function called");
1160 if ( strategy != 13 && strategy != 14 ) {
1161 elog(ERROR,
"unrecognized strategy number: %d", strategy);
1162 PG_RETURN_FLOAT8(FLT_MAX);
1168 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1169 PG_RETURN_FLOAT8(FLT_MAX);
1173 entry_box = (BOX2DF*)DatumGetPointer(entry->key);
1176 if ( strategy == 14 )
1181 else if ( strategy == 13 )
1188 if (GIST_LEAF(entry))
1193 elog(ERROR,
"%s: reached unreachable code", __func__);
1219 unsigned value : 31, sign : 1;
1222 unsigned value : 30, realm : 1, sign : 1;
1227 a.rbits.value = a.vbits.value >> 1;
1228 a.rbits.realm = realm;
1236 float b1xmin = b1->xmin, b1xmax = b1->xmax;
1237 float b1ymin = b1->ymin, b1ymax = b1->ymax;
1238 float b2xmin = b2->xmin, b2xmax = b2->xmax;
1239 float b2ymin = b2->ymin, b2ymax = b2->ymax;
1241 float box_union_xmin = Min(b1xmin, b2xmin), box_union_xmax = Max(b1xmax, b2xmax);
1242 float box_union_ymin = Min(b1ymin, b2ymin), box_union_ymax = Max(b1ymax, b2ymax);
1244 float b1dx = b1xmax - b1xmin, b1dy = b1ymax - b1ymin;
1245 float box_union_dx = box_union_xmax - box_union_xmin, box_union_dy = box_union_ymax - box_union_ymin;
1247 float box_union_area = box_union_dx * box_union_dy, box1area = b1dx * b1dy;
1248 float box_union_edge = box_union_dx + box_union_dy, box1edge = b1dx + b1dy;
1250 float area_extension = box_union_area - box1area;
1251 float edge_extension = box_union_edge - box1edge;
1254 if (area_extension > FLT_EPSILON)
1257 else if (edge_extension > FLT_EPSILON)
1270 GISTENTRY *origentry = (GISTENTRY*) PG_GETARG_POINTER(0);
1271 GISTENTRY *newentry = (GISTENTRY*) PG_GETARG_POINTER(1);
1272 float *
result = (
float*) PG_GETARG_POINTER(2);
1275 b1 = (BOX2DF *)DatumGetPointer(origentry->key);
1276 b2 = (BOX2DF *)DatumGetPointer(newentry->key);
1287 PG_RETURN_POINTER(
result);
1296 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1297 int *sizep = (
int *) PG_GETARG_POINTER(1);
1299 BOX2DF *box_cur, *box_union;
1301 POSTGIS_DEBUG(4,
"[GIST] 'union' function called");
1303 numranges = entryvec->n;
1305 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[0].key);
1309 for ( i = 1; i < numranges; i++ )
1311 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[i].key);
1315 *sizep =
sizeof(BOX2DF);
1317 POSTGIS_DEBUGF(4,
"[GIST] 'union', numranges(%i), pageunion %s", numranges,
box2df_to_string(box_union));
1319 PG_RETURN_POINTER(box_union);
1329 BOX2DF *b1 = (BOX2DF*)PG_GETARG_POINTER(0);
1330 BOX2DF *b2 = (BOX2DF*)PG_GETARG_POINTER(1);
1331 bool *
result = (
bool*)PG_GETARG_POINTER(2);
1333 POSTGIS_DEBUG(4,
"[GIST] 'same' function called");
1337 PG_RETURN_POINTER(
result);
1344 if (
x == 0 ||
y == 0 ||
x ==
y)
1367 BOX2DF *b1 = (BOX2DF *)a;
1368 BOX2DF *b2 = (BOX2DF *)b;
1369 uint64_t hash1, hash2;
1372 cmp = memcmp(b1, b2,
sizeof(BOX2DF));
1380 else if (hash1 < hash2)
1383 return cmp > 0 ? 1 : -1;
1389 SortSupport ssup = (SortSupport)PG_GETARG_POINTER(0);
1392 ssup->ssup_extra = NULL;
1394 if (ssup->abbreviate &&
sizeof(Datum) == 8)
1411 if (b->xmax < addon->xmax || isnan(b->xmax))
1412 b->xmax = addon->xmax;
1413 if (b->xmin > addon->xmin || isnan(b->xmin))
1414 b->xmin = addon->xmin;
1415 if (b->ymax < addon->ymax || isnan(b->ymax))
1416 b->ymax = addon->ymax;
1417 if (b->ymin > addon->ymin || isnan(b->ymin))
1418 b->ymin = addon->ymin;
1430 BOX2DF *unionL = NULL,
1434 maxoff = entryvec->n - 1;
1436 nbytes = (maxoff + 2) *
sizeof(OffsetNumber);
1437 v->spl_left = (OffsetNumber *) palloc(nbytes);
1438 v->spl_right = (OffsetNumber *) palloc(nbytes);
1439 v->spl_nleft = v->spl_nright = 0;
1441 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1443 BOX2DF *
cur = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1445 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
1447 v->spl_left[v->spl_nleft] = i;
1450 unionL = (BOX2DF *) palloc(
sizeof(BOX2DF));
1460 v->spl_right[v->spl_nright] = i;
1463 unionR = (BOX2DF *) palloc(
sizeof(BOX2DF));
1473 if (v->spl_ldatum_exists)
1474 adjustBox(unionL, (BOX2DF *) DatumGetPointer(v->spl_ldatum));
1475 v->spl_ldatum = PointerGetDatum(unionL);
1477 if (v->spl_rdatum_exists)
1478 adjustBox(unionR, (BOX2DF *) DatumGetPointer(v->spl_rdatum));
1479 v->spl_rdatum = PointerGetDatum(unionR);
1481 v->spl_ldatum_exists = v->spl_rdatum_exists =
false;
1544 else if (isnan(lower2))
1550 if (lower1 < lower2)
1552 else if (lower1 > lower2)
1576 else if (isnan(upper2))
1582 if (upper1 < upper2)
1584 else if (upper1 > upper2)
1608 float rightLower,
int minLeftCount,
1609 float leftUpper,
int maxLeftCount)
1617 POSTGIS_DEBUGF(5,
"consider split: dimNum = %d, rightLower = %f, "
1618 "minLeftCount = %d, leftUpper = %f, maxLeftCount = %d ",
1619 dimNum, rightLower, minLeftCount, leftUpper, maxLeftCount);
1627 leftCount = minLeftCount;
1631 if (maxLeftCount <= context->entriesCount / 2)
1632 leftCount = maxLeftCount;
1642 ratio = ((float4) Min(leftCount, rightCount)) /
1647 bool selectthis =
false;
1661 overlap = (leftUpper - rightLower) / range;
1666 else if (context->
dim == dimNum)
1672 if (overlap < context->overlap ||
1673 (overlap == context->
overlap && ratio > context->
ratio))
1696 (range > context->
range &&
1704 context->
first =
false;
1705 context->
ratio = ratio;
1706 context->
range = range;
1710 context->
dim = dimNum;
1711 POSTGIS_DEBUG(5,
"split selected");
1725 if (delta1 < delta2)
1727 else if (delta1 > delta2)
1762 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1763 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1777 POSTGIS_DEBUG(3,
"[GIST] 'picksplit' entered");
1781 maxoff = entryvec->n - 1;
1782 nentries = context.
entriesCount = maxoff - FirstOffsetNumber + 1;
1791 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1793 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1794 if (i == FirstOffsetNumber)
1806 context.
first =
true;
1807 for (dim = 0; dim < 2; dim++)
1815 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1817 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1820 intervalsLower[i - FirstOffsetNumber].
lower = box->xmin;
1821 intervalsLower[i - FirstOffsetNumber].
upper = box->xmax;
1825 intervalsLower[i - FirstOffsetNumber].
lower = box->ymin;
1826 intervalsLower[i - FirstOffsetNumber].
upper = box->ymax;
1834 memcpy(intervalsUpper, intervalsLower,
1877 rightLower = intervalsLower[i1].
lower;
1878 leftUpper = intervalsUpper[i2].
lower;
1884 while (i1 < nentries && (rightLower == intervalsLower[i1].lower ||
1885 isnan(intervalsLower[i1].lower)))
1887 leftUpper = Max(leftUpper, intervalsLower[i1].upper);
1892 rightLower = intervalsLower[i1].
lower;
1898 while (i2 < nentries && intervalsUpper[i2].upper <= leftUpper)
1913 rightLower = intervalsLower[i1].
upper;
1914 leftUpper = intervalsUpper[i2].
upper;
1920 while (i2 >= 0 && (leftUpper == intervalsUpper[i2].upper ||
1921 isnan(intervalsUpper[i2].upper)))
1923 rightLower = Min(rightLower, intervalsUpper[i2].lower);
1928 leftUpper = intervalsUpper[i2].
upper;
1934 while (i1 >= 0 && intervalsLower[i1].lower >= rightLower)
1941 rightLower, i1 + 1, leftUpper, i2 + 1);
1950 POSTGIS_DEBUG(4,
"no acceptable splits, trivial split");
1952 PG_RETURN_POINTER(v);
1963 POSTGIS_DEBUGF(4,
"split direction: %d", context.
dim);
1966 v->spl_left = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
1967 v->spl_right = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
1972 leftBox = palloc0(
sizeof(BOX2DF));
1973 rightBox = palloc0(
sizeof(BOX2DF));
1979 commonEntriesCount = 0;
1983 #define PLACE_LEFT(box, off) \
1985 if (v->spl_nleft > 0) \
1986 adjustBox(leftBox, box); \
1988 *leftBox = *(box); \
1989 v->spl_left[v->spl_nleft++] = off; \
1992 #define PLACE_RIGHT(box, off) \
1994 if (v->spl_nright > 0) \
1995 adjustBox(rightBox, box); \
1997 *rightBox = *(box); \
1998 v->spl_right[v->spl_nright++] = off; \
2005 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
2013 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
2014 if (context.
dim == 0)
2025 if (upper <= context.
leftUpper || isnan(upper))
2028 if (lower >= context.
rightLower || isnan(lower))
2031 commonEntries[commonEntriesCount++].
index = i;
2059 if (commonEntriesCount > 0)
2072 for (i = 0; i < (OffsetNumber)commonEntriesCount; i++)
2074 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
2075 commonEntries[i].
index].key);
2089 for (i = 0; i < (OffsetNumber)commonEntriesCount; i++)
2091 float right_penalty, left_penalty;
2092 bool place_right =
true;
2093 box = (BOX2DF *)DatumGetPointer(entryvec->vector[commonEntries[i].
index].key);
2100 if (right_penalty > 0 && left_penalty == 0)
2101 place_right =
false;
2102 else if (right_penalty == 0 && left_penalty > 0)
2105 else if (v->spl_nleft + (commonEntriesCount - i) <= m)
2106 place_right =
false;
2107 else if (v->spl_nright + (commonEntriesCount - i) <= m)
2110 else if (left_penalty < right_penalty)
2111 place_right =
false;
2112 else if (right_penalty < left_penalty)
2115 else if (v->spl_nleft < v->spl_nright)
2116 place_right =
false;
2126 v->spl_ldatum = PointerGetDatum(leftBox);
2127 v->spl_rdatum = PointerGetDatum(rightBox);
2129 POSTGIS_DEBUG(4,
"[GIST] 'picksplit' completed");
2131 PG_RETURN_POINTER(v);
2141 ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2142 errmsg(
"function box2df_in not implemented")));
2143 PG_RETURN_POINTER(NULL);
2149 BOX2DF *box = (BOX2DF *) PG_GETARG_POINTER(0);
2151 PG_RETURN_CSTRING(
result);
char result[OUT_DOUBLE_BUFFER_SIZE]
int gserialized_has_bbox(const GSERIALIZED *g)
Check if a GSERIALIZED has a bounding box without deserializing first.
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
const float * gserialized_get_float_box_p(const GSERIALIZED *g, size_t *ndims)
Access to the float bounding box, if there is one.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
uint32_t gserialized_max_header_size(void)
Returns the size in bytes to read from toast to get the basic information from a geometry: GSERIALIZE...
lwflags_t gserialized_get_lwflags(const GSERIALIZED *g)
Read the flags from a GSERIALIZED and return a standard lwflag integer.
bool box2df_left(const BOX2DF *a, const BOX2DF *b)
static char * box2df_to_string(const BOX2DF *a)
void box2df_merge(BOX2DF *b_union, BOX2DF *b_new)
static void fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
Datum gserialized_overbelow_2d(PG_FUNCTION_ARGS)
Datum gserialized_gist_sortsupport_2d(PG_FUNCTION_ARGS)
void box2df_set_empty(BOX2DF *a)
Datum gserialized_gist_same_2d(PG_FUNCTION_ARGS)
Datum gserialized_contains_box2df_geom_2d(PG_FUNCTION_ARGS)
bool box2df_is_empty(const BOX2DF *a)
static int gserialized_datum_predicate_2d(Datum gs1, Datum gs2, box2df_predicate predicate)
Support function.
Datum gserialized_within_2d(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(gserialized_contains_box2df_geom_2d)
Datum box2df_out(PG_FUNCTION_ARGS)
static Datum gserialized_gist_abbrev_convert_2d(Datum original, SortSupport ssup)
Datum gserialized_within_box2df_geom_2d(PG_FUNCTION_ARGS)
Datum gserialized_gist_penalty_2d(PG_FUNCTION_ARGS)
Datum gserialized_left_2d(PG_FUNCTION_ARGS)
Datum gserialized_contains_2d(PG_FUNCTION_ARGS)
#define INDEX_TUPLES_PER_PAGE
Datum gserialized_gist_consistent_2d(PG_FUNCTION_ARGS)
static int interval_cmp_upper(const void *i1, const void *i2)
Datum gserialized_distance_box_2d(PG_FUNCTION_ARGS)
bool box2df_equals(const BOX2DF *a, const BOX2DF *b)
static uint64_t box2df_get_sortable_hash(const BOX2DF *b)
static int gserialized_gist_cmp_abbrev_2d(Datum x, Datum y, SortSupport ssup)
bool box2df_contains(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_gist_union_2d(PG_FUNCTION_ARGS)
#define PLACE_RIGHT(box, off)
static int gserialized_gist_cmp_full_2d(Datum a, Datum b, SortSupport ssup)
Datum gserialized_gist_compress_2d(PG_FUNCTION_ARGS)
Datum gserialized_distance_centroid_2d(PG_FUNCTION_ARGS)
Datum gserialized_contains_box2df_box2df_2d(PG_FUNCTION_ARGS)
Datum gserialized_overlaps_2d(PG_FUNCTION_ARGS)
Datum gserialized_overlaps_box2df_geom_2d(PG_FUNCTION_ARGS)
Datum gserialized_within_box2df_box2df_2d(PG_FUNCTION_ARGS)
bool box2df_right(const BOX2DF *a, const BOX2DF *b)
bool box2df_overlaps(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_overleft_2d(PG_FUNCTION_ARGS)
void box2df_set_finite(BOX2DF *a)
static bool gserialized_gist_consistent_internal_2d(BOX2DF *key, BOX2DF *query, StrategyNumber strategy)
Datum gserialized_overlaps_box2df_box2df_2d(PG_FUNCTION_ARGS)
Datum gserialized_gist_distance_2d(PG_FUNCTION_ARGS)
Datum gserialized_overright_2d(PG_FUNCTION_ARGS)
static bool box2df_within(const BOX2DF *a, const BOX2DF *b)
bool box2df_above(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_right_2d(PG_FUNCTION_ARGS)
static bool gserialized_gist_abbrev_abort_2d(int memtupcount, SortSupport ssup)
bool box2df_overbelow(const BOX2DF *a, const BOX2DF *b)
bool(* box2df_predicate)(const BOX2DF *a, const BOX2DF *b)
static double box2df_distance(const BOX2DF *a, const BOX2DF *b)
Calculate the box->box distance.
static double box2df_distance_leaf_centroid(const BOX2DF *a, const BOX2DF *b)
Calculate the centroid->centroid distance between the boxes.
Datum gserialized_below_2d(PG_FUNCTION_ARGS)
Datum gserialized_overabove_2d(PG_FUNCTION_ARGS)
static void g_box_consider_split(ConsiderSplitContext *context, int dimNum, float rightLower, int minLeftCount, float leftUpper, int maxLeftCount)
int box2df_to_gbox_p(BOX2DF *a, GBOX *box)
static int interval_cmp_lower(const void *i1, const void *i2)
bool box2df_overright(const BOX2DF *a, const BOX2DF *b)
static double pt_distance(double ax, double ay, double bx, double by)
static float pack_float(const float value, const uint8_t realm)
static int common_entry_cmp(const void *i1, const void *i2)
Datum gserialized_gist_decompress_2d(PG_FUNCTION_ARGS)
int gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
int gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, lwflags_t *flags, uint8_t *type, int32_t *srid)
Peak into a GSERIALIZED datum to find its bounding box and some other metadata.
int gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox)
Given a GSERIALIZED datum, as quickly as possible (peaking into the top of the memory) return the gbo...
static int box2df_from_gbox_p(GBOX *box, BOX2DF *a)
bool box2df_overabove(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_gist_picksplit_2d(PG_FUNCTION_ARGS)
#define PLACE_LEFT(box, off)
void box2df_validate(BOX2DF *b)
static float box2df_penalty(const BOX2DF *b1, const BOX2DF *b2)
bool box2df_below(const BOX2DF *a, const BOX2DF *b)
static bool gserialized_gist_consistent_leaf_2d(BOX2DF *key, BOX2DF *query, StrategyNumber strategy)
bool box2df_overleft(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_above_2d(PG_FUNCTION_ARGS)
static int gserialized_datum_predicate_box2df_geom_2d(const BOX2DF *br1, Datum gs2, box2df_predicate predicate)
BOX2DF * box2df_copy(BOX2DF *b)
Datum gserialized_same_2d(PG_FUNCTION_ARGS)
Datum box2df_in(PG_FUNCTION_ARGS)
static void adjustBox(BOX2DF *b, BOX2DF *addon)
static float non_negative(float val)
#define LWSIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
float next_float_up(double d)
#define LW_TRUE
Return types for functions with status returns.
float next_float_down(double d)
This library is the generic geometry handling section of PostGIS.
#define OUT_MAX_BYTES_DOUBLE
int lwprint_double(double d, int maxdd, char *buf)
#define POSTGIS_FREE_IF_COPY_P(ptrsrc, ptrori)
static uint64_t uint32_hilbert(uint32_t px, uint32_t py)
static double distance(double x1, double y1, double x2, double y2)