2 * contrib/btree_gist/btree_ts.c
8 #include "btree_gist.h"
9 #include "btree_utils_num.h"
10 #include "utils/builtins.h"
11 #include "utils/datetime.h"
12 #include "utils/float.h"
23 PG_FUNCTION_INFO_V1(gbt_ts_compress
);
24 PG_FUNCTION_INFO_V1(gbt_tstz_compress
);
25 PG_FUNCTION_INFO_V1(gbt_ts_fetch
);
26 PG_FUNCTION_INFO_V1(gbt_ts_union
);
27 PG_FUNCTION_INFO_V1(gbt_ts_picksplit
);
28 PG_FUNCTION_INFO_V1(gbt_ts_consistent
);
29 PG_FUNCTION_INFO_V1(gbt_ts_distance
);
30 PG_FUNCTION_INFO_V1(gbt_tstz_consistent
);
31 PG_FUNCTION_INFO_V1(gbt_tstz_distance
);
32 PG_FUNCTION_INFO_V1(gbt_ts_penalty
);
33 PG_FUNCTION_INFO_V1(gbt_ts_same
);
36 #ifdef USE_FLOAT8_BYVAL
37 #define TimestampGetDatumFast(X) TimestampGetDatum(X)
39 #define TimestampGetDatumFast(X) PointerGetDatum(&(X))
44 gbt_tsgt(const void *a
, const void *b
, FmgrInfo
*flinfo
)
46 const Timestamp
*aa
= (const Timestamp
*) a
;
47 const Timestamp
*bb
= (const Timestamp
*) b
;
49 return DatumGetBool(DirectFunctionCall2(timestamp_gt
,
50 TimestampGetDatumFast(*aa
),
51 TimestampGetDatumFast(*bb
)));
55 gbt_tsge(const void *a
, const void *b
, FmgrInfo
*flinfo
)
57 const Timestamp
*aa
= (const Timestamp
*) a
;
58 const Timestamp
*bb
= (const Timestamp
*) b
;
60 return DatumGetBool(DirectFunctionCall2(timestamp_ge
,
61 TimestampGetDatumFast(*aa
),
62 TimestampGetDatumFast(*bb
)));
66 gbt_tseq(const void *a
, const void *b
, FmgrInfo
*flinfo
)
68 const Timestamp
*aa
= (const Timestamp
*) a
;
69 const Timestamp
*bb
= (const Timestamp
*) b
;
71 return DatumGetBool(DirectFunctionCall2(timestamp_eq
,
72 TimestampGetDatumFast(*aa
),
73 TimestampGetDatumFast(*bb
)));
77 gbt_tsle(const void *a
, const void *b
, FmgrInfo
*flinfo
)
79 const Timestamp
*aa
= (const Timestamp
*) a
;
80 const Timestamp
*bb
= (const Timestamp
*) b
;
82 return DatumGetBool(DirectFunctionCall2(timestamp_le
,
83 TimestampGetDatumFast(*aa
),
84 TimestampGetDatumFast(*bb
)));
88 gbt_tslt(const void *a
, const void *b
, FmgrInfo
*flinfo
)
90 const Timestamp
*aa
= (const Timestamp
*) a
;
91 const Timestamp
*bb
= (const Timestamp
*) b
;
93 return DatumGetBool(DirectFunctionCall2(timestamp_lt
,
94 TimestampGetDatumFast(*aa
),
95 TimestampGetDatumFast(*bb
)));
100 gbt_tskey_cmp(const void *a
, const void *b
, FmgrInfo
*flinfo
)
102 tsKEY
*ia
= (tsKEY
*) (((const Nsrt
*) a
)->t
);
103 tsKEY
*ib
= (tsKEY
*) (((const Nsrt
*) b
)->t
);
106 res
= DatumGetInt32(DirectFunctionCall2(timestamp_cmp
, TimestampGetDatumFast(ia
->lower
), TimestampGetDatumFast(ib
->lower
)));
108 return DatumGetInt32(DirectFunctionCall2(timestamp_cmp
, TimestampGetDatumFast(ia
->upper
), TimestampGetDatumFast(ib
->upper
)));
114 gbt_ts_dist(const void *a
, const void *b
, FmgrInfo
*flinfo
)
116 const Timestamp
*aa
= (const Timestamp
*) a
;
117 const Timestamp
*bb
= (const Timestamp
*) b
;
120 if (TIMESTAMP_NOT_FINITE(*aa
) || TIMESTAMP_NOT_FINITE(*bb
))
121 return get_float8_infinity();
123 i
= DatumGetIntervalP(DirectFunctionCall2(timestamp_mi
,
124 TimestampGetDatumFast(*aa
),
125 TimestampGetDatumFast(*bb
)));
126 return (float8
) Abs(INTERVAL_TO_SEC(i
));
130 static const gbtree_ninfo tinfo
=
134 16, /* sizeof(gbtreekey16) */
145 PG_FUNCTION_INFO_V1(ts_dist
);
147 ts_dist(PG_FUNCTION_ARGS
)
149 Timestamp a
= PG_GETARG_TIMESTAMP(0);
150 Timestamp b
= PG_GETARG_TIMESTAMP(1);
153 if (TIMESTAMP_NOT_FINITE(a
) || TIMESTAMP_NOT_FINITE(b
))
155 Interval
*p
= palloc(sizeof(Interval
));
159 p
->time
= PG_INT64_MAX
;
160 PG_RETURN_INTERVAL_P(p
);
163 r
= DatumGetIntervalP(DirectFunctionCall2(timestamp_mi
,
165 PG_GETARG_DATUM(1)));
166 PG_RETURN_INTERVAL_P(abs_interval(r
));
169 PG_FUNCTION_INFO_V1(tstz_dist
);
171 tstz_dist(PG_FUNCTION_ARGS
)
173 TimestampTz a
= PG_GETARG_TIMESTAMPTZ(0);
174 TimestampTz b
= PG_GETARG_TIMESTAMPTZ(1);
177 if (TIMESTAMP_NOT_FINITE(a
) || TIMESTAMP_NOT_FINITE(b
))
179 Interval
*p
= palloc(sizeof(Interval
));
183 p
->time
= PG_INT64_MAX
;
184 PG_RETURN_INTERVAL_P(p
);
187 r
= DatumGetIntervalP(DirectFunctionCall2(timestamp_mi
,
189 PG_GETARG_DATUM(1)));
190 PG_RETURN_INTERVAL_P(abs_interval(r
));
194 /**************************************************
196 **************************************************/
199 static inline Timestamp
200 tstz_to_ts_gmt(TimestampTz ts
)
202 /* No timezone correction is needed, since GMT is offset 0 by definition */
203 return (Timestamp
) ts
;
208 gbt_ts_compress(PG_FUNCTION_ARGS
)
210 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
212 PG_RETURN_POINTER(gbt_num_compress(entry
, &tinfo
));
217 gbt_tstz_compress(PG_FUNCTION_ARGS
)
219 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
224 tsKEY
*r
= (tsKEY
*) palloc(sizeof(tsKEY
));
225 TimestampTz ts
= DatumGetTimestampTz(entry
->key
);
228 gmt
= tstz_to_ts_gmt(ts
);
230 retval
= palloc(sizeof(GISTENTRY
));
231 r
->lower
= r
->upper
= gmt
;
232 gistentryinit(*retval
, PointerGetDatum(r
),
233 entry
->rel
, entry
->page
,
234 entry
->offset
, false);
239 PG_RETURN_POINTER(retval
);
243 gbt_ts_fetch(PG_FUNCTION_ARGS
)
245 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
247 PG_RETURN_POINTER(gbt_num_fetch(entry
, &tinfo
));
251 gbt_ts_consistent(PG_FUNCTION_ARGS
)
253 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
254 Timestamp query
= PG_GETARG_TIMESTAMP(1);
255 StrategyNumber strategy
= (StrategyNumber
) PG_GETARG_UINT16(2);
257 /* Oid subtype = PG_GETARG_OID(3); */
258 bool *recheck
= (bool *) PG_GETARG_POINTER(4);
259 tsKEY
*kkk
= (tsKEY
*) DatumGetPointer(entry
->key
);
262 /* All cases served by this function are exact */
265 key
.lower
= (GBT_NUMKEY
*) &kkk
->lower
;
266 key
.upper
= (GBT_NUMKEY
*) &kkk
->upper
;
268 PG_RETURN_BOOL(gbt_num_consistent(&key
, (void *) &query
, &strategy
,
269 GIST_LEAF(entry
), &tinfo
, fcinfo
->flinfo
));
273 gbt_ts_distance(PG_FUNCTION_ARGS
)
275 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
276 Timestamp query
= PG_GETARG_TIMESTAMP(1);
278 /* Oid subtype = PG_GETARG_OID(3); */
279 tsKEY
*kkk
= (tsKEY
*) DatumGetPointer(entry
->key
);
282 key
.lower
= (GBT_NUMKEY
*) &kkk
->lower
;
283 key
.upper
= (GBT_NUMKEY
*) &kkk
->upper
;
285 PG_RETURN_FLOAT8(gbt_num_distance(&key
, (void *) &query
, GIST_LEAF(entry
),
286 &tinfo
, fcinfo
->flinfo
));
290 gbt_tstz_consistent(PG_FUNCTION_ARGS
)
292 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
293 TimestampTz query
= PG_GETARG_TIMESTAMPTZ(1);
294 StrategyNumber strategy
= (StrategyNumber
) PG_GETARG_UINT16(2);
296 /* Oid subtype = PG_GETARG_OID(3); */
297 bool *recheck
= (bool *) PG_GETARG_POINTER(4);
298 char *kkk
= (char *) DatumGetPointer(entry
->key
);
302 /* All cases served by this function are exact */
305 key
.lower
= (GBT_NUMKEY
*) &kkk
[0];
306 key
.upper
= (GBT_NUMKEY
*) &kkk
[MAXALIGN(tinfo
.size
)];
307 qqq
= tstz_to_ts_gmt(query
);
309 PG_RETURN_BOOL(gbt_num_consistent(&key
, (void *) &qqq
, &strategy
,
310 GIST_LEAF(entry
), &tinfo
, fcinfo
->flinfo
));
314 gbt_tstz_distance(PG_FUNCTION_ARGS
)
316 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
317 TimestampTz query
= PG_GETARG_TIMESTAMPTZ(1);
319 /* Oid subtype = PG_GETARG_OID(3); */
320 char *kkk
= (char *) DatumGetPointer(entry
->key
);
324 key
.lower
= (GBT_NUMKEY
*) &kkk
[0];
325 key
.upper
= (GBT_NUMKEY
*) &kkk
[MAXALIGN(tinfo
.size
)];
326 qqq
= tstz_to_ts_gmt(query
);
328 PG_RETURN_FLOAT8(gbt_num_distance(&key
, (void *) &qqq
, GIST_LEAF(entry
),
329 &tinfo
, fcinfo
->flinfo
));
334 gbt_ts_union(PG_FUNCTION_ARGS
)
336 GistEntryVector
*entryvec
= (GistEntryVector
*) PG_GETARG_POINTER(0);
337 void *out
= palloc(sizeof(tsKEY
));
339 *(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY
);
340 PG_RETURN_POINTER(gbt_num_union((void *) out
, entryvec
, &tinfo
, fcinfo
->flinfo
));
344 #define penalty_check_max_float(val) do { \
345 if ( val > FLT_MAX ) \
347 if ( val < -FLT_MAX ) \
353 gbt_ts_penalty(PG_FUNCTION_ARGS
)
355 tsKEY
*origentry
= (tsKEY
*) DatumGetPointer(((GISTENTRY
*) PG_GETARG_POINTER(0))->key
);
356 tsKEY
*newentry
= (tsKEY
*) DatumGetPointer(((GISTENTRY
*) PG_GETARG_POINTER(1))->key
);
357 float *result
= (float *) PG_GETARG_POINTER(2);
363 * We are always using "double" timestamps here. Precision should be good
366 orgdbl
[0] = ((double) origentry
->lower
);
367 orgdbl
[1] = ((double) origentry
->upper
);
368 newdbl
[0] = ((double) newentry
->lower
);
369 newdbl
[1] = ((double) newentry
->upper
);
371 penalty_check_max_float(orgdbl
[0]);
372 penalty_check_max_float(orgdbl
[1]);
373 penalty_check_max_float(newdbl
[0]);
374 penalty_check_max_float(newdbl
[1]);
376 penalty_num(result
, orgdbl
[0], orgdbl
[1], newdbl
[0], newdbl
[1]);
378 PG_RETURN_POINTER(result
);
384 gbt_ts_picksplit(PG_FUNCTION_ARGS
)
386 PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector
*) PG_GETARG_POINTER(0),
387 (GIST_SPLITVEC
*) PG_GETARG_POINTER(1),
388 &tinfo
, fcinfo
->flinfo
));
392 gbt_ts_same(PG_FUNCTION_ARGS
)
394 tsKEY
*b1
= (tsKEY
*) PG_GETARG_POINTER(0);
395 tsKEY
*b2
= (tsKEY
*) PG_GETARG_POINTER(1);
396 bool *result
= (bool *) PG_GETARG_POINTER(2);
398 *result
= gbt_num_same((void *) b1
, (void *) b2
, &tinfo
, fcinfo
->flinfo
);
399 PG_RETURN_POINTER(result
);