Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * contrib/btree_gist/btree_ts.c
3 : : */
4 : : #include "postgres.h"
5 : :
6 : : #include <limits.h>
7 : :
8 : : #include "btree_gist.h"
9 : : #include "btree_utils_num.h"
10 : : #include "utils/fmgrprotos.h"
11 : : #include "utils/timestamp.h"
12 : : #include "utils/float.h"
13 : : #include "utils/rel.h"
14 : : #include "utils/sortsupport.h"
15 : :
16 : : typedef struct
17 : : {
18 : : Timestamp lower;
19 : : Timestamp upper;
20 : : } tsKEY;
21 : :
22 : : /* GiST support functions */
7771 teodor@sigaev.ru 23 :CBC 5 : PG_FUNCTION_INFO_V1(gbt_ts_compress);
24 : 4 : PG_FUNCTION_INFO_V1(gbt_tstz_compress);
3816 heikki.linnakangas@i 25 : 6 : PG_FUNCTION_INFO_V1(gbt_ts_fetch);
7771 teodor@sigaev.ru 26 : 6 : PG_FUNCTION_INFO_V1(gbt_ts_union);
27 : 6 : PG_FUNCTION_INFO_V1(gbt_ts_picksplit);
28 : 5 : PG_FUNCTION_INFO_V1(gbt_ts_consistent);
5302 tgl@sss.pgh.pa.us 29 : 5 : PG_FUNCTION_INFO_V1(gbt_ts_distance);
7771 teodor@sigaev.ru 30 : 4 : PG_FUNCTION_INFO_V1(gbt_tstz_consistent);
5302 tgl@sss.pgh.pa.us 31 : 4 : PG_FUNCTION_INFO_V1(gbt_tstz_distance);
7771 teodor@sigaev.ru 32 : 6 : PG_FUNCTION_INFO_V1(gbt_ts_penalty);
33 : 6 : PG_FUNCTION_INFO_V1(gbt_ts_same);
156 heikki.linnakangas@i 34 : 6 : PG_FUNCTION_INFO_V1(gbt_ts_sortsupport);
35 : :
36 : :
37 : : /* define for comparison */
38 : :
39 : : static bool
3091 andrew@dunslane.net 40 : 12969 : gbt_tsgt(const void *a, const void *b, FmgrInfo *flinfo)
41 : : {
6347 tgl@sss.pgh.pa.us 42 : 12969 : const Timestamp *aa = (const Timestamp *) a;
43 : 12969 : const Timestamp *bb = (const Timestamp *) b;
44 : :
45 : 12969 : return DatumGetBool(DirectFunctionCall2(timestamp_gt,
46 : : TimestampGetDatum(*aa),
47 : : TimestampGetDatum(*bb)));
48 : : }
49 : :
50 : : static bool
3091 andrew@dunslane.net 51 : 2345 : gbt_tsge(const void *a, const void *b, FmgrInfo *flinfo)
52 : : {
6347 tgl@sss.pgh.pa.us 53 : 2345 : const Timestamp *aa = (const Timestamp *) a;
54 : 2345 : const Timestamp *bb = (const Timestamp *) b;
55 : :
56 : 2345 : return DatumGetBool(DirectFunctionCall2(timestamp_ge,
57 : : TimestampGetDatum(*aa),
58 : : TimestampGetDatum(*bb)));
59 : : }
60 : :
61 : : static bool
3091 andrew@dunslane.net 62 : 5185 : gbt_tseq(const void *a, const void *b, FmgrInfo *flinfo)
63 : : {
6347 tgl@sss.pgh.pa.us 64 : 5185 : const Timestamp *aa = (const Timestamp *) a;
65 : 5185 : const Timestamp *bb = (const Timestamp *) b;
66 : :
67 : 5185 : return DatumGetBool(DirectFunctionCall2(timestamp_eq,
68 : : TimestampGetDatum(*aa),
69 : : TimestampGetDatum(*bb)));
70 : : }
71 : :
72 : : static bool
3091 andrew@dunslane.net 73 : 1987 : gbt_tsle(const void *a, const void *b, FmgrInfo *flinfo)
74 : : {
6347 tgl@sss.pgh.pa.us 75 : 1987 : const Timestamp *aa = (const Timestamp *) a;
76 : 1987 : const Timestamp *bb = (const Timestamp *) b;
77 : :
78 : 1987 : return DatumGetBool(DirectFunctionCall2(timestamp_le,
79 : : TimestampGetDatum(*aa),
80 : : TimestampGetDatum(*bb)));
81 : : }
82 : :
83 : : static bool
3091 andrew@dunslane.net 84 : 12431 : gbt_tslt(const void *a, const void *b, FmgrInfo *flinfo)
85 : : {
6347 tgl@sss.pgh.pa.us 86 : 12431 : const Timestamp *aa = (const Timestamp *) a;
87 : 12431 : const Timestamp *bb = (const Timestamp *) b;
88 : :
89 : 12431 : return DatumGetBool(DirectFunctionCall2(timestamp_lt,
90 : : TimestampGetDatum(*aa),
91 : : TimestampGetDatum(*bb)));
92 : : }
93 : :
94 : : static int
3091 andrew@dunslane.net 95 : 4834 : gbt_tskey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
96 : : {
5109 peter_e@gmx.net 97 : 4834 : tsKEY *ia = (tsKEY *) (((const Nsrt *) a)->t);
98 : 4834 : tsKEY *ib = (tsKEY *) (((const Nsrt *) b)->t);
99 : : int res;
100 : :
24 tgl@sss.pgh.pa.us 101 :GNC 4834 : res = DatumGetInt32(DirectFunctionCall2(timestamp_cmp, TimestampGetDatum(ia->lower), TimestampGetDatum(ib->lower)));
5757 teodor@sigaev.ru 102 [ + + ]:CBC 4834 : if (res == 0)
24 tgl@sss.pgh.pa.us 103 :GNC 3747 : return DatumGetInt32(DirectFunctionCall2(timestamp_cmp, TimestampGetDatum(ia->upper), TimestampGetDatum(ib->upper)));
104 : :
5757 teodor@sigaev.ru 105 :CBC 1087 : return res;
106 : : }
107 : :
108 : : static float8
3091 andrew@dunslane.net 109 : 561 : gbt_ts_dist(const void *a, const void *b, FmgrInfo *flinfo)
110 : : {
5302 tgl@sss.pgh.pa.us 111 : 561 : const Timestamp *aa = (const Timestamp *) a;
112 : 561 : const Timestamp *bb = (const Timestamp *) b;
113 : : Interval *i;
114 : :
115 [ + - + - : 561 : if (TIMESTAMP_NOT_FINITE(*aa) || TIMESTAMP_NOT_FINITE(*bb))
+ + + + ]
116 : 20 : return get_float8_infinity();
117 : :
118 : 541 : i = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
119 : : TimestampGetDatum(*aa),
120 : : TimestampGetDatum(*bb)));
1065 peter@eisentraut.org 121 : 541 : return fabs(INTERVAL_TO_SEC(i));
122 : : }
123 : :
124 : : static const gbtree_ninfo tinfo =
125 : : {
126 : : gbt_t_ts,
127 : : sizeof(Timestamp),
128 : : 16, /* sizeof(gbtreekey16) */
129 : : gbt_tsgt,
130 : : gbt_tsge,
131 : : gbt_tseq,
132 : : gbt_tsle,
133 : : gbt_tslt,
134 : : gbt_tskey_cmp,
135 : : gbt_ts_dist
136 : : };
137 : :
138 : :
5302 tgl@sss.pgh.pa.us 139 : 4 : PG_FUNCTION_INFO_V1(ts_dist);
140 : : Datum
141 : 571 : ts_dist(PG_FUNCTION_ARGS)
142 : : {
143 : 571 : Timestamp a = PG_GETARG_TIMESTAMP(0);
144 : 571 : Timestamp b = PG_GETARG_TIMESTAMP(1);
145 : : Interval *r;
146 : :
147 [ + + + + : 571 : if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
+ - - + ]
148 : : {
5263 bruce@momjian.us 149 : 24 : Interval *p = palloc(sizeof(Interval));
150 : :
5302 tgl@sss.pgh.pa.us 151 : 24 : p->day = INT_MAX;
152 : 24 : p->month = INT_MAX;
3810 andres@anarazel.de 153 : 24 : p->time = PG_INT64_MAX;
5302 tgl@sss.pgh.pa.us 154 : 24 : PG_RETURN_INTERVAL_P(p);
155 : : }
156 : : else
5263 bruce@momjian.us 157 : 547 : r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
158 : : PG_GETARG_DATUM(0),
159 : : PG_GETARG_DATUM(1)));
160 : 547 : PG_RETURN_INTERVAL_P(abs_interval(r));
161 : : }
162 : :
5302 tgl@sss.pgh.pa.us 163 : 4 : PG_FUNCTION_INFO_V1(tstz_dist);
164 : : Datum
165 : 552 : tstz_dist(PG_FUNCTION_ARGS)
166 : : {
5263 bruce@momjian.us 167 : 552 : TimestampTz a = PG_GETARG_TIMESTAMPTZ(0);
168 : 552 : TimestampTz b = PG_GETARG_TIMESTAMPTZ(1);
169 : : Interval *r;
170 : :
5302 tgl@sss.pgh.pa.us 171 [ + + + + : 552 : if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
+ - - + ]
172 : : {
5263 bruce@momjian.us 173 : 18 : Interval *p = palloc(sizeof(Interval));
174 : :
5302 tgl@sss.pgh.pa.us 175 : 18 : p->day = INT_MAX;
176 : 18 : p->month = INT_MAX;
3810 andres@anarazel.de 177 : 18 : p->time = PG_INT64_MAX;
5302 tgl@sss.pgh.pa.us 178 : 18 : PG_RETURN_INTERVAL_P(p);
179 : : }
180 : :
181 : 534 : r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
182 : : PG_GETARG_DATUM(0),
183 : : PG_GETARG_DATUM(1)));
5263 bruce@momjian.us 184 : 534 : PG_RETURN_INTERVAL_P(abs_interval(r));
185 : : }
186 : :
187 : : /**************************************************
188 : : * GiST support functions
189 : : **************************************************/
190 : :
191 : : static inline Timestamp
6347 tgl@sss.pgh.pa.us 192 : 6625 : tstz_to_ts_gmt(TimestampTz ts)
193 : : {
194 : : /* No timezone correction is needed, since GMT is offset 0 by definition */
3978 195 : 6625 : return (Timestamp) ts;
196 : : }
197 : :
198 : :
199 : : Datum
7771 teodor@sigaev.ru 200 : 2612 : gbt_ts_compress(PG_FUNCTION_ARGS)
201 : : {
7678 bruce@momjian.us 202 : 2612 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
203 : :
3817 heikki.linnakangas@i 204 : 2612 : PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
205 : : }
206 : :
207 : : Datum
7771 teodor@sigaev.ru 208 : 551 : gbt_tstz_compress(PG_FUNCTION_ARGS)
209 : : {
7678 bruce@momjian.us 210 : 551 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
211 : : GISTENTRY *retval;
212 : :
213 [ + + ]: 551 : if (entry->leafkey)
214 : : {
215 : 549 : tsKEY *r = (tsKEY *) palloc(sizeof(tsKEY));
6347 tgl@sss.pgh.pa.us 216 : 549 : TimestampTz ts = DatumGetTimestampTz(entry->key);
217 : : Timestamp gmt;
218 : :
219 : 549 : gmt = tstz_to_ts_gmt(ts);
220 : :
7678 bruce@momjian.us 221 : 549 : retval = palloc(sizeof(GISTENTRY));
222 : 549 : r->lower = r->upper = gmt;
223 : 549 : gistentryinit(*retval, PointerGetDatum(r),
224 : : entry->rel, entry->page,
225 : : entry->offset, false);
226 : : }
227 : : else
228 : 2 : retval = entry;
229 : :
230 : 551 : PG_RETURN_POINTER(retval);
231 : : }
232 : :
233 : : Datum
3816 heikki.linnakangas@i 234 : 559 : gbt_ts_fetch(PG_FUNCTION_ARGS)
235 : : {
236 : 559 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
237 : :
238 : 559 : PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
239 : : }
240 : :
241 : : Datum
7771 teodor@sigaev.ru 242 : 2204 : gbt_ts_consistent(PG_FUNCTION_ARGS)
243 : : {
7678 bruce@momjian.us 244 : 2204 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
6347 tgl@sss.pgh.pa.us 245 : 2204 : Timestamp query = PG_GETARG_TIMESTAMP(1);
6354 246 : 2204 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
247 : :
248 : : /* Oid subtype = PG_GETARG_OID(3); */
249 : 2204 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
7678 bruce@momjian.us 250 : 2204 : tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key);
251 : : GBT_NUMKEY_R key;
252 : :
253 : : /* All cases served by this function are exact */
6354 tgl@sss.pgh.pa.us 254 : 2204 : *recheck = false;
255 : :
5931 bruce@momjian.us 256 : 2204 : key.lower = (GBT_NUMKEY *) &kkk->lower;
257 : 2204 : key.upper = (GBT_NUMKEY *) &kkk->upper;
258 : :
282 peter@eisentraut.org 259 : 2204 : PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
260 : : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
261 : : }
262 : :
263 : : Datum
5302 tgl@sss.pgh.pa.us 264 : 286 : gbt_ts_distance(PG_FUNCTION_ARGS)
265 : : {
266 : 286 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
267 : 286 : Timestamp query = PG_GETARG_TIMESTAMP(1);
268 : :
269 : : /* Oid subtype = PG_GETARG_OID(3); */
270 : 286 : tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key);
271 : : GBT_NUMKEY_R key;
272 : :
273 : 286 : key.lower = (GBT_NUMKEY *) &kkk->lower;
274 : 286 : key.upper = (GBT_NUMKEY *) &kkk->upper;
275 : :
282 peter@eisentraut.org 276 : 286 : PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
277 : : &tinfo, fcinfo->flinfo));
278 : : }
279 : :
280 : : Datum
7771 teodor@sigaev.ru 281 : 5799 : gbt_tstz_consistent(PG_FUNCTION_ARGS)
282 : : {
7678 bruce@momjian.us 283 : 5799 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
5931 284 : 5799 : TimestampTz query = PG_GETARG_TIMESTAMPTZ(1);
6354 tgl@sss.pgh.pa.us 285 : 5799 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
286 : :
287 : : /* Oid subtype = PG_GETARG_OID(3); */
288 : 5799 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
7678 bruce@momjian.us 289 : 5799 : char *kkk = (char *) DatumGetPointer(entry->key);
290 : : GBT_NUMKEY_R key;
291 : : Timestamp qqq;
292 : :
293 : : /* All cases served by this function are exact */
6354 tgl@sss.pgh.pa.us 294 : 5799 : *recheck = false;
295 : :
5931 bruce@momjian.us 296 : 5799 : key.lower = (GBT_NUMKEY *) &kkk[0];
297 : 5799 : key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)];
6347 tgl@sss.pgh.pa.us 298 : 5799 : qqq = tstz_to_ts_gmt(query);
299 : :
282 peter@eisentraut.org 300 : 5799 : PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy,
301 : : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
302 : : }
303 : :
304 : : Datum
5302 tgl@sss.pgh.pa.us 305 : 277 : gbt_tstz_distance(PG_FUNCTION_ARGS)
306 : : {
307 : 277 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
308 : 277 : TimestampTz query = PG_GETARG_TIMESTAMPTZ(1);
309 : :
310 : : /* Oid subtype = PG_GETARG_OID(3); */
311 : 277 : char *kkk = (char *) DatumGetPointer(entry->key);
312 : : GBT_NUMKEY_R key;
313 : : Timestamp qqq;
314 : :
315 : 277 : key.lower = (GBT_NUMKEY *) &kkk[0];
316 : 277 : key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)];
317 : 277 : qqq = tstz_to_ts_gmt(query);
318 : :
282 peter@eisentraut.org 319 : 277 : PG_RETURN_FLOAT8(gbt_num_distance(&key, &qqq, GIST_LEAF(entry),
320 : : &tinfo, fcinfo->flinfo));
321 : : }
322 : :
323 : :
324 : : Datum
7771 teodor@sigaev.ru 325 : 1858 : gbt_ts_union(PG_FUNCTION_ARGS)
326 : : {
7678 bruce@momjian.us 327 : 1858 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
328 : 1858 : void *out = palloc(sizeof(tsKEY));
329 : :
330 : 1858 : *(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY);
282 peter@eisentraut.org 331 : 1858 : PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
332 : : }
333 : :
334 : :
335 : : #define penalty_check_max_float(val) \
336 : : do { \
337 : : if ( val > FLT_MAX ) \
338 : : val = FLT_MAX; \
339 : : if ( val < -FLT_MAX ) \
340 : : val = -FLT_MAX; \
341 : : } while (0)
342 : :
343 : :
344 : : Datum
7771 teodor@sigaev.ru 345 : 4077 : gbt_ts_penalty(PG_FUNCTION_ARGS)
346 : : {
7678 bruce@momjian.us 347 : 4077 : tsKEY *origentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
348 : 4077 : tsKEY *newentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
349 : 4077 : float *result = (float *) PG_GETARG_POINTER(2);
350 : :
351 : : double orgdbl[2],
352 : : newdbl[2];
353 : :
354 : : /*
355 : : * We are always using "double" timestamps here. Precision should be good
356 : : * enough.
357 : : */
7266 358 : 4077 : orgdbl[0] = ((double) origentry->lower);
359 : 4077 : orgdbl[1] = ((double) origentry->upper);
360 : 4077 : newdbl[0] = ((double) newentry->lower);
361 : 4077 : newdbl[1] = ((double) newentry->upper);
362 : :
363 [ - + - + ]: 4077 : penalty_check_max_float(orgdbl[0]);
364 [ - + - + ]: 4077 : penalty_check_max_float(orgdbl[1]);
365 [ - + - + ]: 4077 : penalty_check_max_float(newdbl[0]);
366 [ - + - + ]: 4077 : penalty_check_max_float(newdbl[1]);
367 : :
368 [ + + + + : 4077 : penalty_num(result, orgdbl[0], orgdbl[1], newdbl[0], newdbl[1]);
+ + ]
369 : :
7678 370 : 4077 : PG_RETURN_POINTER(result);
371 : : }
372 : :
373 : :
374 : : Datum
7771 teodor@sigaev.ru 375 : 21 : gbt_ts_picksplit(PG_FUNCTION_ARGS)
376 : : {
2046 alvherre@alvh.no-ip. 377 : 21 : PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
378 : : (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
379 : : &tinfo, fcinfo->flinfo));
380 : : }
381 : :
382 : : Datum
7771 teodor@sigaev.ru 383 : 1835 : gbt_ts_same(PG_FUNCTION_ARGS)
384 : : {
7678 bruce@momjian.us 385 : 1835 : tsKEY *b1 = (tsKEY *) PG_GETARG_POINTER(0);
386 : 1835 : tsKEY *b2 = (tsKEY *) PG_GETARG_POINTER(1);
387 : 1835 : bool *result = (bool *) PG_GETARG_POINTER(2);
388 : :
3091 andrew@dunslane.net 389 : 1835 : *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
7678 bruce@momjian.us 390 : 1835 : PG_RETURN_POINTER(result);
391 : : }
392 : :
393 : : static int
156 heikki.linnakangas@i 394 : 11115 : gbt_ts_ssup_cmp(Datum x, Datum y, SortSupport ssup)
395 : : {
396 : 11115 : tsKEY *arg1 = (tsKEY *) DatumGetPointer(x);
397 : 11115 : tsKEY *arg2 = (tsKEY *) DatumGetPointer(y);
398 : :
399 : : /* for leaf items we expect lower == upper, so only compare lower */
400 : 11115 : return DatumGetInt32(DirectFunctionCall2(timestamp_cmp,
401 : : TimestampGetDatum(arg1->lower),
402 : : TimestampGetDatum(arg2->lower)));
403 : : }
404 : :
405 : : Datum
406 : 3 : gbt_ts_sortsupport(PG_FUNCTION_ARGS)
407 : : {
408 : 3 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
409 : :
410 : 3 : ssup->comparator = gbt_ts_ssup_cmp;
411 : 3 : ssup->ssup_extra = NULL;
412 : :
413 : 3 : PG_RETURN_VOID();
414 : : }
|