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)
1266 float boxxmin = box->xmin, boxxmax = box->xmax;
1267 float boxymin = box->ymin, boxymax = box->ymax;
1269 float dx = boxxmax - boxxmin, dy = boxymax - boxymin;
1271 float area = dx * dy;
1272 float edge = dx + dy;
1275 if (area > FLT_EPSILON)
1278 else if (edge > FLT_EPSILON)
1291 GISTENTRY *origentry = (GISTENTRY*) PG_GETARG_POINTER(0);
1292 GISTENTRY *newentry = (GISTENTRY*) PG_GETARG_POINTER(1);
1293 float *
result = (
float*) PG_GETARG_POINTER(2);
1296 b1 = (BOX2DF *)DatumGetPointer(origentry->key);
1297 b2 = (BOX2DF *)DatumGetPointer(newentry->key);
1308 PG_RETURN_POINTER(
result);
1317 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1318 int *sizep = (
int *) PG_GETARG_POINTER(1);
1320 BOX2DF *box_cur, *box_union;
1322 POSTGIS_DEBUG(4,
"[GIST] 'union' function called");
1324 numranges = entryvec->n;
1326 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[0].key);
1330 for ( i = 1; i < numranges; i++ )
1332 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[i].key);
1336 *sizep =
sizeof(BOX2DF);
1338 POSTGIS_DEBUGF(4,
"[GIST] 'union', numranges(%i), pageunion %s", numranges,
box2df_to_string(box_union));
1340 PG_RETURN_POINTER(box_union);
1350 BOX2DF *b1 = (BOX2DF*)PG_GETARG_POINTER(0);
1351 BOX2DF *b2 = (BOX2DF*)PG_GETARG_POINTER(1);
1352 bool *
result = (
bool*)PG_GETARG_POINTER(2);
1354 POSTGIS_DEBUG(4,
"[GIST] 'same' function called");
1358 PG_RETURN_POINTER(
result);
1365 if (
x == 0 ||
y == 0 ||
x ==
y)
1388 BOX2DF *b1 = (BOX2DF *)a;
1389 BOX2DF *b2 = (BOX2DF *)b;
1390 uint64_t hash1, hash2;
1393 cmp = memcmp(b1, b2,
sizeof(BOX2DF));
1401 else if (hash1 < hash2)
1404 return cmp > 0 ? 1 : -1;
1410 SortSupport ssup = (SortSupport)PG_GETARG_POINTER(0);
1413 ssup->ssup_extra = NULL;
1415 if (ssup->abbreviate &&
sizeof(Datum) == 8)
1432 if (b->xmax < addon->xmax || isnan(b->xmax))
1433 b->xmax = addon->xmax;
1434 if (b->xmin > addon->xmin || isnan(b->xmin))
1435 b->xmin = addon->xmin;
1436 if (b->ymax < addon->ymax || isnan(b->ymax))
1437 b->ymax = addon->ymax;
1438 if (b->ymin > addon->ymin || isnan(b->ymin))
1439 b->ymin = addon->ymin;
1451 BOX2DF *unionL = NULL,
1455 maxoff = entryvec->n - 1;
1457 nbytes = (maxoff + 2) *
sizeof(OffsetNumber);
1458 v->spl_left = (OffsetNumber *) palloc(nbytes);
1459 v->spl_right = (OffsetNumber *) palloc(nbytes);
1460 v->spl_nleft = v->spl_nright = 0;
1462 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1464 BOX2DF *
cur = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1466 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
1468 v->spl_left[v->spl_nleft] = i;
1471 unionL = (BOX2DF *) palloc(
sizeof(BOX2DF));
1481 v->spl_right[v->spl_nright] = i;
1484 unionR = (BOX2DF *) palloc(
sizeof(BOX2DF));
1494 if (v->spl_ldatum_exists)
1495 adjustBox(unionL, (BOX2DF *) DatumGetPointer(v->spl_ldatum));
1496 v->spl_ldatum = PointerGetDatum(unionL);
1498 if (v->spl_rdatum_exists)
1499 adjustBox(unionR, (BOX2DF *) DatumGetPointer(v->spl_rdatum));
1500 v->spl_rdatum = PointerGetDatum(unionR);
1502 v->spl_ldatum_exists = v->spl_rdatum_exists =
false;
1565 else if (isnan(lower2))
1571 if (lower1 < lower2)
1573 else if (lower1 > lower2)
1597 else if (isnan(upper2))
1603 if (upper1 < upper2)
1605 else if (upper1 > upper2)
1629 float rightLower,
int minLeftCount,
1630 float leftUpper,
int maxLeftCount)
1638 POSTGIS_DEBUGF(5,
"consider split: dimNum = %d, rightLower = %f, "
1639 "minLeftCount = %d, leftUpper = %f, maxLeftCount = %d ",
1640 dimNum, rightLower, minLeftCount, leftUpper, maxLeftCount);
1648 leftCount = minLeftCount;
1652 if (maxLeftCount <= context->entriesCount / 2)
1653 leftCount = maxLeftCount;
1663 ratio = ((float4) Min(leftCount, rightCount)) /
1668 bool selectthis =
false;
1682 overlap = (leftUpper - rightLower) / range;
1687 else if (context->
dim == dimNum)
1693 if (overlap < context->overlap ||
1694 (overlap == context->
overlap && ratio > context->
ratio))
1717 (range > context->
range &&
1725 context->
first =
false;
1726 context->
ratio = ratio;
1727 context->
range = range;
1731 context->
dim = dimNum;
1732 POSTGIS_DEBUG(5,
"split selected");
1746 if (delta1 < delta2)
1748 else if (delta1 > delta2)
1783 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1784 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1788 BOX2DF *leftBox, *rightBox;
1796 POSTGIS_DEBUG(3,
"[GIST] 'picksplit' entered");
1800 maxoff = entryvec->n - 1;
1801 nentries = context.
entriesCount = maxoff - FirstOffsetNumber + 1;
1810 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1812 BOX2DF *box = (BOX2DF *)DatumGetPointer(entryvec->vector[i].key);
1813 if (i == FirstOffsetNumber)
1825 context.
first =
true;
1826 for (dim = 0; dim < 2; dim++)
1834 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1836 BOX2DF *box = (BOX2DF *)DatumGetPointer(entryvec->vector[i].key);
1839 intervalsLower[i - FirstOffsetNumber].
lower = box->xmin;
1840 intervalsLower[i - FirstOffsetNumber].
upper = box->xmax;
1844 intervalsLower[i - FirstOffsetNumber].
lower = box->ymin;
1845 intervalsLower[i - FirstOffsetNumber].
upper = box->ymax;
1853 memcpy(intervalsUpper, intervalsLower,
1896 rightLower = intervalsLower[i1].
lower;
1897 leftUpper = intervalsUpper[i2].
lower;
1903 while (i1 < nentries && (rightLower == intervalsLower[i1].lower ||
1904 isnan(intervalsLower[i1].lower)))
1906 leftUpper = Max(leftUpper, intervalsLower[i1].upper);
1911 rightLower = intervalsLower[i1].
lower;
1917 while (i2 < nentries && intervalsUpper[i2].upper <= leftUpper)
1932 rightLower = intervalsLower[i1].
upper;
1933 leftUpper = intervalsUpper[i2].
upper;
1939 while (i2 >= 0 && (leftUpper == intervalsUpper[i2].upper ||
1940 isnan(intervalsUpper[i2].upper)))
1942 rightLower = Min(rightLower, intervalsUpper[i2].lower);
1947 leftUpper = intervalsUpper[i2].
upper;
1953 while (i1 >= 0 && intervalsLower[i1].lower >= rightLower)
1960 rightLower, i1 + 1, leftUpper, i2 + 1);
1969 POSTGIS_DEBUG(4,
"no acceptable splits, trivial split");
1971 PG_RETURN_POINTER(v);
1982 POSTGIS_DEBUGF(4,
"split direction: %d", context.
dim);
1985 v->spl_left = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
1986 v->spl_right = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
1991 leftBox = palloc0(
sizeof(BOX2DF));
1992 rightBox = palloc0(
sizeof(BOX2DF));
1998 commonEntriesCount = 0;
2002 #define PLACE_LEFT(box, off) \
2004 if (v->spl_nleft > 0) \
2005 adjustBox(leftBox, box); \
2007 *leftBox = *(box); \
2008 v->spl_left[v->spl_nleft++] = off; \
2011 #define PLACE_RIGHT(box, off) \
2013 if (v->spl_nright > 0) \
2014 adjustBox(rightBox, box); \
2016 *rightBox = *(box); \
2017 v->spl_right[v->spl_nright++] = off; \
2024 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
2032 BOX2DF *box = (BOX2DF *)DatumGetPointer(entryvec->vector[i].key);
2033 if (context.
dim == 0)
2044 if (upper <= context.
leftUpper || isnan(upper))
2047 if (lower >= context.
rightLower || isnan(lower))
2050 commonEntries[commonEntriesCount++].
index = i;
2078 if (commonEntriesCount > 0)
2089 for (i = 0; i < (OffsetNumber)commonEntriesCount; i++)
2091 BOX2DF *box = (BOX2DF *)DatumGetPointer(entryvec->vector[commonEntries[i].
index].key);
2093 if (v->spl_nright > 0 && v->spl_nleft > 0)
2096 commonEntries[i].
delta =
2110 for (i = 0; i < (OffsetNumber)commonEntriesCount; i++)
2112 bool place_right =
true;
2113 BOX2DF *box = (BOX2DF *)DatumGetPointer(entryvec->vector[commonEntries[i].
index].key);
2120 if (v->spl_nright == 0 && v->spl_nleft > 0)
2122 else if (v->spl_nleft == 0 && v->spl_nright > 0)
2123 place_right =
false;
2125 else if (v->spl_nleft + (commonEntriesCount - i) <= m)
2126 place_right =
false;
2127 else if (v->spl_nright + (commonEntriesCount - i) <= m)
2130 else if (left_penalty < right_penalty)
2131 place_right =
false;
2132 else if (right_penalty < left_penalty)
2135 else if (v->spl_nleft < v->spl_nright)
2136 place_right =
false;
2146 v->spl_ldatum = PointerGetDatum(leftBox);
2147 v->spl_rdatum = PointerGetDatum(rightBox);
2149 POSTGIS_DEBUG(4,
"[GIST] 'picksplit' completed");
2151 PG_RETURN_POINTER(v);
2161 ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2162 errmsg(
"function box2df_in not implemented")));
2163 PG_RETURN_POINTER(NULL);
2169 BOX2DF *box = (BOX2DF *) PG_GETARG_POINTER(0);
2171 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)
static float box2df_penalty_single(const BOX2DF *box)
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)