40 #include "access/gist.h"
41 #include "access/itup.h"
42 #include "access/skey.h"
44 #include "../postgis_config.h"
47 #include "lwgeom_pg.h"
48 #include "gserialized_gist.h"
58 #define LIMIT_RATIO 0.1
63 #if POSTGIS_DEBUG_LEVEL > 0
64 static int geog_counter_leaf = 0;
65 static int geog_counter_internal = 0;
72 Datum
gidx_in(PG_FUNCTION_ARGS);
113 GIDX *c = (GIDX *)palloc(VARSIZE(b));
114 POSTGIS_DEBUGF(5,
"copied gidx (%p) to gidx (%p)", b, c);
115 memcpy((
void *)c, (
void *)b, VARSIZE(b));
125 POSTGIS_DEBUGF(5,
"validating gidx (%s)", gidx_to_string(b));
126 for (i = 0; i < GIDX_NDIMS(b); i++)
128 if (GIDX_GET_MIN(b, i) > GIDX_GET_MAX(b, i))
131 tmp = GIDX_GET_MIN(b, i);
132 GIDX_SET_MIN(b, i, GIDX_GET_MAX(b, i));
133 GIDX_SET_MAX(b, i, tmp);
145 size_t size = VARSIZE_ANY_EXHDR(a);
155 SET_VARSIZE(a, VARHDRSZ);
162 int i, dims_union, dims_new;
181 dims_union = GIDX_NDIMS(*b_union);
182 dims_new = GIDX_NDIMS(b_new);
186 if (dims_new < dims_union)
188 *b_union = (GIDX *)repalloc(*b_union, GIDX_SIZE(dims_new));
189 SET_VARSIZE(*b_union, VARSIZE(b_new));
190 dims_union = dims_new;
193 for (i = 0; i < dims_union; i++)
196 GIDX_SET_MIN(*b_union, i, Min(GIDX_GET_MIN(*b_union, i), GIDX_GET_MIN(b_new, i)));
198 GIDX_SET_MAX(*b_union, i, Max(GIDX_GET_MAX(*b_union, i), GIDX_GET_MAX(b_new, i)));
210 result = GIDX_GET_MAX(a, 0) - GIDX_GET_MIN(a, 0);
211 for (i = 1; i < GIDX_NDIMS(a); i++)
212 result *= (GIDX_GET_MAX(a, i) - GIDX_GET_MIN(a, i));
213 POSTGIS_DEBUGF(5,
"calculated volume of %s as %.8g", gidx_to_string(a), result);
225 result = GIDX_GET_MAX(a, 0) - GIDX_GET_MIN(a, 0);
226 for (i = 1; i < GIDX_NDIMS(a); i++)
227 result += (GIDX_GET_MAX(a, i) - GIDX_GET_MIN(a, i));
228 POSTGIS_DEBUGF(5,
"calculated edge of %s as %.8g", gidx_to_string(a), result);
236 if (GIDX_NDIMS(*a) < GIDX_NDIMS(*b))
250 int ndims_a, ndims_b;
252 POSTGIS_DEBUG(5,
"entered function");
256 elog(ERROR,
"gidx_union_volume received two null arguments");
272 ndims_a = GIDX_NDIMS(a);
273 ndims_b = GIDX_NDIMS(b);
276 result = Max(GIDX_GET_MAX(a, 0), GIDX_GET_MAX(b, 0)) - Min(GIDX_GET_MIN(a, 0), GIDX_GET_MIN(b, 0));
279 for (i = 1; i < ndims_b; i++)
280 result *= (Max(GIDX_GET_MAX(a, i), GIDX_GET_MAX(b, i)) - Min(GIDX_GET_MIN(a, i), GIDX_GET_MIN(b, i)));
283 for (i = ndims_b; i < ndims_a; i++)
284 result *= (GIDX_GET_MAX(a, i) - GIDX_GET_MIN(a, i));
286 POSTGIS_DEBUGF(5,
"volume( %s union %s ) = %.12g", gidx_to_string(a), gidx_to_string(b), result);
297 int ndims_a, ndims_b;
299 POSTGIS_DEBUG(5,
"entered function");
303 elog(ERROR,
"gidx_union_edge received two null arguments");
319 ndims_a = GIDX_NDIMS(a);
320 ndims_b = GIDX_NDIMS(b);
323 result = Max(GIDX_GET_MAX(a, 0), GIDX_GET_MAX(b, 0)) - Min(GIDX_GET_MIN(a, 0), GIDX_GET_MIN(b, 0));
326 for (i = 1; i < ndims_b; i++)
327 result += (Max(GIDX_GET_MAX(a, i), GIDX_GET_MAX(b, i)) - Min(GIDX_GET_MIN(a, i), GIDX_GET_MIN(b, i)));
330 for (i = ndims_b; i < ndims_a; i++)
331 result += (GIDX_GET_MAX(a, i) - GIDX_GET_MIN(a, i));
333 POSTGIS_DEBUGF(5,
"edge( %s union %s ) = %.12g", gidx_to_string(a), gidx_to_string(b), result);
345 POSTGIS_DEBUG(5,
"entered function");
349 elog(ERROR,
"gidx_inter_volume received a null argument");
360 result = Min(GIDX_GET_MAX(a, 0), GIDX_GET_MAX(b, 0)) - Max(GIDX_GET_MIN(a, 0), GIDX_GET_MIN(b, 0));
367 for (i = 1; i < GIDX_NDIMS(b); i++)
369 float width = Min(GIDX_GET_MAX(a, i), GIDX_GET_MAX(b, i)) - Max(GIDX_GET_MIN(a, i), GIDX_GET_MIN(b, i));
375 POSTGIS_DEBUGF(5,
"volume( %s intersection %s ) = %.12g", gidx_to_string(a), gidx_to_string(b), result);
395 int i, dims_a, dims_b;
397 POSTGIS_DEBUG(5,
"entered function");
405 dims_a = GIDX_NDIMS(a);
406 dims_b = GIDX_NDIMS(b);
410 for (i = 0; i < Min(dims_a, dims_b); i++)
413 if (GIDX_GET_MAX(a, i) != FLT_MAX && GIDX_GET_MAX(b, i) != FLT_MAX)
415 if (GIDX_GET_MIN(a, i) > GIDX_GET_MAX(b, i))
417 if (GIDX_GET_MIN(b, i) > GIDX_GET_MAX(a, i))
433 uint32_t i, dims_a, dims_b;
441 dims_a = GIDX_NDIMS(a);
442 dims_b = GIDX_NDIMS(b);
446 for (i = 0; i < Min(dims_a, dims_b); i++)
449 if (GIDX_GET_MAX(a, i) != FLT_MAX && GIDX_GET_MAX(b, i) != FLT_MAX)
451 if (GIDX_GET_MIN(a, i) > GIDX_GET_MIN(b, i))
453 if (GIDX_GET_MAX(a, i) < GIDX_GET_MAX(b, i))
469 uint32_t i, dims_a, dims_b;
482 dims_a = GIDX_NDIMS(a);
483 dims_b = GIDX_NDIMS(b);
487 for (i = 0; i < Min(dims_a, dims_b); i++)
490 if (GIDX_GET_MAX(a, i) != FLT_MAX && GIDX_GET_MAX(b, i) != FLT_MAX)
492 if (GIDX_GET_MIN(a, i) != GIDX_GET_MIN(b, i))
494 if (GIDX_GET_MAX(a, i) != GIDX_GET_MAX(b, i))
509 char boxmem1[GIDX_MAX_SIZE];
510 char boxmem2[GIDX_MAX_SIZE];
511 GIDX *gidx1 = (GIDX *)boxmem1;
512 GIDX *gidx2 = (GIDX *)boxmem2;
514 POSTGIS_DEBUG(3,
"entered function");
518 if ((gserialized_datum_get_gidx_p(gs1, gidx1) ==
LW_SUCCESS) &&
519 (gserialized_datum_get_gidx_p(gs2, gidx2) ==
LW_SUCCESS) && predicate(gidx1, gidx2))
521 POSTGIS_DEBUGF(3,
"got boxes %s and %s", gidx_to_string(gidx1), gidx_to_string(gidx2));
531 char boxmem2[GIDX_MAX_SIZE];
532 GIDX *gidx2 = (GIDX *)boxmem2;
534 POSTGIS_DEBUG(3,
"entered function");
538 if ((gserialized_datum_get_gidx_p(gs2, gidx2) ==
LW_SUCCESS) && predicate(gidx1, gidx2))
540 POSTGIS_DEBUGF(3,
"got boxes %s and %s", gidx_to_string(gidx1), gidx_to_string(gidx2));
550 char boxmem2[GIDX_MAX_SIZE];
551 GIDX *gidx1 = (GIDX *)boxmem2;
553 POSTGIS_DEBUG(3,
"entered function");
557 if ((gserialized_datum_get_gidx_p(gs1, gidx1) ==
LW_SUCCESS) && predicate(gidx1, gidx2))
559 POSTGIS_DEBUGF(3,
"got boxes %s and %s", gidx_to_string(gidx1), gidx_to_string(gidx2));
575 ndims = Min(GIDX_NDIMS(b), GIDX_NDIMS(a));
576 for (i = 0; i < ndims; ++i)
579 double amin = GIDX_GET_MIN(a, i);
580 double amax = GIDX_GET_MAX(a, i);
581 double bmin = GIDX_GET_MIN(b, i);
582 double bmax = GIDX_GET_MAX(b, i);
583 POSTGIS_DEBUGF(3,
"A %g - %g", amin, amax);
584 POSTGIS_DEBUGF(3,
"B %g - %g", bmin, bmax);
586 if ((amin <= bmax && amax >= bmin))
591 else if (i == 4 && m_is_time)
595 else if (bmax < amin)
612 POSTGIS_DEBUGF(3,
"dist %g, squared %g, grows sum to %g", d, d * d, sum);
669 double m1 = 0, m2 = 0;
730 PG_FREE_IF_COPY(geom1, 0);
731 PG_FREE_IF_COPY(geom2, 1);
743 PG_RETURN_BOOL(
true);
745 PG_RETURN_BOOL(
false);
755 GIDX *gidx = (GIDX *)PG_GETARG_POINTER(0);
758 PG_RETURN_BOOL(
true);
760 PG_RETURN_BOOL(
false);
770 if (
gidx_contains((GIDX *)PG_GETARG_POINTER(1), (GIDX *)PG_GETARG_POINTER(0)))
771 PG_RETURN_BOOL(
true);
773 PG_RETURN_BOOL(
false);
784 PG_RETURN_BOOL(
true);
786 PG_RETURN_BOOL(
false);
796 GIDX *gidx = (GIDX *)PG_GETARG_POINTER(0);
799 PG_RETURN_BOOL(
true);
801 PG_RETURN_BOOL(
false);
811 if (
gidx_contains((GIDX *)PG_GETARG_POINTER(0), (GIDX *)PG_GETARG_POINTER(1)))
812 PG_RETURN_BOOL(
true);
814 PG_RETURN_BOOL(
false);
825 PG_RETURN_BOOL(
true);
827 PG_RETURN_BOOL(
false);
833 GIDX *gidx = (GIDX *)PG_GETARG_POINTER(0);
836 PG_RETURN_BOOL(
true);
838 PG_RETURN_BOOL(
false);
848 if (
gidx_equals((GIDX *)PG_GETARG_POINTER(0), (GIDX *)PG_GETARG_POINTER(1)))
849 PG_RETURN_BOOL(
true);
851 PG_RETURN_BOOL(
false);
862 PG_RETURN_BOOL(
true);
864 PG_RETURN_BOOL(
false);
873 GIDX *gidx = (GIDX *)PG_GETARG_POINTER(0);
876 PG_RETURN_BOOL(
true);
878 PG_RETURN_BOOL(
false);
884 GIDX *gidx = (GIDX *)PG_GETARG_POINTER(0);
887 PG_RETURN_BOOL(
true);
889 PG_RETURN_BOOL(
false);
895 if (
gidx_overlaps((GIDX *)PG_GETARG_POINTER(0), (GIDX *)PG_GETARG_POINTER(1)))
896 PG_RETURN_BOOL(
true);
898 PG_RETURN_BOOL(
false);
914 GISTENTRY *entry_in = (GISTENTRY *)PG_GETARG_POINTER(0);
915 GISTENTRY *entry_out = NULL;
916 char gidxmem[GIDX_MAX_SIZE];
917 GIDX *bbox_out = (GIDX *)gidxmem;
921 POSTGIS_DEBUG(4,
"[GIST] 'compress' function called");
927 if (!entry_in->leafkey)
929 POSTGIS_DEBUG(4,
"[GIST] non-leafkey entry, returning input unaltered");
930 PG_RETURN_POINTER(entry_in);
933 POSTGIS_DEBUG(4,
"[GIST] processing leafkey input");
934 entry_out = palloc(
sizeof(GISTENTRY));
940 if (!DatumGetPointer(entry_in->key))
942 POSTGIS_DEBUG(4,
"[GIST] leafkey is null");
943 gistentryinit(*entry_out, (Datum)0, entry_in->rel, entry_in->page, entry_in->offset,
false);
944 POSTGIS_DEBUG(4,
"[GIST] returning copy of input");
945 PG_RETURN_POINTER(entry_out);
949 result = gserialized_datum_get_gidx_p(entry_in->key, bbox_out);
955 POSTGIS_DEBUG(4,
"[GIST] empty geometry!");
957 gistentryinit(*entry_out,
963 PG_RETURN_POINTER(entry_out);
966 POSTGIS_DEBUGF(4,
"[GIST] got entry_in->key: %s", gidx_to_string(bbox_out));
971 for (i = 0; i < GIDX_NDIMS(bbox_out); i++)
973 if (!isfinite(GIDX_GET_MAX(bbox_out, i)) || !isfinite(GIDX_GET_MIN(bbox_out, i)))
976 gistentryinit(*entry_out,
982 PG_RETURN_POINTER(entry_out);
991 *entry_out, PointerGetDatum(
gidx_copy(bbox_out)), entry_in->rel, entry_in->page, entry_in->offset,
false);
994 POSTGIS_DEBUG(4,
"[GIST] 'compress' function complete");
995 PG_RETURN_POINTER(entry_out);
1005 POSTGIS_DEBUG(5,
"[GIST] 'decompress' function called");
1007 PG_RETURN_POINTER(PG_GETARG_POINTER(0));
1018 POSTGIS_DEBUGF(4,
"[GIST] leaf consistent, strategy [%d], count[%i]", strategy, geog_counter_leaf++);
1022 case RTOverlapStrategyNumber:
1025 case RTSameStrategyNumber:
1028 case RTContainsStrategyNumber:
1029 case RTOldContainsStrategyNumber:
1032 case RTContainedByStrategyNumber:
1033 case RTOldContainedByStrategyNumber:
1052 "[GIST] internal consistent, strategy [%d], count[%i], query[%s], key[%s]",
1054 geog_counter_internal++,
1055 gidx_to_string(query),
1056 gidx_to_string(key));
1060 case RTOverlapStrategyNumber:
1061 case RTContainedByStrategyNumber:
1062 case RTOldContainedByStrategyNumber:
1065 case RTSameStrategyNumber:
1066 case RTContainsStrategyNumber:
1067 case RTOldContainsStrategyNumber:
1084 GISTENTRY *entry = (GISTENTRY *)PG_GETARG_POINTER(0);
1085 StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2);
1087 char gidxmem[GIDX_MAX_SIZE];
1088 GIDX *query_gbox_index = (GIDX *)gidxmem;
1092 bool *recheck = (
bool *)PG_GETARG_POINTER(4);
1099 POSTGIS_DEBUG(4,
"[GIST] 'consistent' function called");
1102 if (!DatumGetPointer(PG_GETARG_DATUM(1)))
1104 POSTGIS_DEBUG(4,
"[GIST] null query pointer (!?!), returning false");
1105 PG_RETURN_BOOL(
false);
1109 if (!DatumGetPointer(entry->key))
1111 POSTGIS_DEBUG(4,
"[GIST] null index entry, returning false");
1112 PG_RETURN_BOOL(
false);
1116 if (gserialized_datum_get_gidx_p(PG_GETARG_DATUM(1), query_gbox_index) ==
LW_FAILURE)
1118 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1119 PG_RETURN_BOOL(
false);
1123 if (GIST_LEAF(entry))
1131 (GIDX *)DatumGetPointer(entry->key), query_gbox_index, strategy);
1134 PG_RETURN_BOOL(result);
1156 unsigned value : 31, sign : 1;
1159 unsigned value : 30, realm : 1, sign : 1;
1164 a.rbits.value = a.vbits.value >> 1;
1165 a.rbits.realm = realm;
1177 GISTENTRY *origentry = (GISTENTRY *)PG_GETARG_POINTER(0);
1178 GISTENTRY *newentry = (GISTENTRY *)PG_GETARG_POINTER(1);
1179 float *result = (
float *)PG_GETARG_POINTER(2);
1180 GIDX *gbox_index_orig, *gbox_index_new;
1182 gbox_index_orig = (GIDX *)DatumGetPointer(origentry->key);
1183 gbox_index_new = (GIDX *)DatumGetPointer(newentry->key);
1192 if (gbox_index_orig && gbox_index_new)
1197 float volume_extension = size_union - size_orig;
1200 if (volume_extension > FLT_EPSILON)
1206 float edge_orig =
gidx_edge(gbox_index_orig);
1207 float edge_extension = edge_union - edge_orig;
1208 if (edge_extension > FLT_EPSILON)
1212 PG_RETURN_POINTER(result);
1221 GistEntryVector *entryvec = (GistEntryVector *)PG_GETARG_POINTER(0);
1222 int *sizep = (
int *)PG_GETARG_POINTER(1);
1224 GIDX *box_cur, *box_union;
1226 POSTGIS_DEBUG(4,
"[GIST] 'union' function called");
1228 numranges = entryvec->n;
1230 box_cur = (GIDX *)DatumGetPointer(entryvec->vector[0].key);
1234 for (i = 1; i < numranges; i++)
1236 box_cur = (GIDX *)DatumGetPointer(entryvec->vector[i].key);
1240 *sizep = VARSIZE(box_union);
1242 POSTGIS_DEBUGF(4,
"[GIST] union called, numranges(%i), pageunion %s", numranges, gidx_to_string(box_union));
1244 PG_RETURN_POINTER(box_union);
1253 GIDX *b1 = (GIDX *)PG_GETARG_POINTER(0);
1254 GIDX *b2 = (GIDX *)PG_GETARG_POINTER(1);
1255 bool *result = (
bool *)PG_GETARG_POINTER(2);
1257 POSTGIS_DEBUG(4,
"[GIST] 'same' function called");
1261 PG_RETURN_POINTER(result);
1267 GISTENTRY *entry = (GISTENTRY *)PG_GETARG_POINTER(0);
1268 Datum query_datum = PG_GETARG_DATUM(1);
1269 StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2);
1270 bool *recheck = (
bool *)PG_GETARG_POINTER(4);
1271 char query_box_mem[GIDX_MAX_SIZE];
1272 GIDX *query_box = (GIDX *)query_box_mem;
1276 POSTGIS_DEBUGF(3,
"[GIST] '%s' function called", __func__);
1281 elog(ERROR,
"unrecognized strategy number: %d", strategy);
1282 PG_RETURN_FLOAT8(FLT_MAX);
1286 if (gserialized_datum_get_gidx_p(query_datum, query_box) ==
LW_FAILURE)
1288 POSTGIS_DEBUG(2,
"[GIST] null query_gbox_index!");
1289 PG_RETURN_FLOAT8(FLT_MAX);
1293 if (GIST_LEAF(entry))
1297 entry_box = (GIDX *)DatumGetPointer(entry->key);
1305 POSTGIS_DEBUGF(2,
"[GIST] '%s' got distance %g", __func__,
distance);
1329 GISTENTRY *entry = (GISTENTRY *)PG_GETARG_POINTER(0);
1330 StrategyNumber strategy = (StrategyNumber)PG_GETARG_UINT16(2);
1331 char query_box_mem[GIDX_MAX_SIZE];
1332 GIDX *query_box = (GIDX *)query_box_mem;
1334 bool *recheck = (
bool *)PG_GETARG_POINTER(4);
1338 POSTGIS_DEBUG(4,
"[GIST] 'distance' function called");
1342 if (strategy != 13 && strategy != 20)
1344 elog(ERROR,
"unrecognized strategy number: %d", strategy);
1345 PG_RETURN_FLOAT8(FLT_MAX);
1349 if (gserialized_datum_get_gidx_p(PG_GETARG_DATUM(1), query_box) ==
LW_FAILURE)
1351 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1352 PG_RETURN_FLOAT8(FLT_MAX);
1356 entry_box = (GIDX *)DatumGetPointer(entry->key);
1362 if (GIST_LEAF(entry))
1394 POSTGIS_DEBUGF(4,
"[GIST] checking split ratio (%d, %d)",
x,
y);
1405 for (i = 0; i < dims; i++)
1420 OffsetNumber i, maxoff;
1421 GIDX *unionL = NULL;
1422 GIDX *unionR = NULL;
1425 POSTGIS_DEBUG(4,
"[GIST] in fallback picksplit function");
1427 maxoff = entryvec->n - 1;
1429 nbytes = (maxoff + 2) *
sizeof(OffsetNumber);
1430 v->spl_left = (OffsetNumber *)palloc(nbytes);
1431 v->spl_right = (OffsetNumber *)palloc(nbytes);
1432 v->spl_nleft = v->spl_nright = 0;
1434 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1436 GIDX *
cur = (GIDX *)DatumGetPointer(entryvec->vector[i].key);
1438 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
1440 v->spl_left[v->spl_nleft] = i;
1449 v->spl_right[v->spl_nright] = i;
1458 if (v->spl_ldatum_exists)
1459 gidx_merge(&unionL, (GIDX *)DatumGetPointer(v->spl_ldatum));
1461 v->spl_ldatum = PointerGetDatum(unionL);
1463 if (v->spl_rdatum_exists)
1464 gidx_merge(&unionR, (GIDX *)DatumGetPointer(v->spl_rdatum));
1466 v->spl_rdatum = PointerGetDatum(unionR);
1467 v->spl_ldatum_exists = v->spl_rdatum_exists =
false;
1472 OffsetNumber *list1,
1475 OffsetNumber *list2,
1479 bool firstToLeft =
true;
1481 POSTGIS_DEBUG(4,
"[GIST] picksplit in constructsplit function");
1483 if (v->spl_ldatum_exists || v->spl_rdatum_exists)
1485 if (v->spl_ldatum_exists && v->spl_rdatum_exists)
1491 double sizeLR, sizeRL;
1493 gidx_merge(&LRl, (GIDX *)DatumGetPointer(v->spl_ldatum));
1494 gidx_merge(&LRr, (GIDX *)DatumGetPointer(v->spl_rdatum));
1495 gidx_merge(&RLl, (GIDX *)DatumGetPointer(v->spl_ldatum));
1496 gidx_merge(&RLr, (GIDX *)DatumGetPointer(v->spl_rdatum));
1501 POSTGIS_DEBUGF(4,
"[GIST] sizeLR / sizeRL == %.12g / %.12g", sizeLR, sizeRL);
1503 if (sizeLR > sizeRL)
1504 firstToLeft =
false;
1509 GISTENTRY oldUnion, addon;
1511 gistentryinit(oldUnion,
1512 (v->spl_ldatum_exists) ? v->spl_ldatum : v->spl_rdatum,
1515 InvalidOffsetNumber,
1518 gistentryinit(addon, PointerGetDatum(*union1), NULL, NULL, InvalidOffsetNumber,
false);
1520 PointerGetDatum(&oldUnion),
1521 PointerGetDatum(&addon),
1522 PointerGetDatum(&p1));
1523 gistentryinit(addon, PointerGetDatum(*union2), NULL, NULL, InvalidOffsetNumber,
false);
1525 PointerGetDatum(&oldUnion),
1526 PointerGetDatum(&addon),
1527 PointerGetDatum(&p2));
1529 POSTGIS_DEBUGF(4,
"[GIST] p1 / p2 == %.12g / %.12g", p1, p2);
1531 if ((v->spl_ldatum_exists && p1 > p2) || (v->spl_rdatum_exists && p1 < p2))
1532 firstToLeft =
false;
1536 POSTGIS_DEBUGF(4,
"[GIST] firstToLeft == %d", firstToLeft);
1540 v->spl_left = list1;
1541 v->spl_right = list2;
1542 v->spl_nleft = nlist1;
1543 v->spl_nright = nlist2;
1544 if (v->spl_ldatum_exists)
1545 gidx_merge(union1, (GIDX *)DatumGetPointer(v->spl_ldatum));
1546 v->spl_ldatum = PointerGetDatum(*union1);
1547 if (v->spl_rdatum_exists)
1548 gidx_merge(union2, (GIDX *)DatumGetPointer(v->spl_rdatum));
1549 v->spl_rdatum = PointerGetDatum(*union2);
1553 v->spl_left = list2;
1554 v->spl_right = list1;
1555 v->spl_nleft = nlist2;
1556 v->spl_nright = nlist1;
1557 if (v->spl_ldatum_exists)
1558 gidx_merge(union2, (GIDX *)DatumGetPointer(v->spl_ldatum));
1559 v->spl_ldatum = PointerGetDatum(*union2);
1560 if (v->spl_rdatum_exists)
1561 gidx_merge(union1, (GIDX *)DatumGetPointer(v->spl_rdatum));
1562 v->spl_rdatum = PointerGetDatum(*union1);
1565 v->spl_ldatum_exists = v->spl_rdatum_exists =
false;
1568 #define BELOW(d) (2 * (d))
1569 #define ABOVE(d) ((2 * (d)) + 1)
1582 GistEntryVector *entryvec = (GistEntryVector *)PG_GETARG_POINTER(0);
1584 GIST_SPLITVEC *v = (GIST_SPLITVEC *)PG_GETARG_POINTER(1);
1589 OffsetNumber **list;
1592 GIDX *box_pageunion;
1595 bool all_entries_equal =
true;
1596 OffsetNumber max_offset;
1597 int nbytes, ndims_pageunion, d;
1598 int posmin = entryvec->n;
1600 POSTGIS_DEBUG(4,
"[GIST] 'picksplit' function called");
1606 max_offset = entryvec->n - 1;
1607 box_current = (GIDX *)DatumGetPointer(entryvec->vector[FirstOffsetNumber].key);
1611 for (i = OffsetNumberNext(FirstOffsetNumber); i <= max_offset; i = OffsetNumberNext(i))
1613 box_current = (GIDX *)DatumGetPointer(entryvec->vector[i].key);
1615 if (all_entries_equal && !
gidx_equals(box_pageunion, box_current))
1616 all_entries_equal =
false;
1621 POSTGIS_DEBUGF(3,
"[GIST] box_pageunion: %s", gidx_to_string(box_pageunion));
1624 if (all_entries_equal)
1626 POSTGIS_DEBUG(4,
"[GIST] picksplit finds all entries equal!");
1628 PG_RETURN_POINTER(v);
1632 nbytes = (max_offset + 2) *
sizeof(OffsetNumber);
1633 ndims_pageunion = GIDX_NDIMS(box_pageunion);
1634 POSTGIS_DEBUGF(4,
"[GIST] ndims_pageunion == %d", ndims_pageunion);
1635 pos = palloc(2 * ndims_pageunion *
sizeof(
int));
1636 list = palloc(2 * ndims_pageunion *
sizeof(OffsetNumber *));
1637 box_union = palloc(2 * ndims_pageunion *
sizeof(GIDX *));
1638 for (d = 0; d < ndims_pageunion; d++)
1640 list[
BELOW(d)] = (OffsetNumber *)palloc(nbytes);
1641 list[
ABOVE(d)] = (OffsetNumber *)palloc(nbytes);
1642 box_union[
BELOW(d)] = gidx_new(ndims_pageunion);
1643 box_union[
ABOVE(d)] = gidx_new(ndims_pageunion);
1653 POSTGIS_DEBUG(4,
"[GIST] 'picksplit' calculating best split axis");
1654 for (i = FirstOffsetNumber; i <= max_offset; i = OffsetNumberNext(i))
1656 box_current = (GIDX *)DatumGetPointer(entryvec->vector[i].key);
1658 for (d = 0; d < ndims_pageunion; d++)
1660 if (GIDX_GET_MIN(box_current, d) - GIDX_GET_MIN(box_pageunion, d) <
1661 GIDX_GET_MAX(box_pageunion, d) - GIDX_GET_MAX(box_current, d))
1663 list[
BELOW(d)], &(box_union[
BELOW(d)]), box_current, &(pos[
BELOW(d)]), i);
1666 list[
ABOVE(d)], &(box_union[
ABOVE(d)]), box_current, &(pos[
ABOVE(d)]), i);
1683 double *avgCenter = palloc(ndims_pageunion *
sizeof(
double));
1685 for (d = 0; d < ndims_pageunion; d++)
1688 POSTGIS_DEBUG(4,
"[GIST] picksplit can't find good split axis, trying center point method");
1690 for (i = FirstOffsetNumber; i <= max_offset; i = OffsetNumberNext(i))
1692 box_current = (GIDX *)DatumGetPointer(entryvec->vector[i].key);
1693 for (d = 0; d < ndims_pageunion; d++)
1694 avgCenter[d] += (GIDX_GET_MAX(box_current, d) + GIDX_GET_MIN(box_current, d)) / 2.0;
1696 for (d = 0; d < ndims_pageunion; d++)
1698 avgCenter[d] /= max_offset;
1700 POSTGIS_DEBUGF(4,
"[GIST] picksplit average center point[%d] = %.12g", d, avgCenter[d]);
1704 for (i = FirstOffsetNumber; i <= max_offset; i = OffsetNumberNext(i))
1707 box_current = (GIDX *)DatumGetPointer(entryvec->vector[i].key);
1709 for (d = 0; d < ndims_pageunion; d++)
1711 center = (GIDX_GET_MIN(box_current, d) + GIDX_GET_MAX(box_current, d)) / 2.0;
1712 if (center < avgCenter[d])
1714 list[
BELOW(d)], &(box_union[
BELOW(d)]), box_current, &(pos[
BELOW(d)]), i);
1715 else if (FPeq(center, avgCenter[d]))
1718 &(box_union[
ABOVE(d)]),
1724 &(box_union[
BELOW(d)]),
1730 list[
ABOVE(d)], &(box_union[
ABOVE(d)]), box_current, &(pos[
ABOVE(d)]), i);
1738 "[GIST] picksplit still cannot find a good split! just cutting the node in half");
1740 PG_RETURN_POINTER(v);
1751 for (d = 0; d < ndims_pageunion; d++)
1753 int posd = Max(pos[
ABOVE(d)], pos[
BELOW(d)]);
1760 if (direction == -1 || posmin == entryvec->n)
1761 elog(ERROR,
"Error in building split, unable to determine split direction.");
1763 POSTGIS_DEBUGF(3,
"[GIST] 'picksplit' splitting on axis %d", direction);
1766 list[
BELOW(direction)],
1767 pos[
BELOW(direction)],
1768 &(box_union[
BELOW(direction)]),
1769 list[
ABOVE(direction)],
1770 pos[
ABOVE(direction)],
1771 &(box_union[
ABOVE(direction)]));
1773 POSTGIS_DEBUGF(4,
"[GIST] spl_ldatum: %s", gidx_to_string((GIDX *)v->spl_ldatum));
1774 POSTGIS_DEBUGF(4,
"[GIST] spl_rdatum: %s", gidx_to_string((GIDX *)v->spl_rdatum));
1778 "[GIST] axis %d: parent range (%.12g, %.12g) left range (%.12g, %.12g), right range (%.12g, %.12g)",
1780 GIDX_GET_MIN(box_pageunion, direction),
1781 GIDX_GET_MAX(box_pageunion, direction),
1782 GIDX_GET_MIN((GIDX *)v->spl_ldatum, direction),
1783 GIDX_GET_MAX((GIDX *)v->spl_ldatum, direction),
1784 GIDX_GET_MIN((GIDX *)v->spl_rdatum, direction),
1785 GIDX_GET_MAX((GIDX *)v->spl_rdatum, direction));
1787 PG_RETURN_POINTER(v);
1797 ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg(
"function gidx_in not implemented")));
1798 PG_RETURN_POINTER(NULL);
1804 GIDX *box = (GIDX *)PG_GETARG_POINTER(0);
1805 char *result = gidx_to_string(box);
1806 PG_RETURN_CSTRING(result);
void gbox_expand(GBOX *g, double d)
Move the box minimums down and the maximums up by the distance provided.
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
GSERIALIZED * gserialized_set_gbox(GSERIALIZED *g, GBOX *gbox)
Copy a new bounding box into an existing gserialized.
static float gidx_union_volume(GIDX *a, GIDX *b)
static bool gserialized_gist_consistent_internal(GIDX *key, GIDX *query, StrategyNumber strategy)
Datum gserialized_distance_nd(PG_FUNCTION_ARGS)
bool(* gidx_predicate)(GIDX *a, GIDX *b)
static void gserialized_gist_picksplit_constructsplit(GIST_SPLITVEC *v, OffsetNumber *list1, int nlist1, GIDX **union1, OffsetNumber *list2, int nlist2, GIDX **union2)
Datum gserialized_gidx_gidx_overlaps(PG_FUNCTION_ARGS)
Datum gserialized_gist_union(PG_FUNCTION_ARGS)
static bool gserialized_gist_picksplit_badratios(int *pos, int dims)
bool gidx_is_unknown(const GIDX *a)
Datum gserialized_within(PG_FUNCTION_ARGS)
Datum gserialized_gist_same(PG_FUNCTION_ARGS)
static float gidx_inter_volume(GIDX *a, GIDX *b)
Datum gserialized_contains(PG_FUNCTION_ARGS)
Datum gserialized_same(PG_FUNCTION_ARGS)
static float gidx_union_edge(GIDX *a, GIDX *b)
static void gserialized_gist_picksplit_addlist(OffsetNumber *list, GIDX **box_union, GIDX *box_current, int *pos, int num)
Datum gserialized_gidx_geom_overlaps(PG_FUNCTION_ARGS)
Datum gserialized_gidx_gidx_within(PG_FUNCTION_ARGS)
void gidx_set_unknown(GIDX *a)
static float gidx_volume(GIDX *a)
GIDX * gidx_copy(GIDX *b)
Datum gserialized_gist_consistent(PG_FUNCTION_ARGS)
Datum gserialized_gidx_geom_contains(PG_FUNCTION_ARGS)
static void gidx_dimensionality_check(GIDX **a, GIDX **b)
bool gidx_contains(GIDX *a, GIDX *b)
Datum gserialized_gist_picksplit(PG_FUNCTION_ARGS)
static int gserialized_datum_predicate_gidx_geom(GIDX *gidx1, Datum gs2, gidx_predicate predicate)
static int gserialized_datum_predicate(Datum gs1, Datum gs2, gidx_predicate predicate)
Support function.
Datum gserialized_gidx_geog_overlaps(PG_FUNCTION_ARGS)
static int gserialized_gist_picksplit_badratio(int x, int y)
static bool gserialized_gist_consistent_leaf(GIDX *key, GIDX *query, StrategyNumber strategy)
static float gidx_edge(GIDX *a)
PG_FUNCTION_INFO_V1(gserialized_distance_nd)
Datum gserialized_gist_compress(PG_FUNCTION_ARGS)
Datum gserialized_gidx_gidx_same(PG_FUNCTION_ARGS)
static int gserialized_datum_predicate_geom_gidx(Datum gs1, GIDX *gidx2, gidx_predicate predicate)
Datum gserialized_overlaps(PG_FUNCTION_ARGS)
Datum gserialized_gidx_gidx_contains(PG_FUNCTION_ARGS)
Datum gserialized_gidx_geom_within(PG_FUNCTION_ARGS)
static float pack_float(const float value, const uint8_t realm)
Datum gidx_out(PG_FUNCTION_ARGS)
bool gidx_equals(GIDX *a, GIDX *b)
Datum gserialized_gist_penalty(PG_FUNCTION_ARGS)
Datum gserialized_gist_distance(PG_FUNCTION_ARGS)
Datum gserialized_gist_decompress(PG_FUNCTION_ARGS)
Datum gserialized_gidx_geom_same(PG_FUNCTION_ARGS)
Datum gidx_in(PG_FUNCTION_ARGS)
Datum gserialized_gist_geog_distance(PG_FUNCTION_ARGS)
static double gidx_distance(const GIDX *a, const GIDX *b, int m_is_time)
Calculate the box->box distance.
static void gserialized_gist_picksplit_fallback(GistEntryVector *entryvec, GIST_SPLITVEC *v)
void gidx_validate(GIDX *b)
bool gidx_overlaps(GIDX *a, GIDX *b)
void gidx_merge(GIDX **b_union, GIDX *b_new)
GSERIALIZED * gserialized_expand(GSERIALIZED *g, double distance)
Return a GSERIALIZED with an expanded bounding box.
int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
void lwpoint_free(LWPOINT *pt)
void lwgeom_free(LWGEOM *geom)
double lwgeom_interpolate_point(const LWGEOM *lwin, const LWPOINT *lwpt)
Find the measure value at the location on the line closest to the point.
double lwgeom_length(const LWGEOM *geom)
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
LWGEOM * lwgeom_closest_line(const LWGEOM *lw1, const LWGEOM *lw2)
double lwgeom_length_2d(const LWGEOM *geom)
#define LW_TRUE
Return types for functions with status returns.
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
LWGEOM * lwgeom_closest_line_3d(const LWGEOM *lw1, const LWGEOM *lw2)
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
This library is the generic geometry handling section of PostGIS.
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
static double distance(double x1, double y1, double x2, double y2)