Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * contrib/btree_gist/btree_time.c
3 : : */
4 : : #include "postgres.h"
5 : :
6 : : #include "btree_gist.h"
7 : : #include "btree_utils_num.h"
8 : : #include "utils/fmgrprotos.h"
9 : : #include "utils/date.h"
10 : : #include "utils/rel.h"
11 : : #include "utils/sortsupport.h"
12 : : #include "utils/timestamp.h"
13 : :
14 : : typedef struct
15 : : {
16 : : TimeADT lower;
17 : : TimeADT upper;
18 : : } timeKEY;
19 : :
20 : : /* GiST support functions */
7771 teodor@sigaev.ru 21 :CBC 4 : PG_FUNCTION_INFO_V1(gbt_time_compress);
22 : 4 : PG_FUNCTION_INFO_V1(gbt_timetz_compress);
3816 heikki.linnakangas@i 23 : 4 : PG_FUNCTION_INFO_V1(gbt_time_fetch);
7771 teodor@sigaev.ru 24 : 5 : PG_FUNCTION_INFO_V1(gbt_time_union);
25 : 5 : PG_FUNCTION_INFO_V1(gbt_time_picksplit);
26 : 4 : PG_FUNCTION_INFO_V1(gbt_time_consistent);
5302 tgl@sss.pgh.pa.us 27 : 4 : PG_FUNCTION_INFO_V1(gbt_time_distance);
7771 teodor@sigaev.ru 28 : 4 : PG_FUNCTION_INFO_V1(gbt_timetz_consistent);
29 : 5 : PG_FUNCTION_INFO_V1(gbt_time_penalty);
30 : 5 : PG_FUNCTION_INFO_V1(gbt_time_same);
156 heikki.linnakangas@i 31 : 5 : PG_FUNCTION_INFO_V1(gbt_time_sortsupport);
156 heikki.linnakangas@i 32 :UBC 0 : PG_FUNCTION_INFO_V1(gbt_timetz_sortsupport);
33 : :
34 : :
35 : : static bool
3091 andrew@dunslane.net 36 :CBC 3211 : gbt_timegt(const void *a, const void *b, FmgrInfo *flinfo)
37 : : {
6347 tgl@sss.pgh.pa.us 38 : 3211 : const TimeADT *aa = (const TimeADT *) a;
39 : 3211 : const TimeADT *bb = (const TimeADT *) b;
40 : :
41 : 3211 : return DatumGetBool(DirectFunctionCall2(time_gt,
42 : : TimeADTGetDatum(*aa),
43 : : TimeADTGetDatum(*bb)));
44 : : }
45 : :
46 : : static bool
3091 andrew@dunslane.net 47 : 1335 : gbt_timege(const void *a, const void *b, FmgrInfo *flinfo)
48 : : {
6347 tgl@sss.pgh.pa.us 49 : 1335 : const TimeADT *aa = (const TimeADT *) a;
50 : 1335 : const TimeADT *bb = (const TimeADT *) b;
51 : :
52 : 1335 : return DatumGetBool(DirectFunctionCall2(time_ge,
53 : : TimeADTGetDatum(*aa),
54 : : TimeADTGetDatum(*bb)));
55 : : }
56 : :
57 : : static bool
3091 andrew@dunslane.net 58 : 1067 : gbt_timeeq(const void *a, const void *b, FmgrInfo *flinfo)
59 : : {
6347 tgl@sss.pgh.pa.us 60 : 1067 : const TimeADT *aa = (const TimeADT *) a;
61 : 1067 : const TimeADT *bb = (const TimeADT *) b;
62 : :
63 : 1067 : return DatumGetBool(DirectFunctionCall2(time_eq,
64 : : TimeADTGetDatum(*aa),
65 : : TimeADTGetDatum(*bb)));
66 : : }
67 : :
68 : : static bool
3091 andrew@dunslane.net 69 : 2439 : gbt_timele(const void *a, const void *b, FmgrInfo *flinfo)
70 : : {
6347 tgl@sss.pgh.pa.us 71 : 2439 : const TimeADT *aa = (const TimeADT *) a;
72 : 2439 : const TimeADT *bb = (const TimeADT *) b;
73 : :
74 : 2439 : return DatumGetBool(DirectFunctionCall2(time_le,
75 : : TimeADTGetDatum(*aa),
76 : : TimeADTGetDatum(*bb)));
77 : : }
78 : :
79 : : static bool
3091 andrew@dunslane.net 80 : 4281 : gbt_timelt(const void *a, const void *b, FmgrInfo *flinfo)
81 : : {
6347 tgl@sss.pgh.pa.us 82 : 4281 : const TimeADT *aa = (const TimeADT *) a;
83 : 4281 : const TimeADT *bb = (const TimeADT *) b;
84 : :
85 : 4281 : return DatumGetBool(DirectFunctionCall2(time_lt,
86 : : TimeADTGetDatum(*aa),
87 : : TimeADTGetDatum(*bb)));
88 : : }
89 : :
90 : : static int
3091 andrew@dunslane.net 91 : 1073 : gbt_timekey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
92 : : {
5109 peter_e@gmx.net 93 : 1073 : timeKEY *ia = (timeKEY *) (((const Nsrt *) a)->t);
94 : 1073 : timeKEY *ib = (timeKEY *) (((const Nsrt *) b)->t);
95 : : int res;
96 : :
24 tgl@sss.pgh.pa.us 97 :GNC 1073 : res = DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatum(ia->lower), TimeADTGetDatum(ib->lower)));
5757 teodor@sigaev.ru 98 [ + + ]:CBC 1073 : if (res == 0)
24 tgl@sss.pgh.pa.us 99 :GNC 1 : return DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatum(ia->upper), TimeADTGetDatum(ib->upper)));
100 : :
5757 teodor@sigaev.ru 101 :CBC 1072 : return res;
102 : : }
103 : :
104 : : static float8
3091 andrew@dunslane.net 105 : 273 : gbt_time_dist(const void *a, const void *b, FmgrInfo *flinfo)
106 : : {
5302 tgl@sss.pgh.pa.us 107 : 273 : const TimeADT *aa = (const TimeADT *) a;
108 : 273 : const TimeADT *bb = (const TimeADT *) b;
109 : : Interval *i;
110 : :
111 : 273 : i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
112 : : TimeADTGetDatum(*aa),
113 : : TimeADTGetDatum(*bb)));
1065 peter@eisentraut.org 114 : 273 : return fabs(INTERVAL_TO_SEC(i));
115 : : }
116 : :
117 : :
118 : : static const gbtree_ninfo tinfo =
119 : : {
120 : : gbt_t_time,
121 : : sizeof(TimeADT),
122 : : 16, /* sizeof(gbtreekey16) */
123 : : gbt_timegt,
124 : : gbt_timege,
125 : : gbt_timeeq,
126 : : gbt_timele,
127 : : gbt_timelt,
128 : : gbt_timekey_cmp,
129 : : gbt_time_dist
130 : : };
131 : :
132 : :
5302 tgl@sss.pgh.pa.us 133 : 4 : PG_FUNCTION_INFO_V1(time_dist);
134 : : Datum
135 : 547 : time_dist(PG_FUNCTION_ARGS)
136 : : {
137 : 547 : Datum diff = DirectFunctionCall2(time_mi_time,
138 : : PG_GETARG_DATUM(0),
139 : : PG_GETARG_DATUM(1));
140 : :
141 : 547 : PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
142 : : }
143 : :
144 : :
145 : : /**************************************************
146 : : * GiST support functions
147 : : **************************************************/
148 : :
149 : : Datum
7771 teodor@sigaev.ru 150 : 546 : gbt_time_compress(PG_FUNCTION_ARGS)
151 : : {
7678 bruce@momjian.us 152 : 546 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
153 : :
3817 heikki.linnakangas@i 154 : 546 : PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
155 : : }
156 : :
157 : : Datum
7771 teodor@sigaev.ru 158 : 533 : gbt_timetz_compress(PG_FUNCTION_ARGS)
159 : : {
7678 bruce@momjian.us 160 : 533 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
161 : : GISTENTRY *retval;
162 : :
163 [ + + ]: 533 : if (entry->leafkey)
164 : : {
165 : 531 : timeKEY *r = (timeKEY *) palloc(sizeof(timeKEY));
166 : 531 : TimeTzADT *tz = DatumGetTimeTzADTP(entry->key);
167 : : TimeADT tmp;
168 : :
169 : 531 : retval = palloc(sizeof(GISTENTRY));
170 : :
171 : : /* We are using the time + zone only to compress */
7439 tgl@sss.pgh.pa.us 172 : 531 : tmp = tz->time + (tz->zone * INT64CONST(1000000));
173 : 531 : r->lower = r->upper = tmp;
7678 bruce@momjian.us 174 : 531 : gistentryinit(*retval, PointerGetDatum(r),
175 : : entry->rel, entry->page,
176 : : entry->offset, false);
177 : : }
178 : : else
179 : 2 : retval = entry;
180 : 533 : PG_RETURN_POINTER(retval);
181 : : }
182 : :
183 : : Datum
3816 heikki.linnakangas@i 184 : 272 : gbt_time_fetch(PG_FUNCTION_ARGS)
185 : : {
186 : 272 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
187 : :
188 : 272 : PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
189 : : }
190 : :
191 : : Datum
7771 teodor@sigaev.ru 192 : 1914 : gbt_time_consistent(PG_FUNCTION_ARGS)
193 : : {
7678 bruce@momjian.us 194 : 1914 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
195 : 1914 : TimeADT query = PG_GETARG_TIMEADT(1);
6354 tgl@sss.pgh.pa.us 196 : 1914 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
197 : :
198 : : /* Oid subtype = PG_GETARG_OID(3); */
199 : 1914 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
7678 bruce@momjian.us 200 : 1914 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
201 : : GBT_NUMKEY_R key;
202 : :
203 : : /* All cases served by this function are exact */
6354 tgl@sss.pgh.pa.us 204 : 1914 : *recheck = false;
205 : :
5931 bruce@momjian.us 206 : 1914 : key.lower = (GBT_NUMKEY *) &kkk->lower;
207 : 1914 : key.upper = (GBT_NUMKEY *) &kkk->upper;
208 : :
282 peter@eisentraut.org 209 : 1914 : PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
210 : : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
211 : : }
212 : :
213 : : Datum
5302 tgl@sss.pgh.pa.us 214 : 274 : gbt_time_distance(PG_FUNCTION_ARGS)
215 : : {
216 : 274 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
217 : 274 : TimeADT query = PG_GETARG_TIMEADT(1);
218 : :
219 : : /* Oid subtype = PG_GETARG_OID(3); */
220 : 274 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
221 : : GBT_NUMKEY_R key;
222 : :
223 : 274 : key.lower = (GBT_NUMKEY *) &kkk->lower;
224 : 274 : key.upper = (GBT_NUMKEY *) &kkk->upper;
225 : :
282 peter@eisentraut.org 226 : 274 : PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
227 : : &tinfo, fcinfo->flinfo));
228 : : }
229 : :
230 : : Datum
7771 teodor@sigaev.ru 231 : 5601 : gbt_timetz_consistent(PG_FUNCTION_ARGS)
232 : : {
7678 bruce@momjian.us 233 : 5601 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
234 : 5601 : TimeTzADT *query = PG_GETARG_TIMETZADT_P(1);
7439 tgl@sss.pgh.pa.us 235 : 5601 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
236 : :
237 : : /* Oid subtype = PG_GETARG_OID(3); */
6354 238 : 5601 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
7678 bruce@momjian.us 239 : 5601 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
240 : : TimeADT qqq;
241 : : GBT_NUMKEY_R key;
242 : :
243 : : /* All cases served by this function are inexact */
6354 tgl@sss.pgh.pa.us 244 : 5601 : *recheck = true;
245 : :
7439 246 : 5601 : qqq = query->time + (query->zone * INT64CONST(1000000));
247 : :
5931 bruce@momjian.us 248 : 5601 : key.lower = (GBT_NUMKEY *) &kkk->lower;
249 : 5601 : key.upper = (GBT_NUMKEY *) &kkk->upper;
250 : :
282 peter@eisentraut.org 251 : 5601 : PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy,
252 : : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
253 : : }
254 : :
255 : : Datum
7771 teodor@sigaev.ru 256 : 2 : gbt_time_union(PG_FUNCTION_ARGS)
257 : : {
7678 bruce@momjian.us 258 : 2 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
259 : 2 : void *out = palloc(sizeof(timeKEY));
260 : :
261 : 2 : *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
282 peter@eisentraut.org 262 : 2 : PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
263 : : }
264 : :
265 : : Datum
7771 teodor@sigaev.ru 266 :UBC 0 : gbt_time_penalty(PG_FUNCTION_ARGS)
267 : : {
7678 bruce@momjian.us 268 : 0 : timeKEY *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
269 : 0 : timeKEY *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
270 : 0 : float *result = (float *) PG_GETARG_POINTER(2);
271 : : Interval *intr;
272 : : double res;
273 : : double res2;
274 : :
2046 alvherre@alvh.no-ip. 275 : 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
276 : : TimeADTGetDatum(newentry->upper),
277 : : TimeADTGetDatum(origentry->upper)));
7352 tgl@sss.pgh.pa.us 278 : 0 : res = INTERVAL_TO_SEC(intr);
279 [ # # ]: 0 : res = Max(res, 0);
280 : :
2046 alvherre@alvh.no-ip. 281 : 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
282 : : TimeADTGetDatum(origentry->lower),
283 : : TimeADTGetDatum(newentry->lower)));
7352 tgl@sss.pgh.pa.us 284 : 0 : res2 = INTERVAL_TO_SEC(intr);
285 [ # # ]: 0 : res2 = Max(res2, 0);
286 : :
287 : 0 : res += res2;
288 : :
7678 bruce@momjian.us 289 : 0 : *result = 0.0;
290 : :
291 [ # # ]: 0 : if (res > 0)
292 : : {
2046 alvherre@alvh.no-ip. 293 : 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
294 : : TimeADTGetDatum(origentry->upper),
295 : : TimeADTGetDatum(origentry->lower)));
7678 bruce@momjian.us 296 : 0 : *result += FLT_MIN;
7352 tgl@sss.pgh.pa.us 297 : 0 : *result += (float) (res / (res + INTERVAL_TO_SEC(intr)));
7678 bruce@momjian.us 298 : 0 : *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
299 : : }
300 : :
301 : 0 : PG_RETURN_POINTER(result);
302 : : }
303 : :
304 : : Datum
7771 teodor@sigaev.ru 305 :CBC 2 : gbt_time_picksplit(PG_FUNCTION_ARGS)
306 : : {
2046 alvherre@alvh.no-ip. 307 : 2 : PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
308 : : (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
309 : : &tinfo, fcinfo->flinfo));
310 : : }
311 : :
312 : : Datum
7771 teodor@sigaev.ru 313 :UBC 0 : gbt_time_same(PG_FUNCTION_ARGS)
314 : : {
7678 bruce@momjian.us 315 : 0 : timeKEY *b1 = (timeKEY *) PG_GETARG_POINTER(0);
316 : 0 : timeKEY *b2 = (timeKEY *) PG_GETARG_POINTER(1);
317 : 0 : bool *result = (bool *) PG_GETARG_POINTER(2);
318 : :
3091 andrew@dunslane.net 319 : 0 : *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
7678 bruce@momjian.us 320 : 0 : PG_RETURN_POINTER(result);
321 : : }
322 : :
323 : : static int
156 heikki.linnakangas@i 324 :CBC 10635 : gbt_timekey_ssup_cmp(Datum x, Datum y, SortSupport ssup)
325 : : {
326 : 10635 : timeKEY *arg1 = (timeKEY *) DatumGetPointer(x);
327 : 10635 : timeKEY *arg2 = (timeKEY *) DatumGetPointer(y);
328 : :
329 : : /* for leaf items we expect lower == upper, so only compare lower */
330 : 10635 : return DatumGetInt32(DirectFunctionCall2(time_cmp,
331 : : TimeADTGetDatum(arg1->lower),
332 : : TimeADTGetDatum(arg2->lower)));
333 : : }
334 : :
335 : : Datum
336 : 2 : gbt_time_sortsupport(PG_FUNCTION_ARGS)
337 : : {
338 : 2 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
339 : :
340 : 2 : ssup->comparator = gbt_timekey_ssup_cmp;
341 : 2 : ssup->ssup_extra = NULL;
342 : :
343 : 2 : PG_RETURN_VOID();
344 : : }
|