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 = (timeKEY *) palloc(sizeof(timeKEY));
166 1062 : TimeTzADT *tz = DatumGetTimeTzADTP(entry->key);
167 : TimeADT tmp;
168 :
169 1062 : retval = palloc(sizeof(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 :
198 : /* Oid subtype = PG_GETARG_OID(3); */
199 3828 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
200 3828 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
201 : GBT_NUMKEY_R key;
202 :
203 : /* All cases served by this function are exact */
204 3828 : *recheck = false;
205 :
206 3828 : key.lower = (GBT_NUMKEY *) &kkk->lower;
207 3828 : key.upper = (GBT_NUMKEY *) &kkk->upper;
208 :
209 3828 : PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
210 : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
211 : }
212 :
213 : Datum
214 548 : gbt_time_distance(PG_FUNCTION_ARGS)
215 : {
216 548 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
217 548 : TimeADT query = PG_GETARG_TIMEADT(1);
218 :
219 : /* Oid subtype = PG_GETARG_OID(3); */
220 548 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
221 : GBT_NUMKEY_R key;
222 :
223 548 : key.lower = (GBT_NUMKEY *) &kkk->lower;
224 548 : key.upper = (GBT_NUMKEY *) &kkk->upper;
225 :
226 548 : PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
227 : &tinfo, fcinfo->flinfo));
228 : }
229 :
230 : Datum
231 11202 : gbt_timetz_consistent(PG_FUNCTION_ARGS)
232 : {
233 11202 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
234 11202 : TimeTzADT *query = PG_GETARG_TIMETZADT_P(1);
235 11202 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
236 :
237 : /* Oid subtype = PG_GETARG_OID(3); */
238 11202 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
239 11202 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
240 : TimeADT qqq;
241 : GBT_NUMKEY_R key;
242 :
243 : /* All cases served by this function are inexact */
244 11202 : *recheck = true;
245 :
246 11202 : qqq = query->time + (query->zone * INT64CONST(1000000));
247 :
248 11202 : key.lower = (GBT_NUMKEY *) &kkk->lower;
249 11202 : key.upper = (GBT_NUMKEY *) &kkk->upper;
250 :
251 11202 : PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy,
252 : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
253 : }
254 :
255 : Datum
256 4 : gbt_time_union(PG_FUNCTION_ARGS)
257 : {
258 4 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
259 4 : void *out = palloc(sizeof(timeKEY));
260 :
261 4 : *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
262 4 : PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
263 : }
264 :
265 : Datum
266 0 : gbt_time_penalty(PG_FUNCTION_ARGS)
267 : {
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 :
275 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
276 : TimeADTGetDatum(newentry->upper),
277 : TimeADTGetDatum(origentry->upper)));
278 0 : res = INTERVAL_TO_SEC(intr);
279 0 : res = Max(res, 0);
280 :
281 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
282 : TimeADTGetDatum(origentry->lower),
283 : TimeADTGetDatum(newentry->lower)));
284 0 : res2 = INTERVAL_TO_SEC(intr);
285 0 : res2 = Max(res2, 0);
286 :
287 0 : res += res2;
288 :
289 0 : *result = 0.0;
290 :
291 0 : if (res > 0)
292 : {
293 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
294 : TimeADTGetDatum(origentry->upper),
295 : TimeADTGetDatum(origentry->lower)));
296 0 : *result += FLT_MIN;
297 0 : *result += (float) (res / (res + INTERVAL_TO_SEC(intr)));
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
305 4 : gbt_time_picksplit(PG_FUNCTION_ARGS)
306 : {
307 4 : 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
313 0 : gbt_time_same(PG_FUNCTION_ARGS)
314 : {
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 :
319 0 : *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
320 0 : PG_RETURN_POINTER(result);
321 : }
322 :
323 : static int
324 21270 : gbt_timekey_ssup_cmp(Datum x, Datum y, SortSupport ssup)
325 : {
326 21270 : timeKEY *arg1 = (timeKEY *) DatumGetPointer(x);
327 21270 : timeKEY *arg2 = (timeKEY *) DatumGetPointer(y);
328 :
329 : /* for leaf items we expect lower == upper, so only compare lower */
330 21270 : return DatumGetInt32(DirectFunctionCall2(time_cmp,
331 : TimeADTGetDatum(arg1->lower),
332 : TimeADTGetDatum(arg2->lower)));
333 : }
334 :
335 : Datum
336 4 : gbt_time_sortsupport(PG_FUNCTION_ARGS)
337 : {
338 4 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
339 :
340 4 : ssup->comparator = gbt_timekey_ssup_cmp;
341 4 : ssup->ssup_extra = NULL;
342 :
343 4 : PG_RETURN_VOID();
344 : }
|