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));
576 BOX2DF b1, b2, *br1=NULL, *br2=NULL;
577 POSTGIS_DEBUG(3,
"entered function");
582 if ( predicate(br1, br2) )
593 BOX2DF b2, *br2=NULL;
594 POSTGIS_DEBUG(3,
"entered function");
598 if ( predicate(br1, br2) )
613 POSTGIS_DEBUG(3,
"entered function");
615 PG_RETURN_BOOL(
true);
617 PG_RETURN_BOOL(
false);
623 if (
box2df_contains((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
624 PG_RETURN_BOOL(
true);
626 PG_RETURN_BOOL(
false);
632 POSTGIS_DEBUG(3,
"entered function");
634 PG_RETURN_BOOL(
true);
636 PG_RETURN_BOOL(
false);
642 if (
box2df_within((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
643 PG_RETURN_BOOL(
true);
645 PG_RETURN_BOOL(
false);
651 POSTGIS_DEBUG(3,
"entered function");
653 PG_RETURN_BOOL(
true);
655 PG_RETURN_BOOL(
false);
661 if (
box2df_overlaps((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
662 PG_RETURN_BOOL(
true);
664 PG_RETURN_BOOL(
false);
675 Datum gs1 = PG_GETARG_DATUM(0);
676 Datum gs2 = PG_GETARG_DATUM(1);
678 POSTGIS_DEBUG(3,
"entered function");
688 PG_RETURN_FLOAT8(FLT_MAX);
695 Datum gs1 = PG_GETARG_DATUM(0);
696 Datum gs2 = PG_GETARG_DATUM(1);
698 POSTGIS_DEBUG(3,
"entered function");
708 PG_RETURN_FLOAT8(FLT_MAX);
715 PG_RETURN_BOOL(
true);
717 PG_RETURN_BOOL(
false);
723 POSTGIS_DEBUG(3,
"entered function");
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);
744 PG_RETURN_BOOL(
true);
746 PG_RETURN_BOOL(
false);
753 PG_RETURN_BOOL(
true);
755 PG_RETURN_BOOL(
false);
762 PG_RETURN_BOOL(
true);
764 PG_RETURN_BOOL(
false);
771 PG_RETURN_BOOL(
true);
773 PG_RETURN_BOOL(
false);
780 PG_RETURN_BOOL(
true);
782 PG_RETURN_BOOL(
false);
789 PG_RETURN_BOOL(
true);
791 PG_RETURN_BOOL(
false);
798 PG_RETURN_BOOL(
true);
800 PG_RETURN_BOOL(
false);
807 PG_RETURN_BOOL(
true);
809 PG_RETURN_BOOL(
false);
816 PG_RETURN_BOOL(
true);
818 PG_RETURN_BOOL(
false);
835 GISTENTRY *entry_in = (GISTENTRY*)PG_GETARG_POINTER(0);
836 GISTENTRY *entry_out = NULL;
840 POSTGIS_DEBUG(4,
"[GIST] 'compress' function called");
846 if ( ! entry_in->leafkey )
848 POSTGIS_DEBUG(4,
"[GIST] non-leafkey entry, returning input unaltered");
849 PG_RETURN_POINTER(entry_in);
852 POSTGIS_DEBUG(4,
"[GIST] processing leafkey input");
853 entry_out = palloc(
sizeof(GISTENTRY));
859 if ( DatumGetPointer(entry_in->key) == NULL )
861 POSTGIS_DEBUG(4,
"[GIST] leafkey is null");
862 gistentryinit(*entry_out, (Datum) 0, entry_in->rel,
863 entry_in->page, entry_in->offset,
false);
864 POSTGIS_DEBUG(4,
"[GIST] returning copy of input");
865 PG_RETURN_POINTER(entry_out);
875 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
876 entry_in->rel, entry_in->page, entry_in->offset,
false);
878 POSTGIS_DEBUG(4,
"[GIST] empty geometry!");
879 PG_RETURN_POINTER(entry_out);
882 POSTGIS_DEBUGF(4,
"[GIST] got entry_in->key: %s",
box2df_to_string(&bbox_out));
885 if ( ! isfinite(bbox_out.xmax) || ! isfinite(bbox_out.xmin) ||
886 ! isfinite(bbox_out.ymax) || ! isfinite(bbox_out.ymin) )
889 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
890 entry_in->rel, entry_in->page, entry_in->offset,
false);
892 POSTGIS_DEBUG(4,
"[GIST] infinite geometry!");
893 PG_RETURN_POINTER(entry_out);
900 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
901 entry_in->rel, entry_in->page, entry_in->offset,
false);
904 POSTGIS_DEBUG(4,
"[GIST] 'compress' function complete");
905 PG_RETURN_POINTER(entry_out);
916 POSTGIS_DEBUG(5,
"[GIST] 'decompress' function called");
918 PG_RETURN_POINTER(PG_GETARG_POINTER(0));
930 POSTGIS_DEBUGF(4,
"[GIST] leaf consistent, strategy [%d], count[%i]",
931 strategy, g2d_counter_leaf++);
937 case RTOverlapStrategyNumber:
940 case RTSameStrategyNumber:
943 case RTContainsStrategyNumber:
944 case RTOldContainsStrategyNumber:
947 case RTContainedByStrategyNumber:
948 case RTOldContainedByStrategyNumber:
953 case RTAboveStrategyNumber:
956 case RTBelowStrategyNumber:
959 case RTRightStrategyNumber:
962 case RTLeftStrategyNumber:
967 case RTOverAboveStrategyNumber:
970 case RTOverBelowStrategyNumber:
973 case RTOverRightStrategyNumber:
976 case RTOverLeftStrategyNumber:
994 POSTGIS_DEBUGF(4,
"[GIST] internal consistent, strategy [%d], count[%i], query[%s], key[%s]",
1001 case RTOverlapStrategyNumber:
1004 case RTSameStrategyNumber:
1005 case RTContainsStrategyNumber:
1006 case RTOldContainsStrategyNumber:
1009 case RTContainedByStrategyNumber:
1010 case RTOldContainedByStrategyNumber:
1015 case RTAboveStrategyNumber:
1018 case RTBelowStrategyNumber:
1021 case RTRightStrategyNumber:
1024 case RTLeftStrategyNumber:
1029 case RTOverAboveStrategyNumber:
1032 case RTOverBelowStrategyNumber:
1035 case RTOverRightStrategyNumber:
1038 case RTOverLeftStrategyNumber:
1056 GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
1057 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
1059 BOX2DF query_gbox_index;
1063 bool *recheck = (
bool *) PG_GETARG_POINTER(4);
1070 POSTGIS_DEBUG(4,
"[GIST] 'consistent' function called");
1073 if ( DatumGetPointer(PG_GETARG_DATUM(1)) == NULL )
1075 POSTGIS_DEBUG(4,
"[GIST] null query pointer (!?!), returning false");
1076 PG_RETURN_BOOL(
false);
1080 if ( DatumGetPointer(entry->key) == NULL )
1082 POSTGIS_DEBUG(4,
"[GIST] null index entry, returning false");
1083 PG_RETURN_BOOL(
false);
1089 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1090 PG_RETURN_BOOL(
false);
1094 if (GIST_LEAF(entry))
1097 (BOX2DF*)DatumGetPointer(entry->key),
1098 &query_gbox_index, strategy);
1103 (BOX2DF*)DatumGetPointer(entry->key),
1104 &query_gbox_index, strategy);
1130 GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
1133 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
1135 bool *recheck = (
bool *) PG_GETARG_POINTER(4);
1137 POSTGIS_DEBUG(4,
"[GIST] 'distance' function called");
1141 if ( strategy != 13 && strategy != 14 ) {
1142 elog(ERROR,
"unrecognized strategy number: %d", strategy);
1143 PG_RETURN_FLOAT8(FLT_MAX);
1149 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1150 PG_RETURN_FLOAT8(FLT_MAX);
1154 entry_box = (BOX2DF*)DatumGetPointer(entry->key);
1157 if ( strategy == 14 )
1162 else if ( strategy == 13 )
1169 if (GIST_LEAF(entry))
1174 elog(ERROR,
"%s: reached unreachable code", __func__);
1200 unsigned value : 31, sign : 1;
1203 unsigned value : 30, realm : 1, sign : 1;
1208 a.rbits.value = a.vbits.value >> 1;
1209 a.rbits.realm = realm;
1217 float b1xmin = b1->xmin, b1xmax = b1->xmax;
1218 float b1ymin = b1->ymin, b1ymax = b1->ymax;
1219 float b2xmin = b2->xmin, b2xmax = b2->xmax;
1220 float b2ymin = b2->ymin, b2ymax = b2->ymax;
1222 float box_union_xmin = Min(b1xmin, b2xmin), box_union_xmax = Max(b1xmax, b2xmax);
1223 float box_union_ymin = Min(b1ymin, b2ymin), box_union_ymax = Max(b1ymax, b2ymax);
1225 float b1dx = b1xmax - b1xmin, b1dy = b1ymax - b1ymin;
1226 float box_union_dx = box_union_xmax - box_union_xmin, box_union_dy = box_union_ymax - box_union_ymin;
1228 float box_union_area = box_union_dx * box_union_dy, box1area = b1dx * b1dy;
1229 float box_union_edge = box_union_dx + box_union_dy, box1edge = b1dx + b1dy;
1231 float area_extension = box_union_area - box1area;
1232 float edge_extension = box_union_edge - box1edge;
1235 if (area_extension > FLT_EPSILON)
1238 else if (edge_extension > FLT_EPSILON)
1251 GISTENTRY *origentry = (GISTENTRY*) PG_GETARG_POINTER(0);
1252 GISTENTRY *newentry = (GISTENTRY*) PG_GETARG_POINTER(1);
1253 float *
result = (
float*) PG_GETARG_POINTER(2);
1256 b1 = (BOX2DF *)DatumGetPointer(origentry->key);
1257 b2 = (BOX2DF *)DatumGetPointer(newentry->key);
1268 PG_RETURN_POINTER(
result);
1277 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1278 int *sizep = (
int *) PG_GETARG_POINTER(1);
1280 BOX2DF *box_cur, *box_union;
1282 POSTGIS_DEBUG(4,
"[GIST] 'union' function called");
1284 numranges = entryvec->n;
1286 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[0].key);
1290 for ( i = 1; i < numranges; i++ )
1292 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[i].key);
1296 *sizep =
sizeof(BOX2DF);
1298 POSTGIS_DEBUGF(4,
"[GIST] 'union', numranges(%i), pageunion %s", numranges,
box2df_to_string(box_union));
1300 PG_RETURN_POINTER(box_union);
1310 BOX2DF *b1 = (BOX2DF*)PG_GETARG_POINTER(0);
1311 BOX2DF *b2 = (BOX2DF*)PG_GETARG_POINTER(1);
1312 bool *
result = (
bool*)PG_GETARG_POINTER(2);
1314 POSTGIS_DEBUG(4,
"[GIST] 'same' function called");
1318 PG_RETURN_POINTER(
result);
1325 if (
x == 0 ||
y == 0 ||
x ==
y)
1348 BOX2DF *b1 = (BOX2DF *)a;
1349 BOX2DF *b2 = (BOX2DF *)b;
1350 uint64_t hash1, hash2;
1353 cmp = memcmp(b1, b2,
sizeof(BOX2DF));
1361 else if (hash1 < hash2)
1364 return cmp > 0 ? 1 : -1;
1370 SortSupport ssup = (SortSupport)PG_GETARG_POINTER(0);
1373 ssup->ssup_extra = NULL;
1375 if (ssup->abbreviate &&
sizeof(Datum) == 8)
1392 if (b->xmax < addon->xmax || isnan(b->xmax))
1393 b->xmax = addon->xmax;
1394 if (b->xmin > addon->xmin || isnan(b->xmin))
1395 b->xmin = addon->xmin;
1396 if (b->ymax < addon->ymax || isnan(b->ymax))
1397 b->ymax = addon->ymax;
1398 if (b->ymin > addon->ymin || isnan(b->ymin))
1399 b->ymin = addon->ymin;
1411 BOX2DF *unionL = NULL,
1415 maxoff = entryvec->n - 1;
1417 nbytes = (maxoff + 2) *
sizeof(OffsetNumber);
1418 v->spl_left = (OffsetNumber *) palloc(nbytes);
1419 v->spl_right = (OffsetNumber *) palloc(nbytes);
1420 v->spl_nleft = v->spl_nright = 0;
1422 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1424 BOX2DF *
cur = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1426 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
1428 v->spl_left[v->spl_nleft] = i;
1431 unionL = (BOX2DF *) palloc(
sizeof(BOX2DF));
1441 v->spl_right[v->spl_nright] = i;
1444 unionR = (BOX2DF *) palloc(
sizeof(BOX2DF));
1454 if (v->spl_ldatum_exists)
1455 adjustBox(unionL, (BOX2DF *) DatumGetPointer(v->spl_ldatum));
1456 v->spl_ldatum = PointerGetDatum(unionL);
1458 if (v->spl_rdatum_exists)
1459 adjustBox(unionR, (BOX2DF *) DatumGetPointer(v->spl_rdatum));
1460 v->spl_rdatum = PointerGetDatum(unionR);
1462 v->spl_ldatum_exists = v->spl_rdatum_exists =
false;
1525 else if (isnan(lower2))
1531 if (lower1 < lower2)
1533 else if (lower1 > lower2)
1557 else if (isnan(upper2))
1563 if (upper1 < upper2)
1565 else if (upper1 > upper2)
1589 float rightLower,
int minLeftCount,
1590 float leftUpper,
int maxLeftCount)
1598 POSTGIS_DEBUGF(5,
"consider split: dimNum = %d, rightLower = %f, "
1599 "minLeftCount = %d, leftUpper = %f, maxLeftCount = %d ",
1600 dimNum, rightLower, minLeftCount, leftUpper, maxLeftCount);
1608 leftCount = minLeftCount;
1612 if (maxLeftCount <= context->entriesCount / 2)
1613 leftCount = maxLeftCount;
1623 ratio = ((float4) Min(leftCount, rightCount)) /
1628 bool selectthis =
false;
1642 overlap = (leftUpper - rightLower) / range;
1647 else if (context->
dim == dimNum)
1653 if (overlap < context->overlap ||
1654 (overlap == context->
overlap && ratio > context->
ratio))
1677 (range > context->
range &&
1685 context->
first =
false;
1686 context->
ratio = ratio;
1687 context->
range = range;
1691 context->
dim = dimNum;
1692 POSTGIS_DEBUG(5,
"split selected");
1706 if (delta1 < delta2)
1708 else if (delta1 > delta2)
1743 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1744 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1758 POSTGIS_DEBUG(3,
"[GIST] 'picksplit' entered");
1762 maxoff = entryvec->n - 1;
1763 nentries = context.
entriesCount = maxoff - FirstOffsetNumber + 1;
1772 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1774 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1775 if (i == FirstOffsetNumber)
1787 context.
first =
true;
1788 for (dim = 0; dim < 2; dim++)
1796 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1798 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1801 intervalsLower[i - FirstOffsetNumber].
lower = box->xmin;
1802 intervalsLower[i - FirstOffsetNumber].
upper = box->xmax;
1806 intervalsLower[i - FirstOffsetNumber].
lower = box->ymin;
1807 intervalsLower[i - FirstOffsetNumber].
upper = box->ymax;
1815 memcpy(intervalsUpper, intervalsLower,
1858 rightLower = intervalsLower[i1].
lower;
1859 leftUpper = intervalsUpper[i2].
lower;
1865 while (i1 < nentries && (rightLower == intervalsLower[i1].lower ||
1866 isnan(intervalsLower[i1].lower)))
1868 leftUpper = Max(leftUpper, intervalsLower[i1].upper);
1873 rightLower = intervalsLower[i1].
lower;
1879 while (i2 < nentries && intervalsUpper[i2].upper <= leftUpper)
1894 rightLower = intervalsLower[i1].
upper;
1895 leftUpper = intervalsUpper[i2].
upper;
1901 while (i2 >= 0 && (leftUpper == intervalsUpper[i2].upper ||
1902 isnan(intervalsUpper[i2].upper)))
1904 rightLower = Min(rightLower, intervalsUpper[i2].lower);
1909 leftUpper = intervalsUpper[i2].
upper;
1915 while (i1 >= 0 && intervalsLower[i1].lower >= rightLower)
1922 rightLower, i1 + 1, leftUpper, i2 + 1);
1931 POSTGIS_DEBUG(4,
"no acceptable splits, trivial split");
1933 PG_RETURN_POINTER(v);
1944 POSTGIS_DEBUGF(4,
"split direction: %d", context.
dim);
1947 v->spl_left = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
1948 v->spl_right = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
1953 leftBox = palloc0(
sizeof(BOX2DF));
1954 rightBox = palloc0(
sizeof(BOX2DF));
1960 commonEntriesCount = 0;
1964 #define PLACE_LEFT(box, off) \
1966 if (v->spl_nleft > 0) \
1967 adjustBox(leftBox, box); \
1969 *leftBox = *(box); \
1970 v->spl_left[v->spl_nleft++] = off; \
1973 #define PLACE_RIGHT(box, off) \
1975 if (v->spl_nright > 0) \
1976 adjustBox(rightBox, box); \
1978 *rightBox = *(box); \
1979 v->spl_right[v->spl_nright++] = off; \
1986 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1994 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1995 if (context.
dim == 0)
2006 if (upper <= context.
leftUpper || isnan(upper))
2009 if (lower >= context.
rightLower || isnan(lower))
2012 commonEntries[commonEntriesCount++].
index = i;
2040 if (commonEntriesCount > 0)
2053 for (i = 0; i < commonEntriesCount; i++)
2055 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
2056 commonEntries[i].
index].key);
2070 for (i = 0; i < commonEntriesCount; i++)
2072 float right_penalty, left_penalty;
2073 bool place_right =
true;
2074 box = (BOX2DF *)DatumGetPointer(entryvec->vector[commonEntries[i].
index].key);
2081 if (right_penalty > 0 && left_penalty == 0)
2082 place_right =
false;
2083 else if (right_penalty == 0 && left_penalty > 0)
2086 else if (v->spl_nleft + (commonEntriesCount - i) <= m)
2087 place_right =
false;
2088 else if (v->spl_nright + (commonEntriesCount - i) <= m)
2091 else if (left_penalty < right_penalty)
2092 place_right =
false;
2093 else if (right_penalty < left_penalty)
2096 else if (v->spl_nleft < v->spl_nright)
2097 place_right =
false;
2107 v->spl_ldatum = PointerGetDatum(leftBox);
2108 v->spl_rdatum = PointerGetDatum(rightBox);
2110 POSTGIS_DEBUG(4,
"[GIST] 'picksplit' completed");
2112 PG_RETURN_POINTER(v);
2122 ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2123 errmsg(
"function box2df_in not implemented")));
2124 PG_RETURN_POINTER(NULL);
2130 BOX2DF *box = (BOX2DF *) PG_GETARG_POINTER(0);
2132 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.
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)