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 */
7961 teodor@sigaev.ru 23 :CBC 5 : PG_FUNCTION_INFO_V1(gbt_ts_compress);
24 : 4 : PG_FUNCTION_INFO_V1(gbt_tstz_compress);
4006 heikki.linnakangas@i 25 : 6 : PG_FUNCTION_INFO_V1(gbt_ts_fetch);
7961 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);
5492 tgl@sss.pgh.pa.us 29 : 5 : PG_FUNCTION_INFO_V1(gbt_ts_distance);
7961 teodor@sigaev.ru 30 : 4 : PG_FUNCTION_INFO_V1(gbt_tstz_consistent);
5492 tgl@sss.pgh.pa.us 31 : 4 : PG_FUNCTION_INFO_V1(gbt_tstz_distance);
7961 teodor@sigaev.ru 32 : 6 : PG_FUNCTION_INFO_V1(gbt_ts_penalty);
33 : 6 : PG_FUNCTION_INFO_V1(gbt_ts_same);
346 heikki.linnakangas@i 34 : 6 : PG_FUNCTION_INFO_V1(gbt_ts_sortsupport);
35 : :
36 : :
37 : : /* define for comparison */
38 : :
39 : : static bool
3281 andrew@dunslane.net 40 : 12969 : gbt_tsgt(const void *a, const void *b, FmgrInfo *flinfo)
41 : : {
6537 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
3281 andrew@dunslane.net 51 : 2345 : gbt_tsge(const void *a, const void *b, FmgrInfo *flinfo)
52 : : {
6537 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
3281 andrew@dunslane.net 62 : 5185 : gbt_tseq(const void *a, const void *b, FmgrInfo *flinfo)
63 : : {
6537 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
3281 andrew@dunslane.net 73 : 1987 : gbt_tsle(const void *a, const void *b, FmgrInfo *flinfo)
74 : : {
6537 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
3281 andrew@dunslane.net 84 : 12431 : gbt_tslt(const void *a, const void *b, FmgrInfo *flinfo)
85 : : {
6537 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
3281 andrew@dunslane.net 95 : 4826 : gbt_tskey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
96 : : {
5299 peter_e@gmx.net 97 : 4826 : tsKEY *ia = (tsKEY *) (((const Nsrt *) a)->t);
98 : 4826 : tsKEY *ib = (tsKEY *) (((const Nsrt *) b)->t);
99 : : int res;
100 : :
214 tgl@sss.pgh.pa.us 101 :GNC 4826 : res = DatumGetInt32(DirectFunctionCall2(timestamp_cmp, TimestampGetDatum(ia->lower), TimestampGetDatum(ib->lower)));
5947 teodor@sigaev.ru 102 [ + + ]:CBC 4826 : if (res == 0)
214 tgl@sss.pgh.pa.us 103 :GNC 3739 : return DatumGetInt32(DirectFunctionCall2(timestamp_cmp, TimestampGetDatum(ia->upper), TimestampGetDatum(ib->upper)));
104 : :
5947 teodor@sigaev.ru 105 :CBC 1087 : return res;
106 : : }
107 : :
108 : : static float8
3281 andrew@dunslane.net 109 : 561 : gbt_ts_dist(const void *a, const void *b, FmgrInfo *flinfo)
110 : : {
5492 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)));
1255 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 : :
5492 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 : : {
100 michael@paquier.xyz 149 :GNC 24 : Interval *p = palloc_object(Interval);
150 : :
5492 tgl@sss.pgh.pa.us 151 :CBC 24 : p->day = INT_MAX;
152 : 24 : p->month = INT_MAX;
4000 andres@anarazel.de 153 : 24 : p->time = PG_INT64_MAX;
5492 tgl@sss.pgh.pa.us 154 : 24 : PG_RETURN_INTERVAL_P(p);
155 : : }
156 : : else
5453 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 : :
5492 tgl@sss.pgh.pa.us 163 : 4 : PG_FUNCTION_INFO_V1(tstz_dist);
164 : : Datum
165 : 552 : tstz_dist(PG_FUNCTION_ARGS)
166 : : {
5453 bruce@momjian.us 167 : 552 : TimestampTz a = PG_GETARG_TIMESTAMPTZ(0);
168 : 552 : TimestampTz b = PG_GETARG_TIMESTAMPTZ(1);
169 : : Interval *r;
170 : :
5492 tgl@sss.pgh.pa.us 171 [ + + + + : 552 : if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
+ - - + ]
172 : : {
100 michael@paquier.xyz 173 :GNC 18 : Interval *p = palloc_object(Interval);
174 : :
5492 tgl@sss.pgh.pa.us 175 :CBC 18 : p->day = INT_MAX;
176 : 18 : p->month = INT_MAX;
4000 andres@anarazel.de 177 : 18 : p->time = PG_INT64_MAX;
5492 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)));
5453 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
6537 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 */
4168 195 : 6625 : return (Timestamp) ts;
196 : : }
197 : :
198 : :
199 : : Datum
7961 teodor@sigaev.ru 200 : 2612 : gbt_ts_compress(PG_FUNCTION_ARGS)
201 : : {
7868 bruce@momjian.us 202 : 2612 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
203 : :
4007 heikki.linnakangas@i 204 : 2612 : PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
205 : : }
206 : :
207 : : Datum
7961 teodor@sigaev.ru 208 : 551 : gbt_tstz_compress(PG_FUNCTION_ARGS)
209 : : {
7868 bruce@momjian.us 210 : 551 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
211 : : GISTENTRY *retval;
212 : :
213 [ + + ]: 551 : if (entry->leafkey)
214 : : {
100 michael@paquier.xyz 215 :GNC 549 : tsKEY *r = palloc_object(tsKEY);
6537 tgl@sss.pgh.pa.us 216 :CBC 549 : TimestampTz ts = DatumGetTimestampTz(entry->key);
217 : : Timestamp gmt;
218 : :
219 : 549 : gmt = tstz_to_ts_gmt(ts);
220 : :
100 michael@paquier.xyz 221 :GNC 549 : retval = palloc_object(GISTENTRY);
7868 bruce@momjian.us 222 :CBC 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
4006 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
7961 teodor@sigaev.ru 242 : 2204 : gbt_ts_consistent(PG_FUNCTION_ARGS)
243 : : {
7868 bruce@momjian.us 244 : 2204 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
6537 tgl@sss.pgh.pa.us 245 : 2204 : Timestamp query = PG_GETARG_TIMESTAMP(1);
6544 246 : 2204 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
247 : : #ifdef NOT_USED
248 : : Oid subtype = PG_GETARG_OID(3);
249 : : #endif
250 : 2204 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
7868 bruce@momjian.us 251 : 2204 : tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key);
252 : : GBT_NUMKEY_R key;
253 : :
254 : : /* All cases served by this function are exact */
6544 tgl@sss.pgh.pa.us 255 : 2204 : *recheck = false;
256 : :
6121 bruce@momjian.us 257 : 2204 : key.lower = (GBT_NUMKEY *) &kkk->lower;
258 : 2204 : key.upper = (GBT_NUMKEY *) &kkk->upper;
259 : :
472 peter@eisentraut.org 260 : 2204 : PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
261 : : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
262 : : }
263 : :
264 : : Datum
5492 tgl@sss.pgh.pa.us 265 : 286 : gbt_ts_distance(PG_FUNCTION_ARGS)
266 : : {
267 : 286 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
268 : 286 : Timestamp query = PG_GETARG_TIMESTAMP(1);
269 : : #ifdef NOT_USED
270 : : Oid subtype = PG_GETARG_OID(3);
271 : : #endif
272 : 286 : tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key);
273 : : GBT_NUMKEY_R key;
274 : :
275 : 286 : key.lower = (GBT_NUMKEY *) &kkk->lower;
276 : 286 : key.upper = (GBT_NUMKEY *) &kkk->upper;
277 : :
472 peter@eisentraut.org 278 : 286 : PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
279 : : &tinfo, fcinfo->flinfo));
280 : : }
281 : :
282 : : Datum
7961 teodor@sigaev.ru 283 : 5799 : gbt_tstz_consistent(PG_FUNCTION_ARGS)
284 : : {
7868 bruce@momjian.us 285 : 5799 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
6121 286 : 5799 : TimestampTz query = PG_GETARG_TIMESTAMPTZ(1);
6544 tgl@sss.pgh.pa.us 287 : 5799 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
288 : : #ifdef NOT_USED
289 : : Oid subtype = PG_GETARG_OID(3);
290 : : #endif
291 : 5799 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
7868 bruce@momjian.us 292 : 5799 : char *kkk = (char *) DatumGetPointer(entry->key);
293 : : GBT_NUMKEY_R key;
294 : : Timestamp qqq;
295 : :
296 : : /* All cases served by this function are exact */
6544 tgl@sss.pgh.pa.us 297 : 5799 : *recheck = false;
298 : :
6121 bruce@momjian.us 299 : 5799 : key.lower = (GBT_NUMKEY *) &kkk[0];
300 : 5799 : key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)];
6537 tgl@sss.pgh.pa.us 301 : 5799 : qqq = tstz_to_ts_gmt(query);
302 : :
472 peter@eisentraut.org 303 : 5799 : PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy,
304 : : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
305 : : }
306 : :
307 : : Datum
5492 tgl@sss.pgh.pa.us 308 : 277 : gbt_tstz_distance(PG_FUNCTION_ARGS)
309 : : {
310 : 277 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
311 : 277 : TimestampTz query = PG_GETARG_TIMESTAMPTZ(1);
312 : : #ifdef NOT_USED
313 : : Oid subtype = PG_GETARG_OID(3);
314 : : #endif
315 : 277 : char *kkk = (char *) DatumGetPointer(entry->key);
316 : : GBT_NUMKEY_R key;
317 : : Timestamp qqq;
318 : :
319 : 277 : key.lower = (GBT_NUMKEY *) &kkk[0];
320 : 277 : key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)];
321 : 277 : qqq = tstz_to_ts_gmt(query);
322 : :
472 peter@eisentraut.org 323 : 277 : PG_RETURN_FLOAT8(gbt_num_distance(&key, &qqq, GIST_LEAF(entry),
324 : : &tinfo, fcinfo->flinfo));
325 : : }
326 : :
327 : :
328 : : Datum
7961 teodor@sigaev.ru 329 : 1858 : gbt_ts_union(PG_FUNCTION_ARGS)
330 : : {
7868 bruce@momjian.us 331 : 1858 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
332 : 1858 : void *out = palloc(sizeof(tsKEY));
333 : :
334 : 1858 : *(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY);
472 peter@eisentraut.org 335 : 1858 : PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
336 : : }
337 : :
338 : :
339 : : #define penalty_check_max_float(val) \
340 : : do { \
341 : : if ( val > FLT_MAX ) \
342 : : val = FLT_MAX; \
343 : : if ( val < -FLT_MAX ) \
344 : : val = -FLT_MAX; \
345 : : } while (0)
346 : :
347 : :
348 : : Datum
7961 teodor@sigaev.ru 349 : 4063 : gbt_ts_penalty(PG_FUNCTION_ARGS)
350 : : {
7868 bruce@momjian.us 351 : 4063 : tsKEY *origentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
352 : 4063 : tsKEY *newentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
353 : 4063 : float *result = (float *) PG_GETARG_POINTER(2);
354 : :
355 : : double orgdbl[2],
356 : : newdbl[2];
357 : :
358 : : /*
359 : : * We are always using "double" timestamps here. Precision should be good
360 : : * enough.
361 : : */
7456 362 : 4063 : orgdbl[0] = ((double) origentry->lower);
363 : 4063 : orgdbl[1] = ((double) origentry->upper);
364 : 4063 : newdbl[0] = ((double) newentry->lower);
365 : 4063 : newdbl[1] = ((double) newentry->upper);
366 : :
367 [ - + - + ]: 4063 : penalty_check_max_float(orgdbl[0]);
368 [ - + - + ]: 4063 : penalty_check_max_float(orgdbl[1]);
369 [ - + - + ]: 4063 : penalty_check_max_float(newdbl[0]);
370 [ - + - + ]: 4063 : penalty_check_max_float(newdbl[1]);
371 : :
372 [ + + + + : 4063 : penalty_num(result, orgdbl[0], orgdbl[1], newdbl[0], newdbl[1]);
+ + ]
373 : :
7868 374 : 4063 : PG_RETURN_POINTER(result);
375 : : }
376 : :
377 : :
378 : : Datum
7961 teodor@sigaev.ru 379 : 21 : gbt_ts_picksplit(PG_FUNCTION_ARGS)
380 : : {
2236 alvherre@alvh.no-ip. 381 : 21 : PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
382 : : (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
383 : : &tinfo, fcinfo->flinfo));
384 : : }
385 : :
386 : : Datum
7961 teodor@sigaev.ru 387 : 1835 : gbt_ts_same(PG_FUNCTION_ARGS)
388 : : {
7868 bruce@momjian.us 389 : 1835 : tsKEY *b1 = (tsKEY *) PG_GETARG_POINTER(0);
390 : 1835 : tsKEY *b2 = (tsKEY *) PG_GETARG_POINTER(1);
391 : 1835 : bool *result = (bool *) PG_GETARG_POINTER(2);
392 : :
3281 andrew@dunslane.net 393 : 1835 : *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
7868 bruce@momjian.us 394 : 1835 : PG_RETURN_POINTER(result);
395 : : }
396 : :
397 : : static int
346 heikki.linnakangas@i 398 : 11115 : gbt_ts_ssup_cmp(Datum x, Datum y, SortSupport ssup)
399 : : {
400 : 11115 : tsKEY *arg1 = (tsKEY *) DatumGetPointer(x);
401 : 11115 : tsKEY *arg2 = (tsKEY *) DatumGetPointer(y);
402 : :
403 : : /* for leaf items we expect lower == upper, so only compare lower */
404 : 11115 : return DatumGetInt32(DirectFunctionCall2(timestamp_cmp,
405 : : TimestampGetDatum(arg1->lower),
406 : : TimestampGetDatum(arg2->lower)));
407 : : }
408 : :
409 : : Datum
410 : 3 : gbt_ts_sortsupport(PG_FUNCTION_ARGS)
411 : : {
412 : 3 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
413 : :
414 : 3 : ssup->comparator = gbt_ts_ssup_cmp;
415 : 3 : ssup->ssup_extra = NULL;
416 : :
417 : 3 : PG_RETURN_VOID();
418 : : }
|