3 #include "access/gist.h"
4 #include "access/itup.h"
5 #include "access/nbtree.h"
7 #include "utils/palloc.h"
8 #include "utils/geo_decls.h"
9 #include "utils/elog.h"
11 typedef int (*CMPFUNC) (const void *a, const void *b);
12 typedef void (*BINARY_UNION) (Datum *, char *);
26 /* used for sorting */
36 PG_FUNCTION_INFO_V1(int4key_in);
37 PG_FUNCTION_INFO_V1(int4key_out);
38 Datum int4key_in(PG_FUNCTION_ARGS);
39 Datum int4key_out(PG_FUNCTION_ARGS);
44 PG_FUNCTION_INFO_V1(tskey_in);
45 PG_FUNCTION_INFO_V1(tskey_out);
46 Datum tskey_in(PG_FUNCTION_ARGS);
47 Datum tskey_out(PG_FUNCTION_ARGS);
52 PG_FUNCTION_INFO_V1(gint4_compress);
53 PG_FUNCTION_INFO_V1(gint4_union);
54 PG_FUNCTION_INFO_V1(gint4_picksplit);
55 PG_FUNCTION_INFO_V1(gint4_consistent);
56 PG_FUNCTION_INFO_V1(gint4_penalty);
57 PG_FUNCTION_INFO_V1(gint4_same);
59 Datum gint4_compress(PG_FUNCTION_ARGS);
60 Datum gint4_union(PG_FUNCTION_ARGS);
61 Datum gint4_picksplit(PG_FUNCTION_ARGS);
62 Datum gint4_consistent(PG_FUNCTION_ARGS);
63 Datum gint4_penalty(PG_FUNCTION_ARGS);
64 Datum gint4_same(PG_FUNCTION_ARGS);
66 static void gint4_binary_union(Datum *r1, char *r2);
67 static int int4key_cmp(const void *a, const void *b);
72 PG_FUNCTION_INFO_V1(gts_compress);
73 PG_FUNCTION_INFO_V1(gts_union);
74 PG_FUNCTION_INFO_V1(gts_picksplit);
75 PG_FUNCTION_INFO_V1(gts_consistent);
76 PG_FUNCTION_INFO_V1(gts_penalty);
77 PG_FUNCTION_INFO_V1(gts_same);
79 Datum gts_compress(PG_FUNCTION_ARGS);
80 Datum gts_union(PG_FUNCTION_ARGS);
81 Datum gts_picksplit(PG_FUNCTION_ARGS);
82 Datum gts_consistent(PG_FUNCTION_ARGS);
83 Datum gts_penalty(PG_FUNCTION_ARGS);
84 Datum gts_same(PG_FUNCTION_ARGS);
86 static void gts_binary_union(Datum *r1, char *r2);
87 static int tskey_cmp(const void *a, const void *b);
89 #define TimestampGetDatumFast(X) Float8GetDatumFast(X)
91 /* define for comparison */
92 #define TSGE( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \
94 PointerGetDatum( ts1 ), \
95 PointerGetDatum( ts2 ) \
97 #define TSGT( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \
99 PointerGetDatum( ts1 ), \
100 PointerGetDatum( ts2 ) \
102 #define TSEQ( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \
104 PointerGetDatum( ts1 ), \
105 PointerGetDatum( ts2 ) \
107 #define TSLT( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \
109 PointerGetDatum( ts1 ), \
110 PointerGetDatum( ts2 ) \
112 #define TSLE( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \
114 PointerGetDatum( ts1 ), \
115 PointerGetDatum( ts2 ) \
119 ** Common btree-function (for all ops)
121 static GIST_SPLITVEC *btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v,
122 BINARY_UNION bu, CMPFUNC cmp);
124 PG_FUNCTION_INFO_V1(btree_decompress);
125 Datum btree_decompress(PG_FUNCTION_ARGS);
127 /**************************************************
129 **************************************************/
132 gint4_compress(PG_FUNCTION_ARGS)
134 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
139 INT4KEY *r = palloc(sizeof(INT4KEY));
141 retval = palloc(sizeof(GISTENTRY));
142 r->lower = r->upper = (entry->key);
144 gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
145 entry->offset, sizeof(INT4KEY), FALSE);
150 PG_RETURN_POINTER(retval);
154 gint4_consistent(PG_FUNCTION_ARGS)
156 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
157 int4 query = PG_GETARG_INT32(1);
158 INT4KEY *kkk = (INT4KEY *) DatumGetPointer(entry->key);
159 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
164 case BTLessEqualStrategyNumber:
165 retval = (query >= kkk->lower);
167 case BTLessStrategyNumber:
168 if (GIST_LEAF(entry))
169 retval = (query > kkk->lower);
171 retval = (query >= kkk->lower);
173 case BTEqualStrategyNumber:
174 /* in leaf page kkk->lower always = kkk->upper */
175 if (GIST_LEAF(entry))
176 retval = (query == kkk->lower);
178 retval = (kkk->lower <= query && query <= kkk->upper);
180 case BTGreaterStrategyNumber:
181 if (GIST_LEAF(entry))
182 retval = (query < kkk->upper);
184 retval = (query <= kkk->upper);
186 case BTGreaterEqualStrategyNumber:
187 retval = (query <= kkk->upper);
192 PG_RETURN_BOOL(retval);
196 gint4_union(PG_FUNCTION_ARGS)
198 bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
202 *out = palloc(sizeof(INT4KEY));
204 numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
205 *(int *) PG_GETARG_POINTER(1) = sizeof(INT4KEY);
207 cur = (INT4KEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[0].key));
208 out->lower = cur->lower;
209 out->upper = cur->upper;
211 for (i = 1; i < numranges; i++)
213 cur = (INT4KEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key));
214 if (out->lower > cur->lower)
215 out->lower = cur->lower;
216 if (out->upper < cur->upper)
217 out->upper = cur->upper;
220 PG_RETURN_POINTER(out);
224 gint4_penalty(PG_FUNCTION_ARGS)
226 INT4KEY *origentry = (INT4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
227 INT4KEY *newentry = (INT4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
228 float *result = (float *) PG_GETARG_POINTER(2);
230 *result = Max(newentry->upper - origentry->upper, 0) +
231 Max(origentry->lower - newentry->lower, 0);
233 PG_RETURN_POINTER(result);
237 gint4_picksplit(PG_FUNCTION_ARGS)
239 PG_RETURN_POINTER(btree_picksplit(
240 (bytea *) PG_GETARG_POINTER(0),
241 (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
248 gint4_same(PG_FUNCTION_ARGS)
250 INT4KEY *b1 = (INT4KEY *) PG_GETARG_POINTER(0);
251 INT4KEY *b2 = (INT4KEY *) PG_GETARG_POINTER(1);
252 bool *result = (bool *) PG_GETARG_POINTER(2);
254 *result = (b1->lower == b2->lower && b1->upper == b2->upper) ? TRUE : FALSE;
255 PG_RETURN_POINTER(result);
259 gint4_binary_union(Datum *r1, char *r2)
262 INT4KEY *b2 = (INT4KEY *) r2;
264 if (!DatumGetPointer(*r1))
266 *r1 = PointerGetDatum(palloc(sizeof(INT4KEY)));
267 b1 = (INT4KEY *) DatumGetPointer(*r1);
268 b1->upper = b2->upper;
269 b1->lower = b2->lower;
273 b1 = (INT4KEY *) DatumGetPointer(*r1);
275 b1->lower = (b1->lower > b2->lower) ?
276 b2->lower : b1->lower;
277 b1->upper = (b1->upper > b2->upper) ?
278 b1->upper : b2->upper;
284 int4key_cmp(const void *a, const void *b)
286 return (((INT4KEY *) (((RIX *) a)->r))->lower - ((INT4KEY *) (((RIX *) b)->r))->lower);
289 /**************************************************
291 **************************************************/
294 gts_compress(PG_FUNCTION_ARGS)
296 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
301 TSKEY *r = (TSKEY *) palloc(sizeof(TSKEY));
303 retval = palloc(sizeof(GISTENTRY));
304 r->lower = r->upper = *(Timestamp *) (entry->key);
305 gistentryinit(*retval, PointerGetDatum(r),
306 entry->rel, entry->page,
307 entry->offset, sizeof(TSKEY), FALSE);
311 PG_RETURN_POINTER(retval);
315 gts_consistent(PG_FUNCTION_ARGS)
317 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
318 Timestamp *query = (Timestamp *) PG_GETARG_POINTER(1);
319 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
324 * * if entry is not leaf, use gbox_internal_consistent, * else use
325 * gbox_leaf_consistent
329 key = (TSKEY *) DatumGetPointer(entry->key);
333 case BTLessEqualStrategyNumber:
334 retval = TSGE(query, &(key->lower));
336 case BTLessStrategyNumber:
337 if (GIST_LEAF(entry))
338 retval = TSGT(query, &(key->lower));
340 retval = TSGE(query, &(key->lower));
342 case BTEqualStrategyNumber:
343 /* in leaf page key->lower always = key->upper */
344 if (GIST_LEAF(entry))
345 retval = TSEQ(query, &(key->lower));
347 retval = (TSLE(&(key->lower), query) && TSLE(query, &(key->upper)));
349 case BTGreaterStrategyNumber:
350 if (GIST_LEAF(entry))
351 retval = TSLT(query, &(key->upper));
353 retval = TSLE(query, &(key->upper));
355 case BTGreaterEqualStrategyNumber:
356 retval = TSLE(query, &(key->upper));
361 PG_RETURN_BOOL(retval);
365 gts_union(PG_FUNCTION_ARGS)
367 bytea *entryvec = (bytea *) PG_GETARG_POINTER(0);
371 *out = palloc(sizeof(TSKEY));
373 numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY);
374 *(int *) PG_GETARG_POINTER(1) = sizeof(TSKEY);
376 cur = (TSKEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[0].key));
377 out->lower = cur->lower;
378 out->upper = cur->upper;
380 for (i = 1; i < numranges; i++)
382 cur = (TSKEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key));
383 if (TSGT(&out->lower, &cur->lower))
384 out->lower = cur->lower;
385 if (TSLT(&out->upper, &cur->upper))
386 out->upper = cur->upper;
389 PG_RETURN_POINTER(out);
393 gts_penalty(PG_FUNCTION_ARGS)
395 TSKEY *origentry = (TSKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
396 TSKEY *newentry = (TSKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
397 float *result = (float *) PG_GETARG_POINTER(2);
400 intr = DatumGetIntervalP(DirectFunctionCall2(
402 TimestampGetDatumFast(newentry->upper),
403 TimestampGetDatumFast(origentry->upper)));
405 /* see interval_larger */
406 *result = Max(intr->time + intr->month * (30.0 * 86400), 0);
409 intr = DatumGetIntervalP(DirectFunctionCall2(
411 TimestampGetDatumFast(origentry->lower),
412 TimestampGetDatumFast(newentry->lower)));
414 /* see interval_larger */
415 *result += Max(intr->time + intr->month * (30.0 * 86400), 0);
418 PG_RETURN_POINTER(result);
422 gts_picksplit(PG_FUNCTION_ARGS)
424 PG_RETURN_POINTER(btree_picksplit(
425 (bytea *) PG_GETARG_POINTER(0),
426 (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
433 gts_same(PG_FUNCTION_ARGS)
435 TSKEY *b1 = (TSKEY *) PG_GETARG_POINTER(0);
436 TSKEY *b2 = (TSKEY *) PG_GETARG_POINTER(1);
438 bool *result = (bool *) PG_GETARG_POINTER(2);
441 *result = (TSEQ(&(b1->lower), &(b2->lower)) && TSEQ(&(b1->upper), &(b2->upper))) ? TRUE : FALSE;
443 *result = (b1 == NULL && b2 == NULL) ? TRUE : FALSE;
444 PG_RETURN_POINTER(result);
448 gts_binary_union(Datum *r1, char *r2)
451 TSKEY *b2 = (TSKEY *) r2;
453 if (!DatumGetPointer(*r1))
455 *r1 = PointerGetDatum(palloc(sizeof(TSKEY)));
456 b1 = (TSKEY *) DatumGetPointer(*r1);
457 b1->upper = b2->upper;
458 b1->lower = b2->lower;
462 b1 = (TSKEY *) DatumGetPointer(*r1);
464 b1->lower = (TSGT(&b1->lower, &b2->lower)) ?
465 b2->lower : b1->lower;
466 b1->upper = (TSGT(&b1->upper, &b2->upper)) ?
467 b1->upper : b2->upper;
472 tskey_cmp(const void *a, const void *b)
474 return DatumGetInt32(
477 TimestampGetDatumFast(((TSKEY *) (((RIX *) a)->r))->lower),
478 TimestampGetDatumFast(((TSKEY *) (((RIX *) b)->r))->lower)
483 /**************************************************
484 * Common btree-function (for all ops)
485 **************************************************/
488 ** The GiST PickSplit method
490 static GIST_SPLITVEC *
491 btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, BINARY_UNION bu, CMPFUNC cmp)
498 maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 1;
499 nbytes = (maxoff + 2) * sizeof(OffsetNumber);
500 v->spl_left = (OffsetNumber *) palloc(nbytes);
501 v->spl_right = (OffsetNumber *) palloc(nbytes);
504 v->spl_ldatum = PointerGetDatum(0);
505 v->spl_rdatum = PointerGetDatum(0);
506 array = (RIX *) palloc(sizeof(RIX) * (maxoff + 1));
508 /* copy the data into RIXes, and sort the RIXes */
509 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
512 array[i].r = (char *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key));
514 qsort((void *) &array[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1,
517 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
519 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
521 v->spl_left[v->spl_nleft] = array[i].index;
523 (*bu) (&v->spl_ldatum, array[i].r);
527 v->spl_right[v->spl_nright] = array[i].index;
529 (*bu) (&v->spl_rdatum, array[i].r);
538 ** GiST DeCompress methods
539 ** do not do anything.
542 btree_decompress(PG_FUNCTION_ARGS)
544 PG_RETURN_POINTER(PG_GETARG_POINTER(0));
548 /**************************************************
549 * In/Out for keys, not really needed
550 **************************************************/
552 int4key_in(PG_FUNCTION_ARGS)
554 INT4KEY *key = palloc(sizeof(INT4KEY));
556 if (sscanf(PG_GETARG_POINTER(0), "%d|%d", &(key->lower), &(key->upper)) != 2)
557 elog(ERROR, "Error in input format");
559 PG_RETURN_POINTER(key);
563 int4key_out(PG_FUNCTION_ARGS)
565 INT4KEY *key = (INT4KEY *) PG_GETARG_POINTER(0);
566 char *str = palloc(sizeof(char) * 22);
568 sprintf(str, "%d|%d", key->lower, key->upper);
569 PG_RETURN_POINTER(str);
573 tskey_in(PG_FUNCTION_ARGS)
575 elog(ERROR, "Not implemented");
576 PG_RETURN_POINTER(NULL);
580 tskey_out(PG_FUNCTION_ARGS)
582 elog(ERROR, "Not implemented");
583 PG_RETURN_POINTER(NULL);