2 * contrib/btree_gist/btree_ts.c
6 #include "btree_gist.h"
7 #include "btree_utils_num.h"
8 #include "utils/builtins.h"
9 #include "utils/datetime.h"
20 PG_FUNCTION_INFO_V1(gbt_ts_compress);
21 PG_FUNCTION_INFO_V1(gbt_tstz_compress);
22 PG_FUNCTION_INFO_V1(gbt_ts_fetch);
23 PG_FUNCTION_INFO_V1(gbt_ts_union);
24 PG_FUNCTION_INFO_V1(gbt_ts_picksplit);
25 PG_FUNCTION_INFO_V1(gbt_ts_consistent);
26 PG_FUNCTION_INFO_V1(gbt_ts_distance);
27 PG_FUNCTION_INFO_V1(gbt_tstz_consistent);
28 PG_FUNCTION_INFO_V1(gbt_tstz_distance);
29 PG_FUNCTION_INFO_V1(gbt_ts_penalty);
30 PG_FUNCTION_INFO_V1(gbt_ts_same);
33 #ifdef USE_FLOAT8_BYVAL
34 #define TimestampGetDatumFast(X) TimestampGetDatum(X)
36 #define TimestampGetDatumFast(X) PointerGetDatum(&(X))
41 gbt_tsgt(const void *a, const void *b)
43 const Timestamp *aa = (const Timestamp *) a;
44 const Timestamp *bb = (const Timestamp *) b;
46 return DatumGetBool(DirectFunctionCall2(timestamp_gt,
47 TimestampGetDatumFast(*aa),
48 TimestampGetDatumFast(*bb)));
52 gbt_tsge(const void *a, const void *b)
54 const Timestamp *aa = (const Timestamp *) a;
55 const Timestamp *bb = (const Timestamp *) b;
57 return DatumGetBool(DirectFunctionCall2(timestamp_ge,
58 TimestampGetDatumFast(*aa),
59 TimestampGetDatumFast(*bb)));
63 gbt_tseq(const void *a, const void *b)
65 const Timestamp *aa = (const Timestamp *) a;
66 const Timestamp *bb = (const Timestamp *) b;
68 return DatumGetBool(DirectFunctionCall2(timestamp_eq,
69 TimestampGetDatumFast(*aa),
70 TimestampGetDatumFast(*bb)));
74 gbt_tsle(const void *a, const void *b)
76 const Timestamp *aa = (const Timestamp *) a;
77 const Timestamp *bb = (const Timestamp *) b;
79 return DatumGetBool(DirectFunctionCall2(timestamp_le,
80 TimestampGetDatumFast(*aa),
81 TimestampGetDatumFast(*bb)));
85 gbt_tslt(const void *a, const void *b)
87 const Timestamp *aa = (const Timestamp *) a;
88 const Timestamp *bb = (const Timestamp *) b;
90 return DatumGetBool(DirectFunctionCall2(timestamp_lt,
91 TimestampGetDatumFast(*aa),
92 TimestampGetDatumFast(*bb)));
97 gbt_tskey_cmp(const void *a, const void *b)
99 tsKEY *ia = (tsKEY *) (((const Nsrt *) a)->t);
100 tsKEY *ib = (tsKEY *) (((const Nsrt *) b)->t);
103 res = DatumGetInt32(DirectFunctionCall2(timestamp_cmp, TimestampGetDatumFast(ia->lower), TimestampGetDatumFast(ib->lower)));
105 return DatumGetInt32(DirectFunctionCall2(timestamp_cmp, TimestampGetDatumFast(ia->upper), TimestampGetDatumFast(ib->upper)));
111 gbt_ts_dist(const void *a, const void *b)
113 const Timestamp *aa = (const Timestamp *) a;
114 const Timestamp *bb = (const Timestamp *) b;
117 if (TIMESTAMP_NOT_FINITE(*aa) || TIMESTAMP_NOT_FINITE(*bb))
118 return get_float8_infinity();
120 i = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
121 TimestampGetDatumFast(*aa),
122 TimestampGetDatumFast(*bb)));
123 return (float8) Abs(INTERVAL_TO_SEC(i));
127 static const gbtree_ninfo tinfo =
131 16, /* sizeof(gbtreekey16) */
142 PG_FUNCTION_INFO_V1(ts_dist);
144 ts_dist(PG_FUNCTION_ARGS)
146 Timestamp a = PG_GETARG_TIMESTAMP(0);
147 Timestamp b = PG_GETARG_TIMESTAMP(1);
150 if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
152 Interval *p = palloc(sizeof(Interval));
156 #ifdef HAVE_INT64_TIMESTAMP
157 p->time = PG_INT64_MAX;
161 PG_RETURN_INTERVAL_P(p);
164 r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
166 PG_GETARG_DATUM(1)));
167 PG_RETURN_INTERVAL_P(abs_interval(r));
170 PG_FUNCTION_INFO_V1(tstz_dist);
172 tstz_dist(PG_FUNCTION_ARGS)
174 TimestampTz a = PG_GETARG_TIMESTAMPTZ(0);
175 TimestampTz b = PG_GETARG_TIMESTAMPTZ(1);
178 if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
180 Interval *p = palloc(sizeof(Interval));
184 #ifdef HAVE_INT64_TIMESTAMP
185 p->time = PG_INT64_MAX;
189 PG_RETURN_INTERVAL_P(p);
192 r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
194 PG_GETARG_DATUM(1)));
195 PG_RETURN_INTERVAL_P(abs_interval(r));
199 /**************************************************
201 **************************************************/
204 static inline Timestamp
205 tstz_to_ts_gmt(TimestampTz ts)
207 /* No timezone correction is needed, since GMT is offset 0 by definition */
208 return (Timestamp) ts;
213 gbt_ts_compress(PG_FUNCTION_ARGS)
215 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
217 PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
222 gbt_tstz_compress(PG_FUNCTION_ARGS)
224 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
229 tsKEY *r = (tsKEY *) palloc(sizeof(tsKEY));
230 TimestampTz ts = DatumGetTimestampTz(entry->key);
233 gmt = tstz_to_ts_gmt(ts);
235 retval = palloc(sizeof(GISTENTRY));
236 r->lower = r->upper = gmt;
237 gistentryinit(*retval, PointerGetDatum(r),
238 entry->rel, entry->page,
239 entry->offset, FALSE);
244 PG_RETURN_POINTER(retval);
248 gbt_ts_fetch(PG_FUNCTION_ARGS)
250 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
252 PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
256 gbt_ts_consistent(PG_FUNCTION_ARGS)
258 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
259 Timestamp query = PG_GETARG_TIMESTAMP(1);
260 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
262 /* Oid subtype = PG_GETARG_OID(3); */
263 bool *recheck = (bool *) PG_GETARG_POINTER(4);
264 tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key);
267 /* All cases served by this function are exact */
270 key.lower = (GBT_NUMKEY *) &kkk->lower;
271 key.upper = (GBT_NUMKEY *) &kkk->upper;
274 gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
279 gbt_ts_distance(PG_FUNCTION_ARGS)
281 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
282 Timestamp query = PG_GETARG_TIMESTAMP(1);
284 /* Oid subtype = PG_GETARG_OID(3); */
285 tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key);
288 key.lower = (GBT_NUMKEY *) &kkk->lower;
289 key.upper = (GBT_NUMKEY *) &kkk->upper;
292 gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
297 gbt_tstz_consistent(PG_FUNCTION_ARGS)
299 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
300 TimestampTz query = PG_GETARG_TIMESTAMPTZ(1);
301 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
303 /* Oid subtype = PG_GETARG_OID(3); */
304 bool *recheck = (bool *) PG_GETARG_POINTER(4);
305 char *kkk = (char *) DatumGetPointer(entry->key);
309 /* All cases served by this function are exact */
312 key.lower = (GBT_NUMKEY *) &kkk[0];
313 key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)];
314 qqq = tstz_to_ts_gmt(query);
317 gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo)
322 gbt_tstz_distance(PG_FUNCTION_ARGS)
324 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
325 TimestampTz query = PG_GETARG_TIMESTAMPTZ(1);
327 /* Oid subtype = PG_GETARG_OID(3); */
328 char *kkk = (char *) DatumGetPointer(entry->key);
332 key.lower = (GBT_NUMKEY *) &kkk[0];
333 key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)];
334 qqq = tstz_to_ts_gmt(query);
337 gbt_num_distance(&key, (void *) &qqq, GIST_LEAF(entry), &tinfo)
343 gbt_ts_union(PG_FUNCTION_ARGS)
345 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
346 void *out = palloc(sizeof(tsKEY));
348 *(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY);
349 PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
353 #define penalty_check_max_float(val) do { \
354 if ( val > FLT_MAX ) \
356 if ( val < -FLT_MAX ) \
362 gbt_ts_penalty(PG_FUNCTION_ARGS)
364 tsKEY *origentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
365 tsKEY *newentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
366 float *result = (float *) PG_GETARG_POINTER(2);
372 * We are allways using "double" timestamps here. Precision should be good
375 orgdbl[0] = ((double) origentry->lower);
376 orgdbl[1] = ((double) origentry->upper);
377 newdbl[0] = ((double) newentry->lower);
378 newdbl[1] = ((double) newentry->upper);
380 penalty_check_max_float(orgdbl[0]);
381 penalty_check_max_float(orgdbl[1]);
382 penalty_check_max_float(newdbl[0]);
383 penalty_check_max_float(newdbl[1]);
385 penalty_num(result, orgdbl[0], orgdbl[1], newdbl[0], newdbl[1]);
387 PG_RETURN_POINTER(result);
393 gbt_ts_picksplit(PG_FUNCTION_ARGS)
395 PG_RETURN_POINTER(gbt_num_picksplit(
396 (GistEntryVector *) PG_GETARG_POINTER(0),
397 (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
403 gbt_ts_same(PG_FUNCTION_ARGS)
405 tsKEY *b1 = (tsKEY *) PG_GETARG_POINTER(0);
406 tsKEY *b2 = (tsKEY *) PG_GETARG_POINTER(1);
407 bool *result = (bool *) PG_GETARG_POINTER(2);
409 *result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
410 PG_RETURN_POINTER(result);