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