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 */
21 8 : PG_FUNCTION_INFO_V1(gbt_time_compress);
22 8 : PG_FUNCTION_INFO_V1(gbt_timetz_compress);
23 8 : PG_FUNCTION_INFO_V1(gbt_time_fetch);
24 10 : PG_FUNCTION_INFO_V1(gbt_time_union);
25 10 : PG_FUNCTION_INFO_V1(gbt_time_picksplit);
26 8 : PG_FUNCTION_INFO_V1(gbt_time_consistent);
27 8 : PG_FUNCTION_INFO_V1(gbt_time_distance);
28 8 : PG_FUNCTION_INFO_V1(gbt_timetz_consistent);
29 10 : PG_FUNCTION_INFO_V1(gbt_time_penalty);
30 10 : PG_FUNCTION_INFO_V1(gbt_time_same);
31 10 : PG_FUNCTION_INFO_V1(gbt_time_sortsupport);
32 0 : PG_FUNCTION_INFO_V1(gbt_timetz_sortsupport);
33 :
34 :
35 : static bool
36 6422 : gbt_timegt(const void *a, const void *b, FmgrInfo *flinfo)
37 : {
38 6422 : const TimeADT *aa = (const TimeADT *) a;
39 6422 : const TimeADT *bb = (const TimeADT *) b;
40 :
41 6422 : return DatumGetBool(DirectFunctionCall2(time_gt,
42 : TimeADTGetDatum(*aa),
43 : TimeADTGetDatum(*bb)));
44 : }
45 :
46 : static bool
47 2670 : gbt_timege(const void *a, const void *b, FmgrInfo *flinfo)
48 : {
49 2670 : const TimeADT *aa = (const TimeADT *) a;
50 2670 : const TimeADT *bb = (const TimeADT *) b;
51 :
52 2670 : return DatumGetBool(DirectFunctionCall2(time_ge,
53 : TimeADTGetDatum(*aa),
54 : TimeADTGetDatum(*bb)));
55 : }
56 :
57 : static bool
58 2134 : gbt_timeeq(const void *a, const void *b, FmgrInfo *flinfo)
59 : {
60 2134 : const TimeADT *aa = (const TimeADT *) a;
61 2134 : const TimeADT *bb = (const TimeADT *) b;
62 :
63 2134 : return DatumGetBool(DirectFunctionCall2(time_eq,
64 : TimeADTGetDatum(*aa),
65 : TimeADTGetDatum(*bb)));
66 : }
67 :
68 : static bool
69 4878 : gbt_timele(const void *a, const void *b, FmgrInfo *flinfo)
70 : {
71 4878 : const TimeADT *aa = (const TimeADT *) a;
72 4878 : const TimeADT *bb = (const TimeADT *) b;
73 :
74 4878 : return DatumGetBool(DirectFunctionCall2(time_le,
75 : TimeADTGetDatum(*aa),
76 : TimeADTGetDatum(*bb)));
77 : }
78 :
79 : static bool
80 8562 : gbt_timelt(const void *a, const void *b, FmgrInfo *flinfo)
81 : {
82 8562 : const TimeADT *aa = (const TimeADT *) a;
83 8562 : const TimeADT *bb = (const TimeADT *) b;
84 :
85 8562 : return DatumGetBool(DirectFunctionCall2(time_lt,
86 : TimeADTGetDatum(*aa),
87 : TimeADTGetDatum(*bb)));
88 : }
89 :
90 : static int
91 2146 : gbt_timekey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
92 : {
93 2146 : timeKEY *ia = (timeKEY *) (((const Nsrt *) a)->t);
94 2146 : timeKEY *ib = (timeKEY *) (((const Nsrt *) b)->t);
95 : int res;
96 :
97 2146 : res = DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatum(ia->lower), TimeADTGetDatum(ib->lower)));
98 2146 : if (res == 0)
99 2 : return DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatum(ia->upper), TimeADTGetDatum(ib->upper)));
100 :
101 2144 : return res;
102 : }
103 :
104 : static float8
105 546 : gbt_time_dist(const void *a, const void *b, FmgrInfo *flinfo)
106 : {
107 546 : const TimeADT *aa = (const TimeADT *) a;
108 546 : const TimeADT *bb = (const TimeADT *) b;
109 : Interval *i;
110 :
111 546 : i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
112 : TimeADTGetDatum(*aa),
113 : TimeADTGetDatum(*bb)));
114 546 : 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 :
133 8 : PG_FUNCTION_INFO_V1(time_dist);
134 : Datum
135 1094 : time_dist(PG_FUNCTION_ARGS)
136 : {
137 1094 : Datum diff = DirectFunctionCall2(time_mi_time,
138 : PG_GETARG_DATUM(0),
139 : PG_GETARG_DATUM(1));
140 :
141 1094 : PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
142 : }
143 :
144 :
145 : /**************************************************
146 : * GiST support functions
147 : **************************************************/
148 :
149 : Datum
150 1092 : gbt_time_compress(PG_FUNCTION_ARGS)
151 : {
152 1092 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
153 :
154 1092 : PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
155 : }
156 :
157 : Datum
158 1066 : gbt_timetz_compress(PG_FUNCTION_ARGS)
159 : {
160 1066 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
161 : GISTENTRY *retval;
162 :
163 1066 : if (entry->leafkey)
164 : {
165 1062 : timeKEY *r = palloc_object(timeKEY);
166 1062 : TimeTzADT *tz = DatumGetTimeTzADTP(entry->key);
167 : TimeADT tmp;
168 :
169 1062 : retval = palloc_object(GISTENTRY);
170 :
171 : /* We are using the time + zone only to compress */
172 1062 : tmp = tz->time + (tz->zone * INT64CONST(1000000));
173 1062 : r->lower = r->upper = tmp;
174 1062 : gistentryinit(*retval, PointerGetDatum(r),
175 : entry->rel, entry->page,
176 : entry->offset, false);
177 : }
178 : else
179 4 : retval = entry;
180 1066 : PG_RETURN_POINTER(retval);
181 : }
182 :
183 : Datum
184 544 : gbt_time_fetch(PG_FUNCTION_ARGS)
185 : {
186 544 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
187 :
188 544 : PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
189 : }
190 :
191 : Datum
192 3828 : gbt_time_consistent(PG_FUNCTION_ARGS)
193 : {
194 3828 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
195 3828 : TimeADT query = PG_GETARG_TIMEADT(1);
196 3828 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
197 : #ifdef NOT_USED
198 : Oid subtype = PG_GETARG_OID(3);
199 : #endif
200 3828 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
201 3828 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
202 : GBT_NUMKEY_R key;
203 :
204 : /* All cases served by this function are exact */
205 3828 : *recheck = false;
206 :
207 3828 : key.lower = (GBT_NUMKEY *) &kkk->lower;
208 3828 : key.upper = (GBT_NUMKEY *) &kkk->upper;
209 :
210 3828 : PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
211 : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
212 : }
213 :
214 : Datum
215 548 : gbt_time_distance(PG_FUNCTION_ARGS)
216 : {
217 548 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
218 548 : TimeADT query = PG_GETARG_TIMEADT(1);
219 : #ifdef NOT_USED
220 : Oid subtype = PG_GETARG_OID(3);
221 : #endif
222 548 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
223 : GBT_NUMKEY_R key;
224 :
225 548 : key.lower = (GBT_NUMKEY *) &kkk->lower;
226 548 : key.upper = (GBT_NUMKEY *) &kkk->upper;
227 :
228 548 : PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
229 : &tinfo, fcinfo->flinfo));
230 : }
231 :
232 : Datum
233 11202 : gbt_timetz_consistent(PG_FUNCTION_ARGS)
234 : {
235 11202 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
236 11202 : TimeTzADT *query = PG_GETARG_TIMETZADT_P(1);
237 11202 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
238 : #ifdef NOT_USED
239 : Oid subtype = PG_GETARG_OID(3);
240 : #endif
241 11202 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
242 11202 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
243 : TimeADT qqq;
244 : GBT_NUMKEY_R key;
245 :
246 : /* All cases served by this function are inexact */
247 11202 : *recheck = true;
248 :
249 11202 : qqq = query->time + (query->zone * INT64CONST(1000000));
250 :
251 11202 : key.lower = (GBT_NUMKEY *) &kkk->lower;
252 11202 : key.upper = (GBT_NUMKEY *) &kkk->upper;
253 :
254 11202 : PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy,
255 : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
256 : }
257 :
258 : Datum
259 4 : gbt_time_union(PG_FUNCTION_ARGS)
260 : {
261 4 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
262 4 : void *out = palloc(sizeof(timeKEY));
263 :
264 4 : *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
265 4 : PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
266 : }
267 :
268 : Datum
269 0 : gbt_time_penalty(PG_FUNCTION_ARGS)
270 : {
271 0 : timeKEY *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
272 0 : timeKEY *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
273 0 : float *result = (float *) PG_GETARG_POINTER(2);
274 : Interval *intr;
275 : double res;
276 : double res2;
277 :
278 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
279 : TimeADTGetDatum(newentry->upper),
280 : TimeADTGetDatum(origentry->upper)));
281 0 : res = INTERVAL_TO_SEC(intr);
282 0 : res = Max(res, 0);
283 :
284 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
285 : TimeADTGetDatum(origentry->lower),
286 : TimeADTGetDatum(newentry->lower)));
287 0 : res2 = INTERVAL_TO_SEC(intr);
288 0 : res2 = Max(res2, 0);
289 :
290 0 : res += res2;
291 :
292 0 : *result = 0.0;
293 :
294 0 : if (res > 0)
295 : {
296 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
297 : TimeADTGetDatum(origentry->upper),
298 : TimeADTGetDatum(origentry->lower)));
299 0 : *result += FLT_MIN;
300 0 : *result += (float) (res / (res + INTERVAL_TO_SEC(intr)));
301 0 : *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
302 : }
303 :
304 0 : PG_RETURN_POINTER(result);
305 : }
306 :
307 : Datum
308 4 : gbt_time_picksplit(PG_FUNCTION_ARGS)
309 : {
310 4 : PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
311 : (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
312 : &tinfo, fcinfo->flinfo));
313 : }
314 :
315 : Datum
316 0 : gbt_time_same(PG_FUNCTION_ARGS)
317 : {
318 0 : timeKEY *b1 = (timeKEY *) PG_GETARG_POINTER(0);
319 0 : timeKEY *b2 = (timeKEY *) PG_GETARG_POINTER(1);
320 0 : bool *result = (bool *) PG_GETARG_POINTER(2);
321 :
322 0 : *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
323 0 : PG_RETURN_POINTER(result);
324 : }
325 :
326 : static int
327 21270 : gbt_timekey_ssup_cmp(Datum x, Datum y, SortSupport ssup)
328 : {
329 21270 : timeKEY *arg1 = (timeKEY *) DatumGetPointer(x);
330 21270 : timeKEY *arg2 = (timeKEY *) DatumGetPointer(y);
331 :
332 : /* for leaf items we expect lower == upper, so only compare lower */
333 21270 : return DatumGetInt32(DirectFunctionCall2(time_cmp,
334 : TimeADTGetDatum(arg1->lower),
335 : TimeADTGetDatum(arg2->lower)));
336 : }
337 :
338 : Datum
339 4 : gbt_time_sortsupport(PG_FUNCTION_ARGS)
340 : {
341 4 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
342 :
343 4 : ssup->comparator = gbt_timekey_ssup_cmp;
344 4 : ssup->ssup_extra = NULL;
345 :
346 4 : PG_RETURN_VOID();
347 : }
|