Age Owner 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/builtins.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 : */
6890 teodor 21 CBC 2 : PG_FUNCTION_INFO_V1(gbt_time_compress);
22 2 : PG_FUNCTION_INFO_V1(gbt_timetz_compress);
2935 heikki.linnakangas 23 2 : PG_FUNCTION_INFO_V1(gbt_time_fetch);
6890 teodor 24 3 : PG_FUNCTION_INFO_V1(gbt_time_union);
25 3 : PG_FUNCTION_INFO_V1(gbt_time_picksplit);
26 2 : PG_FUNCTION_INFO_V1(gbt_time_consistent);
4421 tgl 27 2 : PG_FUNCTION_INFO_V1(gbt_time_distance);
6890 teodor 28 2 : PG_FUNCTION_INFO_V1(gbt_timetz_consistent);
29 3 : PG_FUNCTION_INFO_V1(gbt_time_penalty);
30 3 : 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
2210 andrew 41 3179 : gbt_timegt(const void *a, const void *b, FmgrInfo *flinfo)
42 : {
5466 tgl 43 3179 : const TimeADT *aa = (const TimeADT *) a;
44 3179 : const TimeADT *bb = (const TimeADT *) b;
45 :
46 3179 : return DatumGetBool(DirectFunctionCall2(time_gt,
47 : TimeADTGetDatumFast(*aa),
48 : TimeADTGetDatumFast(*bb)));
49 : }
50 :
51 : static bool
2210 andrew 52 1199 : gbt_timege(const void *a, const void *b, FmgrInfo *flinfo)
53 : {
5466 tgl 54 1199 : const TimeADT *aa = (const TimeADT *) a;
55 1199 : const TimeADT *bb = (const TimeADT *) b;
56 :
57 1199 : return DatumGetBool(DirectFunctionCall2(time_ge,
58 : TimeADTGetDatumFast(*aa),
59 : TimeADTGetDatumFast(*bb)));
60 : }
61 :
62 : static bool
2210 andrew 63 1853 : gbt_timeeq(const void *a, const void *b, FmgrInfo *flinfo)
64 : {
5466 tgl 65 1853 : const TimeADT *aa = (const TimeADT *) a;
66 1853 : const TimeADT *bb = (const TimeADT *) b;
67 :
68 1853 : return DatumGetBool(DirectFunctionCall2(time_eq,
69 : TimeADTGetDatumFast(*aa),
70 : TimeADTGetDatumFast(*bb)));
71 : }
72 :
73 : static bool
2210 andrew 74 1919 : gbt_timele(const void *a, const void *b, FmgrInfo *flinfo)
75 : {
5466 tgl 76 1919 : const TimeADT *aa = (const TimeADT *) a;
77 1919 : const TimeADT *bb = (const TimeADT *) b;
78 :
79 1919 : return DatumGetBool(DirectFunctionCall2(time_le,
80 : TimeADTGetDatumFast(*aa),
81 : TimeADTGetDatumFast(*bb)));
82 : }
83 :
84 : static bool
2210 andrew 85 3846 : gbt_timelt(const void *a, const void *b, FmgrInfo *flinfo)
86 : {
5466 tgl 87 3846 : const TimeADT *aa = (const TimeADT *) a;
88 3846 : const TimeADT *bb = (const TimeADT *) b;
89 :
90 3846 : return DatumGetBool(DirectFunctionCall2(time_lt,
91 : TimeADTGetDatumFast(*aa),
92 : TimeADTGetDatumFast(*bb)));
93 : }
94 :
95 :
96 :
97 : static int
2210 andrew 98 9061 : gbt_timekey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
99 : {
4228 peter_e 100 9061 : timeKEY *ia = (timeKEY *) (((const Nsrt *) a)->t);
101 9061 : timeKEY *ib = (timeKEY *) (((const Nsrt *) b)->t);
102 : int res;
103 :
4876 teodor 104 9061 : res = DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatumFast(ia->lower), TimeADTGetDatumFast(ib->lower)));
105 9061 : if (res == 0)
4876 teodor 106 UBC 0 : return DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatumFast(ia->upper), TimeADTGetDatumFast(ib->upper)));
107 :
4876 teodor 108 CBC 9061 : return res;
109 : }
110 :
111 : static float8
2210 andrew 112 144 : gbt_time_dist(const void *a, const void *b, FmgrInfo *flinfo)
113 : {
4421 tgl 114 144 : const TimeADT *aa = (const TimeADT *) a;
115 144 : const TimeADT *bb = (const TimeADT *) b;
116 : Interval *i;
117 :
118 144 : i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
119 : TimeADTGetDatumFast(*aa),
120 : TimeADTGetDatumFast(*bb)));
184 peter 121 GNC 144 : 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 :
4421 tgl 140 CBC 2 : PG_FUNCTION_INFO_V1(time_dist);
141 : Datum
142 547 : time_dist(PG_FUNCTION_ARGS)
143 : {
144 547 : Datum diff = DirectFunctionCall2(time_mi_time,
145 : PG_GETARG_DATUM(0),
146 : PG_GETARG_DATUM(1));
147 :
148 547 : PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
149 : }
150 :
151 :
152 : /**************************************************
153 : * time ops
154 : **************************************************/
155 :
156 :
157 :
158 : Datum
6890 teodor 159 553 : gbt_time_compress(PG_FUNCTION_ARGS)
160 : {
6797 bruce 161 553 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
162 :
2936 heikki.linnakangas 163 553 : PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
164 : }
165 :
166 :
167 : Datum
6890 teodor 168 538 : gbt_timetz_compress(PG_FUNCTION_ARGS)
169 : {
6797 bruce 170 538 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
171 : GISTENTRY *retval;
172 :
173 538 : if (entry->leafkey)
174 : {
175 531 : timeKEY *r = (timeKEY *) palloc(sizeof(timeKEY));
176 531 : TimeTzADT *tz = DatumGetTimeTzADTP(entry->key);
177 : TimeADT tmp;
178 :
179 531 : retval = palloc(sizeof(GISTENTRY));
180 :
181 : /* We are using the time + zone only to compress */
6558 tgl 182 531 : tmp = tz->time + (tz->zone * INT64CONST(1000000));
183 531 : r->lower = r->upper = tmp;
6797 bruce 184 531 : gistentryinit(*retval, PointerGetDatum(r),
185 : entry->rel, entry->page,
186 : entry->offset, false);
187 : }
188 : else
189 7 : retval = entry;
190 538 : PG_RETURN_POINTER(retval);
191 : }
192 :
193 : Datum
2935 heikki.linnakangas 194 142 : gbt_time_fetch(PG_FUNCTION_ARGS)
195 : {
196 142 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
197 :
198 142 : PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
199 : }
200 :
201 : Datum
6890 teodor 202 1529 : gbt_time_consistent(PG_FUNCTION_ARGS)
203 : {
6797 bruce 204 1529 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
205 1529 : TimeADT query = PG_GETARG_TIMEADT(1);
5473 tgl 206 1529 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
207 :
208 : /* Oid subtype = PG_GETARG_OID(3); */
209 1529 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
6797 bruce 210 1529 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
211 : GBT_NUMKEY_R key;
212 :
213 : /* All cases served by this function are exact */
5473 tgl 214 1529 : *recheck = false;
215 :
5050 bruce 216 1529 : key.lower = (GBT_NUMKEY *) &kkk->lower;
217 1529 : key.upper = (GBT_NUMKEY *) &kkk->upper;
218 :
1165 alvherre 219 1529 : PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy,
220 : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
221 : }
222 :
223 : Datum
4421 tgl 224 145 : gbt_time_distance(PG_FUNCTION_ARGS)
225 : {
226 145 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
227 145 : TimeADT query = PG_GETARG_TIMEADT(1);
228 :
229 : /* Oid subtype = PG_GETARG_OID(3); */
230 145 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
231 : GBT_NUMKEY_R key;
232 :
233 145 : key.lower = (GBT_NUMKEY *) &kkk->lower;
234 145 : key.upper = (GBT_NUMKEY *) &kkk->upper;
235 :
1165 alvherre 236 145 : PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry),
237 : &tinfo, fcinfo->flinfo));
238 : }
239 :
240 : Datum
6890 teodor 241 4791 : gbt_timetz_consistent(PG_FUNCTION_ARGS)
242 : {
6797 bruce 243 4791 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
244 4791 : TimeTzADT *query = PG_GETARG_TIMETZADT_P(1);
6558 tgl 245 4791 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
246 :
247 : /* Oid subtype = PG_GETARG_OID(3); */
5473 248 4791 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
6797 bruce 249 4791 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
250 : TimeADT qqq;
251 : GBT_NUMKEY_R key;
252 :
253 : /* All cases served by this function are inexact */
5473 tgl 254 4791 : *recheck = true;
255 :
6558 256 4791 : qqq = query->time + (query->zone * INT64CONST(1000000));
257 :
5050 bruce 258 4791 : key.lower = (GBT_NUMKEY *) &kkk->lower;
259 4791 : key.upper = (GBT_NUMKEY *) &kkk->upper;
260 :
1165 alvherre 261 4791 : PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &qqq, &strategy,
262 : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
263 : }
264 :
265 :
266 : Datum
6890 teodor 267 599 : gbt_time_union(PG_FUNCTION_ARGS)
268 : {
6797 bruce 269 599 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
270 599 : void *out = palloc(sizeof(timeKEY));
271 :
272 599 : *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
2210 andrew 273 599 : PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
274 : }
275 :
276 :
277 : Datum
6890 teodor 278 1055 : gbt_time_penalty(PG_FUNCTION_ARGS)
279 : {
6797 bruce 280 1055 : timeKEY *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
281 1055 : timeKEY *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
282 1055 : float *result = (float *) PG_GETARG_POINTER(2);
283 : Interval *intr;
284 : double res;
285 : double res2;
286 :
1165 alvherre 287 1055 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
288 : TimeADTGetDatumFast(newentry->upper),
289 : TimeADTGetDatumFast(origentry->upper)));
6471 tgl 290 1055 : res = INTERVAL_TO_SEC(intr);
291 1055 : res = Max(res, 0);
292 :
1165 alvherre 293 1055 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
294 : TimeADTGetDatumFast(origentry->lower),
295 : TimeADTGetDatumFast(newentry->lower)));
6471 tgl 296 1055 : res2 = INTERVAL_TO_SEC(intr);
297 1055 : res2 = Max(res2, 0);
298 :
299 1055 : res += res2;
300 :
6797 bruce 301 1055 : *result = 0.0;
302 :
303 1055 : if (res > 0)
304 : {
1165 alvherre 305 464 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
306 : TimeADTGetDatumFast(origentry->upper),
307 : TimeADTGetDatumFast(origentry->lower)));
6797 bruce 308 464 : *result += FLT_MIN;
6471 tgl 309 464 : *result += (float) (res / (res + INTERVAL_TO_SEC(intr)));
6797 bruce 310 464 : *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
311 : }
312 :
313 1055 : PG_RETURN_POINTER(result);
314 : }
315 :
316 :
317 : Datum
6890 teodor 318 4 : gbt_time_picksplit(PG_FUNCTION_ARGS)
319 : {
1165 alvherre 320 4 : 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
6890 teodor 326 597 : gbt_time_same(PG_FUNCTION_ARGS)
327 : {
6797 bruce 328 597 : timeKEY *b1 = (timeKEY *) PG_GETARG_POINTER(0);
329 597 : timeKEY *b2 = (timeKEY *) PG_GETARG_POINTER(1);
330 597 : bool *result = (bool *) PG_GETARG_POINTER(2);
331 :
2210 andrew 332 597 : *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
6797 bruce 333 597 : PG_RETURN_POINTER(result);
334 : }
|